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 def test_new_builtins_issue_43102(self): 684 self.assertEqual( 685 namedtuple('C', ()).__new__.__globals__['__builtins__'], 686 {}) 687 688 689################################################################################ 690### Abstract Base Classes 691################################################################################ 692 693class ABCTestCase(unittest.TestCase): 694 695 def validate_abstract_methods(self, abc, *names): 696 methodstubs = dict.fromkeys(names, lambda s, *args: 0) 697 698 # everything should work will all required methods are present 699 C = type('C', (abc,), methodstubs) 700 C() 701 702 # instantiation should fail if a required method is missing 703 for name in names: 704 stubs = methodstubs.copy() 705 del stubs[name] 706 C = type('C', (abc,), stubs) 707 self.assertRaises(TypeError, C, name) 708 709 def validate_isinstance(self, abc, name): 710 stub = lambda s, *args: 0 711 712 C = type('C', (object,), {'__hash__': None}) 713 setattr(C, name, stub) 714 self.assertIsInstance(C(), abc) 715 self.assertTrue(issubclass(C, abc)) 716 717 C = type('C', (object,), {'__hash__': None}) 718 self.assertNotIsInstance(C(), abc) 719 self.assertFalse(issubclass(C, abc)) 720 721 def validate_comparison(self, instance): 722 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub'] 723 operators = {} 724 for op in ops: 725 name = '__' + op + '__' 726 operators[name] = getattr(operator, name) 727 728 class Other: 729 def __init__(self): 730 self.right_side = False 731 def __eq__(self, other): 732 self.right_side = True 733 return True 734 __lt__ = __eq__ 735 __gt__ = __eq__ 736 __le__ = __eq__ 737 __ge__ = __eq__ 738 __ne__ = __eq__ 739 __ror__ = __eq__ 740 __rand__ = __eq__ 741 __rxor__ = __eq__ 742 __rsub__ = __eq__ 743 744 for name, op in operators.items(): 745 if not hasattr(instance, name): 746 continue 747 other = Other() 748 op(instance, other) 749 self.assertTrue(other.right_side,'Right side not called for %s.%s' 750 % (type(instance), name)) 751 752def _test_gen(): 753 yield 754 755class TestOneTrickPonyABCs(ABCTestCase): 756 757 def test_Awaitable(self): 758 def gen(): 759 yield 760 761 @types.coroutine 762 def coro(): 763 yield 764 765 async def new_coro(): 766 pass 767 768 class Bar: 769 def __await__(self): 770 yield 771 772 class MinimalCoro(Coroutine): 773 def send(self, value): 774 return value 775 def throw(self, typ, val=None, tb=None): 776 super().throw(typ, val, tb) 777 def __await__(self): 778 yield 779 780 non_samples = [None, int(), gen(), object()] 781 for x in non_samples: 782 self.assertNotIsInstance(x, Awaitable) 783 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x))) 784 785 samples = [Bar(), MinimalCoro()] 786 for x in samples: 787 self.assertIsInstance(x, Awaitable) 788 self.assertTrue(issubclass(type(x), Awaitable)) 789 790 c = coro() 791 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE 792 # flag don't have '__await__' method, hence can't be instances 793 # of Awaitable. Use inspect.isawaitable to detect them. 794 self.assertNotIsInstance(c, Awaitable) 795 796 c = new_coro() 797 self.assertIsInstance(c, Awaitable) 798 c.close() # avoid RuntimeWarning that coro() was not awaited 799 800 class CoroLike: pass 801 Coroutine.register(CoroLike) 802 self.assertTrue(isinstance(CoroLike(), Awaitable)) 803 self.assertTrue(issubclass(CoroLike, Awaitable)) 804 CoroLike = None 805 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache 806 807 def test_Coroutine(self): 808 def gen(): 809 yield 810 811 @types.coroutine 812 def coro(): 813 yield 814 815 async def new_coro(): 816 pass 817 818 class Bar: 819 def __await__(self): 820 yield 821 822 class MinimalCoro(Coroutine): 823 def send(self, value): 824 return value 825 def throw(self, typ, val=None, tb=None): 826 super().throw(typ, val, tb) 827 def __await__(self): 828 yield 829 830 non_samples = [None, int(), gen(), object(), Bar()] 831 for x in non_samples: 832 self.assertNotIsInstance(x, Coroutine) 833 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x))) 834 835 samples = [MinimalCoro()] 836 for x in samples: 837 self.assertIsInstance(x, Awaitable) 838 self.assertTrue(issubclass(type(x), Awaitable)) 839 840 c = coro() 841 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE 842 # flag don't have '__await__' method, hence can't be instances 843 # of Coroutine. Use inspect.isawaitable to detect them. 844 self.assertNotIsInstance(c, Coroutine) 845 846 c = new_coro() 847 self.assertIsInstance(c, Coroutine) 848 c.close() # avoid RuntimeWarning that coro() was not awaited 849 850 class CoroLike: 851 def send(self, value): 852 pass 853 def throw(self, typ, val=None, tb=None): 854 pass 855 def close(self): 856 pass 857 def __await__(self): 858 pass 859 self.assertTrue(isinstance(CoroLike(), Coroutine)) 860 self.assertTrue(issubclass(CoroLike, Coroutine)) 861 862 class CoroLike: 863 def send(self, value): 864 pass 865 def close(self): 866 pass 867 def __await__(self): 868 pass 869 self.assertFalse(isinstance(CoroLike(), Coroutine)) 870 self.assertFalse(issubclass(CoroLike, Coroutine)) 871 872 def test_Hashable(self): 873 # Check some non-hashables 874 non_samples = [bytearray(), list(), set(), dict()] 875 for x in non_samples: 876 self.assertNotIsInstance(x, Hashable) 877 self.assertFalse(issubclass(type(x), Hashable), repr(type(x))) 878 # Check some hashables 879 samples = [None, 880 int(), float(), complex(), 881 str(), 882 tuple(), frozenset(), 883 int, list, object, type, bytes() 884 ] 885 for x in samples: 886 self.assertIsInstance(x, Hashable) 887 self.assertTrue(issubclass(type(x), Hashable), repr(type(x))) 888 self.assertRaises(TypeError, Hashable) 889 # Check direct subclassing 890 class H(Hashable): 891 def __hash__(self): 892 return super().__hash__() 893 self.assertEqual(hash(H()), 0) 894 self.assertFalse(issubclass(int, H)) 895 self.validate_abstract_methods(Hashable, '__hash__') 896 self.validate_isinstance(Hashable, '__hash__') 897 898 def test_AsyncIterable(self): 899 class AI: 900 def __aiter__(self): 901 return self 902 self.assertTrue(isinstance(AI(), AsyncIterable)) 903 self.assertTrue(issubclass(AI, AsyncIterable)) 904 # Check some non-iterables 905 non_samples = [None, object, []] 906 for x in non_samples: 907 self.assertNotIsInstance(x, AsyncIterable) 908 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x))) 909 self.validate_abstract_methods(AsyncIterable, '__aiter__') 910 self.validate_isinstance(AsyncIterable, '__aiter__') 911 912 def test_AsyncIterator(self): 913 class AI: 914 def __aiter__(self): 915 return self 916 async def __anext__(self): 917 raise StopAsyncIteration 918 self.assertTrue(isinstance(AI(), AsyncIterator)) 919 self.assertTrue(issubclass(AI, AsyncIterator)) 920 non_samples = [None, object, []] 921 # Check some non-iterables 922 for x in non_samples: 923 self.assertNotIsInstance(x, AsyncIterator) 924 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x))) 925 # Similarly to regular iterators (see issue 10565) 926 class AnextOnly: 927 async def __anext__(self): 928 raise StopAsyncIteration 929 self.assertNotIsInstance(AnextOnly(), AsyncIterator) 930 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__') 931 932 def test_Iterable(self): 933 # Check some non-iterables 934 non_samples = [None, 42, 3.14, 1j] 935 for x in non_samples: 936 self.assertNotIsInstance(x, Iterable) 937 self.assertFalse(issubclass(type(x), Iterable), repr(type(x))) 938 # Check some iterables 939 samples = [bytes(), str(), 940 tuple(), list(), set(), frozenset(), dict(), 941 dict().keys(), dict().items(), dict().values(), 942 _test_gen(), 943 (x for x in []), 944 ] 945 for x in samples: 946 self.assertIsInstance(x, Iterable) 947 self.assertTrue(issubclass(type(x), Iterable), repr(type(x))) 948 # Check direct subclassing 949 class I(Iterable): 950 def __iter__(self): 951 return super().__iter__() 952 self.assertEqual(list(I()), []) 953 self.assertFalse(issubclass(str, I)) 954 self.validate_abstract_methods(Iterable, '__iter__') 955 self.validate_isinstance(Iterable, '__iter__') 956 # Check None blocking 957 class It: 958 def __iter__(self): return iter([]) 959 class ItBlocked(It): 960 __iter__ = None 961 self.assertTrue(issubclass(It, Iterable)) 962 self.assertTrue(isinstance(It(), Iterable)) 963 self.assertFalse(issubclass(ItBlocked, Iterable)) 964 self.assertFalse(isinstance(ItBlocked(), Iterable)) 965 966 def test_Reversible(self): 967 # Check some non-reversibles 968 non_samples = [None, 42, 3.14, 1j, set(), frozenset()] 969 for x in non_samples: 970 self.assertNotIsInstance(x, Reversible) 971 self.assertFalse(issubclass(type(x), Reversible), repr(type(x))) 972 # Check some non-reversible iterables 973 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])] 974 for x in non_reversibles: 975 self.assertNotIsInstance(x, Reversible) 976 self.assertFalse(issubclass(type(x), Reversible), repr(type(x))) 977 # Check some reversible iterables 978 samples = [bytes(), str(), tuple(), list(), OrderedDict(), 979 OrderedDict().keys(), OrderedDict().items(), 980 OrderedDict().values(), Counter(), Counter().keys(), 981 Counter().items(), Counter().values(), dict(), 982 dict().keys(), dict().items(), dict().values()] 983 for x in samples: 984 self.assertIsInstance(x, Reversible) 985 self.assertTrue(issubclass(type(x), Reversible), repr(type(x))) 986 # Check also Mapping, MutableMapping, and Sequence 987 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence)) 988 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping)) 989 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping)) 990 # Check direct subclassing 991 class R(Reversible): 992 def __iter__(self): 993 return iter(list()) 994 def __reversed__(self): 995 return iter(list()) 996 self.assertEqual(list(reversed(R())), []) 997 self.assertFalse(issubclass(float, R)) 998 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__') 999 # Check reversible non-iterable (which is not Reversible) 1000 class RevNoIter: 1001 def __reversed__(self): return reversed([]) 1002 class RevPlusIter(RevNoIter): 1003 def __iter__(self): return iter([]) 1004 self.assertFalse(issubclass(RevNoIter, Reversible)) 1005 self.assertFalse(isinstance(RevNoIter(), Reversible)) 1006 self.assertTrue(issubclass(RevPlusIter, Reversible)) 1007 self.assertTrue(isinstance(RevPlusIter(), Reversible)) 1008 # Check None blocking 1009 class Rev: 1010 def __iter__(self): return iter([]) 1011 def __reversed__(self): return reversed([]) 1012 class RevItBlocked(Rev): 1013 __iter__ = None 1014 class RevRevBlocked(Rev): 1015 __reversed__ = None 1016 self.assertTrue(issubclass(Rev, Reversible)) 1017 self.assertTrue(isinstance(Rev(), Reversible)) 1018 self.assertFalse(issubclass(RevItBlocked, Reversible)) 1019 self.assertFalse(isinstance(RevItBlocked(), Reversible)) 1020 self.assertFalse(issubclass(RevRevBlocked, Reversible)) 1021 self.assertFalse(isinstance(RevRevBlocked(), Reversible)) 1022 1023 def test_Collection(self): 1024 # Check some non-collections 1025 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x] 1026 for x in non_collections: 1027 self.assertNotIsInstance(x, Collection) 1028 self.assertFalse(issubclass(type(x), Collection), repr(type(x))) 1029 # Check some non-collection iterables 1030 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()), 1031 (x for x in [])] 1032 for x in non_col_iterables: 1033 self.assertNotIsInstance(x, Collection) 1034 self.assertFalse(issubclass(type(x), Collection), repr(type(x))) 1035 # Check some collections 1036 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(), 1037 list(), dict().keys(), dict().items(), dict().values()] 1038 for x in samples: 1039 self.assertIsInstance(x, Collection) 1040 self.assertTrue(issubclass(type(x), Collection), repr(type(x))) 1041 # Check also Mapping, MutableMapping, etc. 1042 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence)) 1043 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping)) 1044 self.assertTrue(issubclass(MutableMapping, Collection), 1045 repr(MutableMapping)) 1046 self.assertTrue(issubclass(Set, Collection), repr(Set)) 1047 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet)) 1048 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet)) 1049 # Check direct subclassing 1050 class Col(Collection): 1051 def __iter__(self): 1052 return iter(list()) 1053 def __len__(self): 1054 return 0 1055 def __contains__(self, item): 1056 return False 1057 class DerCol(Col): pass 1058 self.assertEqual(list(iter(Col())), []) 1059 self.assertFalse(issubclass(list, Col)) 1060 self.assertFalse(issubclass(set, Col)) 1061 self.assertFalse(issubclass(float, Col)) 1062 self.assertEqual(list(iter(DerCol())), []) 1063 self.assertFalse(issubclass(list, DerCol)) 1064 self.assertFalse(issubclass(set, DerCol)) 1065 self.assertFalse(issubclass(float, DerCol)) 1066 self.validate_abstract_methods(Collection, '__len__', '__iter__', 1067 '__contains__') 1068 # Check sized container non-iterable (which is not Collection) etc. 1069 class ColNoIter: 1070 def __len__(self): return 0 1071 def __contains__(self, item): return False 1072 class ColNoSize: 1073 def __iter__(self): return iter([]) 1074 def __contains__(self, item): return False 1075 class ColNoCont: 1076 def __iter__(self): return iter([]) 1077 def __len__(self): return 0 1078 self.assertFalse(issubclass(ColNoIter, Collection)) 1079 self.assertFalse(isinstance(ColNoIter(), Collection)) 1080 self.assertFalse(issubclass(ColNoSize, Collection)) 1081 self.assertFalse(isinstance(ColNoSize(), Collection)) 1082 self.assertFalse(issubclass(ColNoCont, Collection)) 1083 self.assertFalse(isinstance(ColNoCont(), Collection)) 1084 # Check None blocking 1085 class SizeBlock: 1086 def __iter__(self): return iter([]) 1087 def __contains__(self): return False 1088 __len__ = None 1089 class IterBlock: 1090 def __len__(self): return 0 1091 def __contains__(self): return True 1092 __iter__ = None 1093 self.assertFalse(issubclass(SizeBlock, Collection)) 1094 self.assertFalse(isinstance(SizeBlock(), Collection)) 1095 self.assertFalse(issubclass(IterBlock, Collection)) 1096 self.assertFalse(isinstance(IterBlock(), Collection)) 1097 # Check None blocking in subclass 1098 class ColImpl: 1099 def __iter__(self): 1100 return iter(list()) 1101 def __len__(self): 1102 return 0 1103 def __contains__(self, item): 1104 return False 1105 class NonCol(ColImpl): 1106 __contains__ = None 1107 self.assertFalse(issubclass(NonCol, Collection)) 1108 self.assertFalse(isinstance(NonCol(), Collection)) 1109 1110 1111 def test_Iterator(self): 1112 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()] 1113 for x in non_samples: 1114 self.assertNotIsInstance(x, Iterator) 1115 self.assertFalse(issubclass(type(x), Iterator), repr(type(x))) 1116 samples = [iter(bytes()), iter(str()), 1117 iter(tuple()), iter(list()), iter(dict()), 1118 iter(set()), iter(frozenset()), 1119 iter(dict().keys()), iter(dict().items()), 1120 iter(dict().values()), 1121 _test_gen(), 1122 (x for x in []), 1123 ] 1124 for x in samples: 1125 self.assertIsInstance(x, Iterator) 1126 self.assertTrue(issubclass(type(x), Iterator), repr(type(x))) 1127 self.validate_abstract_methods(Iterator, '__next__', '__iter__') 1128 1129 # Issue 10565 1130 class NextOnly: 1131 def __next__(self): 1132 yield 1 1133 return 1134 self.assertNotIsInstance(NextOnly(), Iterator) 1135 1136 def test_Generator(self): 1137 class NonGen1: 1138 def __iter__(self): return self 1139 def __next__(self): return None 1140 def close(self): pass 1141 def throw(self, typ, val=None, tb=None): pass 1142 1143 class NonGen2: 1144 def __iter__(self): return self 1145 def __next__(self): return None 1146 def close(self): pass 1147 def send(self, value): return value 1148 1149 class NonGen3: 1150 def close(self): pass 1151 def send(self, value): return value 1152 def throw(self, typ, val=None, tb=None): pass 1153 1154 non_samples = [ 1155 None, 42, 3.14, 1j, b"", "", (), [], {}, set(), 1156 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()] 1157 for x in non_samples: 1158 self.assertNotIsInstance(x, Generator) 1159 self.assertFalse(issubclass(type(x), Generator), repr(type(x))) 1160 1161 class Gen: 1162 def __iter__(self): return self 1163 def __next__(self): return None 1164 def close(self): pass 1165 def send(self, value): return value 1166 def throw(self, typ, val=None, tb=None): pass 1167 1168 class MinimalGen(Generator): 1169 def send(self, value): 1170 return value 1171 def throw(self, typ, val=None, tb=None): 1172 super().throw(typ, val, tb) 1173 1174 def gen(): 1175 yield 1 1176 1177 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()] 1178 for x in samples: 1179 self.assertIsInstance(x, Iterator) 1180 self.assertIsInstance(x, Generator) 1181 self.assertTrue(issubclass(type(x), Generator), repr(type(x))) 1182 self.validate_abstract_methods(Generator, 'send', 'throw') 1183 1184 # mixin tests 1185 mgen = MinimalGen() 1186 self.assertIs(mgen, iter(mgen)) 1187 self.assertIs(mgen.send(None), next(mgen)) 1188 self.assertEqual(2, mgen.send(2)) 1189 self.assertIsNone(mgen.close()) 1190 self.assertRaises(ValueError, mgen.throw, ValueError) 1191 self.assertRaisesRegex(ValueError, "^huhu$", 1192 mgen.throw, ValueError, ValueError("huhu")) 1193 self.assertRaises(StopIteration, mgen.throw, StopIteration()) 1194 1195 class FailOnClose(Generator): 1196 def send(self, value): return value 1197 def throw(self, *args): raise ValueError 1198 1199 self.assertRaises(ValueError, FailOnClose().close) 1200 1201 class IgnoreGeneratorExit(Generator): 1202 def send(self, value): return value 1203 def throw(self, *args): pass 1204 1205 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close) 1206 1207 def test_AsyncGenerator(self): 1208 class NonAGen1: 1209 def __aiter__(self): return self 1210 def __anext__(self): return None 1211 def aclose(self): pass 1212 def athrow(self, typ, val=None, tb=None): pass 1213 1214 class NonAGen2: 1215 def __aiter__(self): return self 1216 def __anext__(self): return None 1217 def aclose(self): pass 1218 def asend(self, value): return value 1219 1220 class NonAGen3: 1221 def aclose(self): pass 1222 def asend(self, value): return value 1223 def athrow(self, typ, val=None, tb=None): pass 1224 1225 non_samples = [ 1226 None, 42, 3.14, 1j, b"", "", (), [], {}, set(), 1227 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()] 1228 for x in non_samples: 1229 self.assertNotIsInstance(x, AsyncGenerator) 1230 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x))) 1231 1232 class Gen: 1233 def __aiter__(self): return self 1234 async def __anext__(self): return None 1235 async def aclose(self): pass 1236 async def asend(self, value): return value 1237 async def athrow(self, typ, val=None, tb=None): pass 1238 1239 class MinimalAGen(AsyncGenerator): 1240 async def asend(self, value): 1241 return value 1242 async def athrow(self, typ, val=None, tb=None): 1243 await super().athrow(typ, val, tb) 1244 1245 async def gen(): 1246 yield 1 1247 1248 samples = [gen(), Gen(), MinimalAGen()] 1249 for x in samples: 1250 self.assertIsInstance(x, AsyncIterator) 1251 self.assertIsInstance(x, AsyncGenerator) 1252 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x))) 1253 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow') 1254 1255 def run_async(coro): 1256 result = None 1257 while True: 1258 try: 1259 coro.send(None) 1260 except StopIteration as ex: 1261 result = ex.args[0] if ex.args else None 1262 break 1263 return result 1264 1265 # mixin tests 1266 mgen = MinimalAGen() 1267 self.assertIs(mgen, mgen.__aiter__()) 1268 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__())) 1269 self.assertEqual(2, run_async(mgen.asend(2))) 1270 self.assertIsNone(run_async(mgen.aclose())) 1271 with self.assertRaises(ValueError): 1272 run_async(mgen.athrow(ValueError)) 1273 1274 class FailOnClose(AsyncGenerator): 1275 async def asend(self, value): return value 1276 async def athrow(self, *args): raise ValueError 1277 1278 with self.assertRaises(ValueError): 1279 run_async(FailOnClose().aclose()) 1280 1281 class IgnoreGeneratorExit(AsyncGenerator): 1282 async def asend(self, value): return value 1283 async def athrow(self, *args): pass 1284 1285 with self.assertRaises(RuntimeError): 1286 run_async(IgnoreGeneratorExit().aclose()) 1287 1288 def test_Sized(self): 1289 non_samples = [None, 42, 3.14, 1j, 1290 _test_gen(), 1291 (x for x in []), 1292 ] 1293 for x in non_samples: 1294 self.assertNotIsInstance(x, Sized) 1295 self.assertFalse(issubclass(type(x), Sized), repr(type(x))) 1296 samples = [bytes(), str(), 1297 tuple(), list(), set(), frozenset(), dict(), 1298 dict().keys(), dict().items(), dict().values(), 1299 ] 1300 for x in samples: 1301 self.assertIsInstance(x, Sized) 1302 self.assertTrue(issubclass(type(x), Sized), repr(type(x))) 1303 self.validate_abstract_methods(Sized, '__len__') 1304 self.validate_isinstance(Sized, '__len__') 1305 1306 def test_Container(self): 1307 non_samples = [None, 42, 3.14, 1j, 1308 _test_gen(), 1309 (x for x in []), 1310 ] 1311 for x in non_samples: 1312 self.assertNotIsInstance(x, Container) 1313 self.assertFalse(issubclass(type(x), Container), repr(type(x))) 1314 samples = [bytes(), str(), 1315 tuple(), list(), set(), frozenset(), dict(), 1316 dict().keys(), dict().items(), 1317 ] 1318 for x in samples: 1319 self.assertIsInstance(x, Container) 1320 self.assertTrue(issubclass(type(x), Container), repr(type(x))) 1321 self.validate_abstract_methods(Container, '__contains__') 1322 self.validate_isinstance(Container, '__contains__') 1323 1324 def test_Callable(self): 1325 non_samples = [None, 42, 3.14, 1j, 1326 "", b"", (), [], {}, set(), 1327 _test_gen(), 1328 (x for x in []), 1329 ] 1330 for x in non_samples: 1331 self.assertNotIsInstance(x, Callable) 1332 self.assertFalse(issubclass(type(x), Callable), repr(type(x))) 1333 samples = [lambda: None, 1334 type, int, object, 1335 len, 1336 list.append, [].append, 1337 ] 1338 for x in samples: 1339 self.assertIsInstance(x, Callable) 1340 self.assertTrue(issubclass(type(x), Callable), repr(type(x))) 1341 self.validate_abstract_methods(Callable, '__call__') 1342 self.validate_isinstance(Callable, '__call__') 1343 1344 def test_direct_subclassing(self): 1345 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: 1346 class C(B): 1347 pass 1348 self.assertTrue(issubclass(C, B)) 1349 self.assertFalse(issubclass(int, C)) 1350 1351 def test_registration(self): 1352 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: 1353 class C: 1354 __hash__ = None # Make sure it isn't hashable by default 1355 self.assertFalse(issubclass(C, B), B.__name__) 1356 B.register(C) 1357 self.assertTrue(issubclass(C, B)) 1358 1359class WithSet(MutableSet): 1360 1361 def __init__(self, it=()): 1362 self.data = set(it) 1363 1364 def __len__(self): 1365 return len(self.data) 1366 1367 def __iter__(self): 1368 return iter(self.data) 1369 1370 def __contains__(self, item): 1371 return item in self.data 1372 1373 def add(self, item): 1374 self.data.add(item) 1375 1376 def discard(self, item): 1377 self.data.discard(item) 1378 1379class TestCollectionABCs(ABCTestCase): 1380 1381 # XXX For now, we only test some virtual inheritance properties. 1382 # We should also test the proper behavior of the collection ABCs 1383 # as real base classes or mix-in classes. 1384 1385 def test_Set(self): 1386 for sample in [set, frozenset]: 1387 self.assertIsInstance(sample(), Set) 1388 self.assertTrue(issubclass(sample, Set)) 1389 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__') 1390 class MySet(Set): 1391 def __contains__(self, x): 1392 return False 1393 def __len__(self): 1394 return 0 1395 def __iter__(self): 1396 return iter([]) 1397 self.validate_comparison(MySet()) 1398 1399 def test_hash_Set(self): 1400 class OneTwoThreeSet(Set): 1401 def __init__(self): 1402 self.contents = [1, 2, 3] 1403 def __contains__(self, x): 1404 return x in self.contents 1405 def __len__(self): 1406 return len(self.contents) 1407 def __iter__(self): 1408 return iter(self.contents) 1409 def __hash__(self): 1410 return self._hash() 1411 a, b = OneTwoThreeSet(), OneTwoThreeSet() 1412 self.assertTrue(hash(a) == hash(b)) 1413 1414 def test_isdisjoint_Set(self): 1415 class MySet(Set): 1416 def __init__(self, itr): 1417 self.contents = itr 1418 def __contains__(self, x): 1419 return x in self.contents 1420 def __iter__(self): 1421 return iter(self.contents) 1422 def __len__(self): 1423 return len([x for x in self.contents]) 1424 s1 = MySet((1, 2, 3)) 1425 s2 = MySet((4, 5, 6)) 1426 s3 = MySet((1, 5, 6)) 1427 self.assertTrue(s1.isdisjoint(s2)) 1428 self.assertFalse(s1.isdisjoint(s3)) 1429 1430 def test_equality_Set(self): 1431 class MySet(Set): 1432 def __init__(self, itr): 1433 self.contents = itr 1434 def __contains__(self, x): 1435 return x in self.contents 1436 def __iter__(self): 1437 return iter(self.contents) 1438 def __len__(self): 1439 return len([x for x in self.contents]) 1440 s1 = MySet((1,)) 1441 s2 = MySet((1, 2)) 1442 s3 = MySet((3, 4)) 1443 s4 = MySet((3, 4)) 1444 self.assertTrue(s2 > s1) 1445 self.assertTrue(s1 < s2) 1446 self.assertFalse(s2 <= s1) 1447 self.assertFalse(s2 <= s3) 1448 self.assertFalse(s1 >= s2) 1449 self.assertEqual(s3, s4) 1450 self.assertNotEqual(s2, s3) 1451 1452 def test_arithmetic_Set(self): 1453 class MySet(Set): 1454 def __init__(self, itr): 1455 self.contents = itr 1456 def __contains__(self, x): 1457 return x in self.contents 1458 def __iter__(self): 1459 return iter(self.contents) 1460 def __len__(self): 1461 return len([x for x in self.contents]) 1462 s1 = MySet((1, 2, 3)) 1463 s2 = MySet((3, 4, 5)) 1464 s3 = s1 & s2 1465 self.assertEqual(s3, MySet((3,))) 1466 1467 def test_MutableSet(self): 1468 self.assertIsInstance(set(), MutableSet) 1469 self.assertTrue(issubclass(set, MutableSet)) 1470 self.assertNotIsInstance(frozenset(), MutableSet) 1471 self.assertFalse(issubclass(frozenset, MutableSet)) 1472 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__', 1473 'add', 'discard') 1474 1475 def test_issue_5647(self): 1476 # MutableSet.__iand__ mutated the set during iteration 1477 s = WithSet('abcd') 1478 s &= WithSet('cdef') # This used to fail 1479 self.assertEqual(set(s), set('cd')) 1480 1481 def test_issue_4920(self): 1482 # MutableSet.pop() method did not work 1483 class MySet(MutableSet): 1484 __slots__=['__s'] 1485 def __init__(self,items=None): 1486 if items is None: 1487 items=[] 1488 self.__s=set(items) 1489 def __contains__(self,v): 1490 return v in self.__s 1491 def __iter__(self): 1492 return iter(self.__s) 1493 def __len__(self): 1494 return len(self.__s) 1495 def add(self,v): 1496 result=v not in self.__s 1497 self.__s.add(v) 1498 return result 1499 def discard(self,v): 1500 result=v in self.__s 1501 self.__s.discard(v) 1502 return result 1503 def __repr__(self): 1504 return "MySet(%s)" % repr(list(self)) 1505 s = MySet([5,43,2,1]) 1506 self.assertEqual(s.pop(), 1) 1507 1508 def test_issue8750(self): 1509 empty = WithSet() 1510 full = WithSet(range(10)) 1511 s = WithSet(full) 1512 s -= s 1513 self.assertEqual(s, empty) 1514 s = WithSet(full) 1515 s ^= s 1516 self.assertEqual(s, empty) 1517 s = WithSet(full) 1518 s &= s 1519 self.assertEqual(s, full) 1520 s |= s 1521 self.assertEqual(s, full) 1522 1523 def test_issue16373(self): 1524 # Recursion error comparing comparable and noncomparable 1525 # Set instances 1526 class MyComparableSet(Set): 1527 def __contains__(self, x): 1528 return False 1529 def __len__(self): 1530 return 0 1531 def __iter__(self): 1532 return iter([]) 1533 class MyNonComparableSet(Set): 1534 def __contains__(self, x): 1535 return False 1536 def __len__(self): 1537 return 0 1538 def __iter__(self): 1539 return iter([]) 1540 def __le__(self, x): 1541 return NotImplemented 1542 def __lt__(self, x): 1543 return NotImplemented 1544 1545 cs = MyComparableSet() 1546 ncs = MyNonComparableSet() 1547 self.assertFalse(ncs < cs) 1548 self.assertTrue(ncs <= cs) 1549 self.assertFalse(ncs > cs) 1550 self.assertTrue(ncs >= cs) 1551 1552 def test_issue26915(self): 1553 # Container membership test should check identity first 1554 class CustomSequence(Sequence): 1555 def __init__(self, seq): 1556 self._seq = seq 1557 def __getitem__(self, index): 1558 return self._seq[index] 1559 def __len__(self): 1560 return len(self._seq) 1561 1562 nan = float('nan') 1563 obj = support.NEVER_EQ 1564 seq = CustomSequence([nan, obj, nan]) 1565 containers = [ 1566 seq, 1567 ItemsView({1: nan, 2: obj}), 1568 ValuesView({1: nan, 2: obj}) 1569 ] 1570 for container in containers: 1571 for elem in container: 1572 self.assertIn(elem, container) 1573 self.assertEqual(seq.index(nan), 0) 1574 self.assertEqual(seq.index(obj), 1) 1575 self.assertEqual(seq.count(nan), 2) 1576 self.assertEqual(seq.count(obj), 1) 1577 1578 def assertSameSet(self, s1, s2): 1579 # coerce both to a real set then check equality 1580 self.assertSetEqual(set(s1), set(s2)) 1581 1582 def test_Set_from_iterable(self): 1583 """Verify _from_iterable overriden to an instance method works.""" 1584 class SetUsingInstanceFromIterable(MutableSet): 1585 def __init__(self, values, created_by): 1586 if not created_by: 1587 raise ValueError(f'created_by must be specified') 1588 self.created_by = created_by 1589 self._values = set(values) 1590 1591 def _from_iterable(self, values): 1592 return type(self)(values, 'from_iterable') 1593 1594 def __contains__(self, value): 1595 return value in self._values 1596 1597 def __iter__(self): 1598 yield from self._values 1599 1600 def __len__(self): 1601 return len(self._values) 1602 1603 def add(self, value): 1604 self._values.add(value) 1605 1606 def discard(self, value): 1607 self._values.discard(value) 1608 1609 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test') 1610 1611 actual = impl - {1} 1612 self.assertIsInstance(actual, SetUsingInstanceFromIterable) 1613 self.assertEqual('from_iterable', actual.created_by) 1614 self.assertEqual({2, 3}, actual) 1615 1616 actual = impl | {4} 1617 self.assertIsInstance(actual, SetUsingInstanceFromIterable) 1618 self.assertEqual('from_iterable', actual.created_by) 1619 self.assertEqual({1, 2, 3, 4}, actual) 1620 1621 actual = impl & {2} 1622 self.assertIsInstance(actual, SetUsingInstanceFromIterable) 1623 self.assertEqual('from_iterable', actual.created_by) 1624 self.assertEqual({2}, actual) 1625 1626 actual = impl ^ {3, 4} 1627 self.assertIsInstance(actual, SetUsingInstanceFromIterable) 1628 self.assertEqual('from_iterable', actual.created_by) 1629 self.assertEqual({1, 2, 4}, actual) 1630 1631 # NOTE: ixor'ing with a list is important here: internally, __ixor__ 1632 # only calls _from_iterable if the other value isn't already a Set. 1633 impl ^= [3, 4] 1634 self.assertIsInstance(impl, SetUsingInstanceFromIterable) 1635 self.assertEqual('test', impl.created_by) 1636 self.assertEqual({1, 2, 4}, impl) 1637 1638 def test_Set_interoperability_with_real_sets(self): 1639 # Issue: 8743 1640 class ListSet(Set): 1641 def __init__(self, elements=()): 1642 self.data = [] 1643 for elem in elements: 1644 if elem not in self.data: 1645 self.data.append(elem) 1646 def __contains__(self, elem): 1647 return elem in self.data 1648 def __iter__(self): 1649 return iter(self.data) 1650 def __len__(self): 1651 return len(self.data) 1652 def __repr__(self): 1653 return 'Set({!r})'.format(self.data) 1654 1655 r1 = set('abc') 1656 r2 = set('bcd') 1657 r3 = set('abcde') 1658 f1 = ListSet('abc') 1659 f2 = ListSet('bcd') 1660 f3 = ListSet('abcde') 1661 l1 = list('abccba') 1662 l2 = list('bcddcb') 1663 l3 = list('abcdeedcba') 1664 1665 target = r1 & r2 1666 self.assertSameSet(f1 & f2, target) 1667 self.assertSameSet(f1 & r2, target) 1668 self.assertSameSet(r2 & f1, target) 1669 self.assertSameSet(f1 & l2, target) 1670 1671 target = r1 | r2 1672 self.assertSameSet(f1 | f2, target) 1673 self.assertSameSet(f1 | r2, target) 1674 self.assertSameSet(r2 | f1, target) 1675 self.assertSameSet(f1 | l2, target) 1676 1677 fwd_target = r1 - r2 1678 rev_target = r2 - r1 1679 self.assertSameSet(f1 - f2, fwd_target) 1680 self.assertSameSet(f2 - f1, rev_target) 1681 self.assertSameSet(f1 - r2, fwd_target) 1682 self.assertSameSet(f2 - r1, rev_target) 1683 self.assertSameSet(r1 - f2, fwd_target) 1684 self.assertSameSet(r2 - f1, rev_target) 1685 self.assertSameSet(f1 - l2, fwd_target) 1686 self.assertSameSet(f2 - l1, rev_target) 1687 1688 target = r1 ^ r2 1689 self.assertSameSet(f1 ^ f2, target) 1690 self.assertSameSet(f1 ^ r2, target) 1691 self.assertSameSet(r2 ^ f1, target) 1692 self.assertSameSet(f1 ^ l2, target) 1693 1694 # Don't change the following to use assertLess or other 1695 # "more specific" unittest assertions. The current 1696 # assertTrue/assertFalse style makes the pattern of test 1697 # case combinations clear and allows us to know for sure 1698 # the exact operator being invoked. 1699 1700 # proper subset 1701 self.assertTrue(f1 < f3) 1702 self.assertFalse(f1 < f1) 1703 self.assertFalse(f1 < f2) 1704 self.assertTrue(r1 < f3) 1705 self.assertFalse(r1 < f1) 1706 self.assertFalse(r1 < f2) 1707 self.assertTrue(r1 < r3) 1708 self.assertFalse(r1 < r1) 1709 self.assertFalse(r1 < r2) 1710 with self.assertRaises(TypeError): 1711 f1 < l3 1712 with self.assertRaises(TypeError): 1713 f1 < l1 1714 with self.assertRaises(TypeError): 1715 f1 < l2 1716 1717 # any subset 1718 self.assertTrue(f1 <= f3) 1719 self.assertTrue(f1 <= f1) 1720 self.assertFalse(f1 <= f2) 1721 self.assertTrue(r1 <= f3) 1722 self.assertTrue(r1 <= f1) 1723 self.assertFalse(r1 <= f2) 1724 self.assertTrue(r1 <= r3) 1725 self.assertTrue(r1 <= r1) 1726 self.assertFalse(r1 <= r2) 1727 with self.assertRaises(TypeError): 1728 f1 <= l3 1729 with self.assertRaises(TypeError): 1730 f1 <= l1 1731 with self.assertRaises(TypeError): 1732 f1 <= l2 1733 1734 # proper superset 1735 self.assertTrue(f3 > f1) 1736 self.assertFalse(f1 > f1) 1737 self.assertFalse(f2 > f1) 1738 self.assertTrue(r3 > r1) 1739 self.assertFalse(f1 > r1) 1740 self.assertFalse(f2 > r1) 1741 self.assertTrue(r3 > r1) 1742 self.assertFalse(r1 > r1) 1743 self.assertFalse(r2 > r1) 1744 with self.assertRaises(TypeError): 1745 f1 > l3 1746 with self.assertRaises(TypeError): 1747 f1 > l1 1748 with self.assertRaises(TypeError): 1749 f1 > l2 1750 1751 # any superset 1752 self.assertTrue(f3 >= f1) 1753 self.assertTrue(f1 >= f1) 1754 self.assertFalse(f2 >= f1) 1755 self.assertTrue(r3 >= r1) 1756 self.assertTrue(f1 >= r1) 1757 self.assertFalse(f2 >= r1) 1758 self.assertTrue(r3 >= r1) 1759 self.assertTrue(r1 >= r1) 1760 self.assertFalse(r2 >= r1) 1761 with self.assertRaises(TypeError): 1762 f1 >= l3 1763 with self.assertRaises(TypeError): 1764 f1 >=l1 1765 with self.assertRaises(TypeError): 1766 f1 >= l2 1767 1768 # equality 1769 self.assertTrue(f1 == f1) 1770 self.assertTrue(r1 == f1) 1771 self.assertTrue(f1 == r1) 1772 self.assertFalse(f1 == f3) 1773 self.assertFalse(r1 == f3) 1774 self.assertFalse(f1 == r3) 1775 self.assertFalse(f1 == l3) 1776 self.assertFalse(f1 == l1) 1777 self.assertFalse(f1 == l2) 1778 1779 # inequality 1780 self.assertFalse(f1 != f1) 1781 self.assertFalse(r1 != f1) 1782 self.assertFalse(f1 != r1) 1783 self.assertTrue(f1 != f3) 1784 self.assertTrue(r1 != f3) 1785 self.assertTrue(f1 != r3) 1786 self.assertTrue(f1 != l3) 1787 self.assertTrue(f1 != l1) 1788 self.assertTrue(f1 != l2) 1789 1790 def test_Mapping(self): 1791 for sample in [dict]: 1792 self.assertIsInstance(sample(), Mapping) 1793 self.assertTrue(issubclass(sample, Mapping)) 1794 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__', 1795 '__getitem__') 1796 class MyMapping(Mapping): 1797 def __len__(self): 1798 return 0 1799 def __getitem__(self, i): 1800 raise IndexError 1801 def __iter__(self): 1802 return iter(()) 1803 self.validate_comparison(MyMapping()) 1804 self.assertRaises(TypeError, reversed, MyMapping()) 1805 1806 def test_MutableMapping(self): 1807 for sample in [dict]: 1808 self.assertIsInstance(sample(), MutableMapping) 1809 self.assertTrue(issubclass(sample, MutableMapping)) 1810 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__', 1811 '__getitem__', '__setitem__', '__delitem__') 1812 1813 def test_MutableMapping_subclass(self): 1814 # Test issue 9214 1815 mymap = UserDict() 1816 mymap['red'] = 5 1817 self.assertIsInstance(mymap.keys(), Set) 1818 self.assertIsInstance(mymap.keys(), KeysView) 1819 self.assertIsInstance(mymap.items(), Set) 1820 self.assertIsInstance(mymap.items(), ItemsView) 1821 1822 mymap = UserDict() 1823 mymap['red'] = 5 1824 z = mymap.keys() | {'orange'} 1825 self.assertIsInstance(z, set) 1826 list(z) 1827 mymap['blue'] = 7 # Shouldn't affect 'z' 1828 self.assertEqual(sorted(z), ['orange', 'red']) 1829 1830 mymap = UserDict() 1831 mymap['red'] = 5 1832 z = mymap.items() | {('orange', 3)} 1833 self.assertIsInstance(z, set) 1834 list(z) 1835 mymap['blue'] = 7 # Shouldn't affect 'z' 1836 self.assertEqual(z, {('orange', 3), ('red', 5)}) 1837 1838 def test_Sequence(self): 1839 for sample in [tuple, list, bytes, str]: 1840 self.assertIsInstance(sample(), Sequence) 1841 self.assertTrue(issubclass(sample, Sequence)) 1842 self.assertIsInstance(range(10), Sequence) 1843 self.assertTrue(issubclass(range, Sequence)) 1844 self.assertIsInstance(memoryview(b""), Sequence) 1845 self.assertTrue(issubclass(memoryview, Sequence)) 1846 self.assertTrue(issubclass(str, Sequence)) 1847 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__', 1848 '__getitem__') 1849 1850 def test_Sequence_mixins(self): 1851 class SequenceSubclass(Sequence): 1852 def __init__(self, seq=()): 1853 self.seq = seq 1854 1855 def __getitem__(self, index): 1856 return self.seq[index] 1857 1858 def __len__(self): 1859 return len(self.seq) 1860 1861 # Compare Sequence.index() behavior to (list|str).index() behavior 1862 def assert_index_same(seq1, seq2, index_args): 1863 try: 1864 expected = seq1.index(*index_args) 1865 except ValueError: 1866 with self.assertRaises(ValueError): 1867 seq2.index(*index_args) 1868 else: 1869 actual = seq2.index(*index_args) 1870 self.assertEqual( 1871 actual, expected, '%r.index%s' % (seq1, index_args)) 1872 1873 for ty in list, str: 1874 nativeseq = ty('abracadabra') 1875 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3)) 1876 seqseq = SequenceSubclass(nativeseq) 1877 for letter in set(nativeseq) | {'z'}: 1878 assert_index_same(nativeseq, seqseq, (letter,)) 1879 for start in range(-3, len(nativeseq) + 3): 1880 assert_index_same(nativeseq, seqseq, (letter, start)) 1881 for stop in range(-3, len(nativeseq) + 3): 1882 assert_index_same( 1883 nativeseq, seqseq, (letter, start, stop)) 1884 1885 def test_ByteString(self): 1886 for sample in [bytes, bytearray]: 1887 self.assertIsInstance(sample(), ByteString) 1888 self.assertTrue(issubclass(sample, ByteString)) 1889 for sample in [str, list, tuple]: 1890 self.assertNotIsInstance(sample(), ByteString) 1891 self.assertFalse(issubclass(sample, ByteString)) 1892 self.assertNotIsInstance(memoryview(b""), ByteString) 1893 self.assertFalse(issubclass(memoryview, ByteString)) 1894 1895 def test_MutableSequence(self): 1896 for sample in [tuple, str, bytes]: 1897 self.assertNotIsInstance(sample(), MutableSequence) 1898 self.assertFalse(issubclass(sample, MutableSequence)) 1899 for sample in [list, bytearray, deque]: 1900 self.assertIsInstance(sample(), MutableSequence) 1901 self.assertTrue(issubclass(sample, MutableSequence)) 1902 self.assertFalse(issubclass(str, MutableSequence)) 1903 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__', 1904 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') 1905 1906 def test_MutableSequence_mixins(self): 1907 # Test the mixins of MutableSequence by creating a minimal concrete 1908 # class inherited from it. 1909 class MutableSequenceSubclass(MutableSequence): 1910 def __init__(self): 1911 self.lst = [] 1912 1913 def __setitem__(self, index, value): 1914 self.lst[index] = value 1915 1916 def __getitem__(self, index): 1917 return self.lst[index] 1918 1919 def __len__(self): 1920 return len(self.lst) 1921 1922 def __delitem__(self, index): 1923 del self.lst[index] 1924 1925 def insert(self, index, value): 1926 self.lst.insert(index, value) 1927 1928 mss = MutableSequenceSubclass() 1929 mss.append(0) 1930 mss.extend((1, 2, 3, 4)) 1931 self.assertEqual(len(mss), 5) 1932 self.assertEqual(mss[3], 3) 1933 mss.reverse() 1934 self.assertEqual(mss[3], 1) 1935 mss.pop() 1936 self.assertEqual(len(mss), 4) 1937 mss.remove(3) 1938 self.assertEqual(len(mss), 3) 1939 mss += (10, 20, 30) 1940 self.assertEqual(len(mss), 6) 1941 self.assertEqual(mss[-1], 30) 1942 mss.clear() 1943 self.assertEqual(len(mss), 0) 1944 1945 # issue 34427 1946 # extending self should not cause infinite loop 1947 items = 'ABCD' 1948 mss2 = MutableSequenceSubclass() 1949 mss2.extend(items + items) 1950 mss.clear() 1951 mss.extend(items) 1952 mss.extend(mss) 1953 self.assertEqual(len(mss), len(mss2)) 1954 self.assertEqual(list(mss), list(mss2)) 1955 1956 1957################################################################################ 1958### Counter 1959################################################################################ 1960 1961class CounterSubclassWithSetItem(Counter): 1962 # Test a counter subclass that overrides __setitem__ 1963 def __init__(self, *args, **kwds): 1964 self.called = False 1965 Counter.__init__(self, *args, **kwds) 1966 def __setitem__(self, key, value): 1967 self.called = True 1968 Counter.__setitem__(self, key, value) 1969 1970class CounterSubclassWithGet(Counter): 1971 # Test a counter subclass that overrides get() 1972 def __init__(self, *args, **kwds): 1973 self.called = False 1974 Counter.__init__(self, *args, **kwds) 1975 def get(self, key, default): 1976 self.called = True 1977 return Counter.get(self, key, default) 1978 1979class TestCounter(unittest.TestCase): 1980 1981 def test_basics(self): 1982 c = Counter('abcaba') 1983 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1})) 1984 self.assertEqual(c, Counter(a=3, b=2, c=1)) 1985 self.assertIsInstance(c, dict) 1986 self.assertIsInstance(c, Mapping) 1987 self.assertTrue(issubclass(Counter, dict)) 1988 self.assertTrue(issubclass(Counter, Mapping)) 1989 self.assertEqual(len(c), 3) 1990 self.assertEqual(sum(c.values()), 6) 1991 self.assertEqual(list(c.values()), [3, 2, 1]) 1992 self.assertEqual(list(c.keys()), ['a', 'b', 'c']) 1993 self.assertEqual(list(c), ['a', 'b', 'c']) 1994 self.assertEqual(list(c.items()), 1995 [('a', 3), ('b', 2), ('c', 1)]) 1996 self.assertEqual(c['b'], 2) 1997 self.assertEqual(c['z'], 0) 1998 self.assertEqual(c.__contains__('c'), True) 1999 self.assertEqual(c.__contains__('z'), False) 2000 self.assertEqual(c.get('b', 10), 2) 2001 self.assertEqual(c.get('z', 10), 10) 2002 self.assertEqual(c, dict(a=3, b=2, c=1)) 2003 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})") 2004 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)]) 2005 for i in range(5): 2006 self.assertEqual(c.most_common(i), 2007 [('a', 3), ('b', 2), ('c', 1)][:i]) 2008 self.assertEqual(''.join(c.elements()), 'aaabbc') 2009 c['a'] += 1 # increment an existing value 2010 c['b'] -= 2 # sub existing value to zero 2011 del c['c'] # remove an entry 2012 del c['c'] # make sure that del doesn't raise KeyError 2013 c['d'] -= 2 # sub from a missing value 2014 c['e'] = -5 # directly assign a missing value 2015 c['f'] += 4 # add to a missing value 2016 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4)) 2017 self.assertEqual(''.join(c.elements()), 'aaaaffff') 2018 self.assertEqual(c.pop('f'), 4) 2019 self.assertNotIn('f', c) 2020 for i in range(3): 2021 elem, cnt = c.popitem() 2022 self.assertNotIn(elem, c) 2023 c.clear() 2024 self.assertEqual(c, {}) 2025 self.assertEqual(repr(c), 'Counter()') 2026 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc') 2027 self.assertRaises(TypeError, hash, c) 2028 c.update(dict(a=5, b=3)) 2029 c.update(c=1) 2030 c.update(Counter('a' * 50 + 'b' * 30)) 2031 c.update() # test case with no args 2032 c.__init__('a' * 500 + 'b' * 300) 2033 c.__init__('cdc') 2034 c.__init__() 2035 self.assertEqual(c, dict(a=555, b=333, c=3, d=1)) 2036 self.assertEqual(c.setdefault('d', 5), 1) 2037 self.assertEqual(c['d'], 1) 2038 self.assertEqual(c.setdefault('e', 5), 5) 2039 self.assertEqual(c['e'], 5) 2040 2041 def test_init(self): 2042 self.assertEqual(list(Counter(self=42).items()), [('self', 42)]) 2043 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)]) 2044 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)]) 2045 self.assertRaises(TypeError, Counter, 42) 2046 self.assertRaises(TypeError, Counter, (), ()) 2047 self.assertRaises(TypeError, Counter.__init__) 2048 2049 def test_order_preservation(self): 2050 # Input order dictates items() order 2051 self.assertEqual(list(Counter('abracadabra').items()), 2052 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]) 2053 # letters with same count: ^----------^ ^---------^ 2054 2055 # Verify retention of order even when all counts are equal 2056 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()), 2057 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)]) 2058 2059 # Input order dictates elements() order 2060 self.assertEqual(list(Counter('abracadabra simsalabim').elements()), 2061 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r', 2062 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l']) 2063 2064 # Math operations order first by the order encountered in the left 2065 # operand and then by the order encountered in the right operand. 2066 ps = 'aaabbcdddeefggghhijjjkkl' 2067 qs = 'abbcccdeefffhkkllllmmnno' 2068 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))} 2069 def correctly_ordered(seq): 2070 'Return true if the letters occur in the expected order' 2071 positions = [order[letter] for letter in seq] 2072 return positions == sorted(positions) 2073 2074 p, q = Counter(ps), Counter(qs) 2075 self.assertTrue(correctly_ordered(+p)) 2076 self.assertTrue(correctly_ordered(-p)) 2077 self.assertTrue(correctly_ordered(p + q)) 2078 self.assertTrue(correctly_ordered(p - q)) 2079 self.assertTrue(correctly_ordered(p | q)) 2080 self.assertTrue(correctly_ordered(p & q)) 2081 2082 p, q = Counter(ps), Counter(qs) 2083 p += q 2084 self.assertTrue(correctly_ordered(p)) 2085 2086 p, q = Counter(ps), Counter(qs) 2087 p -= q 2088 self.assertTrue(correctly_ordered(p)) 2089 2090 p, q = Counter(ps), Counter(qs) 2091 p |= q 2092 self.assertTrue(correctly_ordered(p)) 2093 2094 p, q = Counter(ps), Counter(qs) 2095 p &= q 2096 self.assertTrue(correctly_ordered(p)) 2097 2098 p, q = Counter(ps), Counter(qs) 2099 p.update(q) 2100 self.assertTrue(correctly_ordered(p)) 2101 2102 p, q = Counter(ps), Counter(qs) 2103 p.subtract(q) 2104 self.assertTrue(correctly_ordered(p)) 2105 2106 def test_update(self): 2107 c = Counter() 2108 c.update(self=42) 2109 self.assertEqual(list(c.items()), [('self', 42)]) 2110 c = Counter() 2111 c.update(iterable=42) 2112 self.assertEqual(list(c.items()), [('iterable', 42)]) 2113 c = Counter() 2114 c.update(iterable=None) 2115 self.assertEqual(list(c.items()), [('iterable', None)]) 2116 self.assertRaises(TypeError, Counter().update, 42) 2117 self.assertRaises(TypeError, Counter().update, {}, {}) 2118 self.assertRaises(TypeError, Counter.update) 2119 2120 def test_copying(self): 2121 # Check that counters are copyable, deepcopyable, picklable, and 2122 #have a repr/eval round-trip 2123 words = Counter('which witch had which witches wrist watch'.split()) 2124 def check(dup): 2125 msg = "\ncopy: %s\nwords: %s" % (dup, words) 2126 self.assertIsNot(dup, words, msg) 2127 self.assertEqual(dup, words) 2128 check(words.copy()) 2129 check(copy.copy(words)) 2130 check(copy.deepcopy(words)) 2131 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 2132 with self.subTest(proto=proto): 2133 check(pickle.loads(pickle.dumps(words, proto))) 2134 check(eval(repr(words))) 2135 update_test = Counter() 2136 update_test.update(words) 2137 check(update_test) 2138 check(Counter(words)) 2139 2140 def test_copy_subclass(self): 2141 class MyCounter(Counter): 2142 pass 2143 c = MyCounter('slartibartfast') 2144 d = c.copy() 2145 self.assertEqual(d, c) 2146 self.assertEqual(len(d), len(c)) 2147 self.assertEqual(type(d), type(c)) 2148 2149 def test_conversions(self): 2150 # Convert to: set, list, dict 2151 s = 'she sells sea shells by the sea shore' 2152 self.assertEqual(sorted(Counter(s).elements()), sorted(s)) 2153 self.assertEqual(sorted(Counter(s)), sorted(set(s))) 2154 self.assertEqual(dict(Counter(s)), dict(Counter(s).items())) 2155 self.assertEqual(set(Counter(s)), set(s)) 2156 2157 def test_invariant_for_the_in_operator(self): 2158 c = Counter(a=10, b=-2, c=0) 2159 for elem in c: 2160 self.assertTrue(elem in c) 2161 self.assertIn(elem, c) 2162 2163 def test_multiset_operations(self): 2164 # Verify that adding a zero counter will strip zeros and negatives 2165 c = Counter(a=10, b=-2, c=0) + Counter() 2166 self.assertEqual(dict(c), dict(a=10)) 2167 2168 elements = 'abcd' 2169 for i in range(1000): 2170 # test random pairs of multisets 2171 p = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2172 p.update(e=1, f=-1, g=0) 2173 q = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2174 q.update(h=1, i=-1, j=0) 2175 for counterop, numberop in [ 2176 (Counter.__add__, lambda x, y: max(0, x+y)), 2177 (Counter.__sub__, lambda x, y: max(0, x-y)), 2178 (Counter.__or__, lambda x, y: max(0,x,y)), 2179 (Counter.__and__, lambda x, y: max(0, min(x,y))), 2180 ]: 2181 result = counterop(p, q) 2182 for x in elements: 2183 self.assertEqual(numberop(p[x], q[x]), result[x], 2184 (counterop, x, p, q)) 2185 # verify that results exclude non-positive counts 2186 self.assertTrue(x>0 for x in result.values()) 2187 2188 elements = 'abcdef' 2189 for i in range(100): 2190 # verify that random multisets with no repeats are exactly like sets 2191 p = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 2192 q = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 2193 for counterop, setop in [ 2194 (Counter.__sub__, set.__sub__), 2195 (Counter.__or__, set.__or__), 2196 (Counter.__and__, set.__and__), 2197 ]: 2198 counter_result = counterop(p, q) 2199 set_result = setop(set(p.elements()), set(q.elements())) 2200 self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) 2201 2202 def test_subset_superset_not_implemented(self): 2203 # Verify that multiset comparison operations are not implemented. 2204 2205 # These operations were intentionally omitted because multiset 2206 # comparison semantics conflict with existing dict equality semantics. 2207 2208 # For multisets, we would expect that if p<=q and p>=q are both true, 2209 # then p==q. However, dict equality semantics require that p!=q when 2210 # one of sets contains an element with a zero count and the other 2211 # doesn't. 2212 2213 p = Counter(a=1, b=0) 2214 q = Counter(a=1, c=0) 2215 self.assertNotEqual(p, q) 2216 with self.assertRaises(TypeError): 2217 p < q 2218 with self.assertRaises(TypeError): 2219 p <= q 2220 with self.assertRaises(TypeError): 2221 p > q 2222 with self.assertRaises(TypeError): 2223 p >= q 2224 2225 def test_inplace_operations(self): 2226 elements = 'abcd' 2227 for i in range(1000): 2228 # test random pairs of multisets 2229 p = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2230 p.update(e=1, f=-1, g=0) 2231 q = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 2232 q.update(h=1, i=-1, j=0) 2233 for inplace_op, regular_op in [ 2234 (Counter.__iadd__, Counter.__add__), 2235 (Counter.__isub__, Counter.__sub__), 2236 (Counter.__ior__, Counter.__or__), 2237 (Counter.__iand__, Counter.__and__), 2238 ]: 2239 c = p.copy() 2240 c_id = id(c) 2241 regular_result = regular_op(c, q) 2242 inplace_result = inplace_op(c, q) 2243 self.assertEqual(inplace_result, regular_result) 2244 self.assertEqual(id(inplace_result), c_id) 2245 2246 def test_subtract(self): 2247 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2248 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50) 2249 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 2250 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2251 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)) 2252 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 2253 c = Counter('aaabbcd') 2254 c.subtract('aaaabbcce') 2255 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1)) 2256 2257 c = Counter() 2258 c.subtract(self=42) 2259 self.assertEqual(list(c.items()), [('self', -42)]) 2260 c = Counter() 2261 c.subtract(iterable=42) 2262 self.assertEqual(list(c.items()), [('iterable', -42)]) 2263 self.assertRaises(TypeError, Counter().subtract, 42) 2264 self.assertRaises(TypeError, Counter().subtract, {}, {}) 2265 self.assertRaises(TypeError, Counter.subtract) 2266 2267 def test_unary(self): 2268 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 2269 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40)) 2270 self.assertEqual(dict(-c), dict(a=5)) 2271 2272 def test_repr_nonsortable(self): 2273 c = Counter(a=2, b=None) 2274 r = repr(c) 2275 self.assertIn("'a': 2", r) 2276 self.assertIn("'b': None", r) 2277 2278 def test_helper_function(self): 2279 # two paths, one for real dicts and one for other mappings 2280 elems = list('abracadabra') 2281 2282 d = dict() 2283 _count_elements(d, elems) 2284 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}) 2285 2286 m = OrderedDict() 2287 _count_elements(m, elems) 2288 self.assertEqual(m, 2289 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])) 2290 2291 # test fidelity to the pure python version 2292 c = CounterSubclassWithSetItem('abracadabra') 2293 self.assertTrue(c.called) 2294 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 }) 2295 c = CounterSubclassWithGet('abracadabra') 2296 self.assertTrue(c.called) 2297 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 }) 2298 2299 2300################################################################################ 2301### Run tests 2302################################################################################ 2303 2304def test_main(verbose=None): 2305 NamedTupleDocs = doctest.DocTestSuite(module=collections) 2306 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, 2307 TestCollectionABCs, TestCounter, TestChainMap, 2308 TestUserObjects, 2309 ] 2310 support.run_unittest(*test_classes) 2311 support.run_doctest(collections, verbose) 2312 2313 2314if __name__ == "__main__": 2315 test_main(verbose=True) 2316