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