Skip to content

Commit 9537149

Browse files
CPython developersyouknowone
CPython developers
authored andcommitted
Update collections/test_{collections,defaultdict} from CPython 3.10.5
1 parent da54c40 commit 9537149

File tree

4 files changed

+198
-178
lines changed

4 files changed

+198
-178
lines changed

Lib/collections/__init__.py

+87-101
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
]
2828

2929
import _collections_abc
30-
import heapq as _heapq
3130
import sys as _sys
3231

3332
from itertools import chain as _chain
@@ -56,22 +55,6 @@
5655
from ._defaultdict import defaultdict
5756

5857

59-
def __getattr__(name):
60-
# For backwards compatibility, continue to make the collections ABCs
61-
# through Python 3.6 available through the collections module.
62-
# Note, no new collections ABCs were added in Python 3.7
63-
if name in _collections_abc.__all__:
64-
obj = getattr(_collections_abc, name)
65-
import warnings
66-
warnings.warn("Using or importing the ABCs from 'collections' instead "
67-
"of from 'collections.abc' is deprecated since Python 3.3, "
68-
"and in 3.10 it will stop working",
69-
DeprecationWarning, stacklevel=2)
70-
globals()[name] = obj
71-
return obj
72-
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
73-
74-
7558
################################################################################
7659
### OrderedDict
7760
################################################################################
@@ -111,25 +94,18 @@ class OrderedDict(dict):
11194
# Individual links are kept alive by the hard reference in self.__map.
11295
# Those hard references disappear when a key is deleted from an OrderedDict.
11396

114-
def __init__(*args, **kwds):
97+
def __init__(self, other=(), /, **kwds):
11598
'''Initialize an ordered dictionary. The signature is the same as
11699
regular dictionaries. Keyword argument order is preserved.
117100
'''
118-
if not args:
119-
raise TypeError("descriptor '__init__' of 'OrderedDict' object "
120-
"needs an argument")
121-
self, *args = args
122-
if len(args) > 1:
123-
raise TypeError('expected at most 1 arguments, got %d' % len(args))
124-
125101
try:
126102
self.__root
127103
except AttributeError:
128104
self.__hardroot = _Link()
129105
self.__root = root = _proxy(self.__hardroot)
130106
root.prev = root.next = root
131107
self.__map = {}
132-
self.__update(*args, **kwds)
108+
self.__update(other, **kwds)
133109

134110
def __setitem__(self, key, value,
135111
dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
@@ -455,8 +431,8 @@ def _make(cls, iterable):
455431
_make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
456432
'or iterable')
457433

458-
def _replace(_self, /, **kwds):
459-
result = _self._make(_map(kwds.pop, field_names, _self))
434+
def _replace(self, /, **kwds):
435+
result = self._make(_map(kwds.pop, field_names, self))
460436
if kwds:
461437
raise ValueError(f'Got unexpected field names: {list(kwds)!r}')
462438
return result
@@ -500,6 +476,7 @@ def __getnewargs__(self):
500476
'__repr__': __repr__,
501477
'_asdict': _asdict,
502478
'__getnewargs__': __getnewargs__,
479+
'__match_args__': field_names,
503480
}
504481
for index, name in enumerate(field_names):
505482
doc = _sys.intern(f'Alias for field number {index}')
@@ -589,7 +566,7 @@ class Counter(dict):
589566
# http://code.activestate.com/recipes/259174/
590567
# Knuth, TAOCP Vol. II section 4.6.3
591568

592-
def __init__(*args, **kwds):
569+
def __init__(self, iterable=None, /, **kwds):
593570
'''Create a new, empty Counter object. And if given, count elements
594571
from an input iterable. Or, initialize the count from another mapping
595572
of elements to their counts.
@@ -600,20 +577,18 @@ def __init__(*args, **kwds):
600577
>>> c = Counter(a=4, b=2) # a new counter from keyword args
601578
602579
'''
603-
if not args:
604-
raise TypeError("descriptor '__init__' of 'Counter' object "
605-
"needs an argument")
606-
self, *args = args
607-
if len(args) > 1:
608-
raise TypeError('expected at most 1 arguments, got %d' % len(args))
609-
super(Counter, self).__init__()
610-
self.update(*args, **kwds)
580+
super().__init__()
581+
self.update(iterable, **kwds)
611582

612583
def __missing__(self, key):
613584
'The count of elements not in the Counter is zero.'
614585
# Needed so that self[missing_item] does not raise KeyError
615586
return 0
616587

588+
def total(self):
589+
'Sum of the counts'
590+
return sum(self.values())
591+
617592
def most_common(self, n=None):
618593
'''List the n most common elements and their counts from the most
619594
common to the least. If n is None, then list all element counts.
@@ -625,7 +600,10 @@ def most_common(self, n=None):
625600
# Emulate Bag.sortedByCount from Smalltalk
626601
if n is None:
627602
return sorted(self.items(), key=_itemgetter(1), reverse=True)
628-
return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
603+
604+
# Lazy import to speedup Python startup time
605+
import heapq
606+
return heapq.nlargest(n, self.items(), key=_itemgetter(1))
629607

630608
def elements(self):
631609
'''Iterator over elements repeating each as many times as its count.
@@ -663,7 +641,7 @@ def fromkeys(cls, iterable, v=None):
663641
raise NotImplementedError(
664642
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
665643

666-
def update(*args, **kwds):
644+
def update(self, iterable=None, /, **kwds):
667645
'''Like dict.update() but add counts instead of replacing them.
668646
669647
Source can be an iterable, a dictionary, or another Counter instance.
@@ -683,14 +661,6 @@ def update(*args, **kwds):
683661
# contexts. Instead, we implement straight-addition. Both the inputs
684662
# and outputs are allowed to contain zero and negative counts.
685663

686-
if not args:
687-
raise TypeError("descriptor 'update' of 'Counter' object "
688-
"needs an argument")
689-
self, *args = args
690-
if len(args) > 1:
691-
raise TypeError('expected at most 1 arguments, got %d' % len(args))
692-
iterable = args[0] if args else None
693-
694664
if iterable is not None:
695665
if isinstance(iterable, _collections_abc.Mapping):
696666
if self:
@@ -699,13 +669,13 @@ def update(*args, **kwds):
699669
self[elem] = count + self_get(elem, 0)
700670
else:
701671
# fast path when counter is empty
702-
super(Counter, self).update(iterable)
672+
super().update(iterable)
703673
else:
704674
_count_elements(self, iterable)
705675
if kwds:
706676
self.update(kwds)
707677

708-
def subtract(*args, **kwds):
678+
def subtract(self, iterable=None, /, **kwds):
709679
'''Like dict.update() but subtracts counts instead of replacing them.
710680
Counts can be reduced below zero. Both the inputs and outputs are
711681
allowed to contain zero and negative counts.
@@ -721,14 +691,6 @@ def subtract(*args, **kwds):
721691
-1
722692
723693
'''
724-
if not args:
725-
raise TypeError("descriptor 'subtract' of 'Counter' object "
726-
"needs an argument")
727-
self, *args = args
728-
if len(args) > 1:
729-
raise TypeError('expected at most 1 arguments, got %d' % len(args))
730-
iterable = args[0] if args else None
731-
732694
if iterable is not None:
733695
self_get = self.get
734696
if isinstance(iterable, _collections_abc.Mapping):
@@ -752,6 +714,42 @@ def __delitem__(self, elem):
752714
if elem in self:
753715
super().__delitem__(elem)
754716

717+
def __eq__(self, other):
718+
'True if all counts agree. Missing counts are treated as zero.'
719+
if not isinstance(other, Counter):
720+
return NotImplemented
721+
return all(self[e] == other[e] for c in (self, other) for e in c)
722+
723+
def __ne__(self, other):
724+
'True if any counts disagree. Missing counts are treated as zero.'
725+
if not isinstance(other, Counter):
726+
return NotImplemented
727+
return not self == other
728+
729+
def __le__(self, other):
730+
'True if all counts in self are a subset of those in other.'
731+
if not isinstance(other, Counter):
732+
return NotImplemented
733+
return all(self[e] <= other[e] for c in (self, other) for e in c)
734+
735+
def __lt__(self, other):
736+
'True if all counts in self are a proper subset of those in other.'
737+
if not isinstance(other, Counter):
738+
return NotImplemented
739+
return self <= other and self != other
740+
741+
def __ge__(self, other):
742+
'True if all counts in self are a superset of those in other.'
743+
if not isinstance(other, Counter):
744+
return NotImplemented
745+
return all(self[e] >= other[e] for c in (self, other) for e in c)
746+
747+
def __gt__(self, other):
748+
'True if all counts in self are a proper superset of those in other.'
749+
if not isinstance(other, Counter):
750+
return NotImplemented
751+
return self >= other and self != other
752+
755753
def __repr__(self):
756754
if not self:
757755
return f'{self.__class__.__name__}()'
@@ -772,12 +770,30 @@ def __repr__(self):
772770
# To strip negative and zero counts, add-in an empty counter:
773771
# c += Counter()
774772
#
775-
# Rich comparison operators for multiset subset and superset tests
776-
# are deliberately omitted due to semantic conflicts with the
777-
# existing inherited dict equality method. Subset and superset
778-
# semantics ignore zero counts and require that p≤q ∧ p≥q → p=q;
779-
# however, that would not be the case for p=Counter(a=1, b=0)
780-
# and q=Counter(a=1) where the dictionaries are not equal.
773+
# Results are ordered according to when an element is first
774+
# encountered in the left operand and then by the order
775+
# encountered in the right operand.
776+
#
777+
# When the multiplicities are all zero or one, multiset operations
778+
# are guaranteed to be equivalent to the corresponding operations
779+
# for regular sets.
780+
# Given counter multisets such as:
781+
# cp = Counter(a=1, b=0, c=1)
782+
# cq = Counter(c=1, d=0, e=1)
783+
# The corresponding regular sets would be:
784+
# sp = {'a', 'c'}
785+
# sq = {'c', 'e'}
786+
# All of the following relations would hold:
787+
# set(cp + cq) == sp | sq
788+
# set(cp - cq) == sp - sq
789+
# set(cp | cq) == sp | sq
790+
# set(cp & cq) == sp & sq
791+
# (cp == cq) == (sp == sq)
792+
# (cp != cq) == (sp != sq)
793+
# (cp <= cq) == (sp <= sq)
794+
# (cp < cq) == (sp < sq)
795+
# (cp >= cq) == (sp >= sq)
796+
# (cp > cq) == (sp > sq)
781797

782798
def __add__(self, other):
783799
'''Add counts from two counters.
@@ -1006,12 +1022,15 @@ def copy(self):
10061022

10071023
__copy__ = copy
10081024

1009-
def new_child(self, m=None): # like Django's Context.push()
1025+
def new_child(self, m=None, **kwargs): # like Django's Context.push()
10101026
'''New ChainMap with a new map followed by all previous maps.
10111027
If no map is provided, an empty dict is used.
1028+
Keyword arguments update the map or new empty dict.
10121029
'''
10131030
if m is None:
1014-
m = {}
1031+
m = kwargs
1032+
elif kwargs:
1033+
m.update(kwargs)
10151034
return self.__class__(m, *self.maps)
10161035

10171036
@property
@@ -1073,34 +1092,16 @@ def __ror__(self, other):
10731092
class UserDict(_collections_abc.MutableMapping):
10741093

10751094
# Start by filling-out the abstract methods
1076-
def __init__(*args, **kwargs):
1077-
if not args:
1078-
raise TypeError("descriptor '__init__' of 'UserDict' object "
1079-
"needs an argument")
1080-
self, *args = args
1081-
if len(args) > 1:
1082-
raise TypeError('expected at most 1 arguments, got %d' % len(args))
1083-
if args:
1084-
dict = args[0]
1085-
elif 'dict' in kwargs:
1086-
dict = kwargs.pop('dict')
1087-
import warnings
1088-
warnings.warn("Passing 'dict' as keyword argument is deprecated",
1089-
DeprecationWarning, stacklevel=2)
1090-
else:
1091-
dict = None
1095+
def __init__(self, dict=None, /, **kwargs):
10921096
self.data = {}
10931097
if dict is not None:
10941098
self.update(dict)
1095-
if len(kwargs):
1099+
if kwargs:
10961100
self.update(kwargs)
10971101

10981102
def __len__(self):
10991103
return len(self.data)
11001104

1101-
def __bool__(self):
1102-
return bool(self.data)
1103-
11041105
def __getitem__(self, key):
11051106
if key in self.data:
11061107
return self.data[key]
@@ -1153,9 +1154,6 @@ def __copy__(self):
11531154
inst.__dict__["data"] = self.__dict__["data"].copy()
11541155
return inst
11551156

1156-
def __sizeof__(self):
1157-
return _sys.getsizeof(self.data)
1158-
11591157
def copy(self):
11601158
if self.__class__ is UserDict:
11611159
return UserDict(self.data.copy())
@@ -1222,9 +1220,6 @@ def __contains__(self, item):
12221220
def __len__(self):
12231221
return len(self.data)
12241222

1225-
def __bool__(self):
1226-
return bool(self.data)
1227-
12281223
def __getitem__(self, i):
12291224
if isinstance(i, slice):
12301225
return self.__class__(self.data[i])
@@ -1276,9 +1271,6 @@ def __copy__(self):
12761271
inst.__dict__["data"] = self.__dict__["data"][:]
12771272
return inst
12781273

1279-
def __sizeof__(self):
1280-
return _sys.getsizeof(self.data)
1281-
12821274
def append(self, item):
12831275
self.data.append(item)
12841276

@@ -1381,9 +1373,6 @@ def __contains__(self, char):
13811373
char = char.data
13821374
return char in self.data
13831375

1384-
def __bool__(self):
1385-
return bool(self.data)
1386-
13871376
def __len__(self):
13881377
return len(self.data)
13891378

@@ -1413,9 +1402,6 @@ def __mod__(self, args):
14131402
def __rmod__(self, template):
14141403
return self.__class__(str(template) % self)
14151404

1416-
def __sizeof__(self):
1417-
return _sys.getsizeof(self.data)
1418-
14191405
# the following methods are defined in alphabetical order:
14201406
def capitalize(self):
14211407
return self.__class__(self.data.capitalize())
@@ -1571,4 +1557,4 @@ def upper(self):
15711557
return self.__class__(self.data.upper())
15721558

15731559
def zfill(self, width):
1574-
return self.__class__(self.data.zfill(width))
1560+
return self.__class__(self.data.zfill(width))

Lib/collections/abc.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from _collections_abc import *
22
from _collections_abc import __all__
3+
from _collections_abc import _CallableGenericAlias

0 commit comments

Comments
 (0)