]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-64595: Fix write file logic in Argument Clinic (#104507)
authorErlend E. Aasland <erlend.aasland@protonmail.com>
Tue, 16 May 2023 10:25:43 +0000 (12:25 +0200)
committerGitHub <noreply@github.com>
Tue, 16 May 2023 10:25:43 +0000 (12:25 +0200)
Check if any clinic output actually changes any of the output files
before deciding if we should touch the source file.

Tools/clinic/clinic.py

index 4270fb3cc566133fbe14cbdd68a2d7af14bd89fc..13fd66b0406f26ebc82ff913e8ca8ba9529ee672 100755 (executable)
@@ -1965,17 +1965,17 @@ legacy_converters = {}
 return_converters = {}
 
 
-def write_file(filename, new_contents, force=False):
+def file_changed(filename: str, new_contents: str) -> bool:
+    """Return true if file contents changed (meaning we must update it)"""
     try:
         with open(filename, 'r', encoding="utf-8") as fp:
             old_contents = fp.read()
-
-        if old_contents == new_contents and not force:
-            # no change: avoid modifying the file modification time
-            return
+        return old_contents != new_contents
     except FileNotFoundError:
-        pass
+        return True
+
 
+def write_file(filename: str, new_contents: str):
     # Atomic write using a temporary file and os.replace()
     filename_new = f"{filename}.new"
     with open(filename_new, "w", encoding="utf-8") as fp:
@@ -2237,11 +2237,12 @@ def parse_file(filename, *, verify=True, output=None):
     clinic = Clinic(language, verify=verify, filename=filename)
     src_out, clinic_out = clinic.parse(raw)
 
-    # If clinic output changed, force updating the source file as well.
-    force = bool(clinic_out)
-    write_file(output, src_out, force=force)
-    for fn, data in clinic_out:
-        write_file(fn, data)
+    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)
 
 
 def compute_checksum(input, length=None):