mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Update collections/test_{collections,defaultdict} from CPython 3.10.5
This commit is contained in:
1 parent
da54c40566
commit
9537149572
4 files changed
+198
-178
No files matched your search
Vendored
+87
-101
@@ -27,7 +27,6 @@ __all__ = [
|
||||
]
|
||||
|
||||
import _collections_abc
|
||||
import heapq as _heapq
|
||||
import sys as _sys
|
||||
|
||||
from itertools import chain as _chain
|
||||
@@ -56,22 +55,6 @@ except ImportError:
|
||||
from ._defaultdict import defaultdict
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
# For backwards compatibility, continue to make the collections ABCs
|
||||
# through Python 3.6 available through the collections module.
|
||||
# Note, no new collections ABCs were added in Python 3.7
|
||||
if name in _collections_abc.__all__:
|
||||
obj = getattr(_collections_abc, name)
|
||||
import warnings
|
||||
warnings.warn("Using or importing the ABCs from 'collections' instead "
|
||||
"of from 'collections.abc' is deprecated since Python 3.3, "
|
||||
"and in 3.10 it will stop working",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
globals()[name] = obj
|
||||
return obj
|
||||
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
|
||||
|
||||
|
||||
################################################################################
|
||||
### OrderedDict
|
||||
################################################################################
|
||||
@@ -111,17 +94,10 @@ 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):
|
||||
def __init__(self, other=(), /, **kwds):
|
||||
'''Initialize an ordered dictionary. The signature is the same as
|
||||
regular dictionaries. Keyword argument order is preserved.
|
||||
'''
|
||||
if not args:
|
||||
raise TypeError("descriptor '__init__' of 'OrderedDict' object "
|
||||
"needs an argument")
|
||||
self, *args = args
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
|
||||
try:
|
||||
self.__root
|
||||
except AttributeError:
|
||||
@@ -129,7 +105,7 @@ class OrderedDict(dict):
|
||||
self.__root = root = _proxy(self.__hardroot)
|
||||
root.prev = root.next = root
|
||||
self.__map = {}
|
||||
self.__update(*args, **kwds)
|
||||
self.__update(other, **kwds)
|
||||
|
||||
def __setitem__(self, key, value,
|
||||
dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
|
||||
@@ -455,8 +431,8 @@ def namedtuple(typename, field_names, *, rename=False, defaults=None, module=Non
|
||||
_make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
|
||||
'or iterable')
|
||||
|
||||
def _replace(_self, /, **kwds):
|
||||
result = _self._make(_map(kwds.pop, field_names, _self))
|
||||
def _replace(self, /, **kwds):
|
||||
result = self._make(_map(kwds.pop, field_names, self))
|
||||
if kwds:
|
||||
raise ValueError(f'Got unexpected field names: {list(kwds)!r}')
|
||||
return result
|
||||
@@ -500,6 +476,7 @@ def namedtuple(typename, field_names, *, rename=False, defaults=None, module=Non
|
||||
'__repr__': __repr__,
|
||||
'_asdict': _asdict,
|
||||
'__getnewargs__': __getnewargs__,
|
||||
'__match_args__': field_names,
|
||||
}
|
||||
for index, name in enumerate(field_names):
|
||||
doc = _sys.intern(f'Alias for field number {index}')
|
||||
@@ -589,7 +566,7 @@ class Counter(dict):
|
||||
# http://code.activestate.com/recipes/259174/
|
||||
# Knuth, TAOCP Vol. II section 4.6.3
|
||||
|
||||
def __init__(*args, **kwds):
|
||||
def __init__(self, iterable=None, /, **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.
|
||||
@@ -600,20 +577,18 @@ class Counter(dict):
|
||||
>>> c = Counter(a=4, b=2) # a new counter from keyword args
|
||||
|
||||
'''
|
||||
if not args:
|
||||
raise TypeError("descriptor '__init__' of 'Counter' object "
|
||||
"needs an argument")
|
||||
self, *args = args
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
super(Counter, self).__init__()
|
||||
self.update(*args, **kwds)
|
||||
super().__init__()
|
||||
self.update(iterable, **kwds)
|
||||
|
||||
def __missing__(self, key):
|
||||
'The count of elements not in the Counter is zero.'
|
||||
# Needed so that self[missing_item] does not raise KeyError
|
||||
return 0
|
||||
|
||||
def total(self):
|
||||
'Sum of the counts'
|
||||
return sum(self.values())
|
||||
|
||||
def most_common(self, n=None):
|
||||
'''List the n most common elements and their counts from the most
|
||||
common to the least. If n is None, then list all element counts.
|
||||
@@ -625,7 +600,10 @@ class Counter(dict):
|
||||
# Emulate Bag.sortedByCount from Smalltalk
|
||||
if n is None:
|
||||
return sorted(self.items(), key=_itemgetter(1), reverse=True)
|
||||
return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
|
||||
|
||||
# Lazy import to speedup Python startup time
|
||||
import heapq
|
||||
return heapq.nlargest(n, self.items(), key=_itemgetter(1))
|
||||
|
||||
def elements(self):
|
||||
'''Iterator over elements repeating each as many times as its count.
|
||||
@@ -663,7 +641,7 @@ class Counter(dict):
|
||||
raise NotImplementedError(
|
||||
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
|
||||
|
||||
def update(*args, **kwds):
|
||||
def update(self, iterable=None, /, **kwds):
|
||||
'''Like dict.update() but add counts instead of replacing them.
|
||||
|
||||
Source can be an iterable, a dictionary, or another Counter instance.
|
||||
@@ -683,14 +661,6 @@ 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:
|
||||
raise TypeError("descriptor 'update' of 'Counter' object "
|
||||
"needs an argument")
|
||||
self, *args = args
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
iterable = args[0] if args else None
|
||||
|
||||
if iterable is not None:
|
||||
if isinstance(iterable, _collections_abc.Mapping):
|
||||
if self:
|
||||
@@ -699,13 +669,13 @@ class Counter(dict):
|
||||
self[elem] = count + self_get(elem, 0)
|
||||
else:
|
||||
# fast path when counter is empty
|
||||
super(Counter, self).update(iterable)
|
||||
super().update(iterable)
|
||||
else:
|
||||
_count_elements(self, iterable)
|
||||
if kwds:
|
||||
self.update(kwds)
|
||||
|
||||
def subtract(*args, **kwds):
|
||||
def subtract(self, iterable=None, /, **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.
|
||||
@@ -721,14 +691,6 @@ class Counter(dict):
|
||||
-1
|
||||
|
||||
'''
|
||||
if not args:
|
||||
raise TypeError("descriptor 'subtract' of 'Counter' object "
|
||||
"needs an argument")
|
||||
self, *args = args
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
iterable = args[0] if args else None
|
||||
|
||||
if iterable is not None:
|
||||
self_get = self.get
|
||||
if isinstance(iterable, _collections_abc.Mapping):
|
||||
@@ -752,6 +714,42 @@ class Counter(dict):
|
||||
if elem in self:
|
||||
super().__delitem__(elem)
|
||||
|
||||
def __eq__(self, other):
|
||||
'True if all counts agree. Missing counts are treated as zero.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return all(self[e] == other[e] for c in (self, other) for e in c)
|
||||
|
||||
def __ne__(self, other):
|
||||
'True if any counts disagree. Missing counts are treated as zero.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return not self == other
|
||||
|
||||
def __le__(self, other):
|
||||
'True if all counts in self are a subset of those in other.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return all(self[e] <= other[e] for c in (self, other) for e in c)
|
||||
|
||||
def __lt__(self, other):
|
||||
'True if all counts in self are a proper subset of those in other.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return self <= other and self != other
|
||||
|
||||
def __ge__(self, other):
|
||||
'True if all counts in self are a superset of those in other.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return all(self[e] >= other[e] for c in (self, other) for e in c)
|
||||
|
||||
def __gt__(self, other):
|
||||
'True if all counts in self are a proper superset of those in other.'
|
||||
if not isinstance(other, Counter):
|
||||
return NotImplemented
|
||||
return self >= other and self != other
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return f'{self.__class__.__name__}()'
|
||||
@@ -772,12 +770,30 @@ class Counter(dict):
|
||||
# To strip negative and zero counts, add-in an empty counter:
|
||||
# c += Counter()
|
||||
#
|
||||
# Rich comparison operators for multiset subset and superset tests
|
||||
# are deliberately omitted due to semantic conflicts with the
|
||||
# existing inherited dict equality method. Subset and superset
|
||||
# semantics ignore zero counts and require that p≤q ∧ p≥q → p=q;
|
||||
# however, that would not be the case for p=Counter(a=1, b=0)
|
||||
# and q=Counter(a=1) where the dictionaries are not equal.
|
||||
# Results are ordered according to when an element is first
|
||||
# encountered in the left operand and then by the order
|
||||
# encountered in the right operand.
|
||||
#
|
||||
# When the multiplicities are all zero or one, multiset operations
|
||||
# are guaranteed to be equivalent to the corresponding operations
|
||||
# for regular sets.
|
||||
# Given counter multisets such as:
|
||||
# cp = Counter(a=1, b=0, c=1)
|
||||
# cq = Counter(c=1, d=0, e=1)
|
||||
# The corresponding regular sets would be:
|
||||
# sp = {'a', 'c'}
|
||||
# sq = {'c', 'e'}
|
||||
# All of the following relations would hold:
|
||||
# set(cp + cq) == sp | sq
|
||||
# set(cp - cq) == sp - sq
|
||||
# set(cp | cq) == sp | sq
|
||||
# set(cp & cq) == sp & sq
|
||||
# (cp == cq) == (sp == sq)
|
||||
# (cp != cq) == (sp != sq)
|
||||
# (cp <= cq) == (sp <= sq)
|
||||
# (cp < cq) == (sp < sq)
|
||||
# (cp >= cq) == (sp >= sq)
|
||||
# (cp > cq) == (sp > sq)
|
||||
|
||||
def __add__(self, other):
|
||||
'''Add counts from two counters.
|
||||
@@ -1006,12 +1022,15 @@ class ChainMap(_collections_abc.MutableMapping):
|
||||
|
||||
__copy__ = copy
|
||||
|
||||
def new_child(self, m=None): # like Django's Context.push()
|
||||
def new_child(self, m=None, **kwargs): # like Django's Context.push()
|
||||
'''New ChainMap with a new map followed by all previous maps.
|
||||
If no map is provided, an empty dict is used.
|
||||
Keyword arguments update the map or new empty dict.
|
||||
'''
|
||||
if m is None:
|
||||
m = {}
|
||||
m = kwargs
|
||||
elif kwargs:
|
||||
m.update(kwargs)
|
||||
return self.__class__(m, *self.maps)
|
||||
|
||||
@property
|
||||
@@ -1073,34 +1092,16 @@ class ChainMap(_collections_abc.MutableMapping):
|
||||
class UserDict(_collections_abc.MutableMapping):
|
||||
|
||||
# Start by filling-out the abstract methods
|
||||
def __init__(*args, **kwargs):
|
||||
if not args:
|
||||
raise TypeError("descriptor '__init__' of 'UserDict' object "
|
||||
"needs an argument")
|
||||
self, *args = args
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
if args:
|
||||
dict = args[0]
|
||||
elif 'dict' in kwargs:
|
||||
dict = kwargs.pop('dict')
|
||||
import warnings
|
||||
warnings.warn("Passing 'dict' as keyword argument is deprecated",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
dict = None
|
||||
def __init__(self, dict=None, /, **kwargs):
|
||||
self.data = {}
|
||||
if dict is not None:
|
||||
self.update(dict)
|
||||
if len(kwargs):
|
||||
if kwargs:
|
||||
self.update(kwargs)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.data)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key in self.data:
|
||||
return self.data[key]
|
||||
@@ -1153,9 +1154,6 @@ class UserDict(_collections_abc.MutableMapping):
|
||||
inst.__dict__["data"] = self.__dict__["data"].copy()
|
||||
return inst
|
||||
|
||||
def __sizeof__(self):
|
||||
return _sys.getsizeof(self.data)
|
||||
|
||||
def copy(self):
|
||||
if self.__class__ is UserDict:
|
||||
return UserDict(self.data.copy())
|
||||
@@ -1222,9 +1220,6 @@ class UserList(_collections_abc.MutableSequence):
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.data)
|
||||
|
||||
def __getitem__(self, i):
|
||||
if isinstance(i, slice):
|
||||
return self.__class__(self.data[i])
|
||||
@@ -1276,9 +1271,6 @@ class UserList(_collections_abc.MutableSequence):
|
||||
inst.__dict__["data"] = self.__dict__["data"][:]
|
||||
return inst
|
||||
|
||||
def __sizeof__(self):
|
||||
return _sys.getsizeof(self.data)
|
||||
|
||||
def append(self, item):
|
||||
self.data.append(item)
|
||||
|
||||
@@ -1381,9 +1373,6 @@ class UserString(_collections_abc.Sequence):
|
||||
char = char.data
|
||||
return char in self.data
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.data)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
@@ -1413,9 +1402,6 @@ class UserString(_collections_abc.Sequence):
|
||||
def __rmod__(self, template):
|
||||
return self.__class__(str(template) % self)
|
||||
|
||||
def __sizeof__(self):
|
||||
return _sys.getsizeof(self.data)
|
||||
|
||||
# the following methods are defined in alphabetical order:
|
||||
def capitalize(self):
|
||||
return self.__class__(self.data.capitalize())
|
||||
@@ -1571,4 +1557,4 @@ class UserString(_collections_abc.Sequence):
|
||||
return self.__class__(self.data.upper())
|
||||
|
||||
def zfill(self, width):
|
||||
return self.__class__(self.data.zfill(width))
|
||||
return self.__class__(self.data.zfill(width))
|
||||
Vendored
+1
@@ -1,2 +1,3 @@
|
||||
from _collections_abc import *
|
||||
from _collections_abc import __all__
|
||||
from _collections_abc import _CallableGenericAlias
|
||||
Vendored
+72
-44
@@ -7,6 +7,7 @@ import inspect
|
||||
import operator
|
||||
import pickle
|
||||
from random import choice, randrange
|
||||
from itertools import product, chain, combinations
|
||||
import string
|
||||
import sys
|
||||
from test import support
|
||||
@@ -248,6 +249,10 @@ class TestChainMap(unittest.TestCase):
|
||||
for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
|
||||
self.assertEqual(d.get(k, 100), v)
|
||||
|
||||
c = ChainMap({'a': 1, 'b': 2})
|
||||
d = c.new_child(b=20, c=30)
|
||||
self.assertEqual(d.maps, [{'b': 20, 'c': 30}, {'a': 1, 'b': 2}])
|
||||
|
||||
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))
|
||||
@@ -663,8 +668,7 @@ class TestNamedTuple(unittest.TestCase):
|
||||
a.w = 5
|
||||
self.assertEqual(a.__dict__, {'w': 5})
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@support.cpython_only
|
||||
def test_field_descriptor(self):
|
||||
Point = namedtuple('Point', 'x y')
|
||||
p = Point(11, 22)
|
||||
@@ -683,9 +687,14 @@ class TestNamedTuple(unittest.TestCase):
|
||||
self.assertEqual(np.y, 2)
|
||||
|
||||
def test_new_builtins_issue_43102(self):
|
||||
self.assertEqual(
|
||||
namedtuple('C', ()).__new__.__globals__['__builtins__'],
|
||||
{})
|
||||
obj = namedtuple('C', ())
|
||||
new_func = obj.__new__
|
||||
self.assertEqual(new_func.__globals__['__builtins__'], {})
|
||||
self.assertEqual(new_func.__builtins__, {})
|
||||
|
||||
def test_match_args(self):
|
||||
Point = namedtuple('Point', 'x y')
|
||||
self.assertEqual(Point.__match_args__, ('x', 'y'))
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -1516,7 +1525,7 @@ class TestCollectionABCs(ABCTestCase):
|
||||
items = [5,43,2,1]
|
||||
s = MySet(items)
|
||||
r = s.pop()
|
||||
self.assertEquals(len(s), len(items) - 1)
|
||||
self.assertEqual(len(s), len(items) - 1)
|
||||
self.assertNotIn(r, s)
|
||||
self.assertIn(r, items)
|
||||
|
||||
@@ -1566,10 +1575,6 @@ class TestCollectionABCs(ABCTestCase):
|
||||
|
||||
def test_issue26915(self):
|
||||
# Container membership test should check identity first
|
||||
class CustomEqualObject:
|
||||
def __eq__(self, other):
|
||||
return False
|
||||
|
||||
class CustomSequence(Sequence):
|
||||
def __init__(self, seq):
|
||||
self._seq = seq
|
||||
@@ -1579,7 +1584,7 @@ class TestCollectionABCs(ABCTestCase):
|
||||
return len(self._seq)
|
||||
|
||||
nan = float('nan')
|
||||
obj = CustomEqualObject
|
||||
obj = support.NEVER_EQ
|
||||
seq = CustomSequence([nan, obj, nan])
|
||||
containers = [
|
||||
seq,
|
||||
@@ -1599,7 +1604,7 @@ class TestCollectionABCs(ABCTestCase):
|
||||
self.assertSetEqual(set(s1), set(s2))
|
||||
|
||||
def test_Set_from_iterable(self):
|
||||
"""Verify _from_iterable overriden to an instance method works."""
|
||||
"""Verify _from_iterable overridden to an instance method works."""
|
||||
class SetUsingInstanceFromIterable(MutableSet):
|
||||
def __init__(self, values, created_by):
|
||||
if not created_by:
|
||||
@@ -1994,6 +1999,12 @@ class TestCollectionABCs(ABCTestCase):
|
||||
self.assertEqual(len(mss), len(mss2))
|
||||
self.assertEqual(list(mss), list(mss2))
|
||||
|
||||
def test_illegal_patma_flags(self):
|
||||
with self.assertRaises(TypeError):
|
||||
class Both(Collection):
|
||||
__abc_tpflags__ = (Sequence.__flags__ | Mapping.__flags__)
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
### Counter
|
||||
@@ -2087,6 +2098,10 @@ class TestCounter(unittest.TestCase):
|
||||
self.assertRaises(TypeError, Counter, (), ())
|
||||
self.assertRaises(TypeError, Counter.__init__)
|
||||
|
||||
def test_total(self):
|
||||
c = Counter(a=10, b=5, c=0)
|
||||
self.assertEqual(c.total(), 15)
|
||||
|
||||
def test_order_preservation(self):
|
||||
# Input order dictates items() order
|
||||
self.assertEqual(list(Counter('abracadabra').items()),
|
||||
@@ -2240,31 +2255,6 @@ class TestCounter(unittest.TestCase):
|
||||
set_result = setop(set(p.elements()), set(q.elements()))
|
||||
self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_subset_superset_not_implemented(self):
|
||||
# Verify that multiset comparison operations are not implemented.
|
||||
|
||||
# These operations were intentionally omitted because multiset
|
||||
# comparison semantics conflict with existing dict equality semantics.
|
||||
|
||||
# For multisets, we would expect that if p<=q and p>=q are both true,
|
||||
# then p==q. However, dict equality semantics require that p!=q when
|
||||
# one of sets contains an element with a zero count and the other
|
||||
# doesn't.
|
||||
|
||||
p = Counter(a=1, b=0)
|
||||
q = Counter(a=1, c=0)
|
||||
self.assertNotEqual(p, q)
|
||||
with self.assertRaises(TypeError):
|
||||
p < q
|
||||
with self.assertRaises(TypeError):
|
||||
p <= q
|
||||
with self.assertRaises(TypeError):
|
||||
p > q
|
||||
with self.assertRaises(TypeError):
|
||||
p >= q
|
||||
|
||||
def test_inplace_operations(self):
|
||||
elements = 'abcd'
|
||||
for i in range(1000):
|
||||
@@ -2339,23 +2329,61 @@ class TestCounter(unittest.TestCase):
|
||||
self.assertTrue(c.called)
|
||||
self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
|
||||
|
||||
def test_multiset_operations_equivalent_to_set_operations(self):
|
||||
# When the multiplicities are all zero or one, multiset operations
|
||||
# are guaranteed to be equivalent to the corresponding operations
|
||||
# for regular sets.
|
||||
s = list(product(('a', 'b', 'c'), range(2)))
|
||||
powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
|
||||
counters = [Counter(dict(groups)) for groups in powerset]
|
||||
for cp, cq in product(counters, repeat=2):
|
||||
sp = set(cp.elements())
|
||||
sq = set(cq.elements())
|
||||
self.assertEqual(set(cp + cq), sp | sq)
|
||||
self.assertEqual(set(cp - cq), sp - sq)
|
||||
self.assertEqual(set(cp | cq), sp | sq)
|
||||
self.assertEqual(set(cp & cq), sp & sq)
|
||||
self.assertEqual(cp == cq, sp == sq)
|
||||
self.assertEqual(cp != cq, sp != sq)
|
||||
self.assertEqual(cp <= cq, sp <= sq)
|
||||
self.assertEqual(cp >= cq, sp >= sq)
|
||||
self.assertEqual(cp < cq, sp < sq)
|
||||
self.assertEqual(cp > cq, sp > sq)
|
||||
|
||||
def test_eq(self):
|
||||
self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
|
||||
self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
|
||||
|
||||
def test_le(self):
|
||||
self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
|
||||
self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
|
||||
|
||||
def test_lt(self):
|
||||
self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
|
||||
self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
|
||||
|
||||
def test_ge(self):
|
||||
self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
|
||||
self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
|
||||
|
||||
def test_gt(self):
|
||||
self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
|
||||
self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
|
||||
|
||||
|
||||
################################################################################
|
||||
### Run tests
|
||||
################################################################################
|
||||
|
||||
def test_main(verbose=None):
|
||||
# TODO: RUSTPYTHON
|
||||
# NamedTupleDocs = doctest.DocTestSuite(module=collections)
|
||||
# test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
|
||||
test_classes = [TestNamedTuple, TestOneTrickPonyABCs,
|
||||
NamedTupleDocs = doctest.DocTestSuite(module=collections)
|
||||
test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
|
||||
TestCollectionABCs, TestCounter, TestChainMap,
|
||||
TestUserObjects,
|
||||
]
|
||||
support.run_unittest(*test_classes)
|
||||
# TODO: RUSTPYTHON
|
||||
# support.run_doctest(collections, verbose)
|
||||
support.run_doctest(collections, verbose)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main(verbose=True)
|
||||
test_main(verbose=True)
|
||||
Vendored
+38
-33
@@ -72,27 +72,6 @@ class TestDefaultDict(unittest.TestCase):
|
||||
d3[13]
|
||||
self.assertEqual(repr(d3), "defaultdict(%s, {13: 43})" % repr(foo))
|
||||
|
||||
def test_print(self):
|
||||
d1 = defaultdict()
|
||||
def foo(): return 42
|
||||
d2 = defaultdict(foo, {1: 2})
|
||||
# NOTE: We can't use tempfile.[Named]TemporaryFile since this
|
||||
# code must exercise the tp_print C code, which only gets
|
||||
# invoked for *real* files.
|
||||
tfn = tempfile.mktemp()
|
||||
try:
|
||||
f = open(tfn, "w+")
|
||||
try:
|
||||
print(d1, file=f)
|
||||
print(d2, file=f)
|
||||
f.seek(0)
|
||||
self.assertEqual(f.readline(), repr(d1) + "\n")
|
||||
self.assertEqual(f.readline(), repr(d2) + "\n")
|
||||
finally:
|
||||
f.close()
|
||||
finally:
|
||||
os.remove(tfn)
|
||||
|
||||
def test_copy(self):
|
||||
d1 = defaultdict()
|
||||
d2 = d1.copy()
|
||||
@@ -160,18 +139,6 @@ class TestDefaultDict(unittest.TestCase):
|
||||
r"sub\(<bound method .*sub\._factory "
|
||||
r"of sub\(\.\.\., \{\}\)>, \{\}\)")
|
||||
|
||||
# NOTE: printing a subclass of a builtin type does not call its
|
||||
# tp_print slot. So this part is essentially the same test as above.
|
||||
tfn = tempfile.mktemp()
|
||||
try:
|
||||
f = open(tfn, "w+")
|
||||
try:
|
||||
print(d, file=f)
|
||||
finally:
|
||||
f.close()
|
||||
finally:
|
||||
os.remove(tfn)
|
||||
|
||||
def test_callable_arg(self):
|
||||
self.assertRaises(TypeError, defaultdict, {})
|
||||
|
||||
@@ -183,5 +150,43 @@ class TestDefaultDict(unittest.TestCase):
|
||||
o = pickle.loads(s)
|
||||
self.assertEqual(d, o)
|
||||
|
||||
def test_union(self):
|
||||
i = defaultdict(int, {1: 1, 2: 2})
|
||||
s = defaultdict(str, {0: "zero", 1: "one"})
|
||||
|
||||
i_s = i | s
|
||||
self.assertIs(i_s.default_factory, int)
|
||||
self.assertDictEqual(i_s, {1: "one", 2: 2, 0: "zero"})
|
||||
self.assertEqual(list(i_s), [1, 2, 0])
|
||||
|
||||
s_i = s | i
|
||||
self.assertIs(s_i.default_factory, str)
|
||||
self.assertDictEqual(s_i, {0: "zero", 1: 1, 2: 2})
|
||||
self.assertEqual(list(s_i), [0, 1, 2])
|
||||
|
||||
i_ds = i | dict(s)
|
||||
self.assertIs(i_ds.default_factory, int)
|
||||
self.assertDictEqual(i_ds, {1: "one", 2: 2, 0: "zero"})
|
||||
self.assertEqual(list(i_ds), [1, 2, 0])
|
||||
|
||||
ds_i = dict(s) | i
|
||||
self.assertIs(ds_i.default_factory, int)
|
||||
self.assertDictEqual(ds_i, {0: "zero", 1: 1, 2: 2})
|
||||
self.assertEqual(list(ds_i), [0, 1, 2])
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
i | list(s.items())
|
||||
with self.assertRaises(TypeError):
|
||||
list(s.items()) | i
|
||||
|
||||
# We inherit a fine |= from dict, so just a few sanity checks here:
|
||||
i |= list(s.items())
|
||||
self.assertIs(i.default_factory, int)
|
||||
self.assertDictEqual(i, {1: "one", 2: 2, 0: "zero"})
|
||||
self.assertEqual(list(i), [1, 2, 0])
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
i |= None
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user