Skip to content

Commit 691a358

Browse files
committed
Align frozendict copy support and tests with CPython 3.15
Import exact-final copy.py with update_lib; defer Mapping ABC registration to the later library stage. Generate only proven marker corrections, retain observed debug recursion-limit expected failures, and copy the complete canonical builtin-doc discovery test using hash-pinned update_lib copy-test. Assisted-by: OpenAI Codex:model identifier unavailable
1 parent 4880699 commit 691a358

7 files changed

Lines changed: 39 additions & 19 deletions

File tree

‎Lib/copy.py‎

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ def copy(x):
100100
return _reconstruct(x, None, *rv)
101101

102102

103-
_copy_atomic_types = {types.NoneType, int, float, bool, complex, str, tuple,
104-
bytes, frozenset, type, range, slice, property,
103+
_copy_atomic_types = frozenset({types.NoneType, int, float, bool, complex, str, tuple,
104+
bytes, frozendict, frozenset, type, range, slice, property,
105105
types.BuiltinFunctionType, types.EllipsisType,
106106
types.NotImplementedType, types.FunctionType, types.CodeType,
107-
weakref.ref, super}
108-
_copy_builtin_containers = {list, dict, set, bytearray}
107+
weakref.ref, super})
108+
_copy_builtin_containers = frozenset({list, dict, set, bytearray})
109109

110-
def deepcopy(x, memo=None, _nil=[]):
110+
def deepcopy(x, memo=None):
111111
"""Deep copy operation on arbitrary Python objects.
112112
113113
See the module's __doc__ string for more info.
@@ -122,8 +122,8 @@ def deepcopy(x, memo=None, _nil=[]):
122122
if memo is None:
123123
memo = {}
124124
else:
125-
y = memo.get(d, _nil)
126-
if y is not _nil:
125+
y = memo.get(d, None)
126+
if y is not None:
127127
return y
128128

129129
copier = _deepcopy_dispatch.get(cls)
@@ -162,9 +162,9 @@ def deepcopy(x, memo=None, _nil=[]):
162162
_keep_alive(x, memo) # Make sure x lives at least as long as d
163163
return y
164164

165-
_atomic_types = {types.NoneType, types.EllipsisType, types.NotImplementedType,
165+
_atomic_types = frozenset({types.NoneType, types.EllipsisType, types.NotImplementedType,
166166
int, float, bool, complex, bytes, str, types.CodeType, type, range,
167-
types.BuiltinFunctionType, types.FunctionType, weakref.ref, property}
167+
types.BuiltinFunctionType, types.FunctionType, weakref.ref, property})
168168

169169
_deepcopy_dispatch = d = {}
170170

@@ -203,6 +203,21 @@ def _deepcopy_dict(x, memo, deepcopy=deepcopy):
203203
return y
204204
d[dict] = _deepcopy_dict
205205

206+
def _deepcopy_frozendict(x, memo, deepcopy=deepcopy):
207+
y = {}
208+
for key, value in x.items():
209+
y[deepcopy(key, memo)] = deepcopy(value, memo)
210+
211+
# We're not going to put the frozendict in the memo, but it's still
212+
# important we check for it, in case the frozendict contains recursive
213+
# mutable structures.
214+
try:
215+
return memo[id(x)]
216+
except KeyError:
217+
pass
218+
return frozendict(y)
219+
d[frozendict] = _deepcopy_frozendict
220+
206221
def _deepcopy_method(x, memo): # Copy instance methods
207222
return type(x)(x.__func__, deepcopy(x.__self__, memo))
208223
d[types.MethodType] = _deepcopy_method
@@ -230,7 +245,7 @@ def _reconstruct(x, memo, func, args,
230245
*, deepcopy=deepcopy):
231246
deep = memo is not None
232247
if deep and args:
233-
args = (deepcopy(arg, memo) for arg in args)
248+
args = [deepcopy(arg, memo) for arg in args]
234249
y = func(*args)
235250
if deep:
236251
memo[id(x)] = y

‎Lib/test/pickletester.py‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4394,8 +4394,6 @@ def test_fast_save_enter_frozenset(self):
43944394
def test_fast_save_enter_set(self):
43954395
self.fast_save_enter(lambda i: set([i]))
43964396

4397-
# TODO: RUSTPYTHON; frozendict support: https://github.com/RustPython/RustPython/pull/8951
4398-
@unittest.expectedFailure
43994397
def test_fast_save_enter_frozendict(self):
44004398
if self.py_version < (3, 15):
44014399
self.skipTest('need frozendict')
@@ -4443,8 +4441,6 @@ def test_deep_nested_struct_set(self):
44434441
depth=FAST_NESTING_LIMIT+1,
44444442
compare_equal=False)
44454443

4446-
# TODO: RUSTPYTHON; frozendict support: https://github.com/RustPython/RustPython/pull/8951
4447-
@unittest.expectedFailure
44484444
def test_deep_nested_struct_frozendict(self):
44494445
if self.py_version < (3, 15):
44504446
self.skipTest('need frozendict')

‎Lib/test/test_dict.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,6 @@ def test_empty_presized_dict_in_freelist(self):
951951
'f': None, 'g': None, 'h': None}
952952
d = {}
953953

954-
@unittest.expectedFailure # TODO: RUSTPYTHON
955954
def test_container_iterator(self):
956955
# Bug #3680: tp_traverse was not implemented for dictiter and
957956
# dictview objects.
@@ -1264,7 +1263,6 @@ def test_free_after_iterating(self):
12641263
support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
12651264
support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
12661265

1267-
@unittest.expectedFailure # TODO: RUSTPYTHON
12681266
def test_equal_operator_modifying_operand(self):
12691267
# test fix for seg fault reported in bpo-27945 part 3.
12701268
class X():

‎Lib/test/test_doctest/test_doctest.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ def non_Python_modules(): r"""
742742
743743
>>> import builtins
744744
>>> tests = doctest.DocTestFinder().find(builtins)
745-
>>> 750 < len(tests) < 800 # approximate number of objects with docstrings
745+
>>> 750 < len(tests) < 850 # approximate number of objects with docstrings
746746
True
747747
>>> real_tests = [t for t in tests if len(t.examples) > 0]
748748
>>> len(real_tests) # objects that actually have doctests

‎Lib/test/test_dynamic.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def test_eval_gives_lambda_custom_globals(self):
135135
self.assertEqual(foo(), 7)
136136

137137

138-
@unittest.expectedFailure # TODO: RUSTPYTHON
138+
@unittest.expectedFailureIf(sys.getrecursionlimit() == 256, "TODO: RUSTPYTHON; default debug recursion limit is 256")
139139
@skip_wasi_stack_overflow()
140140
def test_load_global_specialization_failure_keeps_oparg(self):
141141
# https://github.com/python/cpython/issues/91625

‎Lib/test/test_pickle.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def loads(self, buf, **kwds):
107107
def test_c_methods(self):
108108
return super().test_c_methods()
109109

110+
@unittest.expectedFailureIf(sys.getrecursionlimit() == 256, "TODO: RUSTPYTHON; default debug recursion limit is 256")
111+
def test_deep_nested_struct_frozendict(self):
112+
return super().test_deep_nested_struct_frozendict()
113+
110114

111115

112116

@@ -408,6 +412,10 @@ class CPicklerTests(PyPicklerTests):
408412
pickler = _pickle.Pickler
409413
unpickler = _pickle.Unpickler
410414

415+
@unittest.expectedSuccess # TODO: RUSTPYTHON; native pickler passes at the default debug recursion limit
416+
def test_deep_nested_struct_frozendict(self):
417+
return super().test_deep_nested_struct_frozendict()
418+
411419
class CPersPicklerTests(PyPersPicklerTests):
412420
pickler = _pickle.Pickler
413421
unpickler = _pickle.Unpickler
@@ -421,6 +429,10 @@ class CDumpPickle_LoadPickle(PyPicklerTests):
421429
pickler = _pickle.Pickler
422430
unpickler = pickle._Unpickler
423431

432+
@unittest.expectedSuccess # TODO: RUSTPYTHON; native pickler passes at the default debug recursion limit
433+
def test_deep_nested_struct_frozendict(self):
434+
return super().test_deep_nested_struct_frozendict()
435+
424436
class DumpPickle_CLoadPickle(PyPicklerTests):
425437
pickler = pickle._Pickler
426438
unpickler = _pickle.Unpickler

‎Lib/test/test_unittest/testmock/testhelpers.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ def test_any_and_datetime(self):
4545
mock.assert_called_with(ANY, foo=ANY)
4646

4747

48-
@unittest.expectedFailure # TODO: RUSTPYTHON
4948
def test_any_mock_calls_comparison_order(self):
5049
mock = Mock()
5150
class Foo(object):

0 commit comments

Comments
 (0)