]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-124442: make `__static_attributes__` deterministic by sorting (#124492)
authorKira <kp2pml30@gmail.com>
Sat, 28 Sep 2024 22:15:43 +0000 (01:15 +0300)
committerGitHub <noreply@github.com>
Sat, 28 Sep 2024 22:15:43 +0000 (15:15 -0700)
Signed-off-by: kp2pml30 <kp2pml30@gmail.com>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Lib/test/test_compile.py
Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst [new file with mode: 0644]
Python/compile.c

index b81d847c824273265b48737a05c4384ac79a0609..f7ef7a1c26f7bd16d17012ef1dbfde1c5e2e9c0e 100644 (file)
@@ -1,6 +1,7 @@
 import contextlib
 import dis
 import io
+import itertools
 import math
 import opcode
 import os
@@ -2687,6 +2688,22 @@ class TestInstructionSequence(unittest.TestCase):
         self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)])
         self.compare_instructions(seq.get_nested()[0], [('LOAD_CONST', 2, 2, 0, 0, 0)])
 
+    def test_static_attributes_are_sorted(self):
+        code = (
+            'class T:\n'
+            '    def __init__(self):\n'
+            '        self.{V1} = 10\n'
+            '        self.{V2} = 10\n'
+            '    def foo(self):\n'
+            '        self.{V3} = 10\n'
+        )
+        attributes = ("a", "b", "c")
+        for perm in itertools.permutations(attributes):
+            var_names = {f'V{i + 1}': name for i, name in enumerate(perm)}
+            ns = run_code(code.format(**var_names))
+            t = ns['T']
+            self.assertEqual(t.__static_attributes__, attributes)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-25-11-53-22.gh-issue-124442.EXC1Ve.rst
new file mode 100644 (file)
index 0000000..58e79f2
--- /dev/null
@@ -0,0 +1,2 @@
+Fix nondeterminism in compilation by sorting the value of
+:attr:`~type.__static_attributes__`. Patch by kp2pml30.
index 7b3e6f336e44b18bc2107c30d790e369aaef43a0..9826d3fbbde976b0fe54874d4bb8373fe967f1e9 100644 (file)
@@ -911,7 +911,17 @@ PyObject *
 _PyCompile_StaticAttributesAsTuple(compiler *c)
 {
     assert(c->u->u_static_attributes);
-    return PySequence_Tuple(c->u->u_static_attributes);
+    PyObject *static_attributes_unsorted = PySequence_List(c->u->u_static_attributes);
+    if (static_attributes_unsorted == NULL) {
+        return NULL;
+    }
+    if (PyList_Sort(static_attributes_unsorted) != 0) {
+        Py_DECREF(static_attributes_unsorted);
+        return NULL;
+    }
+    PyObject *static_attributes = PySequence_Tuple(static_attributes_unsorted);
+    Py_DECREF(static_attributes_unsorted);
+    return static_attributes;
 }
 
 int