Skip to content

Commit b99c662

Browse files
JelleZijlstrakp2pml30AA-Turner
authored
[3.13] gh-124442: make __static_attributes__ deterministic by sorting (GH-124492) (#124738)
* [3.13] gh-124442: make `__static_attributes__` deterministic by sorting (GH-124492) (cherry picked from commit 04c837d) Co-authored-by: Kira <[email protected]> Signed-off-by: kp2pml30 <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]> Co-authored-by: Adam Turner <[email protected]>
1 parent b843974 commit b99c662

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-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
@@ -2619,6 +2620,22 @@ def test_nested(self):
26192620
self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)])
26202621
self.compare_instructions(seq.get_nested()[0], [('LOAD_CONST', 2, 2, 0, 0, 0)])
26212622

2623+
def test_static_attributes_are_sorted(self):
2624+
code = (
2625+
'class T:\n'
2626+
' def __init__(self):\n'
2627+
' self.{V1} = 10\n'
2628+
' self.{V2} = 10\n'
2629+
' def foo(self):\n'
2630+
' self.{V3} = 10\n'
2631+
)
2632+
attributes = ("a", "b", "c")
2633+
for perm in itertools.permutations(attributes):
2634+
var_names = {f'V{i + 1}': name for i, name in enumerate(perm)}
2635+
ns = run_code(code.format(**var_names))
2636+
t = ns['T']
2637+
self.assertEqual(t.__static_attributes__, attributes)
2638+
26222639

26232640
if __name__ == "__main__":
26242641
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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2544,7 +2544,18 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
25442544
return ERROR;
25452545
}
25462546
assert(c->u->u_static_attributes);
2547-
PyObject *static_attributes = PySequence_Tuple(c->u->u_static_attributes);
2547+
PyObject *static_attributes_unsorted = PySequence_List(c->u->u_static_attributes);
2548+
if (static_attributes_unsorted == NULL) {
2549+
compiler_exit_scope(c);
2550+
return ERROR;
2551+
}
2552+
if (PyList_Sort(static_attributes_unsorted) != 0) {
2553+
compiler_exit_scope(c);
2554+
Py_DECREF(static_attributes_unsorted);
2555+
return ERROR;
2556+
}
2557+
PyObject *static_attributes = PySequence_Tuple(static_attributes_unsorted);
2558+
Py_DECREF(static_attributes_unsorted);
25482559
if (static_attributes == NULL) {
25492560
compiler_exit_scope(c);
25502561
return ERROR;

0 commit comments

Comments
 (0)