Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 620065c

Browse files
[3.14] gh-133403: Check Tools/build/deepfreeze.py with mypy (GH-133802) (#134038)
gh-133403: Check `Tools/build/deepfreeze.py` with mypy (GH-133802) (cherry picked from commit 7eaa097) Co-authored-by: sobolevn <[email protected]>
1 parent fede4ed commit 620065c

File tree

5 files changed

+45
-25
lines changed

5 files changed

+45
-25
lines changed

.github/workflows/mypy.yml

+2
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ on:
1414
- "Lib/tomllib/**"
1515
- "Misc/mypy/**"
1616
- "Tools/build/compute-changes.py"
17+
- "Tools/build/deepfreeze.py"
1718
- "Tools/build/generate_sbom.py"
1819
- "Tools/build/generate-build-details.py"
1920
- "Tools/build/verify_ensurepip_wheels.py"
2021
- "Tools/build/update_file.py"
22+
- "Tools/build/umarshal.py"
2123
- "Tools/cases_generator/**"
2224
- "Tools/clinic/**"
2325
- "Tools/jit/**"

Tools/build/.ruff.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extend = "../../.ruff.toml" # Inherit the project-wide settings
22

33
[per-file-target-version]
4-
"deepfreeze.py" = "py310"
4+
"deepfreeze.py" = "py311" # requires `code.co_exceptiontable`
55
"stable_abi.py" = "py311" # requires 'tomllib'
66

77
[format]

Tools/build/deepfreeze.py

+33-18
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
33
The script may be executed by _bootstrap_python interpreter.
44
Shared library extension modules are not available in that case.
5-
On Windows, and in cross-compilation cases, it is executed
6-
by Python 3.10, and 3.11 features are not available.
5+
Requires 3.11+ to be executed,
6+
because relies on `code.co_qualname` and `code.co_exceptiontable`.
77
"""
8+
9+
from __future__ import annotations
10+
811
import argparse
912
import builtins
1013
import collections
@@ -13,10 +16,14 @@
1316
import re
1417
import time
1518
import types
16-
from typing import TextIO
1719

1820
import umarshal
1921

22+
TYPE_CHECKING = False
23+
if TYPE_CHECKING:
24+
from collections.abc import Iterator
25+
from typing import Any, TextIO
26+
2027
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
2128

2229
verbose = False
@@ -45,8 +52,8 @@ def make_string_literal(b: bytes) -> str:
4552

4653
next_code_version = 1
4754

48-
def get_localsplus(code: types.CodeType):
49-
a = collections.defaultdict(int)
55+
def get_localsplus(code: types.CodeType) -> tuple[tuple[str, ...], bytes]:
56+
a: collections.defaultdict[str, int] = collections.defaultdict(int)
5057
for name in code.co_varnames:
5158
a[name] |= CO_FAST_LOCAL
5259
for name in code.co_cellvars:
@@ -136,7 +143,7 @@ def get_identifiers_and_strings(self) -> tuple[set[str], dict[str, str]]:
136143
return identifiers, strings
137144

138145
@contextlib.contextmanager
139-
def indent(self) -> None:
146+
def indent(self) -> Iterator[None]:
140147
save_level = self.level
141148
try:
142149
self.level += 1
@@ -148,7 +155,7 @@ def write(self, arg: str) -> None:
148155
self.file.writelines((" "*self.level, arg, "\n"))
149156

150157
@contextlib.contextmanager
151-
def block(self, prefix: str, suffix: str = "") -> None:
158+
def block(self, prefix: str, suffix: str = "") -> Iterator[None]:
152159
self.write(prefix + " {")
153160
with self.indent():
154161
yield
@@ -250,9 +257,17 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
250257
co_names = self.generate(name + "_names", code.co_names)
251258
co_filename = self.generate(name + "_filename", code.co_filename)
252259
co_name = self.generate(name + "_name", code.co_name)
253-
co_qualname = self.generate(name + "_qualname", code.co_qualname)
254260
co_linetable = self.generate(name + "_linetable", code.co_linetable)
255-
co_exceptiontable = self.generate(name + "_exceptiontable", code.co_exceptiontable)
261+
# We use 3.10 for type checking, but this module requires 3.11
262+
# TODO: bump python version for this script.
263+
co_qualname = self.generate(
264+
name + "_qualname",
265+
code.co_qualname, # type: ignore[attr-defined]
266+
)
267+
co_exceptiontable = self.generate(
268+
name + "_exceptiontable",
269+
code.co_exceptiontable, # type: ignore[attr-defined]
270+
)
256271
# These fields are not directly accessible
257272
localsplusnames, localspluskinds = get_localsplus(code)
258273
co_localsplusnames = self.generate(name + "_localsplusnames", localsplusnames)
@@ -379,13 +394,13 @@ def generate_complex(self, name: str, z: complex) -> str:
379394
self.write(f".cval = {{ {z.real}, {z.imag} }},")
380395
return f"&{name}.ob_base"
381396

382-
def generate_frozenset(self, name: str, fs: frozenset[object]) -> str:
397+
def generate_frozenset(self, name: str, fs: frozenset[Any]) -> str:
383398
try:
384-
fs = sorted(fs)
399+
fs_sorted = sorted(fs)
385400
except TypeError:
386401
# frozen set with incompatible types, fallback to repr()
387-
fs = sorted(fs, key=repr)
388-
ret = self.generate_tuple(name, tuple(fs))
402+
fs_sorted = sorted(fs, key=repr)
403+
ret = self.generate_tuple(name, tuple(fs_sorted))
389404
self.write("// TODO: The above tuple should be a frozenset")
390405
return ret
391406

@@ -402,7 +417,7 @@ def generate(self, name: str, obj: object) -> str:
402417
# print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}")
403418
return self.cache[key]
404419
self.misses += 1
405-
if isinstance(obj, (types.CodeType, umarshal.Code)) :
420+
if isinstance(obj, types.CodeType) :
406421
val = self.generate_code(name, obj)
407422
elif isinstance(obj, tuple):
408423
val = self.generate_tuple(name, obj)
@@ -458,7 +473,7 @@ def decode_frozen_data(source: str) -> types.CodeType:
458473
if re.match(FROZEN_DATA_LINE, line):
459474
values.extend([int(x) for x in line.split(",") if x.strip()])
460475
data = bytes(values)
461-
return umarshal.loads(data)
476+
return umarshal.loads(data) # type: ignore[no-any-return]
462477

463478

464479
def generate(args: list[str], output: TextIO) -> None:
@@ -494,12 +509,12 @@ def generate(args: list[str], output: TextIO) -> None:
494509
help="Input file and module name (required) in file:modname format")
495510

496511
@contextlib.contextmanager
497-
def report_time(label: str):
498-
t0 = time.time()
512+
def report_time(label: str) -> Iterator[None]:
513+
t0 = time.perf_counter()
499514
try:
500515
yield
501516
finally:
502-
t1 = time.time()
517+
t1 = time.perf_counter()
503518
if verbose:
504519
print(f"{label}: {t1-t0:.3f} sec")
505520

Tools/build/mypy.ini

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
# .github/workflows/mypy.yml
55
files =
66
Tools/build/compute-changes.py,
7+
Tools/build/deepfreeze.py,
78
Tools/build/generate-build-details.py,
89
Tools/build/generate_sbom.py,
910
Tools/build/verify_ensurepip_wheels.py,
10-
Tools/build/update_file.py
11+
Tools/build/update_file.py,
12+
Tools/build/umarshal.py
1113

1214
pretty = True
1315

Tools/build/umarshal.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ def r_PyLong(self) -> int:
145145
def r_float_bin(self) -> float:
146146
buf = self.r_string(8)
147147
import struct # Lazy import to avoid breaking UNIX build
148-
return struct.unpack("d", buf)[0]
148+
return struct.unpack("d", buf)[0] # type: ignore[no-any-return]
149149

150150
def r_float_str(self) -> float:
151151
n = self.r_byte()
152152
buf = self.r_string(n)
153-
return ast.literal_eval(buf.decode("ascii"))
153+
return ast.literal_eval(buf.decode("ascii")) # type: ignore[no-any-return]
154154

155155
def r_ref_reserve(self, flag: int) -> int:
156156
if flag:
@@ -306,16 +306,17 @@ def loads(data: bytes) -> Any:
306306
return r.r_object()
307307

308308

309-
def main():
309+
def main() -> None:
310310
# Test
311311
import marshal
312312
import pprint
313313
sample = {'foo': {(42, "bar", 3.14)}}
314314
data = marshal.dumps(sample)
315315
retval = loads(data)
316316
assert retval == sample, retval
317-
sample = main.__code__
318-
data = marshal.dumps(sample)
317+
318+
sample2 = main.__code__
319+
data = marshal.dumps(sample2)
319320
retval = loads(data)
320321
assert isinstance(retval, Code), retval
321322
pprint.pprint(retval.__dict__)

0 commit comments

Comments
 (0)