Skip to content

Commit 04c837d

Browse files
kp2pml30JelleZijlstraAA-Turner
authored
gh-124442: make __static_attributes__ deterministic by sorting (#124492)
Signed-off-by: kp2pml30 <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]> Co-authored-by: Adam Turner <[email protected]>
1 parent 69a4063 commit 04c837d

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

Lib/test/test_compile.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
import dis
33
import io
4+
import itertools
45
import math
56
import opcode
67
import os
@@ -2687,6 +2688,22 @@ def test_nested(self):
26872688
self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)])
26882689
self.compare_instructions(seq.get_nested()[0], [('LOAD_CONST', 2, 2, 0, 0, 0)])
26892690

2691+
def test_static_attributes_are_sorted(self):
2692+
code = (
2693+
'class T:\n'
2694+
' def __init__(self):\n'
2695+
' self.{V1} = 10\n'
2696+
' self.{V2} = 10\n'
2697+
' def foo(self):\n'
2698+
' self.{V3} = 10\n'
2699+
)
2700+
attributes = ("a", "b", "c")
2701+
for perm in itertools.permutations(attributes):
2702+
var_names = {f'V{i + 1}': name for i, name in enumerate(perm)}
2703+
ns = run_code(code.format(**var_names))
2704+
t = ns['T']
2705+
self.assertEqual(t.__static_attributes__, attributes)
2706+
26902707

26912708
if __name__ == "__main__":
26922709
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix nondeterminism in compilation by sorting the value of
2+
:attr:`~type.__static_attributes__`. Patch by kp2pml30.

Python/compile.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,17 @@ PyObject *
911911
_PyCompile_StaticAttributesAsTuple(compiler *c)
912912
{
913913
assert(c->u->u_static_attributes);
914-
return PySequence_Tuple(c->u->u_static_attributes);
914+
PyObject *static_attributes_unsorted = PySequence_List(c->u->u_static_attributes);
915+
if (static_attributes_unsorted == NULL) {
916+
return NULL;
917+
}
918+
if (PyList_Sort(static_attributes_unsorted) != 0) {
919+
Py_DECREF(static_attributes_unsorted);
920+
return NULL;
921+
}
922+
PyObject *static_attributes = PySequence_Tuple(static_attributes_unsorted);
923+
Py_DECREF(static_attributes_unsorted);
924+
return static_attributes;
915925
}
916926

917927
int

0 commit comments

Comments
 (0)