cpython: 3dfe4f0c626b (original) (raw)
--- a/Lib/_abcoll.py +++ b/Lib/_abcoll.py @@ -548,23 +548,25 @@ 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)
if not args:[](#l1.12)
raise TypeError("descriptor 'update' of 'MutableMapping' object "[](#l1.13)
"needs an argument")[](#l1.14) self = args[0][](#l1.15)
other = args[1] if len(args) >= 2 else ()[](#l1.16)
if isinstance(other, Mapping):[](#l1.18)
for key in other:[](#l1.19)
self[key] = other[key][](#l1.20)
elif hasattr(other, "keys"):[](#l1.21)
for key in other.keys():[](#l1.22)
self[key] = other[key][](#l1.23)
else:[](#l1.24)
for key, value in other:[](#l1.25)
self[key] = value[](#l1.26)
args = args[1:][](#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.py +++ b/Lib/collections.py @@ -35,12 +35,17 @@ class OrderedDict(dict): # The sentinel element never gets deleted (this simplifies the algorithm). # Each link is stored as a list of length three: [PREV, NEXT, KEY].
- 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[0][](#l2.17)
args = args[1:][](#l2.18) if len(args) > 1:[](#l2.19) raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.20) try:[](#l2.21)
@@ -438,7 +443,7 @@ class Counter(dict): # http://code.activestate.com/recipes/259174/[](#l2.23) # 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.
@@ -449,8 +454,15 @@ class Counter(dict): >>> c = Counter(a=4, b=2) # a new counter from keyword args '''
if not args:[](#l2.35)
raise TypeError("descriptor '__init__' of 'Counter' object "[](#l2.36)
"needs an argument")[](#l2.37)
self = args[0][](#l2.38)
args = args[1:][](#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(iterable, **kwds)[](#l2.43)
self.update(*args, **kwds)[](#l2.44)
def missing(self, key): 'The count of elements not in the Counter is zero.' @@ -501,7 +513,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. @@ -521,6 +533,14 @@ 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.61)
raise TypeError("descriptor 'update' of 'Counter' object "[](#l2.62)
"needs an argument")[](#l2.63)
self = args[0][](#l2.64)
args = args[1:][](#l2.65)
if len(args) > 1:[](#l2.66)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.67)
iterable = args[0] if args else None[](#l2.68) if iterable is not None:[](#l2.69) if isinstance(iterable, Mapping):[](#l2.70) if self:[](#l2.71)
@@ -536,7 +556,7 @@ class Counter(dict): if kwds: self.update(kwds)
- 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.
@@ -552,6 +572,14 @@ class Counter(dict): -1 '''
if not args:[](#l2.85)
raise TypeError("descriptor 'subtract' of 'Counter' object "[](#l2.86)
"needs an argument")[](#l2.87)
self = args[0][](#l2.88)
args = args[1:][](#l2.89)
if len(args) > 1:[](#l2.90)
raise TypeError('expected at most 1 arguments, got %d' % len(args))[](#l2.91)
iterable = args[0] if args else None[](#l2.92) if iterable is not None:[](#l2.93) self_get = self.get[](#l2.94) if isinstance(iterable, Mapping):[](#l2.95)
--- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -905,6 +905,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 @@ -1006,6 +1028,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)
+ class TestOrderedDict(unittest.TestCase): def test_init(self): @@ -1019,8 +1051,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)]) @@ -1065,6 +1100,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))
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins Library ------- +- Issue #22609: Constructors and update methods of mapping classes in the