1"""Unit tests for collections.py.""" 2 3import collections 4import copy 5import doctest 6import inspect 7import operator 8import pickle 9from random import choice, randrange 10import string 11import sys 12from test import support 13import types 14import unittest 15 16from collections import namedtuple, Counter, OrderedDict, _count_elements 17from collections import UserDict, UserString, UserList 18from collections import ChainMap 19from collections import deque 20from collections.abc import Awaitable, Coroutine 21from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator 22from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible 23from collections.abc import Sized, Container, Callable, Collection 24from collections.abc import Set, MutableSet 25from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView 26from collections.abc import Sequence, MutableSequence 27from collections.abc import ByteString 28 29 30class TestUserObjects(unittest.TestCase): 31 def _superset_test(self, a, b): 32 self.assertGreaterEqual( 33 set(dir(a)), 34 set(dir(b)), 35 '{a} should have all the methods of {b}'.format( 36 a=a.__name__, 37 b=b.__name__, 38 ), 39 ) 40 41 def _copy_test(self, obj): 42 # Test internal copy 43 obj_copy = obj.copy() 44 self.assertIsNot(obj.data, obj_copy.data) 45 self.assertEqual(obj.data, obj_copy.data) 46 47 # Test copy.copy 48 obj.test = [1234] # Make sure instance vars are also copied. 49 obj_copy = copy.copy(obj) 50 self.assertIsNot(obj.data, obj_copy.data) 51 self.assertEqual(obj.data, obj_copy.data) 52 self.assertIs(obj.test, obj_copy.test) 53 54 def test_str_protocol(self): 55 self._superset_test(UserString, str) 56 57 def test_list_protocol(self): 58 self._superset_test(UserList, list) 59 60 def test_dict_protocol(self): 61 self._superset_test(UserDict, dict) 62 63 def test_list_copy(self): 64 obj = UserList() 65 obj.append(123) 66 self._copy_test(obj) 67 68 def test_dict_copy(self): 69 obj = UserDict() 70 obj[123] = "abc" 71 self._copy_test(obj) 72 73 74################################################################################ 75### ChainMap (helper class for configparser and the string module) 76################################################################################ 77 78class TestChainMap(unittest.TestCase): 79 80 def test_basics(self): 81 c = ChainMap() 82 c['a'] = 1 83 c['b'] = 2 84 d = c.new_child() 85 d['b'] = 20 86 d['c'] = 30 87 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state 88 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem 89 self.assertEqual(len(d), 3) # check len 90 for key in 'abc': # check contains 91 self.assertIn(key, d) 92 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get 93 self.assertEqual(d.get(k, 100), v) 94 95 del d['b'] # unmask a value 96 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state 97 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem 98 self.assertEqual(len(d), 3) # check len 99 for key in 'abc': # check contains 100 self.assertIn(key, d) 101 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get 102 self.assertEqual(d.get(k, 100), v) 103 self.assertIn(repr(d), [ # check repr 104 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})", 105 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})" 106 ]) 107 108 for e in d.copy(), copy.copy(d): # check shallow copies 109 self.assertEqual(d, e) 110 self.assertEqual(d.maps, e.maps) 111 self.assertIsNot(d, e) 112 self.assertIsNot(d.maps[0], e.maps[0]) 113 for m1, m2 in zip(d.maps[1:], e.maps[1:]): 114 self.assertIs(m1, m2) 115 116 # check deep copies 117 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 118 e = pickle.loads(pickle.dumps(d, proto)) 119 self.assertEqual(d, e) 120 self.assertEqual(d.maps, e.maps) 121 self.assertIsNot(d, e) 122 for m1, m2 in zip(d.maps, e.maps): 123 self.assertIsNot(m1, m2, e) 124 for e in [copy.deepcopy(d), 125 eval(repr(d)) 126 ]: 127 self.assertEqual(d, e) 128 self.assertEqual(d.maps, e.maps) 129 self.assertIsNot(d, e) 130 for m1, m2 in zip(d.maps, e.maps): 131 self.assertIsNot(m1, m2, e) 132 133 f = d.new_child() 134 f['b'] = 5 135 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}]) 136 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents 137 self.assertEqual(f['b'], 5) # find first in chain 138 self.assertEqual(f.parents['b'], 2) # look beyond maps[0] 139 140 def test_ordering(self): 141 # Combined order matches a series of dict updates from last to first. 142 # This test relies on the ordering of the underlying dicts. 143 144 baseline = {'music': 'bach', 'art': 'rembrandt'} 145 adjustments = {'art': 'van gogh', 'opera': 'carmen'} 146 147 cm = ChainMap(adjustments, baseline) 148 149 combined = baseline.copy() 150 combined.update(adjustments) 151 152 self.assertEqual(list(combined.items()), list(cm.items())) 153 154 def test_constructor(self): 155 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict 156 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list 157 158 def test_bool(self): 159 self.assertFalse(ChainMap()) 160 self.assertFalse(ChainMap({}, {})) 161 self.assertTrue(ChainMap({1:2}, {})) 162 self.assertTrue(ChainMap({}, {1:2})) 163 164 def test_missing(self): 165 class DefaultChainMap(ChainMap): 166 def __missing__(self, key): 167 return 999 168 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30)) 169 for k, v in dict(a=1, b=2, c=30, d=999).items(): 170 self.assertEqual(d[k], v) # check __getitem__ w/missing 171 for k, v in dict(a=1, b=2, c=30, d=77).items(): 172 self.assertEqual(d.get(k, 77), v) # check get() w/ missing 173 for k, v in dict(a=True, b=True, c=True, d=False).items(): 174 self.assertEqual(k in d, v) # check __contains__ w/missing 175 self.assertEqual(d.pop('a', 1001), 1, d) 176 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing 177 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing 178 with self.assertRaises(KeyError): 179 d.popitem() 180 181 def test_order_preservation(self): 182 d = ChainMap( 183 OrderedDict(j=0, h=88888), 184 OrderedDict(), 185 OrderedDict(i=9999, d=4444, c=3333), 186 OrderedDict(f=666, b=222, g=777, c=333, h=888), 187 OrderedDict(), 188 OrderedDict(e=55, b=22), 189 OrderedDict(a=1, b=2, c=3, d=4, e=5), 190 OrderedDict(), 191 ) 192 self.assertEqual(''.join(d), 'abcdefghij') 193 self.assertEqual(list(d.items()), 194 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444), 195 ('e', 55), ('f', 666), ('g', 777), ('h', 88888), 196 ('i', 9999), ('j', 0)]) 197 198 def test_dict_coercion(self): 199 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30)) 200 self.assertEqual(dict(d), dict(a=1, b=2, c=30)) 201 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30)) 202 203 def test_new_child(self): 204 'Tests for changes for issue #16613.' 205 c = ChainMap() 206 c['a'] = 1 207 c['b'] = 2 208 m = {'b':20, 'c': 30} 209 d = c.new_child(m) 210 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state 211 self.assertIs(m, d.maps[0]) 212 213 # Use a different map than a dict 214 class lowerdict(dict): 215 def __getitem__(self, key): 216 if isinstance(key, str): 217 key = key.lower() 218 return dict.__getitem__(self, key) 219 def __contains__(self, key): 220 if isinstance(key, str): 221 key = key.lower() 222 return dict.__contains__(self, key) 223 224 c = ChainMap() 225 c['a'] = 1 226 c['b'] = 2 227 m = lowerdict(b=20, c=30) 228 d = c.new_child(m) 229 self.assertIs(m, d.maps[0]) 230 for key in 'abc': # check contains 231 self.assertIn(key, d) 232 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get 233 self.assertEqual(d.get(k, 100), v) 234 235 236################################################################################ 237### Named Tuples 238################################################################################ 239 240TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests 241 242class TestNamedTuple(unittest.TestCase): 243 244 def test_factory(self): 245 Point = namedtuple('Point', 'x y') 246 self.assertEqual(Point.__name__, 'Point') 247 self.assertEqual(Point.__slots__, ()) 248 self.assertEqual(Point.__module__, __name__) 249 self.assertEqual(Point.__getitem__, tuple.__getitem__) 250 self.assertEqual(Point._fields, ('x', 'y')) 251 252 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char 253 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword 254 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit 255 256 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char 257 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword 258 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit 259 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore 260 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field 261 262 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names 263 namedtuple('_', 'a b c') # Test leading underscores in a typename 264 265 nt = namedtuple('nt', 'the quick brown fox') # check unicode input 266 self.assertNotIn("u'", repr(nt._fields)) 267 nt = namedtuple('nt', ('the', 'quick')) # check unicode input 268 self.assertNotIn("u'", repr(nt._fields)) 269 270 self.assertRaises(TypeError, Point._make, [11]) # catch too few args 271 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args 272 273 def test_defaults(self): 274 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults 275 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20}) 276 self.assertEqual(Point(1, 2), (1, 2)) 277 self.assertEqual(Point(1), (1, 20)) 278 self.assertEqual(Point(), (10, 20)) 279 280 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default 281 self.assertEqual(Point._field_defaults, {'y': 20}) 282 self.assertEqual(Point(1, 2), (1, 2)) 283 self.assertEqual(Point(1), (1, 20)) 284 285 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults 286 self.assertEqual(Point._field_defaults, {}) 287 self.assertEqual(Point(1, 2), (1, 2)) 288 with self.assertRaises(TypeError): 289 Point(1) 290 291 with self.assertRaises(TypeError): # catch too few args 292 Point() 293 with self.assertRaises(TypeError): # catch too many args 294 Point(1, 2, 3) 295 with self.assertRaises(TypeError): # too many defaults 296 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30)) 297 with self.assertRaises(TypeError): # non-iterable defaults 298 Point = namedtuple('Point', 'x y', defaults=10) 299 with self.assertRaises(TypeError): # another non-iterable default 300 Point = namedtuple('Point', 'x y', defaults=False) 301 302 Point = namedtuple('Point', 'x y', defaults=None) # default is None 303 self.assertEqual(Point._field_defaults, {}) 304 self.assertIsNone(Point.__new__.__defaults__, None) 305 self.assertEqual(Point(10, 20), (10, 20)) 306 with self.assertRaises(TypeError): # catch too few args 307 Point(10) 308 309 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable 310 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20}) 311 self.assertEqual(Point.__new__.__defaults__, (10, 20)) 312 self.assertEqual(Point(1, 2), (1, 2)) 313 self.assertEqual(Point(1), (1, 20)) 314 self.assertEqual(Point(), (10, 20)) 315 316 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator 317 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20}) 318 self.assertEqual(Point.__new__.__defaults__, (10, 20)) 319 self.assertEqual(Point(1, 2), (1, 2)) 320 self.assertEqual(Point(1), (1, 20)) 321 self.assertEqual(Point(), (10, 20)) 322 323 def test_readonly(self): 324 Point = namedtuple('Point', 'x y') 325 p = Point(11, 22) 326 with self.assertRaises(AttributeError): 327 p.x = 33 328 with self.assertRaises(AttributeError): 329 del p.x 330 with self.assertRaises(TypeError): 331 p[0] = 33 332 with self.assertRaises(TypeError): 333 del p[0] 334 self.assertEqual(p.x, 11) 335 self.assertEqual(p[0], 11) 336 337 @unittest.skipIf(sys.flags.optimize >= 2, 338 "Docstrings are omitted with -O2 and above") 339 def test_factory_doc_attr(self): 340 Point = namedtuple('Point', 'x y') 341 self.assertEqual(Point.__doc__, 'Point(x, y)') 342 Point.__doc__ = '2D point' 343 self.assertEqual(Point.__doc__, '2D point') 344 345 @unittest.skipIf(sys.flags.optimize >= 2, 346 "Docstrings are omitted with -O2 and above") 347 def test_field_doc(self): 348 Point = namedtuple('Point', 'x y') 349 self.assertEqual(Point.x.__doc__, 'Alias for field number 0') 350 self.assertEqual(Point.y.__doc__, 'Alias for field number 1') 351 Point.x.__doc__ = 'docstring for Point.x' 352 self.assertEqual(Point.x.__doc__, 'docstring for Point.x') 353 # namedtuple can mutate doc of descriptors independently 354 Vector = namedtuple('Vector', 'x y') 355 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0') 356 Vector.x.__doc__ = 'docstring for Vector.x' 357 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x') 358 359 @support.cpython_only 360 @unittest.skipIf(sys.flags.optimize >= 2, 361 "Docstrings are omitted with -O2 and above") 362 def test_field_doc_reuse(self): 363 P = namedtuple('P', ['m', 'n']) 364 Q = namedtuple('Q', ['o', 'p']) 365 self.assertIs(P.m.__doc__, Q.o.__doc__) 366 self.assertIs(P.n.__doc__, Q.p.__doc__) 367 368 def test_name_fixer(self): 369 for spec, renamed in [ 370 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char 371 [('abc', 'class'), ('abc', '_1')], # field has keyword 372 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit 373 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore 374 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field 375 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space 376 ]: 377 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed) 378 379 def test_module_parameter(self): 380 NT = namedtuple('NT', ['x', 'y'], module=collections) 381 self.assertEqual(NT.__module__, collections) 382 383 def test_instance(self): 384 Point = namedtuple('Point', 'x y') 385 p = Point(11, 22) 386 self.assertEqual(p, Point(x=11, y=22)) 387 self.assertEqual(p, Point(11, y=22)) 388 self.assertEqual(p, Point(y=22, x=11)) 389 self.assertEqual(p, Point(*(11, 22))) 390 self.assertEqual(p, Point(**dict(x=11, y=22))) 391 self.assertRaises(TypeError, Point, 1) # too few args 392 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args 393 with self.assertRaises(TypeError): # wrong keyword argument 394 Point(XXX=1, y=2) 395 with self.assertRaises(TypeError): # missing keyword argument 396 Point(x=1) 397 self.assertEqual(repr(p), 'Point(x=11, y=22)') 398 self.assertNotIn('__weakref__', dir(p)) 399 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod 400 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute 401 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method 402 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method 403 404 try: 405 p._replace(x=1, error=2) 406 except ValueError: 407 pass 408 else: 409 self._fail('Did not detect an incorrect fieldname') 410 411 # verify that field string can have commas 412 Point = namedtuple('Point', 'x, y') 413 p = Point(x=11, y=22) 414 self.assertEqual(repr(p), 'Point(x=11, y=22)') 415 416 # verify that fieldspec can be a non-string sequence 417 Point = namedtuple('Point', ('x', 'y')) 418 p = Point(x=11, y=22) 419 self.assertEqual(repr(p), 'Point(x=11, y=22)') 420 421 def test_tupleness(self): 422 Point = namedtuple('Point', 'x y') 423 p = Point(11, 22) 424 425 self.assertIsInstance(p, tuple) 426 self.assertEqual(p, (11, 22)) # matches a real tuple 427 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple 428 self.assertEqual(list(p), [11, 22]) # coercable to a list 429 self.assertEqual(max(p), 22) # iterable 430 self.assertEqual(max(*p), 22) # star-able 431 x, y = p 432 self.assertEqual(p, (x, y)) # unpacks like a tuple 433 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple 434 with self.assertRaises(IndexError): 435 p[3] 436 self.assertEqual(p[-1], 22) 437 self.assertEqual(hash(p), hash((11, 22))) 438 439 self.assertEqual(p.x, x) 440 self.assertEqual(p.y, y) 441 with self.assertRaises(AttributeError): 442 p.z 443 444 def test_odd_sizes(self): 445 Zero = namedtuple('Zero', '') 446 self.assertEqual(Zero(), ()) 447 self.assertEqual(Zero._make([]), ()) 448 self.assertEqual(repr(Zero()), 'Zero()') 449 self.assertEqual(Zero()._asdict(), {}) 450 self.assertEqual(Zero()._fields, ()) 451 452 Dot = namedtuple('Dot', 'd') 453 self.assertEqual(Dot(1), (1,)) 454 self.assertEqual(Dot._make([1]), (1,)) 455 self.assertEqual(Dot(1).d, 1) 456 self.assertEqual(repr(Dot(1)), 'Dot(d=1)') 457 self.assertEqual(Dot(1)._asdict(), {'d':1}) 458 self.assertEqual(Dot(1)._replace(d=999), (999,)) 459 self.assertEqual(Dot(1)._fields, ('d',)) 460 461 n = 5000 462 names = list(set(''.join([choice(string.ascii_letters) 463 for j in range(10)]) for i in range(n))) 464 n = len(names) 465 Big = namedtuple('Big', names) 466 b = Big(*range(n)) 467 self.assertEqual(b, tuple(range(n))) 468 self.assertEqual(Big._make(range(n)), tuple(range(n))) 469 for pos, name in enumerate(names): 470 self.assertEqual(getattr(b, name), pos) 471 repr(b) # make sure repr() doesn't blow-up 472 d = b._asdict() 473 d_expected = dict(zip(names, range(n))) 474 self.assertEqual(d, d_expected) 475 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)])) 476 b2_expected = list(range(n)) 477 b2_expected[1] = 999 478 b2_expected[-5] = 42 479 self.assertEqual(b2, tuple(b2_expected)) 480 self.assertEqual(b._fields, tuple(names)) 481 482 def test_pickle(self): 483 p = TestNT(x=10, y=20, z=30) 484 for module in (pickle,): 485 loads = getattr(module, 'loads') 486 dumps = getattr(module, 'dumps') 487 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1): 488 q = loads(dumps(p, protocol)) 489 self.assertEqual(p, q) 490 self.assertEqual(p._fields, q._fields) 491 self.assertNotIn(b'OrderedDict', dumps(p, protocol)) 492 493 def test_copy(self): 494 p = TestNT(x=10, y=20, z=30) 495 for copier in copy.copy, copy.deepcopy: 496 q = copier(p) 497 self.assertEqual(p, q) 498 self.assertEqual(p._fields, q._fields) 499 500 def test_name_conflicts(self): 501 # Some names like "self", "cls", "tuple", "itemgetter", and "property" 502 # failed when used as field names. Test to make sure these now work. 503 T = namedtuple('T', 'itemgetter property self cls tuple') 504 t = T(1, 2, 3, 4, 5) 505 self.assertEqual(t, (1,2,3,4,5)) 506 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50) 507 self.assertEqual(newt, (10,20,30,40,50)) 508 509 # Broader test of all interesting names taken from the code, old 510 # template, and an example 511 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create', 512 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper', 513 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note', 514 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError', 515 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add', 516 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments', 517 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot', 518 'class_namespace', 'classmethod', 'cls', 'collections', 'convert', 519 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict', 520 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect', 521 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f', 522 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame', 523 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater', 524 'has', 'help', 'identifiers', 'index', 'indexable', 'instance', 525 'instantiate', 'interning', 'introspection', 'isidentifier', 526 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords', 527 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata', 528 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named', 529 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new', 530 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option', 531 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional', 532 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr', 533 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen', 534 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start', 535 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys', 536 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new', 537 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use', 538 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where', 539 'which', 'work', 'x', 'y', 'z', 'zip'} 540 T = namedtuple('T', words) 541 # test __new__ 542 values = tuple(range(len(words))) 543 t = T(*values) 544 self.assertEqual(t, values) 545 t = T(**dict(zip(T._fields, values))) 546 self.assertEqual(t, values) 547 # test _make 548 t = T._make(values) 549 self.assertEqual(t, values) 550 # exercise __repr__ 551 repr(t) 552 # test _asdict 553 self.assertEqual(t._asdict(), dict(zip(T._fields, values))) 554 # test _replace 555 t = T._make(values) 556 newvalues = tuple(v*10 for v in values) 557 newt = t._replace(**dict(zip(T._fields, newvalues))) 558 self.assertEqual(newt, newvalues) 559 # test _fields 560 self.assertEqual(T._fields, tuple(words)) 561 # test __getnewargs__ 562 self.assertEqual(t.__getnewargs__(), values) 563 564 def test_repr(self): 565 A = namedtuple('A', 'x') 566 self.assertEqual(repr(A(1)), 'A(x=1)') 567 # repr should show the name of the subclass 568 class B(A): 569 pass 570 self.assertEqual(repr(B(1)), 'B(x=1)') 571 572 def test_keyword_only_arguments(self): 573 # See issue 25628 574 with self.assertRaises(TypeError): 575 NT = namedtuple('NT', ['x', 'y'], True) 576 577 NT = namedtuple('NT', ['abc', 'def'], rename=True) 578 self.assertEqual(NT._fields, ('abc', '_1')) 579 with self.assertRaises(TypeError): 580 NT = namedtuple('NT', ['abc', 'def'], False, True) 581 582 def test_namedtuple_subclass_issue_24931(self): 583 class Point(namedtuple('_Point', ['x', 'y'])): 584 pass 585 586 a = Point(3, 4) 587 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)])) 588 589 a.w = 5 590 self.assertEqual(a.__dict__, {'w': 5}) 591 592 def test_field_descriptor(self): 593 Point = namedtuple('Point', 'x y') 594 p = Point(11, 22) 595 self.assertTrue(inspect.isdatadescriptor(Point.x)) 596 self.assertEqual(Point.x.__get__(p), 11) 597 self.assertRaises(AttributeError, Point.x.__set__, p, 33) 598 self.assertRaises(AttributeError, Point.x.__delete__, p) 599 600 class NewPoint(tuple): 601 x = pickle.loads(pickle.dumps(Point.x)) 602 y = pickle.loads(pickle.dumps(Point.y)) 603 604 np = NewPoint([1, 2]) 605 606 self.assertEqual(np.x, 1) 607 self.assertEqual(np.y, 2) 608 609 610################################################################################ 611### Abstract Base Classes 612################################################################################ 613 614class ABCTestCase(unittest.TestCase): 615 616 def validate_abstract_methods(self, abc, *names): 617 methodstubs = dict.fromkeys(names, lambda s, *args: 0) 618 619 # everything should work will all required methods are present 620 C = type('C', (abc,), methodstubs) 621 C() 622 623 # instantiation should fail if a required method is missing 624 for name in names: 625 stubs = methodstubs.copy() 626 del stubs[name] 627 C = type('C', (abc,), stubs) 628 self.assertRaises(TypeError, C, name) 629 630 def validate_isinstance(self, abc, name): 631 stub = lambda s, *args: 0 632 633 C = type('C', (object,), {'__hash__': None}) 634 setattr(C, name, stub) 635 self.assertIsInstance(C(), abc) 636 self.assertTrue(issubclass(C, abc)) 637 638 C = type('C', (object,), {'__hash__': None}) 639 self.assertNotIsInstance(C(), abc) 640 self.assertFalse(issubclass(C, abc)) 641 642 def validate_comparison(self, instance): 643 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub'] 644 operators = {} 645 for op in ops: 646 name = '__' + op + '__' 647 operators[name] = getattr(operator, name) 648 649 class Other: 650 def __init__(self): 651 self.right_side = False 652 def __eq__(self, other): 653 self.right_side = True 654 return True 655 __lt__ = __eq__ 656 __gt__ = __eq__ 657 __le__ = __eq__ 658 __ge__ = __eq__ 659 __ne__ = __eq__ 660 __ror__ = __eq__ 661 __rand__ = __eq__ 662 __rxor__ = __eq__ 663 __rsub__ = __eq__ 664 665 for name, op in operators.items(): 666 if not hasattr(instance, name): 667 continue 668 other = Other() 669 op(instance, other) 670 self.assertTrue(other.right_side,'Right side not called for %s.%s' 671 % (type(instance), name)) 672 673def _test_gen(): 674 yield 675 676class TestOneTrickPonyABCs(ABCTestCase): 677 678 def test_Awaitable(self): 679 def gen(): 680 yield 681 682 @types.coroutine 683 def coro(): 684 yield 685 686 async def new_coro(): 687 pass 688 689 class Bar: 690 def __await__(self): 691 yield 692 693 class MinimalCoro(Coroutine): 694 def send(self, value): 695 return value 696 def throw(self, typ, val=None, tb=None): 697 super().throw(typ, val, tb) 698 def __await__(self): 699 yield 700 701 non_samples = [None, int(), gen(), object()] 702 for x in non_samples: 703 self.assertNotIsInstance(x, Awaitable) 704 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x))) 705 706 samples = [Bar(), MinimalCoro()] 707 for x in samples: 708 self.assertIsInstance(x, Awaitable) 709 self.assertTrue(issubclass(type(x), Awaitable)) 710 711 c = coro() 712 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE 713 # flag don't have '__await__' method, hence can't be instances 714 # of Awaitable. Use inspect.isawaitable to detect them. 715 self.assertNotIsInstance(c, Awaitable) 716 717 c = new_coro() 718 self.assertIsInstance(c, Awaitable) 719 c.close() # avoid RuntimeWarning that coro() was not awaited 720 721 class CoroLike: pass 722 Coroutine.register(CoroLike) 723 self.assertTrue(isinstance(CoroLike(), Awaitable)) 724 self.assertTrue(issubclass(CoroLike, Awaitable)) 725 CoroLike = None 726 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache 727 728 def test_Coroutine(self): 729 def gen(): 730 yield 731 732 @types.coroutine 733 def coro(): 734 yield 735 736 async def new_coro(): 737 pass 738 739 class Bar: 740 def __await__(self): 741 yield 742 743 class MinimalCoro(Coroutine): 744 def send(self, value): 745 return value 746 def throw(self, typ, val=None, tb=None): 747 super().throw(typ, val, tb) 748 def __await__(self): 749 yield 750 751 non_samples = [None, int(), gen(), object(), Bar()] 752 for x in non_samples: 753 self.assertNotIsInstance(x, Coroutine) 754 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x))) 755 756 samples = [MinimalCoro()] 757 for x in samples: 758 self.assertIsInstance(x, Awaitable) 759 self.assertTrue(issubclass(type(x), Awaitable)) 760 761 c = coro() 762 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE 763 # flag don't have '__await__' method, hence can't be instances 764 # of Coroutine. Use inspect.isawaitable to detect them. 765 self.assertNotIsInstance(c, Coroutine) 766 767 c = new_coro() 768 self.assertIsInstance(c, Coroutine) 769 c.close() # avoid RuntimeWarning that coro() was not awaited 770 771 class CoroLike: 772 def send(self, value): 773 pass 774 def throw(self, typ, val=None, tb=None): 775 pass 776 def close(self): 777 pass 778 def __await__(self): 779 pass 780 self.assertTrue(isinstance(CoroLike(), Coroutine)) 781 self.assertTrue(issubclass(CoroLike, Coroutine)) 782 783 class CoroLike: 784 def send(self, value): 785 pass 786 def close(self): 787 pass 788 def __await__(self): 789 pass 790 self.assertFalse(isinstance(CoroLike(), Coroutine)) 791 self.assertFalse(issubclass(CoroLike, Coroutine)) 792 793 def test_Hashable(self): 794 # Check some non-hashables 795 non_samples = [bytearray(), list(), set(), dict()] 796 for x in non_samples: 797 self.assertNotIsInstance(x, Hashable) 798 self.assertFalse(issubclass(type(x), Hashable), repr(type(x))) 799 # Check some hashables 800 samples = [None, 801 int(), float(), complex(), 802 str(), 803 tuple(), frozenset(), 804 int, list, object, type, bytes() 805 ] 806 for x in samples: 807 self.assertIsInstance(x, Hashable) 808 self.assertTrue(issubclass(type(x), Hashable), repr(type(x))) 809 self.assertRaises(TypeError, Hashable) 810 # Check direct subclassing 811 class H(Hashable): 812 def __hash__(self): 813 return super().__hash__() 814 self.assertEqual(hash(H()), 0) 815 self.assertFalse(issubclass(int, H)) 816 self.validate_abstract_methods(Hashable, '__hash__') 817 self.validate_isinstance(Hashable, '__hash__') 818 819 def test_AsyncIterable(self): 820 class AI: 821 def __aiter__(self): 822 return self 823 self.assertTrue(isinstance(AI(), AsyncIterable)) 824 self.assertTrue(issubclass(AI, AsyncIterable)) 825 # Check some non-iterables 826 non_samples = [None, object, []] 827 for x in non_samples: 828 self.assertNotIsInstance(x, AsyncIterable) 829 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x))) 830 self.validate_abstract_methods(AsyncIterable, '__aiter__') 831 self.validate_isinstance(AsyncIterable, '__aiter__') 832 833 def test_AsyncIterator(self): 834 class AI: 835 def __aiter__(self): 836 return self 837 async def __anext__(self): 838 raise StopAsyncIteration 839 self.assertTrue(isinstance(AI(), AsyncIterator)) 840 self.assertTrue(issubclass(AI, AsyncIterator)) 841 non_samples = [None, object, []] 842 # Check some non-iterables 843 for x in non_samples: 844 self.assertNotIsInstance(x, AsyncIterator) 845 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x))) 846 # Similarly to regular iterators (see issue 10565) 847 class AnextOnly: 848 async def __anext__(self): 849 raise StopAsyncIteration 850 self.assertNotIsInstance(AnextOnly(), AsyncIterator) 851 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__') 852 853 def test_Iterable(self): 854 # Check some non-iterables 855 non_samples = [None, 42, 3.14, 1j] 856 for x in non_samples: 857 self.assertNotIsInstance(x, Iterable) 858 self.assertFalse(issubclass(type(x), Iterable), repr(type(x))) 859 # Check some iterables 860 samples = [bytes(), str(), 861 tuple(), list(), set(), frozenset(), dict(), 862 dict().keys(), dict().items(), dict().values(), 863 _test_gen(), 864 (x for x in []), 865 ] 866 for x in samples: 867 self.assertIsInstance(x, Iterable) 868 self.assertTrue(issubclass(type(x), Iterable), repr(type(x))) 869 # Check direct subclassing 870 class I(Iterable): 871 def __iter__(self): 872 return super().__iter__() 873 self.assertEqual(list(I()), []) 874 self.assertFalse(issubclass(str, I)) 875 self.validate_abstract_methods(Iterable, '__iter__') 876 self.validate_isinstance(Iterable, '__iter__') 877 # Check None blocking 878 class It: 879 def __iter__(self): return iter([]) 880 class ItBlocked(It): 881 __iter__ = None 882 self.assertTrue(issubclass(It, Iterable)) 883 self.assertTrue(isinstance(It(), Iterable)) 884 self.assertFalse(issubclass(ItBlocked, Iterable)) 885 self.assertFalse(isinstance(ItBlocked(), Iterable)) 886 887 def test_Reversible(self): 888 # Check some non-reversibles 889 non_samples = [None, 42, 3.14, 1j, set(), frozenset()] 890 for x in non_samples: 891 self.assertNotIsInstance(x, Reversible) 892 self.assertFalse(issubclass(type(x), Reversible), repr(type(x))) 893 # Check some non-reversible iterables 894 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])] 895 for x in non_reversibles: 896 self.assertNotIsInstance(x, Reversible) 897 self.assertFalse(issubclass(type(x), Reversible), repr(type(x))) 898 # Check some reversible iterables 899 samples = [bytes(), str(), tuple(), list(), OrderedDict(), 900 OrderedDict().keys(), OrderedDict().items(), 901 OrderedDict().values(), Counter(), Counter().keys(), 902 Counter().items(), Counter().values(), dict(), 903 dict().keys(), dict().items(), dict().values()] 904 for x in samples: 905 self.assertIsInstance(x, Reversible) 906 self.assertTrue(issubclass(type(x), Reversible), repr(type(x))) 907 # Check also Mapping, MutableMapping, and Sequence 908 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence)) 909 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping)) 910 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping)) 911 # Check direct subclassing 912 class R(Reversible): 913 def __iter__(self): 914 return iter(list()) 915 def __reversed__(self): 916 return iter(list()) 917 self.assertEqual(list(reversed(R())), []) 918 self.assertFalse(issubclass(float, R)) 919 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__') 920 # Check reversible non-iterable (which is not Reversible) 921 class RevNoIter: 922 def __reversed__(self): return reversed([]) 923 class RevPlusIter(RevNoIter): 924 def __iter__(self): return iter([]) 925 self.assertFalse(issubclass(RevNoIter, Reversible)) 926 self.assertFalse(isinstance(RevNoIter(), Reversible)) 927 self.assertTrue(issubclass(RevPlusIter, Reversible)) 928 self.assertTrue(isinstance(RevPlusIter(), Reversible)) 929 # Check None blocking 930 class Rev: 931 def __iter__(self): return iter([]) 932 def __reversed__(self): return reversed([]) 933 class RevItBlocked(Rev): 934 __iter__ = None 935 class RevRevBlocked(Rev): 936 __reversed__ = None 937 self.assertTrue(issubclass(Rev, Reversible)) 938 self.assertTrue(isinstance(Rev(), Reversible)) 939 self.assertFalse(issubclass(RevItBlocked, Reversible)) 940 self.assertFalse(isinstance(RevItBlocked(), Reversible)) 941 self.assertFalse(issubclass(RevRevBlocked, Reversible)) 942 self.assertFalse(isinstance(RevRevBlocked(), Reversible)) 943 944 def test_Collection(self): 945 # Check some non-collections 946 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x] 947 for x in non_collections: 948 self.assertNotIsInstance(x, Collection) 949 self.assertFalse(issubclass(type(x), Collection), repr(type(x))) 950 # Check some non-collection iterables 951 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()), 952 (x for x in [])] 953 for x in non_col_iterables: 954 self.assertNotIsInstance(x, Collection) 955 self.assertFalse(issubclass(type(x), Collection), repr(type(x))) 956 # Check some collections 957 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(), 958 list(), dict().keys(), dict().items(), dict().values()] 959 for x in samples: 960 self.assertIsInstance(x, Collection) 961 self.assertTrue(issubclass(type(x), Collection), repr(type(x))) 962 # Check also Mapping, MutableMapping, etc. 963 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence)) 964 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping)) 965 self.assertTrue(issubclass(MutableMapping, Collection), 966 repr(MutableMapping)) 967 self.assertTrue(issubclass(Set, Collection), repr(Set)) 968 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet)) 969 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet)) 970 # Check direct subclassing 971 class Col(Collection): 972 def __iter__(self): 973 return iter(list()) 974 def __len__(self): 975 return 0 976 def __contains__(self, item): 977 return False 978 class DerCol(Col): pass 979 self.assertEqual(list(iter(Col())), []) 980 self.assertFalse(issubclass(list, Col)) 981 self.assertFalse(issubclass(set, Col)) 982 self.assertFalse(issubclass(float, Col)) 983 self.assertEqual(list(iter(DerCol())), []) 984 self.assertFalse(issubclass(list, DerCol)) 985 self.assertFalse(issubclass(set, DerCol)) 986 self.assertFalse(issubclass(float, DerCol)) 987 self.validate_abstract_methods(Collection, '__len__', '__iter__', 988 '__contains__') 989 # Check sized container non-iterable (which is not Collection) etc. 990 class ColNoIter: 991 def __len__(self): return 0 992 def __contains__(self, item): return False 993 class ColNoSize: 994 def __iter__(self): return iter([]) 995 def __contains__(self, item): return False 996 class ColNoCont: 997 def __iter__(self): return iter([]) 998 def __len__(self): return 0 999 self.assertFalse(issubclass(ColNoIter, Collection)) 1000 self.assertFalse(isinstance(ColNoIter(), Collection)) 1001 self.assertFalse(issubclass(ColNoSize, Collection)) 1002 self.assertFalse(isinstance(ColNoSize(), Collection)) 1003 self.assertFalse(issubclass(ColNoCont, Collection)) 1004 self.assertFalse(isinstance(ColNoCont(), Collection)) 1005 # Check None blocking 1006 class SizeBlock: 1007 def __iter__(self): return iter([]) 1008 def __contains__(self): return False 1009 __len__ = None 1010 class IterBlock: 1011 def __len__(self): return 0 1012 def __contains__(self): return True 1013 __iter__ = None 1014 self.assertFalse(issubclass(SizeBlock, Collection)) 1015 self.assertFalse(isinstance(SizeBlock(), Collection)) 1016 self.assertFalse(issubclass(IterBlock, Collection)) 1017 self.assertFalse(isinstance(IterBlock(), Collection)) 1018 # Check None blocking in subclass 1019 class ColImpl: 1020 def __iter__(self): 1021 return iter(list()) 1022 def __len__(self): 1023 return 0 1024 def __contains__(self, item): 1025 return False 1026 class NonCol(ColImpl): 1027 __contains__ = None 1028 self.assertFalse(issubclass(NonCol, Collection)) 1029 self.assertFalse(isinstance(NonCol(), Collection)) 1030 1031 1032 def test_Iterator(self): 1033 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()] 1034 for x in non_samples: 1035 self.assertNotIsInstance(x, Iterator) 1036 self.assertFalse(issubclass(type(x), Iterator), repr(type(x))) 1037 samples = [iter(bytes()), iter(str()), 1038 iter(tuple()), iter(list()), iter(dict()), 1039 iter(set()), iter(frozenset()), 1040 iter(dict().keys()), iter(dict().items()), 1041 iter(dict().values()), 1042 _test_gen(), 1043 (x for x in []), 1044 ] 1045 for x in samples: 1046 self.assertIsInstance(x, Iterator) 1047 self.assertTrue(issubclass(type(x), Iterator), repr(type(x))) 1048 self.validate_abstract_methods(Iterator, '__next__', '__iter__') 1049 1050 # Issue 10565 1051 class NextOnly: 1052 def __next__(self): 1053 yield 1 1054 return 1055 self.assertNotIsInstance(NextOnly(), Iterator) 1056 1057 def test_Generator(self): 1058 class NonGen1: 1059 def __iter__(self): return self 1060 def __next__(self): return None 1061 def close(self): pass 1062 def throw(self, typ, val=None, tb=None): pass 1063 1064 class NonGen2: 1065 def __iter__(self): return self 1066 def __next__(self): return None 1067 def close(self): pass 1068 def send(self, value): return value 1069 1070 class NonGen3: 1071 def close(self): pass 1072 def send(self, value): return value 1073 def throw(self, typ, val=None, tb=None): pass 1074 1075 non_samples = [ 1076 None, 42, 3.14, 1j, b"", "", (), [], {}, set(), 1077 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()] 1078 for x in non_samples: 1079 self.assertNotIsInstance(x, Generator) 1080 self.assertFalse(issubclass(type(x), Generator), repr(type(x))) 1081 1082 class Gen: 1083 def __iter__(self): return self 1084 def __next__(self): return None 1085 def close(self): pass 1086 def send(self, value): return value 1087 def throw(self, typ, val=None, tb=None): pass 1088 1089 class MinimalGen(Generator): 1090 def send(self, value): 1091 return value 1092 def throw(self, typ, val=None, tb=None): 1093 super().throw(typ, val, tb) 1094 1095 def gen(): 1096 yield 1 1097 1098 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()] 1099 for x in samples: 1100 self.assertIsInstance(x, Iterator) 1101 self.assertIsInstance(x, Generator) 1102 self.assertTrue(issubclass(type(x), Generator), repr(type(x))) 1103 self.validate_abstract_methods(Generator, 'send', 'throw') 1104 1105 # mixin tests 1106 mgen = MinimalGen() 1107 self.assertIs(mgen, iter(mgen)) 1108 self.assertIs(mgen.send(None), next(mgen)) 1109 self.assertEqual(2, mgen.send(2)) 1110 self.assertIsNone(mgen.close()) 1111 self.assertRaises(ValueError, mgen.throw, ValueError) 1112 self.assertRaisesRegex(ValueError, "^huhu$", 1113 mgen.throw, ValueError, ValueError("huhu")) 1114 self.assertRaises(StopIteration, mgen.throw, StopIteration()) 1115 1116 class FailOnClose(Generator): 1117 def send(self, value): return value 1118 def throw(self, *args): raise ValueError 1119 1120 self.assertRaises(ValueError, FailOnClose().close) 1121 1122 class IgnoreGeneratorExit(Generator): 1123 def send(self, value): return value 1124 def throw(self, *args): pass 1125 1126 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close) 1127 1128 def test_AsyncGenerator(self): 1129 class NonAGen1: 1130 def __aiter__(self): return self 1131 def __anext__(self): return None 1132 def aclose(self): pass 1133 def athrow(self, typ, val=None, tb=None): pass 1134 1135 class NonAGen2: 1136 def __aiter__(self): return self 1137 def __anext__(self): return None 1138 def aclose(self): pass 1139 def asend(self, value): return value 1140 1141 class NonAGen3: 1142 def aclose(self): pass 1143 def asend(self, value): return value 1144 def athrow(self, typ, val=None, tb=None): pass 1145 1146 non_samples = [ 1147 None, 42, 3.14, 1j, b"", "", (), [], {}, set(), 1148 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()] 1149 for x in non_samples: 1150 self.assertNotIsInstance(x, AsyncGenerator) 1151 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x))) 1152 1153 class Gen: 1154 def __aiter__(self): return self 1155 async def __anext__(self): return None 1156 async def aclose(self): pass 1157 async def asend(self, value): return value 1158 async def athrow(self, typ, val=None, tb=None): pass 1159 1160 class MinimalAGen(AsyncGenerator): 1161 async def asend(self, value): 1162 return value 1163 async def athrow(self, typ, val=None, tb=None): 1164 await super().athrow(typ, val, tb) 1165 1166 async def gen(): 1167 yield 1 1168 1169 samples = [gen(), Gen(), MinimalAGen()] 1170 for x in samples: 1171 self.assertIsInstance(x, AsyncIterator) 1172 self.assertIsInstance(x, AsyncGenerator) 1173 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x))) 1174 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow') 1175 1176 def run_async(coro): 1177 result = None 1178 while True: 1179 try: 1180 coro.send(None) 1181 except StopIteration as ex: 1182 result = ex.args[0] if ex.args else None 1183 break 1184 return result 1185 1186 # mixin tests 1187 mgen = MinimalAGen() 1188 self.assertIs(mgen, mgen.__aiter__()) 1189 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__())) 1190 self.assertEqual(2, run_async(mgen.asend(2))) 1191 self.assertIsNone(run_async(mgen.aclose())) 1192 with self.assertRaises(ValueError): 1193 run_async(mgen.athrow(ValueError)) 1194 1195 class FailOnClose(AsyncGenerator): 1196 async def asend(self, value): return value 1197 async def athrow(self, *args): raise ValueError 1198 1199 with self.assertRaises(ValueError): 1200 run_async(FailOnClose().aclose()) 1201 1202 class IgnoreGeneratorExit(AsyncGenerator): 1203 async def asend(self, value): return value 1204 async def athrow(self, *args): pass 1205 1206 with self.assertRaises(RuntimeError): 1207 run_async(IgnoreGeneratorExit().aclose()) 1208 1209 def test_Sized(self): 1210 non_samples = [None, 42, 3.14, 1j, 1211 _test_gen(), 1212 (x for x in []), 1213 ] 1214 for x in non_samples: 1215 self.assertNotIsInstance(x, Sized) 1216 self.assertFalse(issubclass(type(x), Sized), repr(type(x))) 1217 samples = [bytes(), str(), 1218 tuple(), list(), set(), frozenset(), dict(), 1219 dict().keys(), dict().items(), dict().values(), 1220 ] 1221 for x in samples: 1222 self.assertIsInstance(x, Sized) 1223 self.assertTrue(issubclass(type(x), Sized), repr(type(x))) 1224 self.validate_abstract_methods(Sized, '__len__') 1225 self.validate_isinstance(Sized, '__len__') 1226 1227 def test_Container(self): 1228 non_samples = [None, 42, 3.14, 1j, 1229 _test_gen(), 1230 (x for x in []), 1231 ] 1232 for x in non_samples: 1233 self.assertNotIsInstance(x, Container) 1234 self.assertFalse(issubclass(type(x), Container), repr(type(x))) 1235 samples = [bytes(), str(), 1236 tuple(), list(), set(), frozenset(), dict(), 1237 dict().keys(), dict().items(), 1238 ] 1239 for x in samples: 1240 self.assertIsInstance(x, Container) 1241 self.assertTrue(issubclass(type(x), Container), repr(type(x))) 1242 self.validate_abstract_methods(Container, '__contains__') 1243 self.validate_isinstance(Container, '__contains__') 1244 1245 def test_Callable(self): 1246 non_samples = [None, 42, 3.14, 1j, 1247 "", b"", (), [], {}, set(), 1248 _test_gen(), 1249 (x for x in []), 1250 ] 1251 for x in non_samples: 1252 self.assertNotIsInstance(x, Callable) 1253 self.assertFalse(issubclass(type(x), Callable), repr(type(x))) 1254 samples = [lambda: None, 1255 type, int, object, 1256 len, 1257 list.append, [].append, 1258 ] 1259 for x in samples: 1260 self.assertIsInstance(x, Callable) 1261 self.assertTrue(issubclass(type(x), Callable), repr(type(x))) 1262 self.validate_abstract_methods(Callable, '__call__') 1263 self.validate_isinstance(Callable, '__call__') 1264 1265 def test_direct_subclassing(self): 1266 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: 1267 class C(B): 1268 pass 1269 self.assertTrue(issubclass(C, B)) 1270 self.assertFalse(issubclass(int, C)) 1271 1272 def test_registration(self): 1273 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: 1274 class C: 1275 __hash__ = None # Make sure it isn't hashable by default 1276 self.assertFalse(issubclass(C, B), B.__name__) 1277 B.register(C) 1278 self.assertTrue(issubclass(C, B)) 1279 1280class WithSet(MutableSet): 1281 1282 def __init__(self, it=()): 1283 self.data = set(it) 1284 1285 def __len__(self): 1286 return len(self.data) 1287 1288 def __iter__(self): 1289 return iter(self.data) 1290 1291 def __contains__(self, item): 1292 return item in self.data 1293 1294 def add(self, item): 1295 self.data.add(item) 1296 1297 def discard(self, item): 1298 self.data.discard(item) 1299 1300class TestCollectionABCs(ABCTestCase): 1301 1302 # XXX For now, we only test some virtual inheritance properties. 1303 # We should also test the proper behavior of the collection ABCs 1304 # as real base classes or mix-in classes. 1305 1306 def test_Set(self): 1307 for sample in [set, frozenset]: 1308 self.assertIsInstance(sample(), Set) 1309 self.assertTrue(issubclass(sample, Set)) 1310 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__') 1311 class MySet(Set): 1312 def __contains__(self, x): 1313 return False 1314 def __len__(self): 1315 return 0 1316 def __iter__(self): 1317 return iter([]) 1318 self.validate_comparison(MySet()) 1319 1320 def test_hash_Set(self): 1321 class OneTwoThreeSet(Set): 1322 def __init__(self): 1323 self.contents = [1, 2, 3] 1324 def __contains__(self, x): 1325 return x in self.contents 1326 def __len__(self): 1327 return len(self.contents) 1328 def __iter__(self): 1329 return iter(self.contents) 1330 def __hash__(self): 1331 return self._hash() 1332 a, b = OneTwoThreeSet(), OneTwoThreeSet() 1333 self.assertTrue(hash(a) == hash(b)) 1334 1335 def test_isdisjoint_Set(self): 1336 class MySet(Set): 1337 def __init__(self, itr): 1338 self.contents = itr 1339 def __contains__(self, x): 1340 return x in self.contents 1341 def __iter__(self): 1342 return iter(self.contents) 1343 def __len__(self): 1344 return len([x for x in self.contents]) 1345 s1 = MySet((1, 2, 3)) 1346 s2 = MySet((4, 5, 6)) 1347 s3 = MySet((1, 5, 6)) 1348 self.assertTrue(s1.isdisjoint(s2)) 1349 self.assertFalse(s1.isdisjoint(s3)) 1350 1351 def test_equality_Set(self): 1352 class MySet(Set): 1353 def __init__(self, itr): 1354 self.contents = itr 1355 def __contains__(self, x): 1356 return x in self.contents 1357 def __iter__(self): 1358 return iter(self.contents) 1359 def __len__(self): 1360 return len([x for x in self.contents]) 1361 s1 = MySet((1,)) 1362 s2 = MySet((1, 2)) 1363 s3 = MySet((3, 4)) 1364 s4 = MySet((3, 4)) 1365 self.assertTrue(s2 > s1) 1366 self.assertTrue(s1 < s2) 1367 self.assertFalse(s2 <= s1) 1368 self.assertFalse(s2 <= s3) 1369 self.assertFalse(s1 >= s2) 1370 self.assertEqual(s3, s4) 1371 self.assertNotEqual(s2, s3) 1372 1373 def test_arithmetic_Set(self): 1374 class MySet(Set): 1375 def __init__(self, itr): 1376 self.contents = itr 1377 def __contains__(self, x): 1378 return x in self.contents 1379 def __iter__(self): 1380 return iter(self.contents) 1381 def __len__(self): 1382 return len([x for x in self.contents]) 1383 s1 = MySet((1, 2, 3)) 1384 s2 = MySet((3, 4, 5)) 1385 s3 = s1 & s2 1386 self.assertEqual(s3, MySet((3,))) 1387 1388 def test_MutableSet(self): 1389 self.assertIsInstance(set(), MutableSet) 1390 self.assertTrue(issubclass(set, MutableSet)) 1391 self.assertNotIsInstance(frozenset(), MutableSet) 1392 self.assertFalse(issubclass(frozenset, MutableSet)) 1393 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__', 1394 'add', 'discard') 1395 1396 def test_issue_5647(self): 1397 # MutableSet.__iand__ mutated the set during iteration 1398 s = WithSet('abcd') 1399 s &= WithSet('cdef') # This used to fail 1400 self.assertEqual(set(s), set('cd')) 1401 1402 def test_issue_4920(self): 1403 # MutableSet.pop() method did not work 1404 class MySet(MutableSet): 1405 __slots__=['__s'] 1406 def __init__(self,items=None): 1407 if items is None: 1408 items=[] 1409 self.__s=set(items) 1410 def __contains__(self,v): 1411 return v in self.__s 1412 def __iter__(self): 1413 return iter(self.__s) 1414 def __len__(self): 1415 return len(self.__s) 1416 def add(self,v): 1417 result=v not in self.__s 1418 self.__s.add(v) 1419 return result 1420 def discard(self,v): 1421 result=v in self.__s 1422 self.__s.discard(v) 1423 return result 1424 def __repr__(self): 1425 return "MySet(%s)" % repr(list(self)) 1426 s = MySet([5,43,2,1]) 1427 self.assertEqual(s.pop(), 1) 1428 1429 def test_issue8750(self): 1430 empty = WithSet() 1431 full = WithSet(range(10)) 1432 s = WithSet(full) 1433 s -= s 1434 self.assertEqual(s, empty) 1435 s = WithSet(full) 1436 s ^= s 1437 self.assertEqual(s, empty) 1438 s = WithSet(full) 1439 s &= s 1440 self.assertEqual(s, full) 1441 s |= s 1442 self.assertEqual(s, full) 1443 1444 def test_issue16373(self): 1445 # Recursion error comparing comparable and noncomparable 1446 # Set instances 1447 class MyComparableSet(Set): 1448 def __contains__(self, x): 1449 return False 1450 def __len__(self): 1451 return 0 1452 def __iter__(self): 1453 return iter([]) 1454 class MyNonComparableSet(Set): 1455 def __contains__(self, x): 1456 return False 1457 def __len__(self): 1458 return 0 1459 def __iter__(self): 1460 return iter([]) 1461 def __le__(self, x): 1462 return NotImplemented 1463 def __lt__(self, x): 1464 return NotImplemented 1465 1466 cs = MyComparableSet() 1467 ncs = MyNonComparableSet() 1468 self.assertFalse(ncs < cs) 1469 self.assertTrue(ncs <= cs) 1470 self.assertFalse(ncs > cs) 1471 self.assertTrue(ncs >= cs) 1472 1473 def test_issue26915(self): 1474 # Container membership test should check identity first 1475 class CustomEqualObject: 1476 def __eq__(self, other): 1477 return False 1478 class CustomSequence(Sequence): 1479 def __init__(self, seq): 1480 self._seq = seq 1481 def __getitem__(self, index): 1482 return self._seq[index] 1483 def __len__(self): 1484 return len(self._seq) 1485 1486 nan = float('nan') 1487 obj = CustomEqualObject() 1488 seq = CustomSequence([nan, obj, nan]) 1489 containers = [ 1490 seq, 1491 ItemsView({1: nan, 2: obj}), 1492 ValuesView({1: nan, 2: obj}) 1493 ] 1494 for container in containers: 1495 for elem in container: 1496 self.assertIn(elem, container) 1497 self.assertEqual(seq.index(nan), 0) 1498 self.assertEqual(seq.index(obj), 1) 1499 self.assertEqual(seq.count(nan), 2) 1500 self.assertEqual(seq.count(obj), 1) 1501 1502 def assertSameSet(self, s1, s2): 1503 # coerce both to a real set then check equality 1504 self.assertSetEqual(set(s1), set(s2)) 1505 1506 def test_Set_interoperability_with_real_sets(self): 1507 # Issue: 8743 1508 class ListSet(Set): 1509 def __init__(self, elements=()): 1510 self.data = [] 1511 for elem in elements: 1512 if elem not in self.data: 1513 self.data.append(elem) 1514 def __contains__(self, elem): 1515 return elem in self.data 1516 def __iter__(self): 1517 return iter(self.data) 1518 def __len__(self): 1519 return len(self.data) 1520 def __repr__(self): 1521 return 'Set({!r})'.format(self.data) 1522 1523 r1 = set('abc') 1524 r2 = set('bcd') 1525 r3 = set('abcde') 1526 f1 = ListSet('abc') 1527 f2 = ListSet('bcd') 1528 f3 = ListSet('abcde') 1529 l1 = list('abccba') 1530 l2 = list('bcddcb') 1531 l3 = list('abcdeedcba') 1532 1533 target = r1 & r2 1534 self.assertSameSet(f1 & f2, target) 1535 self.assertSameSet(f1 & r2, target) 1536 self.assertSameSet(r2 & f1, target) 1537 self.assertSameSet(f1 & l2, target) 1538 1539 target = r1 | r2 1540 self.assertSameSet(f1 | f2, target) 1541 self.assertSameSet(f1 | r2, target) 1542 self.assertSameSet(r2 | f1, target) 1543 self.assertSameSet(f1 | l2, target) 1544 1545 fwd_target = r1 - r2 1546 rev_target = r2 - r1 1547 self.assertSameSet(f1 - f2, fwd_target) 1548 self.assertSameSet(f2 - f1, rev_target) 1549 self.assertSameSet(f1 - r2, fwd_target) 1550 self.assertSameSet(f2 - r1, rev_target) 1551 self.assertSameSet(r1 - f2, fwd_target) 1552 self.assertSameSet(r2 - f1, rev_target) 1553 self.assertSameSet(f1 - l2, fwd_target) 1554 self.assertSameSet(f2 - l1, rev_target) 1555 1556 target = r1 ^ r2 1557 self.assertSameSet(f1 ^ f2, target) 1558 self.assertSameSet(f1 ^ r2, target) 1559 self.assertSameSet(r2 ^ f1, target) 1560 self.assertSameSet(f1 ^ l2, target) 1561 1562 # Don't change the following to use assertLess or other 1563 # "more specific" unittest assertions. The current 1564 # assertTrue/assertFalse style makes the pattern of test 1565 # case combinations clear and allows us to know for sure 1566 # the exact operator being invoked. 1567 1568 # proper subset 1569 self.assertTrue(f1 < f3) 1570 self.assertFalse(f1 < f1) 1571 self.assertFalse(f1 < f2) 1572 self.assertTrue(r1 < f3) 1573 self.assertFalse(r1 < f1) 1574 self.assertFalse(r1 < f2) 1575 self.assertTrue(r1 < r3) 1576 self.assertFalse(r1 < r1) 1577 self.assertFalse(r1 < r2) 1578 with self.assertRaises(TypeError): 1579 f1 < l3 1580 with self.assertRaises(TypeError): 1581 f1 < l1 1582 with self.assertRaises(TypeError): 1583 f1 < l2 1584 1585 # any subset 1586 self.assertTrue(f1 <= f3) 1587 self.assertTrue(f1 <= f1) 1588 self.assertFalse(f1 <= f2) 1589 self.assertTrue(r1 <= f3) 1590 self.assertTrue(r1 <= f1) 1591 self.assertFalse(r1 <= f2) 1592 self.assertTrue(r1 <= r3) 1593 self.assertTrue(r1 <= r1) 1594 self.assertFalse(r1 <= r2) 1595 with self.assertRaises(TypeError): 1596 f1 <= l3 1597 with self.assertRaises(TypeError): 1598 f1 <= l1 1599 with self.assertRaises(TypeError): 1600 f1 <= l2 1601 1602 # proper superset 1603 self.assertTrue(f3 > f1) 1604 self.assertFalse(f1 > f1) 1605 self.assertFalse(f2 > f1) 1606 self.assertTrue(r3 > r1) 1607 self.assertFalse(f1 > r1) 1608 self.assertFalse(f2 > r1) 1609 self.assertTrue(r3 > r1) 1610 self.assertFalse(r1 > r1) 1611 self.assertFalse(r2 > r1) 1612 with self.assertRaises(TypeError): 1613 f1 > l3 1614 with self.assertRaises(TypeError): 1615 f1 > l1 1616 with self.assertRaises(TypeError): 1617 f1 > l2 1618 1619 # any superset 1620 self.assertTrue(f3 >= f1) 1621 self.assertTrue(f1 >= f1) 1622 self.assertFalse(f2 >= f1) 1623 self.assertTrue(r3 >= r1) 1624 self.assertTrue(f1 >= r1) 1625 self.assertFalse(f2 >= r1) 1626 self.assertTrue(r3 >= r1) 1627 self.assertTrue(r1 >= r1) 1628 self.assertFalse(r2 >= r1) 1629 with self.assertRaises(TypeError): 1630 f1 >= l3 1631 with self.assertRaises(TypeError): 1632 f1 >=l1 1633 with self.assertRaises(TypeError): 1634 f1 >= l2 1635 1636 # equality 1637 self.assertTrue(f1 == f1) 1638 self.assertTrue(r1 == f1) 1639 self.assertTrue(f1 == r1) 1640 self.assertFalse(f1 == f3) 1641 self.assertFalse(r1 == f3) 1642 self.assertFalse(f1 == r3) 1643 self.assertFalse(f1 == l3) 1644 self.assertFalse(f1 == l1) 1645 self.assertFalse(f1 == l2) 1646 1647 # inequality 1648 self.assertFalse(f1 != f1) 1649 self.assertFalse(r1 != f1) 1650 self.assertFalse(f1 != r1) 1651 self.assertTrue(f1 != f3) 1652 self.assertTrue(r1 != f3) 1653 self.assertTrue(f1 != r3) 1654 self.assertTrue(f1 != l3) 1655 self.assertTrue(f1 != l1) 1656 self.assertTrue(f1 != l2) 1657 1658 def test_Mapping(self): 1659 for sample in [dict]: 1660 self.assertIsInstance(sample(), Mapping) 1661 self.assertTrue(issubclass(sample, Mapping)) 1662 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__', 1663 '__getitem__') 1664 class MyMapping(Mapping): 1665 def __len__(self): 1666 return 0 1667 def __getitem__(self, i): 1668 raise IndexError 1669 def __iter__(self): 1670 return iter(()) 1671 self.validate_comparison(MyMapping()) 1672 self.assertRaises(TypeError, reversed, MyMapping()) 1673 1674 def test_MutableMapping(self): 1675 for sample in [dict]: 1676 self.assertIsInstance(sample(), MutableMapping) 1677 self.assertTrue(issubclass(sample, MutableMapping)) 1678 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__', 1679 '__getitem__', '__setitem__', '__delitem__') 1680 1681 def test_MutableMapping_subclass(self): 1682 # Test issue 9214 1683 mymap = UserDict() 1684 mymap['red'] = 5 1685 self.assertIsInstance(mymap.keys(), Set) 1686 self.assertIsInstance(mymap.keys(), KeysView) 1687 self.assertIsInstance(mymap.items(), Set) 1688 self.assertIsInstance(mymap.items(), ItemsView) 1689 1690 mymap = UserDict() 1691 mymap['red'] = 5 1692 z = mymap.keys() | {'orange'} 1693 self.assertIsInstance(z, set) 1694 list(z) 1695 mymap['blue'] = 7 # Shouldn't affect 'z' 1696 self.assertEqual(sorted(z), ['orange', 'red']) 1697 1698 mymap = UserDict() 1699 mymap['red'] = 5 1700 z = mymap.items() | {('orange', 3)} 1701 self.assertIsInstance(z, set) 1702 list(z) 1703 mymap['blue'] = 7 # Shouldn't affect 'z' 1704 self.assertEqual(z, {('orange', 3), ('red', 5)}) 1705 1706 def test_Sequence(self): 1707 for sample in [tuple, list, bytes, str]: 1708 self.assertIsInstance(sample(), Sequence) 1709 self.assertTrue(issubclass(sample, Sequence)) 1710 self.assertIsInstance(range(10), Sequence) 1711 self.assertTrue(issubclass(range, Sequence)) 1712 self.assertIsInstance(memoryview(b""), Sequence) 1713 self.assertTrue(issubclass(memoryview, Sequence)) 1714 self.assertTrue(issubclass(str, Sequence)) 1715 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__', 1716 '__getitem__') 1717 1718 def test_Sequence_mixins(self): 1719 class SequenceSubclass(Sequence): 1720 def __init__(self, seq=()): 1721 self.seq = seq 1722 1723 def __getitem__(self, index): 1724 return self.seq[index] 1725 1726 def __len__(self): 1727 return len(self.seq) 1728 1729 # Compare Sequence.index() behavior to (list|str).index() behavior 1730 def assert_index_same(seq1, seq2, index_args): 1731 try: 1732 expected = seq1.index(*index_args) 1733 except ValueError: 1734 with self.assertRaises(ValueError): 1735 seq2.index(*index_args) 1736 else: 1737 actual = seq2.index(*index_args) 1738 self.assertEqual( 1739 actual, expected, '%r.index%s' % (seq1, index_args)) 1740 1741 for ty in list, str: 1742 nativeseq = ty('abracadabra') 1743 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3)) 1744 seqseq = SequenceSubclass(nativeseq) 1745 for letter in set(nativeseq) | {'z'}: 1746 assert_index_same(nativeseq, seqseq, (letter,)) 1747 for start in range(-3, len(nativeseq) + 3): 1748 assert_index_same(nativeseq, seqseq, (letter, start)) 1749 for stop in range(-3, len(nativeseq) + 3): 1750 assert_index_same( 1751 nativeseq, seqseq, (letter, start, stop)) 1752 1753 def test_ByteString(self): 1754 for sample in [bytes, bytearray]: 1755 self.assertIsInstance(sample(), ByteString) 1756 self.assertTrue(issubclass(sample, ByteString)) 1757 for sample in [str, list, tuple]: 1758 self.assertNotIsInstance(sample(), ByteString) 1759 self.assertFalse(issubclass(sample, ByteString)) 1760 self.assertNotIsInstance(memoryview(b""), ByteString) 1761 self.assertFalse(issubclass(memoryview, ByteString)) 1762 1763 def test_MutableSequence(self): 1764 for sample in [tuple, str, bytes]: 1765 self.assertNotIsInstance(sample(), MutableSequence) 1766 self.assertFalse(issubclass(sample, MutableSequence)) 1767 for sample in [list, bytearray, deque]: 1768 self.assertIsInstance(sample(), MutableSequence) 1769 self.assertTrue(issubclass(sample, MutableSequence)) 1770 self.assertFalse(issubclass(str, MutableSequence)) 1771 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__', 1772 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') 1773 1774 def test_MutableSequence_mixins(self): 1775 # Test the mixins of MutableSequence by creating a minimal concrete 1776 # class inherited from it. 1777 class MutableSequenceSubclass(MutableSequence): 1778 def __init__(self): 1779 self.lst = [] 1780 1781 def __setitem__(self, index, value): 1782 self.lst[index] = value 1783 1784 def __getitem__(self, index): 1785 return self.lst[index] 1786 1787 def __len__(self): 1788 return len(self.lst) 1789 1790 def __delitem__(self, index): 1791 del self.lst[index] 1792 1793 def insert(self, index, value): 1794 self.lst.insert(index, value) 1795 1796 mss = MutableSequenceSubclass() 1797 mss.append(0) 1798 mss.extend((1, 2, 3, 4)) 1799 self.assertEqual(len(mss), 5) 1800 self.assertEqual(mss[3], 3) 1801 mss.reverse() 1802 self.assertEqual(mss[3], 1) 1803 mss.pop() 1804 self.assertEqual(len(mss), 4) 1805 mss.remove(3) 1806 self.assertEqual(len(mss), 3) 1807 mss += (10, 20, 30) 1808 self.assertEqual(len(mss), 6) 1809 self.assertEqual(mss[-1], 30) 1810 mss.clear() 1811 self.assertEqual(len(mss), 0) 1812 1813 # issue 34427 1814 # extending self should not cause infinite loop 1815 items = 'ABCD' 1816 mss2 = MutableSequenceSubclass() 1817 mss2.extend(items + items) 1818 mss.clear() 1819 mss.extend(items) 1820 mss.extend(mss) 1821 self.assertEqual(len(mss), len(mss2)) 1822 self.assertEqual(list(mss), list(mss2)) 1823 1824 1825################################################################################ 1826### Counter 1827################################################################################ 1828 1829class CounterSubclassWithSetItem(Counter): 1830 # Test a counter subclass that overrides __setitem__ 1831 def __init__(self, *args, **kwds): 1832 self.called = False 1833 Counter.__init__(self, *args, **kwds) 1834 def __setitem__(self, key, value): 1835 self.called = True 1836 Counter.__setitem__(self, key, value) 1837 1838class CounterSubclassWithGet(Counter): 1839 # Test a counter subclass that overrides get() 1840 def __init__(self, *args, **kwds): 1841 self.called = False 1842 Counter.__init__(self, *args, **kwds) 1843 def get(self, key, default): 1844 self.called = True 1845 return Counter.get(self, key, default) 1846 1847class TestCounter(unittest.TestCase): 1848 1849 def test_basics(self): 1850 c = Counter('abcaba') 1851 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1})) 1852 self.assertEqual(c, Counter(a=3, b=2, c=1)) 1853 self.assertIsInstance(c, dict) 1854 self.assertIsInstance(c, Mapping) 1855 self.assertTrue(issubclass(Counter, dict)) 1856 self.assertTrue(issubclass(Counter, Mapping)) 1857 self.assertEqual(len(c), 3) 1858 self.assertEqual(sum(c.values()), 6) 1859 self.assertEqual(list(c.values()), [3, 2, 1]) 1860 self.assertEqual(list(c.keys()), ['a', 'b', 'c']) 1861 self.assertEqual(list(c), ['a', 'b', 'c']) 1862 self.assertEqual(list(c.items()), 1863 [('a', 3), ('b', 2), ('c', 1)]) 1864 self.assertEqual(c['b'], 2) 1865 self.assertEqual(c['z'], 0) 1866 self.assertEqual(c.__contains__('c'), True) 1867 self.assertEqual(c.__contains__('z'), False) 1868 self.assertEqual(c.get('b', 10), 2) 1869 self.assertEqual(c.get('z', 10), 10) 1870 self.assertEqual(c, dict(a=3, b=2, c=1)) 1871 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})") 1872 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)]) 1873 for i in range(5): 1874 self.assertEqual(c.most_common(i), 1875 [('a', 3), ('b', 2), ('c', 1)][:i]) 1876 self.assertEqual(''.join(c.elements()), 'aaabbc') 1877 c['a'] += 1 # increment an existing value 1878 c['b'] -= 2 # sub existing value to zero 1879 del c['c'] # remove an entry 1880 del c['c'] # make sure that del doesn't raise KeyError 1881 c['d'] -= 2 # sub from a missing value 1882 c['e'] = -5 # directly assign a missing value 1883 c['f'] += 4 # add to a missing value 1884 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4)) 1885 self.assertEqual(''.join(c.elements()), 'aaaaffff') 1886 self.assertEqual(c.pop('f'), 4) 1887 self.assertNotIn('f', c) 1888 for i in range(3): 1889 elem, cnt = c.popitem() 1890 self.assertNotIn(elem, c) 1891 c.clear() 1892 self.assertEqual(c, {}) 1893 self.assertEqual(repr(c), 'Counter()') 1894 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc') 1895 self.assertRaises(TypeError, hash, c) 1896 c.update(dict(a=5, b=3)) 1897 c.update(c=1) 1898 c.update(Counter('a' * 50 + 'b' * 30)) 1899 c.update() # test case with no args 1900 c.__init__('a' * 500 + 'b' * 300) 1901 c.__init__('cdc') 1902 c.__init__() 1903 self.assertEqual(c, dict(a=555, b=333, c=3, d=1)) 1904 self.assertEqual(c.setdefault('d', 5), 1) 1905 self.assertEqual(c['d'], 1) 1906 self.assertEqual(c.setdefault('e', 5), 5) 1907 self.assertEqual(c['e'], 5) 1908 1909 def test_init(self): 1910 self.assertEqual(list(Counter(self=42).items()), [('self', 42)]) 1911 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)]) 1912 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)]) 1913 self.assertRaises(TypeError, Counter, 42) 1914 self.assertRaises(TypeError, Counter, (), ()) 1915 self.assertRaises(TypeError, Counter.__init__) 1916 1917 def test_order_preservation(self): 1918 # Input order dictates items() order 1919 self.assertEqual(list(Counter('abracadabra').items()), 1920 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]) 1921 # letters with same count: ^----------^ ^---------^ 1922 1923 # Verify retention of order even when all counts are equal 1924 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()), 1925 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)]) 1926 1927 # Input order dictates elements() order 1928 self.assertEqual(list(Counter('abracadabra simsalabim').elements()), 1929 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r', 1930 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l']) 1931 1932 # Math operations order first by the order encountered in the left 1933 # operand and then by the order encountered in the right operand. 1934 ps = 'aaabbcdddeefggghhijjjkkl' 1935 qs = 'abbcccdeefffhkkllllmmnno' 1936 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))} 1937 def correctly_ordered(seq): 1938 'Return true if the letters occur in the expected order' 1939 positions = [order[letter] for letter in seq] 1940 return positions == sorted(positions) 1941 1942 p, q = Counter(ps), Counter(qs) 1943 self.assertTrue(correctly_ordered(+p)) 1944 self.assertTrue(correctly_ordered(-p)) 1945 self.assertTrue(correctly_ordered(p + q)) 1946 self.assertTrue(correctly_ordered(p - q)) 1947 self.assertTrue(correctly_ordered(p | q)) 1948 self.assertTrue(correctly_ordered(p & q)) 1949 1950 p, q = Counter(ps), Counter(qs) 1951 p += q 1952 self.assertTrue(correctly_ordered(p)) 1953 1954 p, q = Counter(ps), Counter(qs) 1955 p -= q 1956 self.assertTrue(correctly_ordered(p)) 1957 1958 p, q = Counter(ps), Counter(qs) 1959 p |= q 1960 self.assertTrue(correctly_ordered(p)) 1961 1962 p, q = Counter(ps), Counter(qs) 1963 p &= q 1964 self.assertTrue(correctly_ordered(p)) 1965 1966 p, q = Counter(ps), Counter(qs) 1967 p.update(q) 1968 self.assertTrue(correctly_ordered(p)) 1969 1970 p, q = Counter(ps), Counter(qs) 1971 p.subtract(q) 1972 self.assertTrue(correctly_ordered(p)) 1973 1974 def test_update(self): 1975 c = Counter() 1976 c.update(self=42) 1977 self.assertEqual(list(c.items()), [('self', 42)]) 1978 c = Counter() 1979 c.update(iterable=42) 1980 self.assertEqual(list(c.items()), [('iterable', 42)]) 1981 c = Counter() 1982 c.update(iterable=None) 1983 self.assertEqual(list(c.items()), [('iterable', None)]) 1984 self.assertRaises(TypeError, Counter().update, 42) 1985 self.assertRaises(TypeError, Counter().update, {}, {}) 1986 self.assertRaises(TypeError, Counter.update) 1987 1988 def test_copying(self): 1989 # Check that counters are copyable, deepcopyable, picklable, and 1990 #have a repr/eval round-trip 1991 words = Counter('which witch had which witches wrist watch'.split()) 1992 def check(dup): 1993 msg = "\ncopy: %s\nwords: %s" % (dup, words) 1994 self.assertIsNot(dup, words, msg) 1995 self.assertEqual(dup, words) 1996 check(words.copy()) 1997 check(copy.copy(words)) 1998 check(copy.deepcopy(words)) 1999 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 2000 with self.subTest(proto=proto): 2001 check(pickle.loads(pickle.dumps(words, proto))) 2002 check(eval(repr(words))) 2003 update_test = Counter() 2004 update_test.update(words) 2005 check(update_test) 2006 check(Counter(words)) 2007 2008 def test_copy_subclass(self): 2009 class MyCounter(Counter): 2010 pass 2011 c = MyCounter('slartibartfast') 2012 d = c.copy() 2013 self.assertEqual(d, c) 2014 self.assertEqual(len(d), len(c)) 2015 self.assertEqual(type(d), type(c)) 2016 2017 def test_conversions(self): 2018 # Convert to: set, list, dict 2019 s = 'she sells sea shells by the sea shore' 2020 self.assertEqual(sorted(Counter(s).elements()), sorted(s)) 2021 self.assertEqual(sorted(Counter(s)), sorted(set(s))) 2022 self.assertEqual(dict(Counter(s)), dict(Counter(s).items())) 2023 self.assertEqual(set(Counter(s)), set(s)) 2024 2025 def test_invariant_for_the_in_operator(self): 2026 c = Counter(a=10, b=-2, c=0) 2027 for elem in c: 2028 self.assertTrue(elem in c) 2029 self.assertIn(elem, c) 2030 2031 def test_multiset_operations(self): 2032 # Verify that adding a zero counter will strip zeros and negatives 2033 c = Counter(a=10, b=-2, c=0) + Counter() 2034 self.assertEqual(dict(c), dict(a=10)) 2035 2036 elements = 'abcd' 2037 for i in range(1000): 2038 # test random pairs of multisets 2039 p = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2040 p.update(e=1, f=-1, g=0) 2041 q = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2042 q.update(h=1, i=-1, j=0) 2043 for counterop, numberop in [ 2044 (Counter.__add__, lambda x, y: max(0, x+y)), 2045 (Counter.__sub__, lambda x, y: max(0, x-y)), 2046 (Counter.__or__, lambda x, y: max(0,x,y)), 2047 (Counter.__and__, lambda x, y: max(0, min(x,y))), 2048 ]: 2049 result = counterop(p, q) 2050 for x in elements: 2051 self.assertEqual(numberop(p[x], q[x]), result[x], 2052 (counterop, x, p, q)) 2053 # verify that results exclude non-positive counts 2054 self.assertTrue(x>0 for x in result.values()) 2055 2056 elements = 'abcdef' 2057 for i in range(100): 2058 # verify that random multisets with no repeats are exactly like sets 2059 p = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 2060 q = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 2061 for counterop, setop in [ 2062 (Counter.__sub__, set.__sub__), 2063 (Counter.__or__, set.__or__), 2064 (Counter.__and__, set.__and__), 2065 ]: 2066 counter_result = counterop(p, q) 2067 set_result = setop(set(p.elements()), set(q.elements())) 2068 self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) 2069 2070 def test_inplace_operations(self): 2071 elements = 'abcd' 2072 for i in range(1000): 2073 # test random pairs of multisets 2074 p = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2075 p.update(e=1, f=-1, g=0) 2076 q = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2077 q.update(h=1, i=-1, j=0) 2078 for inplace_op, regular_op in [ 2079 (Counter.__iadd__, Counter.__add__), 2080 (Counter.__isub__, Counter.__sub__), 2081 (Counter.__ior__, Counter.__or__), 2082 (Counter.__iand__, Counter.__and__), 2083 ]: 2084 c = p.copy() 2085 c_id = id(c) 2086 regular_result = regular_op(c, q) 2087 inplace_result = inplace_op(c, q) 2088 self.assertEqual(inplace_result, regular_result) 2089 self.assertEqual(id(inplace_result), c_id) 2090 2091 def test_subtract(self): 2092 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2093 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50) 2094 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 2095 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2096 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)) 2097 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 2098 c = Counter('aaabbcd') 2099 c.subtract('aaaabbcce') 2100 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1)) 2101 2102 c = Counter() 2103 c.subtract(self=42) 2104 self.assertEqual(list(c.items()), [('self', -42)]) 2105 c = Counter() 2106 c.subtract(iterable=42) 2107 self.assertEqual(list(c.items()), [('iterable', -42)]) 2108 self.assertRaises(TypeError, Counter().subtract, 42) 2109 self.assertRaises(TypeError, Counter().subtract, {}, {}) 2110 self.assertRaises(TypeError, Counter.subtract) 2111 2112 def test_unary(self): 2113 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2114 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40)) 2115 self.assertEqual(dict(-c), dict(a=5)) 2116 2117 def test_repr_nonsortable(self): 2118 c = Counter(a=2, b=None) 2119 r = repr(c) 2120 self.assertIn("'a': 2", r) 2121 self.assertIn("'b': None", r) 2122 2123 def test_helper_function(self): 2124 # two paths, one for real dicts and one for other mappings 2125 elems = list('abracadabra') 2126 2127 d = dict() 2128 _count_elements(d, elems) 2129 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}) 2130 2131 m = OrderedDict() 2132 _count_elements(m, elems) 2133 self.assertEqual(m, 2134 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])) 2135 2136 # test fidelity to the pure python version 2137 c = CounterSubclassWithSetItem('abracadabra') 2138 self.assertTrue(c.called) 2139 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 }) 2140 c = CounterSubclassWithGet('abracadabra') 2141 self.assertTrue(c.called) 2142 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 }) 2143 2144 2145################################################################################ 2146### Run tests 2147################################################################################ 2148 2149def test_main(verbose=None): 2150 NamedTupleDocs = doctest.DocTestSuite(module=collections) 2151 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, 2152 TestCollectionABCs, TestCounter, TestChainMap, 2153 TestUserObjects, 2154 ] 2155 support.run_unittest(*test_classes) 2156 support.run_doctest(collections, verbose) 2157 2158 2159if __name__ == "__main__": 2160 test_main(verbose=True) 2161