From 9d1d4f9c73a71192b22ab52a2eb9278737f98ddb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 5 Jul 2023 13:23:22 +0200 Subject: [PATCH] gh-64595: Fix regression in file write logic in Argument Clinic (#106449) Revert the two commits that introduced the regressions: - gh-104152 - gh-104507 --- Lib/test/test_clinic.py | 7 +++---- Tools/clinic/clinic.py | 35 ++++++++++++----------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 7c46e8a81803a2..685ba58642a5ae 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -100,9 +100,8 @@ def test_eol(self): # the last line of the block got corrupted. c = clinic.Clinic(clinic.CLanguage(None), filename="file") raw = "/*[clinic]\nfoo\n[clinic]*/" - cooked, _ = c.parse(raw) - lines = cooked.splitlines() - end_line = lines[2].rstrip() + cooked = c.parse(raw).splitlines() + end_line = cooked[2].rstrip() # this test is redundant, it's just here explicitly to catch # the regression test so we don't forget what it looked like self.assertNotEqual(end_line, "[clinic]*/[clinic]*/") @@ -261,7 +260,7 @@ def _test_clinic(self, input, output): c = clinic.Clinic(language, filename="file") c.parsers['inert'] = InertParser(c) c.parsers['copy'] = CopyParser(c) - computed, _ = c.parse(input) + computed = c.parse(input) self.assertEqual(output, computed) def test_clinic_1(self): diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 5f5d024b5aa6f8..7ada7e9d917b38 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2021,22 +2021,20 @@ def dump(self): extensions['py'] = PythonLanguage -def file_changed(filename: str, new_contents: str) -> bool: - """Return true if file contents changed (meaning we must update it)""" +def write_file(filename: str, new_contents: str) -> None: try: - with open(filename, encoding="utf-8") as fp: + with open(filename, 'r', encoding="utf-8") as fp: old_contents = fp.read() - return old_contents != new_contents - except FileNotFoundError: - return True - -def write_file(filename: str, new_contents: str) -> None: + if old_contents == new_contents: + # no change: avoid modifying the file modification time + return + except FileNotFoundError: + pass # Atomic write using a temporary file and os.replace() filename_new = f"{filename}.new" with open(filename_new, "w", encoding="utf-8") as fp: fp.write(new_contents) - try: os.replace(filename_new, filename) except: @@ -2214,8 +2212,6 @@ def parse(self, input): traceback.format_exc().rstrip()) printer.print_block(block) - clinic_out = [] - # these are destinations not buffers for name, destination in self.destinations.items(): if destination.type == 'suppress': @@ -2223,7 +2219,6 @@ def parse(self, input): output = destination.dump() if output: - block = Block("", dsl_name="clinic", output=output) if destination.type == 'buffer': @@ -2255,11 +2250,10 @@ def parse(self, input): block.input = 'preserve\n' printer_2 = BlockPrinter(self.language) printer_2.print_block(block, core_includes=True) - pair = destination.filename, printer_2.f.getvalue() - clinic_out.append(pair) + write_file(destination.filename, printer_2.f.getvalue()) continue - return printer.f.getvalue(), clinic_out + return printer.f.getvalue() def _module_and_class(self, fields): @@ -2321,14 +2315,9 @@ def parse_file( assert isinstance(language, CLanguage) clinic = Clinic(language, verify=verify, filename=filename) - src_out, clinic_out = clinic.parse(raw) - - changes = [(fn, data) for fn, data in clinic_out if file_changed(fn, data)] - if changes: - # Always (re)write the source file. - write_file(output, src_out) - for fn, data in clinic_out: - write_file(fn, data) + cooked = clinic.parse(raw) + + write_file(output, cooked) def compute_checksum(