Restore defaultdict fallback and update test markers

This commit is contained in:
Jeong, YunWon
2026-03-04 18:44:27 +09:00
parent 624ea3b13d
commit 5a5ddbbed4
4 changed files with 65 additions and 6 deletions

View File

@@ -57,7 +57,8 @@ except ImportError:
try:
from _collections import defaultdict
except ImportError:
pass
# TODO: RUSTPYTHON - implement defaultdict in Rust
from ._defaultdict import defaultdict
heapq = None # Lazily imported

58
Lib/collections/_defaultdict.py vendored Normal file
View File

@@ -0,0 +1,58 @@
from reprlib import recursive_repr as _recursive_repr
class defaultdict(dict):
def __init__(self, *args, **kwargs):
if len(args) >= 1:
default_factory = args[0]
if default_factory is not None and not callable(default_factory):
raise TypeError("first argument must be callable or None")
args = args[1:]
else:
default_factory = None
super().__init__(*args, **kwargs)
self.default_factory = default_factory
def __missing__(self, key):
if self.default_factory is not None:
val = self.default_factory()
else:
raise KeyError(key)
self[key] = val
return val
@_recursive_repr()
def __repr_factory(factory):
return repr(factory)
def __repr__(self):
return f"{type(self).__name__}({defaultdict.__repr_factory(self.default_factory)}, {dict.__repr__(self)})"
def copy(self):
return type(self)(self.default_factory, self)
__copy__ = copy
def __reduce__(self):
if self.default_factory is not None:
args = self.default_factory,
else:
args = ()
return type(self), args, None, None, iter(self.items())
def __or__(self, other):
if not isinstance(other, dict):
return NotImplemented
new = defaultdict(self.default_factory, self)
new.update(other)
return new
def __ror__(self, other):
if not isinstance(other, dict):
return NotImplemented
new = defaultdict(self.default_factory, other)
new.update(self)
return new
defaultdict.__module__ = 'collections'

View File

@@ -262,7 +262,7 @@ class TestChainMap(unittest.TestCase):
d = c.new_child(b=20, c=30)
self.assertEqual(d.maps, [{'b': 20, 'c': 30}, {'a': 1, 'b': 2}])
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: <class 'test.test_collections.TestChainMap.test_union_operators.<locals>.Subclass'> is not <class 'collections.ChainMap'>
def test_union_operators(self):
cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
@@ -2029,7 +2029,7 @@ class TestCollectionABCs(ABCTestCase):
self.assertEqual(len(mss), len(mss2))
self.assertEqual(list(mss), list(mss2))
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: TypeError not raised
def test_illegal_patma_flags(self):
with self.assertRaises(TypeError):
class Both(Collection):

View File

@@ -726,7 +726,7 @@ class TestBasic(unittest.TestCase):
d.append(1)
gc.collect()
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False is not true : Cycle was not collected
def test_container_iterator(self):
# Bug #3680: tp_traverse was not implemented for deque iterator objects
class C(object):
@@ -817,7 +817,7 @@ class TestSubclass(unittest.TestCase):
d.clear()
self.assertEqual(len(d), 0)
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'Deque' object has no attribute 'x'
def test_copy_pickle(self):
for cls in Deque, DequeWithSlots:
for d in cls('abc'), cls('abcde', maxlen=4):
@@ -842,7 +842,7 @@ class TestSubclass(unittest.TestCase):
self.assertEqual(e.z, d.z)
self.assertNotHasAttr(e, 'y')
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'Deque' object has no attribute 'x'
def test_pickle_recursive(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
for d in Deque('abc'), Deque('abc', 3):