1 2 import unittest, doctest, operator 3 import inspect 4 from test import test_support 5 from collections import namedtuple, Counter, OrderedDict 6 from test import mapping_tests 7 import pickle, cPickle, copy 8 from random import randrange, shuffle 9 import keyword 10 import re 11 import sys 12 from collections import Hashable, Iterable, Iterator 13 from collections import Sized, Container, Callable 14 from collections import Set, MutableSet 15 from collections import Mapping, MutableMapping 16 from collections import Sequence, MutableSequence 17 18 TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests 19 20 class TestNamedTuple(unittest.TestCase): 21 22 def test_factory(self): 23 Point = namedtuple('Point', 'x y') 24 self.assertEqual(Point.__name__, 'Point') 25 self.assertEqual(Point.__slots__, ()) 26 self.assertEqual(Point.__module__, __name__) 27 self.assertEqual(Point.__getitem__, tuple.__getitem__) 28 self.assertEqual(Point._fields, ('x', 'y')) 29 30 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char 31 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword 32 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit 33 34 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char 35 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword 36 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit 37 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore 38 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field 39 40 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names 41 namedtuple('_', 'a b c') # Test leading underscores in a typename 42 43 nt = namedtuple('nt', u'the quick brown fox') # check unicode input 44 self.assertNotIn("u'", repr(nt._fields)) 45 nt = namedtuple('nt', (u'the', u'quick')) # check unicode input 46 self.assertNotIn("u'", repr(nt._fields)) 47 48 self.assertRaises(TypeError, Point._make, [11]) # catch too few args 49 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args 50 51 @unittest.skipIf(sys.flags.optimize >= 2, 52 "Docstrings are omitted with -O2 and above") 53 def test_factory_doc_attr(self): 54 Point = namedtuple('Point', 'x y') 55 self.assertEqual(Point.__doc__, 'Point(x, y)') 56 57 def test_name_fixer(self): 58 for spec, renamed in [ 59 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char 60 [('abc', 'class'), ('abc', '_1')], # field has keyword 61 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit 62 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore 63 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field 64 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space 65 ]: 66 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed) 67 68 def test_instance(self): 69 Point = namedtuple('Point', 'x y') 70 p = Point(11, 22) 71 self.assertEqual(p, Point(x=11, y=22)) 72 self.assertEqual(p, Point(11, y=22)) 73 self.assertEqual(p, Point(y=22, x=11)) 74 self.assertEqual(p, Point(*(11, 22))) 75 self.assertEqual(p, Point(**dict(x=11, y=22))) 76 self.assertRaises(TypeError, Point, 1) # too few args 77 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args 78 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument 79 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument 80 self.assertEqual(repr(p), 'Point(x=11, y=22)') 81 self.assertNotIn('__dict__', dir(p)) # verify instance has no dict 82 self.assertNotIn('__weakref__', dir(p)) 83 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod 84 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute 85 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method 86 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method 87 88 try: 89 p._replace(x=1, error=2) 90 except ValueError: 91 pass 92 else: 93 self._fail('Did not detect an incorrect fieldname') 94 95 # verify that field string can have commas 96 Point = namedtuple('Point', 'x, y') 97 p = Point(x=11, y=22) 98 self.assertEqual(repr(p), 'Point(x=11, y=22)') 99 100 # verify that fieldspec can be a non-string sequence 101 Point = namedtuple('Point', ('x', 'y')) 102 p = Point(x=11, y=22) 103 self.assertEqual(repr(p), 'Point(x=11, y=22)') 104 105 def test_tupleness(self): 106 Point = namedtuple('Point', 'x y') 107 p = Point(11, 22) 108 109 self.assertIsInstance(p, tuple) 110 self.assertEqual(p, (11, 22)) # matches a real tuple 111 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple 112 self.assertEqual(list(p), [11, 22]) # coercable to a list 113 self.assertEqual(max(p), 22) # iterable 114 self.assertEqual(max(*p), 22) # star-able 115 x, y = p 116 self.assertEqual(p, (x, y)) # unpacks like a tuple 117 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple 118 self.assertRaises(IndexError, p.__getitem__, 3) 119 120 self.assertEqual(p.x, x) 121 self.assertEqual(p.y, y) 122 self.assertRaises(AttributeError, eval, 'p.z', locals()) 123 124 def test_odd_sizes(self): 125 Zero = namedtuple('Zero', '') 126 self.assertEqual(Zero(), ()) 127 self.assertEqual(Zero._make([]), ()) 128 self.assertEqual(repr(Zero()), 'Zero()') 129 self.assertEqual(Zero()._asdict(), {}) 130 self.assertEqual(Zero()._fields, ()) 131 132 Dot = namedtuple('Dot', 'd') 133 self.assertEqual(Dot(1), (1,)) 134 self.assertEqual(Dot._make([1]), (1,)) 135 self.assertEqual(Dot(1).d, 1) 136 self.assertEqual(repr(Dot(1)), 'Dot(d=1)') 137 self.assertEqual(Dot(1)._asdict(), {'d':1}) 138 self.assertEqual(Dot(1)._replace(d=999), (999,)) 139 self.assertEqual(Dot(1)._fields, ('d',)) 140 141 n = 5000 142 import string, random 143 names = list(set(''.join([random.choice(string.ascii_letters) 144 for j in range(10)]) for i in range(n))) 145 n = len(names) 146 Big = namedtuple('Big', names) 147 b = Big(*range(n)) 148 self.assertEqual(b, tuple(range(n))) 149 self.assertEqual(Big._make(range(n)), tuple(range(n))) 150 for pos, name in enumerate(names): 151 self.assertEqual(getattr(b, name), pos) 152 repr(b) # make sure repr() doesn't blow-up 153 d = b._asdict() 154 d_expected = dict(zip(names, range(n))) 155 self.assertEqual(d, d_expected) 156 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)])) 157 b2_expected = range(n) 158 b2_expected[1] = 999 159 b2_expected[-5] = 42 160 self.assertEqual(b2, tuple(b2_expected)) 161 self.assertEqual(b._fields, tuple(names)) 162 163 def test_pickle(self): 164 p = TestNT(x=10, y=20, z=30) 165 for module in pickle, cPickle: 166 loads = getattr(module, 'loads') 167 dumps = getattr(module, 'dumps') 168 for protocol in -1, 0, 1, 2: 169 q = loads(dumps(p, protocol)) 170 self.assertEqual(p, q) 171 self.assertEqual(p._fields, q._fields) 172 173 def test_copy(self): 174 p = TestNT(x=10, y=20, z=30) 175 for copier in copy.copy, copy.deepcopy: 176 q = copier(p) 177 self.assertEqual(p, q) 178 self.assertEqual(p._fields, q._fields) 179 180 def test_name_conflicts(self): 181 # Some names like "self", "cls", "tuple", "itemgetter", and "property" 182 # failed when used as field names. Test to make sure these now work. 183 T = namedtuple('T', 'itemgetter property self cls tuple') 184 t = T(1, 2, 3, 4, 5) 185 self.assertEqual(t, (1,2,3,4,5)) 186 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50) 187 self.assertEqual(newt, (10,20,30,40,50)) 188 189 # Broader test of all interesting names in a template 190 with test_support.captured_stdout() as template: 191 T = namedtuple('T', 'x', verbose=True) 192 words = set(re.findall('[A-Za-z]+', template.getvalue())) 193 words -= set(keyword.kwlist) 194 T = namedtuple('T', words) 195 # test __new__ 196 values = tuple(range(len(words))) 197 t = T(*values) 198 self.assertEqual(t, values) 199 t = T(**dict(zip(T._fields, values))) 200 self.assertEqual(t, values) 201 # test _make 202 t = T._make(values) 203 self.assertEqual(t, values) 204 # exercise __repr__ 205 repr(t) 206 # test _asdict 207 self.assertEqual(t._asdict(), dict(zip(T._fields, values))) 208 # test _replace 209 t = T._make(values) 210 newvalues = tuple(v*10 for v in values) 211 newt = t._replace(**dict(zip(T._fields, newvalues))) 212 self.assertEqual(newt, newvalues) 213 # test _fields 214 self.assertEqual(T._fields, tuple(words)) 215 # test __getnewargs__ 216 self.assertEqual(t.__getnewargs__(), values) 217 218 class ABCTestCase(unittest.TestCase): 219 220 def validate_abstract_methods(self, abc, *names): 221 methodstubs = dict.fromkeys(names, lambda s, *args: 0) 222 223 # everything should work will all required methods are present 224 C = type('C', (abc,), methodstubs) 225 C() 226 227 # instantiation should fail if a required method is missing 228 for name in names: 229 stubs = methodstubs.copy() 230 del stubs[name] 231 C = type('C', (abc,), stubs) 232 self.assertRaises(TypeError, C, name) 233 234 def validate_isinstance(self, abc, name): 235 stub = lambda s, *args: 0 236 237 # new-style class 238 C = type('C', (object,), {name: stub}) 239 self.assertIsInstance(C(), abc) 240 self.assertTrue(issubclass(C, abc)) 241 # old-style class 242 class C: pass 243 setattr(C, name, stub) 244 self.assertIsInstance(C(), abc) 245 self.assertTrue(issubclass(C, abc)) 246 247 # new-style class 248 C = type('C', (object,), {'__hash__': None}) 249 self.assertNotIsInstance(C(), abc) 250 self.assertFalse(issubclass(C, abc)) 251 # old-style class 252 class C: pass 253 self.assertNotIsInstance(C(), abc) 254 self.assertFalse(issubclass(C, abc)) 255 256 def validate_comparison(self, instance): 257 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub'] 258 operators = {} 259 for op in ops: 260 name = '__' + op + '__' 261 operators[name] = getattr(operator, name) 262 263 class Other: 264 def __init__(self): 265 self.right_side = False 266 def __eq__(self, other): 267 self.right_side = True 268 return True 269 __lt__ = __eq__ 270 __gt__ = __eq__ 271 __le__ = __eq__ 272 __ge__ = __eq__ 273 __ne__ = __eq__ 274 __ror__ = __eq__ 275 __rand__ = __eq__ 276 __rxor__ = __eq__ 277 __rsub__ = __eq__ 278 279 for name, op in operators.items(): 280 if not hasattr(instance, name): 281 continue 282 other = Other() 283 op(instance, other) 284 self.assertTrue(other.right_side,'Right side not called for %s.%s' 285 % (type(instance), name)) 286 287 class TestOneTrickPonyABCs(ABCTestCase): 288 289 def test_Hashable(self): 290 # Check some non-hashables 291 non_samples = [list(), set(), dict()] 292 for x in non_samples: 293 self.assertNotIsInstance(x, Hashable) 294 self.assertFalse(issubclass(type(x), Hashable), repr(type(x))) 295 # Check some hashables 296 samples = [None, 297 int(), float(), complex(), 298 str(), 299 tuple(), frozenset(), 300 int, list, object, type, 301 ] 302 for x in samples: 303 self.assertIsInstance(x, Hashable) 304 self.assertTrue(issubclass(type(x), Hashable), repr(type(x))) 305 self.assertRaises(TypeError, Hashable) 306 # Check direct subclassing 307 class H(Hashable): 308 def __hash__(self): 309 return super(H, self).__hash__() 310 __eq__ = Hashable.__eq__ # Silence Py3k warning 311 self.assertEqual(hash(H()), 0) 312 self.assertFalse(issubclass(int, H)) 313 self.validate_abstract_methods(Hashable, '__hash__') 314 self.validate_isinstance(Hashable, '__hash__') 315 316 def test_Iterable(self): 317 # Check some non-iterables 318 non_samples = [None, 42, 3.14, 1j] 319 for x in non_samples: 320 self.assertNotIsInstance(x, Iterable) 321 self.assertFalse(issubclass(type(x), Iterable), repr(type(x))) 322 # Check some iterables 323 samples = [str(), 324 tuple(), list(), set(), frozenset(), dict(), 325 dict().keys(), dict().items(), dict().values(), 326 (lambda: (yield))(), 327 (x for x in []), 328 ] 329 for x in samples: 330 self.assertIsInstance(x, Iterable) 331 self.assertTrue(issubclass(type(x), Iterable), repr(type(x))) 332 # Check direct subclassing 333 class I(Iterable): 334 def __iter__(self): 335 return super(I, self).__iter__() 336 self.assertEqual(list(I()), []) 337 self.assertFalse(issubclass(str, I)) 338 self.validate_abstract_methods(Iterable, '__iter__') 339 self.validate_isinstance(Iterable, '__iter__') 340 341 def test_Iterator(self): 342 non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [], 343 {}, set()] 344 for x in non_samples: 345 self.assertNotIsInstance(x, Iterator) 346 self.assertFalse(issubclass(type(x), Iterator), repr(type(x))) 347 samples = [iter(str()), 348 iter(tuple()), iter(list()), iter(dict()), 349 iter(set()), iter(frozenset()), 350 iter(dict().keys()), iter(dict().items()), 351 iter(dict().values()), 352 (lambda: (yield))(), 353 (x for x in []), 354 ] 355 for x in samples: 356 self.assertIsInstance(x, Iterator) 357 self.assertTrue(issubclass(type(x), Iterator), repr(type(x))) 358 self.validate_abstract_methods(Iterator, 'next', '__iter__') 359 360 # Issue 10565 361 class NextOnly: 362 def __next__(self): 363 yield 1 364 raise StopIteration 365 self.assertNotIsInstance(NextOnly(), Iterator) 366 class NextOnlyNew(object): 367 def __next__(self): 368 yield 1 369 raise StopIteration 370 self.assertNotIsInstance(NextOnlyNew(), Iterator) 371 372 def test_Sized(self): 373 non_samples = [None, 42, 3.14, 1j, 374 (lambda: (yield))(), 375 (x for x in []), 376 ] 377 for x in non_samples: 378 self.assertNotIsInstance(x, Sized) 379 self.assertFalse(issubclass(type(x), Sized), repr(type(x))) 380 samples = [str(), 381 tuple(), list(), set(), frozenset(), dict(), 382 dict().keys(), dict().items(), dict().values(), 383 ] 384 for x in samples: 385 self.assertIsInstance(x, Sized) 386 self.assertTrue(issubclass(type(x), Sized), repr(type(x))) 387 self.validate_abstract_methods(Sized, '__len__') 388 self.validate_isinstance(Sized, '__len__') 389 390 def test_Container(self): 391 non_samples = [None, 42, 3.14, 1j, 392 (lambda: (yield))(), 393 (x for x in []), 394 ] 395 for x in non_samples: 396 self.assertNotIsInstance(x, Container) 397 self.assertFalse(issubclass(type(x), Container), repr(type(x))) 398 samples = [str(), 399 tuple(), list(), set(), frozenset(), dict(), 400 dict().keys(), dict().items(), 401 ] 402 for x in samples: 403 self.assertIsInstance(x, Container) 404 self.assertTrue(issubclass(type(x), Container), repr(type(x))) 405 self.validate_abstract_methods(Container, '__contains__') 406 self.validate_isinstance(Container, '__contains__') 407 408 def test_Callable(self): 409 non_samples = [None, 42, 3.14, 1j, 410 "", "".encode('ascii'), (), [], {}, set(), 411 (lambda: (yield))(), 412 (x for x in []), 413 ] 414 for x in non_samples: 415 self.assertNotIsInstance(x, Callable) 416 self.assertFalse(issubclass(type(x), Callable), repr(type(x))) 417 samples = [lambda: None, 418 type, int, object, 419 len, 420 list.append, [].append, 421 ] 422 for x in samples: 423 self.assertIsInstance(x, Callable) 424 self.assertTrue(issubclass(type(x), Callable), repr(type(x))) 425 self.validate_abstract_methods(Callable, '__call__') 426 self.validate_isinstance(Callable, '__call__') 427 428 def test_direct_subclassing(self): 429 for B in Hashable, Iterable, Iterator, Sized, Container, Callable: 430 class C(B): 431 pass 432 self.assertTrue(issubclass(C, B)) 433 self.assertFalse(issubclass(int, C)) 434 435 def test_registration(self): 436 for B in Hashable, Iterable, Iterator, Sized, Container, Callable: 437 class C: 438 __metaclass__ = type 439 __hash__ = None # Make sure it isn't hashable by default 440 self.assertFalse(issubclass(C, B), B.__name__) 441 B.register(C) 442 self.assertTrue(issubclass(C, B)) 443 444 class WithSet(MutableSet): 445 446 def __init__(self, it=()): 447 self.data = set(it) 448 449 def __len__(self): 450 return len(self.data) 451 452 def __iter__(self): 453 return iter(self.data) 454 455 def __contains__(self, item): 456 return item in self.data 457 458 def add(self, item): 459 self.data.add(item) 460 461 def discard(self, item): 462 self.data.discard(item) 463 464 class TestCollectionABCs(ABCTestCase): 465 466 # XXX For now, we only test some virtual inheritance properties. 467 # We should also test the proper behavior of the collection ABCs 468 # as real base classes or mix-in classes. 469 470 def test_Set(self): 471 for sample in [set, frozenset]: 472 self.assertIsInstance(sample(), Set) 473 self.assertTrue(issubclass(sample, Set)) 474 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__') 475 class MySet(Set): 476 def __contains__(self, x): 477 return False 478 def __len__(self): 479 return 0 480 def __iter__(self): 481 return iter([]) 482 self.validate_comparison(MySet()) 483 484 def test_hash_Set(self): 485 class OneTwoThreeSet(Set): 486 def __init__(self): 487 self.contents = [1, 2, 3] 488 def __contains__(self, x): 489 return x in self.contents 490 def __len__(self): 491 return len(self.contents) 492 def __iter__(self): 493 return iter(self.contents) 494 def __hash__(self): 495 return self._hash() 496 a, b = OneTwoThreeSet(), OneTwoThreeSet() 497 self.assertTrue(hash(a) == hash(b)) 498 499 def test_MutableSet(self): 500 self.assertIsInstance(set(), MutableSet) 501 self.assertTrue(issubclass(set, MutableSet)) 502 self.assertNotIsInstance(frozenset(), MutableSet) 503 self.assertFalse(issubclass(frozenset, MutableSet)) 504 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__', 505 'add', 'discard') 506 507 def test_issue_5647(self): 508 # MutableSet.__iand__ mutated the set during iteration 509 s = WithSet('abcd') 510 s &= WithSet('cdef') # This used to fail 511 self.assertEqual(set(s), set('cd')) 512 513 def test_issue_4920(self): 514 # MutableSet.pop() method did not work 515 class MySet(collections.MutableSet): 516 __slots__=['__s'] 517 def __init__(self,items=None): 518 if items is None: 519 items=[] 520 self.__s=set(items) 521 def __contains__(self,v): 522 return v in self.__s 523 def __iter__(self): 524 return iter(self.__s) 525 def __len__(self): 526 return len(self.__s) 527 def add(self,v): 528 result=v not in self.__s 529 self.__s.add(v) 530 return result 531 def discard(self,v): 532 result=v in self.__s 533 self.__s.discard(v) 534 return result 535 def __repr__(self): 536 return "MySet(%s)" % repr(list(self)) 537 s = MySet([5,43,2,1]) 538 self.assertEqual(s.pop(), 1) 539 540 def test_issue8750(self): 541 empty = WithSet() 542 full = WithSet(range(10)) 543 s = WithSet(full) 544 s -= s 545 self.assertEqual(s, empty) 546 s = WithSet(full) 547 s ^= s 548 self.assertEqual(s, empty) 549 s = WithSet(full) 550 s &= s 551 self.assertEqual(s, full) 552 s |= s 553 self.assertEqual(s, full) 554 555 def test_Mapping(self): 556 for sample in [dict]: 557 self.assertIsInstance(sample(), Mapping) 558 self.assertTrue(issubclass(sample, Mapping)) 559 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__', 560 '__getitem__') 561 class MyMapping(collections.Mapping): 562 def __len__(self): 563 return 0 564 def __getitem__(self, i): 565 raise IndexError 566 def __iter__(self): 567 return iter(()) 568 self.validate_comparison(MyMapping()) 569 570 def test_MutableMapping(self): 571 for sample in [dict]: 572 self.assertIsInstance(sample(), MutableMapping) 573 self.assertTrue(issubclass(sample, MutableMapping)) 574 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__', 575 '__getitem__', '__setitem__', '__delitem__') 576 577 def test_Sequence(self): 578 for sample in [tuple, list, str]: 579 self.assertIsInstance(sample(), Sequence) 580 self.assertTrue(issubclass(sample, Sequence)) 581 self.assertTrue(issubclass(basestring, Sequence)) 582 self.assertIsInstance(range(10), Sequence) 583 self.assertTrue(issubclass(xrange, Sequence)) 584 self.assertTrue(issubclass(str, Sequence)) 585 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__', 586 '__getitem__') 587 588 def test_MutableSequence(self): 589 for sample in [tuple, str]: 590 self.assertNotIsInstance(sample(), MutableSequence) 591 self.assertFalse(issubclass(sample, MutableSequence)) 592 for sample in [list]: 593 self.assertIsInstance(sample(), MutableSequence) 594 self.assertTrue(issubclass(sample, MutableSequence)) 595 self.assertFalse(issubclass(basestring, MutableSequence)) 596 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__', 597 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert') 598 599 class TestCounter(unittest.TestCase): 600 601 def test_basics(self): 602 c = Counter('abcaba') 603 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1})) 604 self.assertEqual(c, Counter(a=3, b=2, c=1)) 605 self.assertIsInstance(c, dict) 606 self.assertIsInstance(c, Mapping) 607 self.assertTrue(issubclass(Counter, dict)) 608 self.assertTrue(issubclass(Counter, Mapping)) 609 self.assertEqual(len(c), 3) 610 self.assertEqual(sum(c.values()), 6) 611 self.assertEqual(sorted(c.values()), [1, 2, 3]) 612 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c']) 613 self.assertEqual(sorted(c), ['a', 'b', 'c']) 614 self.assertEqual(sorted(c.items()), 615 [('a', 3), ('b', 2), ('c', 1)]) 616 self.assertEqual(c['b'], 2) 617 self.assertEqual(c['z'], 0) 618 with test_support.check_py3k_warnings(): 619 self.assertEqual(c.has_key('c'), True) 620 self.assertEqual(c.has_key('z'), False) 621 self.assertEqual(c.__contains__('c'), True) 622 self.assertEqual(c.__contains__('z'), False) 623 self.assertEqual(c.get('b', 10), 2) 624 self.assertEqual(c.get('z', 10), 10) 625 self.assertEqual(c, dict(a=3, b=2, c=1)) 626 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})") 627 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)]) 628 for i in range(5): 629 self.assertEqual(c.most_common(i), 630 [('a', 3), ('b', 2), ('c', 1)][:i]) 631 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc') 632 c['a'] += 1 # increment an existing value 633 c['b'] -= 2 # sub existing value to zero 634 del c['c'] # remove an entry 635 del c['c'] # make sure that del doesn't raise KeyError 636 c['d'] -= 2 # sub from a missing value 637 c['e'] = -5 # directly assign a missing value 638 c['f'] += 4 # add to a missing value 639 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4)) 640 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff') 641 self.assertEqual(c.pop('f'), 4) 642 self.assertNotIn('f', c) 643 for i in range(3): 644 elem, cnt = c.popitem() 645 self.assertNotIn(elem, c) 646 c.clear() 647 self.assertEqual(c, {}) 648 self.assertEqual(repr(c), 'Counter()') 649 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc') 650 self.assertRaises(TypeError, hash, c) 651 c.update(dict(a=5, b=3)) 652 c.update(c=1) 653 c.update(Counter('a' * 50 + 'b' * 30)) 654 c.update() # test case with no args 655 c.__init__('a' * 500 + 'b' * 300) 656 c.__init__('cdc') 657 c.__init__() 658 self.assertEqual(c, dict(a=555, b=333, c=3, d=1)) 659 self.assertEqual(c.setdefault('d', 5), 1) 660 self.assertEqual(c['d'], 1) 661 self.assertEqual(c.setdefault('e', 5), 5) 662 self.assertEqual(c['e'], 5) 663 664 def test_copying(self): 665 # Check that counters are copyable, deepcopyable, picklable, and 666 #have a repr/eval round-trip 667 words = Counter('which witch had which witches wrist watch'.split()) 668 update_test = Counter() 669 update_test.update(words) 670 for i, dup in enumerate([ 671 words.copy(), 672 copy.copy(words), 673 copy.deepcopy(words), 674 pickle.loads(pickle.dumps(words, 0)), 675 pickle.loads(pickle.dumps(words, 1)), 676 pickle.loads(pickle.dumps(words, 2)), 677 pickle.loads(pickle.dumps(words, -1)), 678 cPickle.loads(cPickle.dumps(words, 0)), 679 cPickle.loads(cPickle.dumps(words, 1)), 680 cPickle.loads(cPickle.dumps(words, 2)), 681 cPickle.loads(cPickle.dumps(words, -1)), 682 eval(repr(words)), 683 update_test, 684 Counter(words), 685 ]): 686 msg = (i, dup, words) 687 self.assertTrue(dup is not words) 688 self.assertEqual(dup, words) 689 self.assertEqual(len(dup), len(words)) 690 self.assertEqual(type(dup), type(words)) 691 692 def test_copy_subclass(self): 693 class MyCounter(Counter): 694 pass 695 c = MyCounter('slartibartfast') 696 d = c.copy() 697 self.assertEqual(d, c) 698 self.assertEqual(len(d), len(c)) 699 self.assertEqual(type(d), type(c)) 700 701 def test_conversions(self): 702 # Convert to: set, list, dict 703 s = 'she sells sea shells by the sea shore' 704 self.assertEqual(sorted(Counter(s).elements()), sorted(s)) 705 self.assertEqual(sorted(Counter(s)), sorted(set(s))) 706 self.assertEqual(dict(Counter(s)), dict(Counter(s).items())) 707 self.assertEqual(set(Counter(s)), set(s)) 708 709 def test_invariant_for_the_in_operator(self): 710 c = Counter(a=10, b=-2, c=0) 711 for elem in c: 712 self.assertTrue(elem in c) 713 self.assertIn(elem, c) 714 715 def test_multiset_operations(self): 716 # Verify that adding a zero counter will strip zeros and negatives 717 c = Counter(a=10, b=-2, c=0) + Counter() 718 self.assertEqual(dict(c), dict(a=10)) 719 720 elements = 'abcd' 721 for i in range(1000): 722 # test random pairs of multisets 723 p = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 724 p.update(e=1, f=-1, g=0) 725 q = Counter(dict((elem, randrange(-2,4)) for elem in elements)) 726 q.update(h=1, i=-1, j=0) 727 for counterop, numberop in [ 728 (Counter.__add__, lambda x, y: max(0, x+y)), 729 (Counter.__sub__, lambda x, y: max(0, x-y)), 730 (Counter.__or__, lambda x, y: max(0,x,y)), 731 (Counter.__and__, lambda x, y: max(0, min(x,y))), 732 ]: 733 result = counterop(p, q) 734 for x in elements: 735 self.assertEqual(numberop(p[x], q[x]), result[x], 736 (counterop, x, p, q)) 737 # verify that results exclude non-positive counts 738 self.assertTrue(x>0 for x in result.values()) 739 740 elements = 'abcdef' 741 for i in range(100): 742 # verify that random multisets with no repeats are exactly like sets 743 p = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 744 q = Counter(dict((elem, randrange(0, 2)) for elem in elements)) 745 for counterop, setop in [ 746 (Counter.__sub__, set.__sub__), 747 (Counter.__or__, set.__or__), 748 (Counter.__and__, set.__and__), 749 ]: 750 counter_result = counterop(p, q) 751 set_result = setop(set(p.elements()), set(q.elements())) 752 self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) 753 754 def test_subtract(self): 755 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 756 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50) 757 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 758 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) 759 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)) 760 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) 761 c = Counter('aaabbcd') 762 c.subtract('aaaabbcce') 763 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1)) 764 765 class TestOrderedDict(unittest.TestCase): 766 767 def test_init(self): 768 with self.assertRaises(TypeError): 769 OrderedDict([('a', 1), ('b', 2)], None) # too many args 770 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] 771 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input 772 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input 773 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input 774 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)], 775 c=3, e=5).items()), pairs) # mixed input 776 777 # make sure no positional args conflict with possible kwdargs 778 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args, 779 ['self']) 780 781 # Make sure that direct calls to __init__ do not clear previous contents 782 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) 783 d.__init__([('e', 5), ('f', 6)], g=7, d=4) 784 self.assertEqual(list(d.items()), 785 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) 786 787 def test_update(self): 788 with self.assertRaises(TypeError): 789 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args 790 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] 791 od = OrderedDict() 792 od.update(dict(pairs)) 793 self.assertEqual(sorted(od.items()), pairs) # dict input 794 od = OrderedDict() 795 od.update(**dict(pairs)) 796 self.assertEqual(sorted(od.items()), pairs) # kwds input 797 od = OrderedDict() 798 od.update(pairs) 799 self.assertEqual(list(od.items()), pairs) # pairs input 800 od = OrderedDict() 801 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5) 802 self.assertEqual(list(od.items()), pairs) # mixed input 803 804 # Issue 9137: Named argument called 'other' or 'self' 805 # shouldn't be treated specially. 806 od = OrderedDict() 807 od.update(self=23) 808 self.assertEqual(list(od.items()), [('self', 23)]) 809 od = OrderedDict() 810 od.update(other={}) 811 self.assertEqual(list(od.items()), [('other', {})]) 812 od = OrderedDict() 813 od.update(red=5, blue=6, other=7, self=8) 814 self.assertEqual(sorted(list(od.items())), 815 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)]) 816 817 # Make sure that direct calls to update do not clear previous contents 818 # add that updates items are not moved to the end 819 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)]) 820 d.update([('e', 5), ('f', 6)], g=7, d=4) 821 self.assertEqual(list(d.items()), 822 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) 823 824 def test_abc(self): 825 self.assertIsInstance(OrderedDict(), MutableMapping) 826 self.assertTrue(issubclass(OrderedDict, MutableMapping)) 827 828 def test_clear(self): 829 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 830 shuffle(pairs) 831 od = OrderedDict(pairs) 832 self.assertEqual(len(od), len(pairs)) 833 od.clear() 834 self.assertEqual(len(od), 0) 835 836 def test_delitem(self): 837 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 838 od = OrderedDict(pairs) 839 del od['a'] 840 self.assertNotIn('a', od) 841 with self.assertRaises(KeyError): 842 del od['a'] 843 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:]) 844 845 def test_setitem(self): 846 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)]) 847 od['c'] = 10 # existing element 848 od['f'] = 20 # new element 849 self.assertEqual(list(od.items()), 850 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)]) 851 852 def test_iterators(self): 853 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 854 shuffle(pairs) 855 od = OrderedDict(pairs) 856 self.assertEqual(list(od), [t[0] for t in pairs]) 857 self.assertEqual(od.keys()[:], [t[0] for t in pairs]) 858 self.assertEqual(od.values()[:], [t[1] for t in pairs]) 859 self.assertEqual(od.items()[:], pairs) 860 self.assertEqual(list(od.iterkeys()), [t[0] for t in pairs]) 861 self.assertEqual(list(od.itervalues()), [t[1] for t in pairs]) 862 self.assertEqual(list(od.iteritems()), pairs) 863 self.assertEqual(list(reversed(od)), 864 [t[0] for t in reversed(pairs)]) 865 866 def test_popitem(self): 867 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 868 shuffle(pairs) 869 od = OrderedDict(pairs) 870 while pairs: 871 self.assertEqual(od.popitem(), pairs.pop()) 872 with self.assertRaises(KeyError): 873 od.popitem() 874 self.assertEqual(len(od), 0) 875 876 def test_pop(self): 877 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 878 shuffle(pairs) 879 od = OrderedDict(pairs) 880 shuffle(pairs) 881 while pairs: 882 k, v = pairs.pop() 883 self.assertEqual(od.pop(k), v) 884 with self.assertRaises(KeyError): 885 od.pop('xyz') 886 self.assertEqual(len(od), 0) 887 self.assertEqual(od.pop(k, 12345), 12345) 888 889 # make sure pop still works when __missing__ is defined 890 class Missing(OrderedDict): 891 def __missing__(self, key): 892 return 0 893 m = Missing(a=1) 894 self.assertEqual(m.pop('b', 5), 5) 895 self.assertEqual(m.pop('a', 6), 1) 896 self.assertEqual(m.pop('a', 6), 6) 897 with self.assertRaises(KeyError): 898 m.pop('a') 899 900 def test_equality(self): 901 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 902 shuffle(pairs) 903 od1 = OrderedDict(pairs) 904 od2 = OrderedDict(pairs) 905 self.assertEqual(od1, od2) # same order implies equality 906 pairs = pairs[2:] + pairs[:2] 907 od2 = OrderedDict(pairs) 908 self.assertNotEqual(od1, od2) # different order implies inequality 909 # comparison to regular dict is not order sensitive 910 self.assertEqual(od1, dict(od2)) 911 self.assertEqual(dict(od2), od1) 912 # different length implied inequality 913 self.assertNotEqual(od1, OrderedDict(pairs[:-1])) 914 915 def test_copying(self): 916 # Check that ordered dicts are copyable, deepcopyable, picklable, 917 # and have a repr/eval round-trip 918 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 919 od = OrderedDict(pairs) 920 update_test = OrderedDict() 921 update_test.update(od) 922 for i, dup in enumerate([ 923 od.copy(), 924 copy.copy(od), 925 copy.deepcopy(od), 926 pickle.loads(pickle.dumps(od, 0)), 927 pickle.loads(pickle.dumps(od, 1)), 928 pickle.loads(pickle.dumps(od, 2)), 929 pickle.loads(pickle.dumps(od, -1)), 930 eval(repr(od)), 931 update_test, 932 OrderedDict(od), 933 ]): 934 self.assertTrue(dup is not od) 935 self.assertEqual(dup, od) 936 self.assertEqual(list(dup.items()), list(od.items())) 937 self.assertEqual(len(dup), len(od)) 938 self.assertEqual(type(dup), type(od)) 939 940 def test_yaml_linkage(self): 941 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature. 942 # In yaml, lists are native but tuples are not. 943 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 944 od = OrderedDict(pairs) 945 # yaml.dump(od) --> 946 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n' 947 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1])) 948 949 def test_reduce_not_too_fat(self): 950 # do not save instance dictionary if not needed 951 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 952 od = OrderedDict(pairs) 953 self.assertEqual(len(od.__reduce__()), 2) 954 od.x = 10 955 self.assertEqual(len(od.__reduce__()), 3) 956 957 def test_repr(self): 958 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]) 959 self.assertEqual(repr(od), 960 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])") 961 self.assertEqual(eval(repr(od)), od) 962 self.assertEqual(repr(OrderedDict()), "OrderedDict()") 963 964 def test_repr_recursive(self): 965 # See issue #9826 966 od = OrderedDict.fromkeys('abc') 967 od['x'] = od 968 self.assertEqual(repr(od), 969 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])") 970 971 def test_setdefault(self): 972 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] 973 shuffle(pairs) 974 od = OrderedDict(pairs) 975 pair_order = list(od.items()) 976 self.assertEqual(od.setdefault('a', 10), 3) 977 # make sure order didn't change 978 self.assertEqual(list(od.items()), pair_order) 979 self.assertEqual(od.setdefault('x', 10), 10) 980 # make sure 'x' is added to the end 981 self.assertEqual(list(od.items())[-1], ('x', 10)) 982 983 # make sure setdefault still works when __missing__ is defined 984 class Missing(OrderedDict): 985 def __missing__(self, key): 986 return 0 987 self.assertEqual(Missing().setdefault(5, 9), 9) 988 989 def test_reinsert(self): 990 # Given insert a, insert b, delete a, re-insert a, 991 # verify that a is now later than b. 992 od = OrderedDict() 993 od['a'] = 1 994 od['b'] = 2 995 del od['a'] 996 od['a'] = 1 997 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)]) 998 999 def test_views(self): 1000 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split() 1001 od = OrderedDict.fromkeys(s) 1002 self.assertEqual(list(od.viewkeys()), s) 1003 self.assertEqual(list(od.viewvalues()), [None for k in s]) 1004 self.assertEqual(list(od.viewitems()), [(k, None) for k in s]) 1005 1006 def test_override_update(self): 1007 # Verify that subclasses can override update() without breaking __init__() 1008 class MyOD(OrderedDict): 1009 def update(self, *args, **kwds): 1010 raise Exception() 1011 items = [('a', 1), ('c', 3), ('b', 2)] 1012 self.assertEqual(list(MyOD(items).items()), items) 1013 1014 class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): 1015 type2test = OrderedDict 1016 1017 def test_popitem(self): 1018 d = self._empty_mapping() 1019 self.assertRaises(KeyError, d.popitem) 1020 1021 class MyOrderedDict(OrderedDict): 1022 pass 1023 1024 class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): 1025 type2test = MyOrderedDict 1026 1027 def test_popitem(self): 1028 d = self._empty_mapping() 1029 self.assertRaises(KeyError, d.popitem) 1030 1031 import collections 1032 1033 def test_main(verbose=None): 1034 NamedTupleDocs = doctest.DocTestSuite(module=collections) 1035 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs, 1036 TestCollectionABCs, TestCounter, 1037 TestOrderedDict, GeneralMappingTests, SubclassMappingTests] 1038 test_support.run_unittest(*test_classes) 1039 test_support.run_doctest(collections, verbose) 1040 1041 if __name__ == "__main__": 1042 test_main(verbose=True) 1043