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