mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
bpo-45873: Get rid of bootstrap_python (#29717)
Instead we use $(PYTHON_FOR_REGEN) .../deepfreeze.py with the frozen .h file as input, as we did for Windows in bpo-45850. We also get rid of the code that generates the .h files when make regen-frozen is run (i.e., .../make_frozen.py), and the MANIFEST file. Restore Python 3.8 and 3.9 as Windows host Python again Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
This commit is contained in:
parent
ae1965ccb4
commit
5be98e57b3
8 changed files with 240 additions and 412 deletions
|
@ -7,7 +7,7 @@ import os
|
|||
import re
|
||||
import time
|
||||
import types
|
||||
import typing
|
||||
from typing import Dict, FrozenSet, Tuple, TextIO
|
||||
|
||||
import umarshal
|
||||
|
||||
|
@ -42,13 +42,14 @@ def get_localsplus(code: types.CodeType):
|
|||
|
||||
|
||||
def get_localsplus_counts(code: types.CodeType,
|
||||
names: tuple[str, ...],
|
||||
kinds: bytes) -> tuple[int, int, int, int]:
|
||||
names: Tuple[str, ...],
|
||||
kinds: bytes) -> Tuple[int, int, int, int]:
|
||||
nlocals = 0
|
||||
nplaincellvars = 0
|
||||
ncellvars = 0
|
||||
nfreevars = 0
|
||||
for name, kind in zip(names, kinds, strict=True):
|
||||
assert len(names) == len(kinds)
|
||||
for name, kind in zip(names, kinds):
|
||||
if kind & CO_FAST_LOCAL:
|
||||
nlocals += 1
|
||||
if kind & CO_FAST_CELL:
|
||||
|
@ -71,7 +72,7 @@ PyUnicode_2BYTE_KIND = 2
|
|||
PyUnicode_4BYTE_KIND = 4
|
||||
|
||||
|
||||
def analyze_character_width(s: str) -> tuple[int, bool]:
|
||||
def analyze_character_width(s: str) -> Tuple[int, bool]:
|
||||
maxchar = ' '
|
||||
for c in s:
|
||||
maxchar = max(maxchar, c)
|
||||
|
@ -86,12 +87,17 @@ def analyze_character_width(s: str) -> tuple[int, bool]:
|
|||
return kind, ascii
|
||||
|
||||
|
||||
def removesuffix(base: str, suffix: str) -> str:
|
||||
if base.endswith(suffix):
|
||||
return base[:len(base) - len(suffix)]
|
||||
return base
|
||||
|
||||
class Printer:
|
||||
|
||||
def __init__(self, file: typing.TextIO):
|
||||
def __init__(self, file: TextIO):
|
||||
self.level = 0
|
||||
self.file = file
|
||||
self.cache: dict[tuple[type, object], str] = {}
|
||||
self.cache: Dict[Tuple[type, object], str] = {}
|
||||
self.hits, self.misses = 0, 0
|
||||
self.patchups: list[str] = []
|
||||
self.write('#include "Python.h"')
|
||||
|
@ -231,7 +237,7 @@ class Printer:
|
|||
# otherwise MSVC doesn't like it.
|
||||
self.write(f".co_consts = {co_consts},")
|
||||
self.write(f".co_names = {co_names},")
|
||||
self.write(f".co_firstinstr = (_Py_CODEUNIT *) {co_code.removesuffix('.ob_base.ob_base')}.ob_sval,")
|
||||
self.write(f".co_firstinstr = (_Py_CODEUNIT *) {removesuffix(co_code, '.ob_base.ob_base')}.ob_sval,")
|
||||
self.write(f".co_exceptiontable = {co_exceptiontable},")
|
||||
self.field(code, "co_flags")
|
||||
self.write(".co_warmup = QUICKENING_INITIAL_WARMUP_VALUE,")
|
||||
|
@ -259,7 +265,7 @@ class Printer:
|
|||
self.write(f".co_freevars = {co_freevars},")
|
||||
return f"& {name}.ob_base"
|
||||
|
||||
def generate_tuple(self, name: str, t: tuple[object, ...]) -> str:
|
||||
def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
|
||||
items = [self.generate(f"{name}_{i}", it) for i, it in enumerate(t)]
|
||||
self.write("static")
|
||||
with self.indent():
|
||||
|
@ -323,7 +329,7 @@ class Printer:
|
|||
self.write(f".cval = {{ {z.real}, {z.imag} }},")
|
||||
return f"&{name}.ob_base"
|
||||
|
||||
def generate_frozenset(self, name: str, fs: frozenset[object]) -> str:
|
||||
def generate_frozenset(self, name: str, fs: FrozenSet[object]) -> str:
|
||||
ret = self.generate_tuple(name, tuple(sorted(fs)))
|
||||
self.write("// TODO: The above tuple should be a frozenset")
|
||||
return ret
|
||||
|
@ -336,34 +342,33 @@ class Printer:
|
|||
# print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}")
|
||||
return self.cache[key]
|
||||
self.misses += 1
|
||||
match obj:
|
||||
case types.CodeType() | umarshal.Code() as code:
|
||||
val = self.generate_code(name, code)
|
||||
case tuple(t):
|
||||
val = self.generate_tuple(name, t)
|
||||
case str(s):
|
||||
val = self.generate_unicode(name, s)
|
||||
case bytes(b):
|
||||
val = self.generate_bytes(name, b)
|
||||
case True:
|
||||
return "Py_True"
|
||||
case False:
|
||||
return "Py_False"
|
||||
case int(i):
|
||||
val = self.generate_int(name, i)
|
||||
case float(x):
|
||||
val = self.generate_float(name, x)
|
||||
case complex() as z:
|
||||
val = self.generate_complex(name, z)
|
||||
case frozenset(fs):
|
||||
val = self.generate_frozenset(name, fs)
|
||||
case builtins.Ellipsis:
|
||||
return "Py_Ellipsis"
|
||||
case None:
|
||||
return "Py_None"
|
||||
case _:
|
||||
raise TypeError(
|
||||
f"Cannot generate code for {type(obj).__name__} object")
|
||||
if isinstance(obj, types.CodeType) or isinstance(obj, umarshal.Code):
|
||||
val = self.generate_code(name, obj)
|
||||
elif isinstance(obj, tuple):
|
||||
val = self.generate_tuple(name, obj)
|
||||
elif isinstance(obj, str):
|
||||
val = self.generate_unicode(name, obj)
|
||||
elif isinstance(obj, bytes):
|
||||
val = self.generate_bytes(name, obj)
|
||||
elif obj is True:
|
||||
return "Py_True"
|
||||
elif obj is False:
|
||||
return "Py_False"
|
||||
elif isinstance(obj, int):
|
||||
val = self.generate_int(name, obj)
|
||||
elif isinstance(obj, float):
|
||||
val = self.generate_float(name, obj)
|
||||
elif isinstance(obj, complex):
|
||||
val = self.generate_complex(name, obj)
|
||||
elif isinstance(obj, frozenset):
|
||||
val = self.generate_frozenset(name, obj)
|
||||
elif obj is builtins.Ellipsis:
|
||||
return "Py_Ellipsis"
|
||||
elif obj is None:
|
||||
return "Py_None"
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Cannot generate code for {type(obj).__name__} object")
|
||||
# print(f"Cache store {key!r:.40}: {val!r:.40}")
|
||||
self.cache[key] = val
|
||||
return val
|
||||
|
@ -393,12 +398,12 @@ def decode_frozen_data(source: str) -> types.CodeType:
|
|||
del lines[0]
|
||||
while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None:
|
||||
del lines[-1]
|
||||
values: tuple[int, ...] = ast.literal_eval("".join(lines))
|
||||
values: Tuple[int, ...] = ast.literal_eval("".join(lines).strip())
|
||||
data = bytes(values)
|
||||
return umarshal.loads(data)
|
||||
|
||||
|
||||
def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None:
|
||||
def generate(source: str, filename: str, modname: str, file: TextIO) -> None:
|
||||
if is_frozen_header(source):
|
||||
code = decode_frozen_data(source)
|
||||
else:
|
||||
|
@ -439,7 +444,7 @@ def main() -> None:
|
|||
verbose = args.verbose
|
||||
with open(args.file, encoding="utf-8") as f:
|
||||
source = f.read()
|
||||
modname = args.module or os.path.basename(args.file).removesuffix(".py")
|
||||
modname = args.module or removesuffix(os.path.basename(args.file), ".py")
|
||||
output = args.output or modname + ".c"
|
||||
with open(output, "w", encoding="utf-8") as file:
|
||||
with report_time("generate"):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue