cpython: 88ab046fdd8a (original) (raw)
--- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -592,23 +592,24 @@ class MutableMapping(Mapping): If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v '''
if len(args) > 2:[](#l1.7)
raise TypeError("update() takes at most 2 positional "[](#l1.8)
"arguments ({} given)".format(len(args)))[](#l1.9)
elif not args:[](#l1.10)
raise TypeError("update() takes at least 1 argument (0 given)")[](#l1.11)
self = args[0][](#l1.12)
other = args[1] if len(args) >= 2 else ()[](#l1.13)
if isinstance(other, Mapping):[](#l1.15)
for key in other:[](#l1.16)
self[key] = other[key][](#l1.17)
elif hasattr(other, "keys"):[](#l1.18)
for key in other.keys():[](#l1.19)
self[key] = other[key][](#l1.20)
else:[](#l1.21)
for key, value in other:[](#l1.22)
self[key] = value[](#l1.23)
if not args:[](#l1.24)
raise TypeError("descriptor 'update' of 'MutableMapping' object "[](#l1.25)
"needs an argument")[](#l1.26)
self, *args = args[](#l1.27)
if len(args) > 1:[](#l1.28)
raise TypeError('update expected at most 1 arguments, got %d' %[](#l1.29)
len(args))[](#l1.30)
if args:[](#l1.31)
other = args[0][](#l1.32)
if isinstance(other, Mapping):[](#l1.33)
for key in other:[](#l1.34)
self[key] = other[key][](#l1.35)
elif hasattr(other, "keys"):[](#l1.36)
for key in other.keys():[](#l1.37)
self[key] = other[key][](#l1.38)
else:[](#l1.39)
for key, value in other:[](#l1.40)
self[key] = value[](#l1.41) for key, value in kwds.items():[](#l1.42) self[key] = value[](#l1.43)
--- a/Lib/collections/init.py +++ b/Lib/collections/init.py @@ -55,12 +55,16 @@ class OrderedDict(dict): # Individual links are kept alive by the hard reference in self.__map. # Those hard references disappear when a key is deleted from an OrderedDict.
- def init(*args, **kwds): '''Initialize an ordered dictionary. The signature is the same as regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary.
if not args:[](#l2.14)
raise TypeError("descriptor '__init__' of 'OrderedDict' object "[](#l2.15)
"needs an argument")[](#l2.16)
self, *args = args[](#l2.17) if len(args) > 1:[](#l2.18) raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.19) try:[](#l2.20)
@@ -479,7 +483,7 @@ class Counter(dict): # http://code.activestate.com/recipes/259174/[](#l2.22) # Knuth, TAOCP Vol. II section 4.6.3
- def init(*args, **kwds): '''Create a new, empty Counter object. And if given, count elements from an input iterable. Or, initialize the count from another mapping of elements to their counts.
@@ -490,8 +494,14 @@ class Counter(dict): >>> c = Counter(a=4, b=2) # a new counter from keyword args '''
super().__init__()[](#l2.34)
self.update(iterable, **kwds)[](#l2.35)
if not args:[](#l2.36)
raise TypeError("descriptor '__init__' of 'Counter' object "[](#l2.37)
"needs an argument")[](#l2.38)
self, *args = args[](#l2.39)
if len(args) > 1:[](#l2.40)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.41)
super(Counter, self).__init__()[](#l2.42)
self.update(*args, **kwds)[](#l2.43)
def missing(self, key): 'The count of elements not in the Counter is zero.' @@ -542,7 +552,7 @@ class Counter(dict): raise NotImplementedError( 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
Source can be an iterable, a dictionary, or another Counter instance. @@ -562,6 +572,13 @@ class Counter(dict): # contexts. Instead, we implement straight-addition. Both the inputs # and outputs are allowed to contain zero and negative counts.
if not args:[](#l2.60)
raise TypeError("descriptor 'update' of 'Counter' object "[](#l2.61)
"needs an argument")[](#l2.62)
self, *args = args[](#l2.63)
if len(args) > 1:[](#l2.64)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.65)
iterable = args[0] if args else None[](#l2.66) if iterable is not None:[](#l2.67) if isinstance(iterable, Mapping):[](#l2.68) if self:[](#l2.69)
@@ -569,13 +586,13 @@ class Counter(dict): for elem, count in iterable.items(): self[elem] = count + self_get(elem, 0) else:
super().update(iterable) # fast path when counter is empty[](#l2.74)
super(Counter, self).update(iterable) # fast path when counter is empty[](#l2.75) else:[](#l2.76) _count_elements(self, iterable)[](#l2.77) if kwds:[](#l2.78) self.update(kwds)[](#l2.79)
- def subtract(*args, **kwds): '''Like dict.update() but subtracts counts instead of replacing them. Counts can be reduced below zero. Both the inputs and outputs are allowed to contain zero and negative counts.
@@ -591,6 +608,13 @@ class Counter(dict): -1 '''
if not args:[](#l2.90)
raise TypeError("descriptor 'subtract' of 'Counter' object "[](#l2.91)
"needs an argument")[](#l2.92)
self, *args = args[](#l2.93)
if len(args) > 1:[](#l2.94)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.95)
iterable = args[0] if args else None[](#l2.96) if iterable is not None:[](#l2.97) self_get = self.get[](#l2.98) if isinstance(iterable, Mapping):[](#l2.99)
@@ -898,7 +922,14 @@ class ChainMap(MutableMapping): class UserDict(MutableMapping): # Start by filling-out the abstract methods
- def init(*args, **kwargs):
if not args:[](#l2.106)
raise TypeError("descriptor '__init__' of 'UserDict' object "[](#l2.107)
"needs an argument")[](#l2.108)
self, *args = args[](#l2.109)
if len(args) > 1:[](#l2.110)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.111)
dict = args[0] if args else None[](#l2.112) self.data = {}[](#l2.113) if dict is not None:[](#l2.114) self.update(dict)[](#l2.115)
--- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1137,6 +1137,28 @@ class TestCounter(unittest.TestCase): self.assertEqual(c.setdefault('e', 5), 5) self.assertEqual(c['e'], 5)
- def test_init(self):
self.assertEqual(list(Counter(self=42).items()), [('self', 42)])[](#l3.8)
self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])[](#l3.9)
self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])[](#l3.10)
self.assertRaises(TypeError, Counter, 42)[](#l3.11)
self.assertRaises(TypeError, Counter, (), ())[](#l3.12)
self.assertRaises(TypeError, Counter.__init__)[](#l3.13)
- def test_update(self):
c = Counter()[](#l3.16)
c.update(self=42)[](#l3.17)
self.assertEqual(list(c.items()), [('self', 42)])[](#l3.18)
c = Counter()[](#l3.19)
c.update(iterable=42)[](#l3.20)
self.assertEqual(list(c.items()), [('iterable', 42)])[](#l3.21)
c = Counter()[](#l3.22)
c.update(iterable=None)[](#l3.23)
self.assertEqual(list(c.items()), [('iterable', None)])[](#l3.24)
self.assertRaises(TypeError, Counter().update, 42)[](#l3.25)
self.assertRaises(TypeError, Counter().update, {}, {})[](#l3.26)
self.assertRaises(TypeError, Counter.update)[](#l3.27)
+ def test_copying(self): # Check that counters are copyable, deepcopyable, picklable, and #have a repr/eval round-trip @@ -1258,6 +1280,16 @@ class TestCounter(unittest.TestCase): c.subtract('aaaabbcce') self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
c = Counter()[](#l3.36)
c.subtract(self=42)[](#l3.37)
self.assertEqual(list(c.items()), [('self', -42)])[](#l3.38)
c = Counter()[](#l3.39)
c.subtract(iterable=42)[](#l3.40)
self.assertEqual(list(c.items()), [('iterable', -42)])[](#l3.41)
self.assertRaises(TypeError, Counter().subtract, 42)[](#l3.42)
self.assertRaises(TypeError, Counter().subtract, {}, {})[](#l3.43)
self.assertRaises(TypeError, Counter.subtract)[](#l3.44)
+ def test_unary(self): c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40)) @@ -1308,8 +1340,11 @@ class TestOrderedDict(unittest.TestCase) c=3, e=5).items()), pairs) # mixed input # make sure no positional args conflict with possible kwdargs
self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,[](#l3.53)
['self'])[](#l3.54)
self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])[](#l3.55)
self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])[](#l3.56)
self.assertRaises(TypeError, OrderedDict, 42)[](#l3.57)
self.assertRaises(TypeError, OrderedDict, (), ())[](#l3.58)
self.assertRaises(TypeError, OrderedDict.__init__)[](#l3.59)
# Make sure that direct calls to init do not clear previous contents d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) @@ -1354,6 +1389,10 @@ class TestOrderedDict(unittest.TestCase) self.assertEqual(list(d.items()), [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
self.assertRaises(TypeError, OrderedDict().update, 42)[](#l3.67)
self.assertRaises(TypeError, OrderedDict().update, (), ())[](#l3.68)
self.assertRaises(TypeError, OrderedDict.update)[](#l3.69)
+ def test_abc(self): self.assertIsInstance(OrderedDict(), MutableMapping) self.assertTrue(issubclass(OrderedDict, MutableMapping)) @@ -1600,6 +1639,24 @@ class SubclassMappingTests(mapping_tests d = self._empty_mapping() self.assertRaises(KeyError, d.popitem) +class TestUserDict(unittest.TestCase): +
- def test_init(self):
self.assertEqual(list(UserDict(self=42).items()), [('self', 42)])[](#l3.81)
self.assertEqual(list(UserDict(dict=42).items()), [('dict', 42)])[](#l3.82)
self.assertEqual(list(UserDict(dict=None).items()), [('dict', None)])[](#l3.83)
self.assertRaises(TypeError, UserDict, 42)[](#l3.84)
self.assertRaises(TypeError, UserDict, (), ())[](#l3.85)
self.assertRaises(TypeError, UserDict.__init__)[](#l3.86)
- def test_update(self):
d = UserDict()[](#l3.89)
d.update(self=42)[](#l3.90)
self.assertEqual(list(d.items()), [('self', 42)])[](#l3.91)
self.assertRaises(TypeError, UserDict().update, 42)[](#l3.92)
self.assertRaises(TypeError, UserDict().update, {}, {})[](#l3.93)
self.assertRaises(TypeError, UserDict.update)[](#l3.94)
+ ################################################################################
Run tests
@@ -1611,7 +1668,8 @@ def test_main(verbose=None): NamedTupleDocs = doctest.DocTestSuite(module=collections) test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, TestCollectionABCs, TestCounter, TestChainMap,
TestOrderedDict, GeneralMappingTests, SubclassMappingTests][](#l3.103)
TestOrderedDict, GeneralMappingTests, SubclassMappingTests,[](#l3.104)
support.run_unittest(*test_classes) support.run_doctest(collections, verbose)TestUserDict,][](#l3.105)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -191,6 +191,9 @@ Core and Builtins Library ------- +- Issue #22609: Constructors and update methods of mapping classes in the