diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2022-03-23 15:55:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-23 15:55:52 (GMT) |
commit | febf54bcf3fdc45ad84b4073e24bbaaee0ac8b2a (patch) | |
tree | abc92afd100f6a13f17314c1d2d72fd74303b78f /Tools | |
parent | 21412d037b07c08266e96dfd0c0e44a1b7693bc1 (diff) | |
download | cpython-febf54bcf3fdc45ad84b4073e24bbaaee0ac8b2a.zip cpython-febf54bcf3fdc45ad84b4073e24bbaaee0ac8b2a.tar.gz cpython-febf54bcf3fdc45ad84b4073e24bbaaee0ac8b2a.tar.bz2 |
bpo-46712: Do not Regen Deep-Frozen Modules before Generating Global Objects (gh-32061)
We have to run "make regen-deepfreeze" before running Tools/scripts/generate-global-objects.py; otherwise we will miss any changes to global objects in deep-frozen modules (which aren't committed in the repo). However, building $(PYTHON_FOR_FREEZE) fails if one of its source files had a global object (e.g. via _Py_ID(...)) added or removed, without generate-global-objects.py running first. So "make regen-global-objects" would sometimes fail.
We solve this by running generate-global-objects.py before *and* after "make regen-deepfreeze". To speed things up and cut down on noise, we also avoid updating the global objects files if there are no changes to them.
https://bugs.python.org/issue46712
Diffstat (limited to 'Tools')
-rw-r--r-- | Tools/scripts/generate_global_objects.py | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/Tools/scripts/generate_global_objects.py b/Tools/scripts/generate_global_objects.py index 17ddb8b..f765360 100644 --- a/Tools/scripts/generate_global_objects.py +++ b/Tools/scripts/generate_global_objects.py @@ -1,5 +1,6 @@ import contextlib import glob +import io import os.path import re import sys @@ -123,6 +124,7 @@ def iter_global_strings(): varname, string = m.groups() yield varname, string, filename, lno, line + def iter_to_marker(lines, marker): for line in lines: if line.rstrip() == marker: @@ -165,6 +167,19 @@ class Printer: self.write("}" + suffix) +@contextlib.contextmanager +def open_for_changes(filename, orig): + """Like open() but only write to the file if it changed.""" + outfile = io.StringIO() + yield outfile + text = outfile.getvalue() + if text != orig: + with open(filename, 'w', encoding='utf-8') as outfile: + outfile.write(text) + else: + print(f'# not changed: {filename}') + + ####################################### # the global objects @@ -177,13 +192,15 @@ def generate_global_strings(identifiers, strings): # Read the non-generated part of the file. with open(filename) as infile: - before = ''.join(iter_to_marker(infile, START))[:-1] - for _ in iter_to_marker(infile, END): - pass - after = infile.read()[:-1] + orig = infile.read() + lines = iter(orig.rstrip().splitlines()) + before = '\n'.join(iter_to_marker(lines, START)) + for _ in iter_to_marker(lines, END): + pass + after = '\n'.join(lines) # Generate the file. - with open(filename, 'w', encoding='utf-8') as outfile: + with open_for_changes(filename, orig) as outfile: printer = Printer(outfile) printer.write(before) printer.write(START) @@ -202,7 +219,6 @@ def generate_global_strings(identifiers, strings): with printer.block('struct', ' latin1[128];'): printer.write("PyCompactUnicodeObject _latin1;") printer.write("uint8_t _data[2];") - printer.write(END) printer.write(after) @@ -227,13 +243,15 @@ def generate_runtime_init(identifiers, strings): # Read the non-generated part of the file. with open(filename) as infile: - before = ''.join(iter_to_marker(infile, START))[:-1] - for _ in iter_to_marker(infile, END): - pass - after = infile.read()[:-1] + orig = infile.read() + lines = iter(orig.rstrip().splitlines()) + before = '\n'.join(iter_to_marker(lines, START)) + for _ in iter_to_marker(lines, END): + pass + after = '\n'.join(lines) # Generate the file. - with open(filename, 'w', encoding='utf-8') as outfile: + with open_for_changes(filename, orig) as outfile: printer = Printer(outfile) printer.write(before) printer.write(START) @@ -286,6 +304,7 @@ def get_identifiers_and_strings() -> 'tuple[set[str], dict[str, str]]': raise ValueError(f'string mismatch for {name!r} ({string!r} != {strings[name]!r}') return identifiers, strings + ####################################### # the script |