1import copy 2import sys 3 4from sqlalchemy import util, sql, exc, testing 5from sqlalchemy.testing import assert_raises, assert_raises_message, fixtures 6from sqlalchemy.testing import eq_, is_, ne_, fails_if, mock, expect_warnings 7from sqlalchemy.testing.util import picklers, gc_collect 8from sqlalchemy.util import classproperty, WeakSequence, get_callable_argspec 9from sqlalchemy.sql import column 10from sqlalchemy.util import langhelpers, compat 11import inspect 12 13 14class _KeyedTupleTest(object): 15 16 def _fixture(self, values, labels): 17 raise NotImplementedError() 18 19 def test_empty(self): 20 keyed_tuple = self._fixture([], []) 21 eq_(str(keyed_tuple), '()') 22 eq_(len(keyed_tuple), 0) 23 24 eq_(list(keyed_tuple.keys()), []) 25 eq_(keyed_tuple._fields, ()) 26 eq_(keyed_tuple._asdict(), {}) 27 28 def test_values_but_no_labels(self): 29 keyed_tuple = self._fixture([1, 2], []) 30 eq_(str(keyed_tuple), '(1, 2)') 31 eq_(len(keyed_tuple), 2) 32 33 eq_(list(keyed_tuple.keys()), []) 34 eq_(keyed_tuple._fields, ()) 35 eq_(keyed_tuple._asdict(), {}) 36 37 eq_(keyed_tuple[0], 1) 38 eq_(keyed_tuple[1], 2) 39 40 def test_basic_creation(self): 41 keyed_tuple = self._fixture([1, 2], ['a', 'b']) 42 eq_(str(keyed_tuple), '(1, 2)') 43 eq_(list(keyed_tuple.keys()), ['a', 'b']) 44 eq_(keyed_tuple._fields, ('a', 'b')) 45 eq_(keyed_tuple._asdict(), {'a': 1, 'b': 2}) 46 47 def test_basic_index_access(self): 48 keyed_tuple = self._fixture([1, 2], ['a', 'b']) 49 eq_(keyed_tuple[0], 1) 50 eq_(keyed_tuple[1], 2) 51 52 def should_raise(): 53 keyed_tuple[2] 54 assert_raises(IndexError, should_raise) 55 56 def test_basic_attribute_access(self): 57 keyed_tuple = self._fixture([1, 2], ['a', 'b']) 58 eq_(keyed_tuple.a, 1) 59 eq_(keyed_tuple.b, 2) 60 61 def should_raise(): 62 keyed_tuple.c 63 assert_raises(AttributeError, should_raise) 64 65 def test_none_label(self): 66 keyed_tuple = self._fixture([1, 2, 3], ['a', None, 'b']) 67 eq_(str(keyed_tuple), '(1, 2, 3)') 68 69 eq_(list(keyed_tuple.keys()), ['a', 'b']) 70 eq_(keyed_tuple._fields, ('a', 'b')) 71 eq_(keyed_tuple._asdict(), {'a': 1, 'b': 3}) 72 73 # attribute access: can't get at value 2 74 eq_(keyed_tuple.a, 1) 75 eq_(keyed_tuple.b, 3) 76 77 # index access: can get at value 2 78 eq_(keyed_tuple[0], 1) 79 eq_(keyed_tuple[1], 2) 80 eq_(keyed_tuple[2], 3) 81 82 def test_duplicate_labels(self): 83 keyed_tuple = self._fixture([1, 2, 3], ['a', 'b', 'b']) 84 eq_(str(keyed_tuple), '(1, 2, 3)') 85 86 eq_(list(keyed_tuple.keys()), ['a', 'b', 'b']) 87 eq_(keyed_tuple._fields, ('a', 'b', 'b')) 88 eq_(keyed_tuple._asdict(), {'a': 1, 'b': 3}) 89 90 # attribute access: can't get at value 2 91 eq_(keyed_tuple.a, 1) 92 eq_(keyed_tuple.b, 3) 93 94 # index access: can get at value 2 95 eq_(keyed_tuple[0], 1) 96 eq_(keyed_tuple[1], 2) 97 eq_(keyed_tuple[2], 3) 98 99 def test_immutable(self): 100 keyed_tuple = self._fixture([1, 2], ['a', 'b']) 101 eq_(str(keyed_tuple), '(1, 2)') 102 103 eq_(keyed_tuple.a, 1) 104 105 assert_raises(AttributeError, setattr, keyed_tuple, "a", 5) 106 107 def should_raise(): 108 keyed_tuple[0] = 100 109 assert_raises(TypeError, should_raise) 110 111 def test_serialize(self): 112 113 keyed_tuple = self._fixture([1, 2, 3], ['a', None, 'b']) 114 115 for loads, dumps in picklers(): 116 kt = loads(dumps(keyed_tuple)) 117 118 eq_(str(kt), '(1, 2, 3)') 119 120 eq_(list(kt.keys()), ['a', 'b']) 121 eq_(kt._fields, ('a', 'b')) 122 eq_(kt._asdict(), {'a': 1, 'b': 3}) 123 124 125class KeyedTupleTest(_KeyedTupleTest, fixtures.TestBase): 126 def _fixture(self, values, labels): 127 return util.KeyedTuple(values, labels) 128 129 130class LWKeyedTupleTest(_KeyedTupleTest, fixtures.TestBase): 131 def _fixture(self, values, labels): 132 return util.lightweight_named_tuple('n', labels)(values) 133 134 135class WeakSequenceTest(fixtures.TestBase): 136 @testing.requires.predictable_gc 137 def test_cleanout_elements(self): 138 class Foo(object): 139 pass 140 f1, f2, f3 = Foo(), Foo(), Foo() 141 w = WeakSequence([f1, f2, f3]) 142 eq_(len(w), 3) 143 eq_(len(w._storage), 3) 144 del f2 145 gc_collect() 146 eq_(len(w), 2) 147 eq_(len(w._storage), 2) 148 149 @testing.requires.predictable_gc 150 def test_cleanout_appended(self): 151 class Foo(object): 152 pass 153 f1, f2, f3 = Foo(), Foo(), Foo() 154 w = WeakSequence() 155 w.append(f1) 156 w.append(f2) 157 w.append(f3) 158 eq_(len(w), 3) 159 eq_(len(w._storage), 3) 160 del f2 161 gc_collect() 162 eq_(len(w), 2) 163 eq_(len(w._storage), 2) 164 165 166class OrderedDictTest(fixtures.TestBase): 167 168 def test_odict(self): 169 o = util.OrderedDict() 170 o['a'] = 1 171 o['b'] = 2 172 o['snack'] = 'attack' 173 o['c'] = 3 174 175 eq_(list(o.keys()), ['a', 'b', 'snack', 'c']) 176 eq_(list(o.values()), [1, 2, 'attack', 3]) 177 178 o.pop('snack') 179 eq_(list(o.keys()), ['a', 'b', 'c']) 180 eq_(list(o.values()), [1, 2, 3]) 181 182 try: 183 o.pop('eep') 184 assert False 185 except KeyError: 186 pass 187 188 eq_(o.pop('eep', 'woot'), 'woot') 189 190 try: 191 o.pop('whiff', 'bang', 'pow') 192 assert False 193 except TypeError: 194 pass 195 196 eq_(list(o.keys()), ['a', 'b', 'c']) 197 eq_(list(o.values()), [1, 2, 3]) 198 199 o2 = util.OrderedDict(d=4) 200 o2['e'] = 5 201 202 eq_(list(o2.keys()), ['d', 'e']) 203 eq_(list(o2.values()), [4, 5]) 204 205 o.update(o2) 206 eq_(list(o.keys()), ['a', 'b', 'c', 'd', 'e']) 207 eq_(list(o.values()), [1, 2, 3, 4, 5]) 208 209 o.setdefault('c', 'zzz') 210 o.setdefault('f', 6) 211 eq_(list(o.keys()), ['a', 'b', 'c', 'd', 'e', 'f']) 212 eq_(list(o.values()), [1, 2, 3, 4, 5, 6]) 213 214 def test_odict_constructor(self): 215 o = util.OrderedDict([('name', 'jbe'), 216 ('fullname', 'jonathan'), ('password', '')]) 217 eq_(list(o.keys()), ['name', 'fullname', 'password']) 218 219 def test_odict_copy(self): 220 o = util.OrderedDict() 221 o["zzz"] = 1 222 o["aaa"] = 2 223 eq_(list(o.keys()), ['zzz', 'aaa']) 224 225 o2 = o.copy() 226 eq_(list(o2.keys()), list(o.keys())) 227 228 o3 = copy.copy(o) 229 eq_(list(o3.keys()), list(o.keys())) 230 231 232class OrderedSetTest(fixtures.TestBase): 233 234 def test_mutators_against_iter(self): 235 # testing a set modified against an iterator 236 o = util.OrderedSet([3, 2, 4, 5]) 237 238 eq_(o.difference(iter([3, 4])), util.OrderedSet([2, 5])) 239 eq_(o.intersection(iter([3, 4, 6])), util.OrderedSet([3, 4])) 240 eq_(o.union(iter([3, 4, 6])), util.OrderedSet([2, 3, 4, 5, 6])) 241 242 243class FrozenDictTest(fixtures.TestBase): 244 245 def test_serialize(self): 246 d = util.immutabledict({1: 2, 3: 4}) 247 for loads, dumps in picklers(): 248 print(loads(dumps(d))) 249 250 251class MemoizedAttrTest(fixtures.TestBase): 252 253 def test_memoized_property(self): 254 val = [20] 255 256 class Foo(object): 257 @util.memoized_property 258 def bar(self): 259 v = val[0] 260 val[0] += 1 261 return v 262 263 ne_(Foo.bar, None) 264 f1 = Foo() 265 assert 'bar' not in f1.__dict__ 266 eq_(f1.bar, 20) 267 eq_(f1.bar, 20) 268 eq_(val[0], 21) 269 eq_(f1.__dict__['bar'], 20) 270 271 def test_memoized_instancemethod(self): 272 val = [20] 273 274 class Foo(object): 275 @util.memoized_instancemethod 276 def bar(self): 277 v = val[0] 278 val[0] += 1 279 return v 280 281 assert inspect.ismethod(Foo().bar) 282 ne_(Foo.bar, None) 283 f1 = Foo() 284 assert 'bar' not in f1.__dict__ 285 eq_(f1.bar(), 20) 286 eq_(f1.bar(), 20) 287 eq_(val[0], 21) 288 289 def test_memoized_slots(self): 290 canary = mock.Mock() 291 292 class Foob(util.MemoizedSlots): 293 __slots__ = ('foo_bar', 'gogo') 294 295 def _memoized_method_gogo(self): 296 canary.method() 297 return "gogo" 298 299 def _memoized_attr_foo_bar(self): 300 canary.attr() 301 return "foobar" 302 303 f1 = Foob() 304 assert_raises(AttributeError, setattr, f1, "bar", "bat") 305 306 eq_(f1.foo_bar, "foobar") 307 308 eq_(f1.foo_bar, "foobar") 309 310 eq_(f1.gogo(), "gogo") 311 312 eq_(f1.gogo(), "gogo") 313 314 eq_(canary.mock_calls, [mock.call.attr(), mock.call.method()]) 315 316 317class WrapCallableTest(fixtures.TestBase): 318 def test_wrapping_update_wrapper_fn(self): 319 def my_fancy_default(): 320 """run the fancy default""" 321 return 10 322 323 c = util.wrap_callable(lambda: my_fancy_default, my_fancy_default) 324 325 eq_(c.__name__, "my_fancy_default") 326 eq_(c.__doc__, "run the fancy default") 327 328 def test_wrapping_update_wrapper_fn_nodocstring(self): 329 def my_fancy_default(): 330 return 10 331 332 c = util.wrap_callable(lambda: my_fancy_default, my_fancy_default) 333 eq_(c.__name__, "my_fancy_default") 334 eq_(c.__doc__, None) 335 336 def test_wrapping_update_wrapper_cls(self): 337 class MyFancyDefault(object): 338 """a fancy default""" 339 340 def __call__(self): 341 """run the fancy default""" 342 return 10 343 344 def_ = MyFancyDefault() 345 c = util.wrap_callable(lambda: def_(), def_) 346 347 eq_(c.__name__, "MyFancyDefault") 348 eq_(c.__doc__, "run the fancy default") 349 350 def test_wrapping_update_wrapper_cls_noclsdocstring(self): 351 class MyFancyDefault(object): 352 353 def __call__(self): 354 """run the fancy default""" 355 return 10 356 357 def_ = MyFancyDefault() 358 c = util.wrap_callable(lambda: def_(), def_) 359 eq_(c.__name__, "MyFancyDefault") 360 eq_(c.__doc__, "run the fancy default") 361 362 def test_wrapping_update_wrapper_cls_nomethdocstring(self): 363 class MyFancyDefault(object): 364 """a fancy default""" 365 366 def __call__(self): 367 return 10 368 369 def_ = MyFancyDefault() 370 c = util.wrap_callable(lambda: def_(), def_) 371 eq_(c.__name__, "MyFancyDefault") 372 eq_(c.__doc__, "a fancy default") 373 374 def test_wrapping_update_wrapper_cls_noclsdocstring_nomethdocstring(self): 375 class MyFancyDefault(object): 376 377 def __call__(self): 378 return 10 379 380 def_ = MyFancyDefault() 381 c = util.wrap_callable(lambda: def_(), def_) 382 eq_(c.__name__, "MyFancyDefault") 383 eq_(c.__doc__, None) 384 385 def test_wrapping_update_wrapper_functools_parial(self): 386 def my_default(x): 387 return x 388 389 import functools 390 my_functools_default = functools.partial(my_default, 5) 391 392 c = util.wrap_callable( 393 lambda: my_functools_default(), my_functools_default) 394 eq_(c.__name__, "partial") 395 eq_(c.__doc__, my_functools_default.__call__.__doc__) 396 eq_(c(), 5) 397 398 399class ToListTest(fixtures.TestBase): 400 def test_from_string(self): 401 eq_( 402 util.to_list("xyz"), 403 ["xyz"] 404 ) 405 406 def test_from_set(self): 407 spec = util.to_list(set([1, 2, 3])) 408 assert isinstance(spec, list) 409 eq_( 410 sorted(spec), 411 [1, 2, 3] 412 ) 413 414 def test_from_dict(self): 415 spec = util.to_list({1: "a", 2: "b", 3: "c"}) 416 assert isinstance(spec, list) 417 eq_( 418 sorted(spec), 419 [1, 2, 3] 420 ) 421 422 def test_from_tuple(self): 423 eq_( 424 util.to_list((1, 2, 3)), 425 [1, 2, 3] 426 ) 427 428 def test_from_bytes(self): 429 430 eq_( 431 util.to_list(compat.b('abc')), 432 [compat.b('abc')] 433 ) 434 435 eq_( 436 util.to_list([ 437 compat.b('abc'), compat.b('def')]), 438 [compat.b('abc'), compat.b('def')] 439 ) 440 441 442class ColumnCollectionTest(fixtures.TestBase): 443 444 def test_in(self): 445 cc = sql.ColumnCollection() 446 cc.add(sql.column('col1')) 447 cc.add(sql.column('col2')) 448 cc.add(sql.column('col3')) 449 assert 'col1' in cc 450 assert 'col2' in cc 451 452 try: 453 cc['col1'] in cc 454 assert False 455 except exc.ArgumentError as e: 456 eq_(str(e), "__contains__ requires a string argument") 457 458 def test_compare(self): 459 cc1 = sql.ColumnCollection() 460 cc2 = sql.ColumnCollection() 461 cc3 = sql.ColumnCollection() 462 c1 = sql.column('col1') 463 c2 = c1.label('col2') 464 c3 = sql.column('col3') 465 cc1.add(c1) 466 cc2.add(c2) 467 cc3.add(c3) 468 assert (cc1 == cc2).compare(c1 == c2) 469 assert not (cc1 == cc3).compare(c2 == c3) 470 471 @testing.emits_warning("Column ") 472 def test_dupes_add(self): 473 cc = sql.ColumnCollection() 474 475 c1, c2a, c3, c2b = (column('c1'), 476 column('c2'), 477 column('c3'), 478 column('c2')) 479 480 cc.add(c1) 481 cc.add(c2a) 482 cc.add(c3) 483 cc.add(c2b) 484 485 eq_(cc._all_columns, [c1, c2a, c3, c2b]) 486 487 # for iter, c2a is replaced by c2b, ordering 488 # is maintained in that way. ideally, iter would be 489 # the same as the "_all_columns" collection. 490 eq_(list(cc), [c1, c2b, c3]) 491 492 assert cc.contains_column(c2a) 493 assert cc.contains_column(c2b) 494 495 ci = cc.as_immutable() 496 eq_(ci._all_columns, [c1, c2a, c3, c2b]) 497 eq_(list(ci), [c1, c2b, c3]) 498 499 def test_replace(self): 500 cc = sql.ColumnCollection() 501 502 c1, c2a, c3, c2b = (column('c1'), 503 column('c2'), 504 column('c3'), 505 column('c2')) 506 507 cc.add(c1) 508 cc.add(c2a) 509 cc.add(c3) 510 511 cc.replace(c2b) 512 513 eq_(cc._all_columns, [c1, c2b, c3]) 514 eq_(list(cc), [c1, c2b, c3]) 515 516 assert not cc.contains_column(c2a) 517 assert cc.contains_column(c2b) 518 519 ci = cc.as_immutable() 520 eq_(ci._all_columns, [c1, c2b, c3]) 521 eq_(list(ci), [c1, c2b, c3]) 522 523 def test_replace_key_matches(self): 524 cc = sql.ColumnCollection() 525 526 c1, c2a, c3, c2b = (column('c1'), 527 column('c2'), 528 column('c3'), 529 column('X')) 530 c2b.key = 'c2' 531 532 cc.add(c1) 533 cc.add(c2a) 534 cc.add(c3) 535 536 cc.replace(c2b) 537 538 assert not cc.contains_column(c2a) 539 assert cc.contains_column(c2b) 540 541 eq_(cc._all_columns, [c1, c2b, c3]) 542 eq_(list(cc), [c1, c2b, c3]) 543 544 ci = cc.as_immutable() 545 eq_(ci._all_columns, [c1, c2b, c3]) 546 eq_(list(ci), [c1, c2b, c3]) 547 548 def test_replace_name_matches(self): 549 cc = sql.ColumnCollection() 550 551 c1, c2a, c3, c2b = (column('c1'), 552 column('c2'), 553 column('c3'), 554 column('c2')) 555 c2b.key = 'X' 556 557 cc.add(c1) 558 cc.add(c2a) 559 cc.add(c3) 560 561 cc.replace(c2b) 562 563 assert not cc.contains_column(c2a) 564 assert cc.contains_column(c2b) 565 566 eq_(cc._all_columns, [c1, c2b, c3]) 567 eq_(list(cc), [c1, c3, c2b]) 568 569 ci = cc.as_immutable() 570 eq_(ci._all_columns, [c1, c2b, c3]) 571 eq_(list(ci), [c1, c3, c2b]) 572 573 def test_replace_no_match(self): 574 cc = sql.ColumnCollection() 575 576 c1, c2, c3, c4 = column('c1'), column('c2'), column('c3'), column('c4') 577 c4.key = 'X' 578 579 cc.add(c1) 580 cc.add(c2) 581 cc.add(c3) 582 583 cc.replace(c4) 584 585 assert cc.contains_column(c2) 586 assert cc.contains_column(c4) 587 588 eq_(cc._all_columns, [c1, c2, c3, c4]) 589 eq_(list(cc), [c1, c2, c3, c4]) 590 591 ci = cc.as_immutable() 592 eq_(ci._all_columns, [c1, c2, c3, c4]) 593 eq_(list(ci), [c1, c2, c3, c4]) 594 595 def test_dupes_extend(self): 596 cc = sql.ColumnCollection() 597 598 c1, c2a, c3, c2b = (column('c1'), 599 column('c2'), 600 column('c3'), 601 column('c2')) 602 603 cc.add(c1) 604 cc.add(c2a) 605 606 cc.extend([c3, c2b]) 607 608 eq_(cc._all_columns, [c1, c2a, c3, c2b]) 609 610 # for iter, c2a is replaced by c2b, ordering 611 # is maintained in that way. ideally, iter would be 612 # the same as the "_all_columns" collection. 613 eq_(list(cc), [c1, c2b, c3]) 614 615 assert cc.contains_column(c2a) 616 assert cc.contains_column(c2b) 617 618 ci = cc.as_immutable() 619 eq_(ci._all_columns, [c1, c2a, c3, c2b]) 620 eq_(list(ci), [c1, c2b, c3]) 621 622 def test_dupes_update(self): 623 cc = sql.ColumnCollection() 624 625 c1, c2a, c3, c2b = (column('c1'), 626 column('c2'), 627 column('c3'), 628 column('c2')) 629 630 cc.add(c1) 631 cc.add(c2a) 632 633 cc.update([(c3.key, c3), (c2b.key, c2b)]) 634 635 eq_(cc._all_columns, [c1, c2a, c3, c2b]) 636 637 assert cc.contains_column(c2a) 638 assert cc.contains_column(c2b) 639 640 # for iter, c2a is replaced by c2b, ordering 641 # is maintained in that way. ideally, iter would be 642 # the same as the "_all_columns" collection. 643 eq_(list(cc), [c1, c2b, c3]) 644 645 def test_extend_existing(self): 646 cc = sql.ColumnCollection() 647 648 c1, c2, c3, c4, c5 = (column('c1'), 649 column('c2'), 650 column('c3'), 651 column('c4'), 652 column('c5')) 653 654 cc.extend([c1, c2]) 655 eq_(cc._all_columns, [c1, c2]) 656 657 cc.extend([c3]) 658 eq_(cc._all_columns, [c1, c2, c3]) 659 cc.extend([c4, c2, c5]) 660 661 eq_(cc._all_columns, [c1, c2, c3, c4, c5]) 662 663 def test_update_existing(self): 664 cc = sql.ColumnCollection() 665 666 c1, c2, c3, c4, c5 = (column('c1'), 667 column('c2'), 668 column('c3'), 669 column('c4'), 670 column('c5')) 671 672 cc.update([('c1', c1), ('c2', c2)]) 673 eq_(cc._all_columns, [c1, c2]) 674 675 cc.update([('c3', c3)]) 676 eq_(cc._all_columns, [c1, c2, c3]) 677 cc.update([('c4', c4), ('c2', c2), ('c5', c5)]) 678 679 eq_(cc._all_columns, [c1, c2, c3, c4, c5]) 680 681 682class LRUTest(fixtures.TestBase): 683 684 def test_lru(self): 685 class item(object): 686 def __init__(self, id): 687 self.id = id 688 689 def __str__(self): 690 return "item id %d" % self.id 691 692 lru = util.LRUCache(10, threshold=.2) 693 694 for id in range(1, 20): 695 lru[id] = item(id) 696 697 # first couple of items should be gone 698 assert 1 not in lru 699 assert 2 not in lru 700 701 # next batch over the threshold of 10 should be present 702 for id_ in range(11, 20): 703 assert id_ in lru 704 705 lru[12] 706 lru[15] 707 lru[23] = item(23) 708 lru[24] = item(24) 709 lru[25] = item(25) 710 lru[26] = item(26) 711 lru[27] = item(27) 712 713 assert 11 not in lru 714 assert 13 not in lru 715 716 for id_ in (25, 24, 23, 14, 12, 19, 18, 17, 16, 15): 717 assert id_ in lru 718 719 i1 = lru[25] 720 i2 = item(25) 721 lru[25] = i2 722 assert 25 in lru 723 assert lru[25] is i2 724 725 726class ImmutableSubclass(str): 727 pass 728 729 730class FlattenIteratorTest(fixtures.TestBase): 731 732 def test_flatten(self): 733 assert list(util.flatten_iterator([[1, 2, 3], [4, 5, 6], 7, 734 8])) == [1, 2, 3, 4, 5, 6, 7, 8] 735 736 def test_str_with_iter(self): 737 """ensure that a str object with an __iter__ method (like in 738 PyPy) is not interpreted as an iterable. 739 740 """ 741 742 class IterString(str): 743 def __iter__(self): 744 return iter(self + '') 745 746 iter_list = [IterString('asdf'), [IterString('x'), IterString('y')]] 747 748 assert list(util.flatten_iterator(iter_list)) == ['asdf', 'x', 'y'] 749 750 751class HashOverride(object): 752 753 def __init__(self, value=None): 754 self.value = value 755 756 def __hash__(self): 757 return hash(self.value) 758 759 760class EqOverride(object): 761 762 def __init__(self, value=None): 763 self.value = value 764 __hash__ = object.__hash__ 765 766 def __eq__(self, other): 767 if isinstance(other, EqOverride): 768 return self.value == other.value 769 else: 770 return False 771 772 def __ne__(self, other): 773 if isinstance(other, EqOverride): 774 return self.value != other.value 775 else: 776 return True 777 778 779class HashEqOverride(object): 780 781 def __init__(self, value=None): 782 self.value = value 783 784 def __hash__(self): 785 return hash(self.value) 786 787 def __eq__(self, other): 788 if isinstance(other, EqOverride): 789 return self.value == other.value 790 else: 791 return False 792 793 def __ne__(self, other): 794 if isinstance(other, EqOverride): 795 return self.value != other.value 796 else: 797 return True 798 799 800class IdentitySetTest(fixtures.TestBase): 801 802 def assert_eq(self, identityset, expected_iterable): 803 expected = sorted([id(o) for o in expected_iterable]) 804 found = sorted([id(o) for o in identityset]) 805 eq_(found, expected) 806 807 def test_init(self): 808 ids = util.IdentitySet([1, 2, 3, 2, 1]) 809 self.assert_eq(ids, [1, 2, 3]) 810 811 ids = util.IdentitySet(ids) 812 self.assert_eq(ids, [1, 2, 3]) 813 814 ids = util.IdentitySet() 815 self.assert_eq(ids, []) 816 817 ids = util.IdentitySet([]) 818 self.assert_eq(ids, []) 819 820 ids = util.IdentitySet(ids) 821 self.assert_eq(ids, []) 822 823 def test_add(self): 824 for type_ in (object, ImmutableSubclass): 825 data = [type_(), type_()] 826 ids = util.IdentitySet() 827 for i in list(range(2)) + list(range(2)): 828 ids.add(data[i]) 829 self.assert_eq(ids, data) 830 831 for type_ in (EqOverride, HashOverride, HashEqOverride): 832 data = [type_(1), type_(1), type_(2)] 833 ids = util.IdentitySet() 834 for i in list(range(3)) + list(range(3)): 835 ids.add(data[i]) 836 self.assert_eq(ids, data) 837 838 def test_dunder_sub2(self): 839 IdentitySet = util.IdentitySet 840 o1, o2, o3 = object(), object(), object() 841 ids1 = IdentitySet([o1]) 842 ids2 = IdentitySet([o1, o2, o3]) 843 eq_( 844 ids2 - ids1, 845 IdentitySet([o2, o3]) 846 ) 847 848 ids2 -= ids1 849 eq_(ids2, IdentitySet([o2, o3])) 850 851 def test_dunder_eq(self): 852 _, _, twin1, twin2, unique1, unique2 = self._create_sets() 853 854 # basic set math 855 eq_(twin1 == twin2, True) 856 eq_(unique1 == unique2, False) 857 858 # not an IdentitySet 859 not_an_identity_set = object() 860 eq_(unique1 == not_an_identity_set, False) 861 862 def test_dunder_ne(self): 863 _, _, twin1, twin2, unique1, unique2 = self._create_sets() 864 865 # basic set math 866 eq_(twin1 != twin2, False) 867 eq_(unique1 != unique2, True) 868 869 # not an IdentitySet 870 not_an_identity_set = object() 871 eq_(unique1 != not_an_identity_set, True) 872 873 def test_dunder_le(self): 874 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 875 876 # basic set math 877 eq_(sub_ <= super_, True) 878 eq_(super_ <= sub_, False) 879 880 # the same sets 881 eq_(twin1 <= twin2, True) 882 eq_(twin2 <= twin1, True) 883 884 # totally different sets 885 eq_(unique1 <= unique2, False) 886 eq_(unique2 <= unique1, False) 887 888 # not an IdentitySet 889 def should_raise(): 890 not_an_identity_set = object() 891 return unique1 <= not_an_identity_set 892 self._assert_unorderable_types(should_raise) 893 894 def test_dunder_lt(self): 895 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 896 897 # basic set math 898 eq_(sub_ < super_, True) 899 eq_(super_ < sub_, False) 900 901 # the same sets 902 eq_(twin1 < twin2, False) 903 eq_(twin2 < twin1, False) 904 905 # totally different sets 906 eq_(unique1 < unique2, False) 907 eq_(unique2 < unique1, False) 908 909 # not an IdentitySet 910 def should_raise(): 911 not_an_identity_set = object() 912 return unique1 < not_an_identity_set 913 self._assert_unorderable_types(should_raise) 914 915 def test_dunder_ge(self): 916 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 917 918 # basic set math 919 eq_(sub_ >= super_, False) 920 eq_(super_ >= sub_, True) 921 922 # the same sets 923 eq_(twin1 >= twin2, True) 924 eq_(twin2 >= twin1, True) 925 926 # totally different sets 927 eq_(unique1 >= unique2, False) 928 eq_(unique2 >= unique1, False) 929 930 # not an IdentitySet 931 def should_raise(): 932 not_an_identity_set = object() 933 return unique1 >= not_an_identity_set 934 self._assert_unorderable_types(should_raise) 935 936 def test_dunder_gt(self): 937 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 938 939 # basic set math 940 eq_(sub_ > super_, False) 941 eq_(super_ > sub_, True) 942 943 # the same sets 944 eq_(twin1 > twin2, False) 945 eq_(twin2 > twin1, False) 946 947 # totally different sets 948 eq_(unique1 > unique2, False) 949 eq_(unique2 > unique1, False) 950 951 # not an IdentitySet 952 def should_raise(): 953 not_an_identity_set = object() 954 return unique1 > not_an_identity_set 955 self._assert_unorderable_types(should_raise) 956 957 def test_issubset(self): 958 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 959 960 # basic set math 961 eq_(sub_.issubset(super_), True) 962 eq_(super_.issubset(sub_), False) 963 964 # the same sets 965 eq_(twin1.issubset(twin2), True) 966 eq_(twin2.issubset(twin1), True) 967 968 # totally different sets 969 eq_(unique1.issubset(unique2), False) 970 eq_(unique2.issubset(unique1), False) 971 972 # not an IdentitySet 973 not_an_identity_set = object() 974 assert_raises(TypeError, unique1.issubset, not_an_identity_set) 975 976 def test_issuperset(self): 977 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 978 979 # basic set math 980 eq_(sub_.issuperset(super_), False) 981 eq_(super_.issuperset(sub_), True) 982 983 # the same sets 984 eq_(twin1.issuperset(twin2), True) 985 eq_(twin2.issuperset(twin1), True) 986 987 # totally different sets 988 eq_(unique1.issuperset(unique2), False) 989 eq_(unique2.issuperset(unique1), False) 990 991 # not an IdentitySet 992 not_an_identity_set = object() 993 assert_raises(TypeError, unique1.issuperset, not_an_identity_set) 994 995 def test_union(self): 996 super_, sub_, twin1, twin2, _, _ = self._create_sets() 997 998 # basic set math 999 eq_(sub_.union(super_), super_) 1000 eq_(super_.union(sub_), super_) 1001 1002 # the same sets 1003 eq_(twin1.union(twin2), twin1) 1004 eq_(twin2.union(twin1), twin1) 1005 1006 # empty sets 1007 empty = util.IdentitySet([]) 1008 eq_(empty.union(empty), empty) 1009 1010 # totally different sets 1011 unique1 = util.IdentitySet([1]) 1012 unique2 = util.IdentitySet([2]) 1013 eq_(unique1.union(unique2), util.IdentitySet([1, 2])) 1014 1015 # not an IdentitySet 1016 not_an_identity_set = object() 1017 assert_raises(TypeError, unique1.union, not_an_identity_set) 1018 1019 def test_dunder_or(self): 1020 super_, sub_, twin1, twin2, _, _ = self._create_sets() 1021 1022 # basic set math 1023 eq_(sub_ | super_, super_) 1024 eq_(super_ | sub_, super_) 1025 1026 # the same sets 1027 eq_(twin1 | twin2, twin1) 1028 eq_(twin2 | twin1, twin1) 1029 1030 # empty sets 1031 empty = util.IdentitySet([]) 1032 eq_(empty | empty, empty) 1033 1034 # totally different sets 1035 unique1 = util.IdentitySet([1]) 1036 unique2 = util.IdentitySet([2]) 1037 eq_(unique1 | unique2, util.IdentitySet([1, 2])) 1038 1039 # not an IdentitySet 1040 def should_raise(): 1041 not_an_identity_set = object() 1042 return unique1 | not_an_identity_set 1043 assert_raises(TypeError, should_raise) 1044 1045 def test_update(self): 1046 pass # TODO 1047 1048 def test_dunder_ior(self): 1049 super_, sub_, _, _, _, _ = self._create_sets() 1050 1051 # basic set math 1052 sub_ |= super_ 1053 eq_(sub_, super_) 1054 super_ |= sub_ 1055 eq_(super_, super_) 1056 1057 # totally different sets 1058 unique1 = util.IdentitySet([1]) 1059 unique2 = util.IdentitySet([2]) 1060 unique1 |= unique2 1061 eq_(unique1, util.IdentitySet([1, 2])) 1062 eq_(unique2, util.IdentitySet([2])) 1063 1064 # not an IdentitySet 1065 def should_raise(): 1066 unique = util.IdentitySet([1]) 1067 not_an_identity_set = object() 1068 unique |= not_an_identity_set 1069 assert_raises(TypeError, should_raise) 1070 1071 def test_difference(self): 1072 _, _, twin1, twin2, _, _ = self._create_sets() 1073 1074 # basic set math 1075 set1 = util.IdentitySet([1, 2, 3]) 1076 set2 = util.IdentitySet([2, 3, 4]) 1077 eq_(set1.difference(set2), util.IdentitySet([1])) 1078 eq_(set2.difference(set1), util.IdentitySet([4])) 1079 1080 # empty sets 1081 empty = util.IdentitySet([]) 1082 eq_(empty.difference(empty), empty) 1083 1084 # the same sets 1085 eq_(twin1.difference(twin2), empty) 1086 eq_(twin2.difference(twin1), empty) 1087 1088 # totally different sets 1089 unique1 = util.IdentitySet([1]) 1090 unique2 = util.IdentitySet([2]) 1091 eq_(unique1.difference(unique2), util.IdentitySet([1])) 1092 eq_(unique2.difference(unique1), util.IdentitySet([2])) 1093 1094 # not an IdentitySet 1095 not_an_identity_set = object() 1096 assert_raises(TypeError, unique1.difference, not_an_identity_set) 1097 1098 def test_dunder_sub(self): 1099 _, _, twin1, twin2, _, _ = self._create_sets() 1100 1101 # basic set math 1102 set1 = util.IdentitySet([1, 2, 3]) 1103 set2 = util.IdentitySet([2, 3, 4]) 1104 eq_(set1 - set2, util.IdentitySet([1])) 1105 eq_(set2 - set1, util.IdentitySet([4])) 1106 1107 # empty sets 1108 empty = util.IdentitySet([]) 1109 eq_(empty - empty, empty) 1110 1111 # the same sets 1112 eq_(twin1 - twin2, empty) 1113 eq_(twin2 - twin1, empty) 1114 1115 # totally different sets 1116 unique1 = util.IdentitySet([1]) 1117 unique2 = util.IdentitySet([2]) 1118 eq_(unique1 - unique2, util.IdentitySet([1])) 1119 eq_(unique2 - unique1, util.IdentitySet([2])) 1120 1121 # not an IdentitySet 1122 def should_raise(): 1123 not_an_identity_set = object() 1124 unique1 - not_an_identity_set 1125 assert_raises(TypeError, should_raise) 1126 1127 def test_difference_update(self): 1128 pass # TODO 1129 1130 def test_dunder_isub(self): 1131 pass # TODO 1132 1133 def test_intersection(self): 1134 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 1135 1136 # basic set math 1137 eq_(sub_.intersection(super_), sub_) 1138 eq_(super_.intersection(sub_), sub_) 1139 1140 # the same sets 1141 eq_(twin1.intersection(twin2), twin1) 1142 eq_(twin2.intersection(twin1), twin1) 1143 1144 # empty sets 1145 empty = util.IdentitySet([]) 1146 eq_(empty.intersection(empty), empty) 1147 1148 # totally different sets 1149 eq_(unique1.intersection(unique2), empty) 1150 1151 # not an IdentitySet 1152 not_an_identity_set = object() 1153 assert_raises(TypeError, unique1.intersection, not_an_identity_set) 1154 1155 def test_dunder_and(self): 1156 super_, sub_, twin1, twin2, unique1, unique2 = self._create_sets() 1157 1158 # basic set math 1159 eq_(sub_ & super_, sub_) 1160 eq_(super_ & sub_, sub_) 1161 1162 # the same sets 1163 eq_(twin1 & twin2, twin1) 1164 eq_(twin2 & twin1, twin1) 1165 1166 # empty sets 1167 empty = util.IdentitySet([]) 1168 eq_(empty & empty, empty) 1169 1170 # totally different sets 1171 eq_(unique1 & unique2, empty) 1172 1173 # not an IdentitySet 1174 def should_raise(): 1175 not_an_identity_set = object() 1176 return unique1 & not_an_identity_set 1177 assert_raises(TypeError, should_raise) 1178 1179 def test_intersection_update(self): 1180 pass # TODO 1181 1182 def test_dunder_iand(self): 1183 pass # TODO 1184 1185 def test_symmetric_difference(self): 1186 _, _, twin1, twin2, _, _ = self._create_sets() 1187 1188 # basic set math 1189 set1 = util.IdentitySet([1, 2, 3]) 1190 set2 = util.IdentitySet([2, 3, 4]) 1191 eq_(set1.symmetric_difference(set2), util.IdentitySet([1, 4])) 1192 eq_(set2.symmetric_difference(set1), util.IdentitySet([1, 4])) 1193 1194 # empty sets 1195 empty = util.IdentitySet([]) 1196 eq_(empty.symmetric_difference(empty), empty) 1197 1198 # the same sets 1199 eq_(twin1.symmetric_difference(twin2), empty) 1200 eq_(twin2.symmetric_difference(twin1), empty) 1201 1202 # totally different sets 1203 unique1 = util.IdentitySet([1]) 1204 unique2 = util.IdentitySet([2]) 1205 eq_(unique1.symmetric_difference(unique2), util.IdentitySet([1, 2])) 1206 eq_(unique2.symmetric_difference(unique1), util.IdentitySet([1, 2])) 1207 1208 # not an IdentitySet 1209 not_an_identity_set = object() 1210 assert_raises( 1211 TypeError, unique1.symmetric_difference, not_an_identity_set) 1212 1213 def test_dunder_xor(self): 1214 _, _, twin1, twin2, _, _ = self._create_sets() 1215 1216 # basic set math 1217 set1 = util.IdentitySet([1, 2, 3]) 1218 set2 = util.IdentitySet([2, 3, 4]) 1219 eq_(set1 ^ set2, util.IdentitySet([1, 4])) 1220 eq_(set2 ^ set1, util.IdentitySet([1, 4])) 1221 1222 # empty sets 1223 empty = util.IdentitySet([]) 1224 eq_(empty ^ empty, empty) 1225 1226 # the same sets 1227 eq_(twin1 ^ twin2, empty) 1228 eq_(twin2 ^ twin1, empty) 1229 1230 # totally different sets 1231 unique1 = util.IdentitySet([1]) 1232 unique2 = util.IdentitySet([2]) 1233 eq_(unique1 ^ unique2, util.IdentitySet([1, 2])) 1234 eq_(unique2 ^ unique1, util.IdentitySet([1, 2])) 1235 1236 # not an IdentitySet 1237 def should_raise(): 1238 not_an_identity_set = object() 1239 return unique1 ^ not_an_identity_set 1240 assert_raises(TypeError, should_raise) 1241 1242 def test_symmetric_difference_update(self): 1243 pass # TODO 1244 1245 def _create_sets(self): 1246 o1, o2, o3, o4, o5 = object(), object(), object(), object(), object() 1247 super_ = util.IdentitySet([o1, o2, o3]) 1248 sub_ = util.IdentitySet([o2]) 1249 twin1 = util.IdentitySet([o3]) 1250 twin2 = util.IdentitySet([o3]) 1251 unique1 = util.IdentitySet([o4]) 1252 unique2 = util.IdentitySet([o5]) 1253 return super_, sub_, twin1, twin2, unique1, unique2 1254 1255 def _assert_unorderable_types(self, callable_): 1256 if util.py36: 1257 assert_raises_message( 1258 TypeError, 'not supported between instances of', callable_) 1259 elif util.py3k: 1260 assert_raises_message( 1261 TypeError, 'unorderable types', callable_) 1262 else: 1263 assert_raises_message( 1264 TypeError, 'cannot compare sets using cmp()', callable_) 1265 1266 def test_basic_sanity(self): 1267 IdentitySet = util.IdentitySet 1268 1269 o1, o2, o3 = object(), object(), object() 1270 ids = IdentitySet([o1]) 1271 ids.discard(o1) 1272 ids.discard(o1) 1273 ids.add(o1) 1274 ids.remove(o1) 1275 assert_raises(KeyError, ids.remove, o1) 1276 1277 eq_(ids.copy(), ids) 1278 1279 # explicit __eq__ and __ne__ tests 1280 assert ids != None # noqa 1281 assert not(ids == None) # noqa 1282 1283 ne_(ids, IdentitySet([o1, o2, o3])) 1284 ids.clear() 1285 assert o1 not in ids 1286 ids.add(o2) 1287 assert o2 in ids 1288 eq_(ids.pop(), o2) 1289 ids.add(o1) 1290 eq_(len(ids), 1) 1291 1292 isuper = IdentitySet([o1, o2]) 1293 assert ids < isuper 1294 assert ids.issubset(isuper) 1295 assert isuper.issuperset(ids) 1296 assert isuper > ids 1297 1298 eq_(ids.union(isuper), isuper) 1299 eq_(ids | isuper, isuper) 1300 eq_(isuper - ids, IdentitySet([o2])) 1301 eq_(isuper.difference(ids), IdentitySet([o2])) 1302 eq_(ids.intersection(isuper), IdentitySet([o1])) 1303 eq_(ids & isuper, IdentitySet([o1])) 1304 eq_(ids.symmetric_difference(isuper), IdentitySet([o2])) 1305 eq_(ids ^ isuper, IdentitySet([o2])) 1306 1307 ids.update(isuper) 1308 ids |= isuper 1309 ids.difference_update(isuper) 1310 ids -= isuper 1311 ids.intersection_update(isuper) 1312 ids &= isuper 1313 ids.symmetric_difference_update(isuper) 1314 ids ^= isuper 1315 1316 ids.update('foobar') 1317 try: 1318 ids |= 'foobar' 1319 assert False 1320 except TypeError: 1321 assert True 1322 1323 try: 1324 s = set([o1, o2]) 1325 s |= ids 1326 assert False 1327 except TypeError: 1328 assert True 1329 1330 assert_raises(TypeError, util.cmp, ids) 1331 assert_raises(TypeError, hash, ids) 1332 1333 1334class OrderedIdentitySetTest(fixtures.TestBase): 1335 1336 def assert_eq(self, identityset, expected_iterable): 1337 expected = [id(o) for o in expected_iterable] 1338 found = [id(o) for o in identityset] 1339 eq_(found, expected) 1340 1341 def test_add(self): 1342 elem = object 1343 s = util.OrderedIdentitySet() 1344 s.add(elem()) 1345 s.add(elem()) 1346 1347 def test_intersection(self): 1348 elem = object 1349 eq_ = self.assert_eq 1350 1351 a, b, c, d, e, f, g = \ 1352 elem(), elem(), elem(), elem(), elem(), elem(), elem() 1353 1354 s1 = util.OrderedIdentitySet([a, b, c]) 1355 s2 = util.OrderedIdentitySet([d, e, f]) 1356 s3 = util.OrderedIdentitySet([a, d, f, g]) 1357 eq_(s1.intersection(s2), []) 1358 eq_(s1.intersection(s3), [a]) 1359 eq_(s1.union(s2).intersection(s3), [a, d, f]) 1360 1361 1362class DictlikeIteritemsTest(fixtures.TestBase): 1363 baseline = set([('a', 1), ('b', 2), ('c', 3)]) 1364 1365 def _ok(self, instance): 1366 iterator = util.dictlike_iteritems(instance) 1367 eq_(set(iterator), self.baseline) 1368 1369 def _notok(self, instance): 1370 assert_raises(TypeError, 1371 util.dictlike_iteritems, 1372 instance) 1373 1374 def test_dict(self): 1375 d = dict(a=1, b=2, c=3) 1376 self._ok(d) 1377 1378 def test_subdict(self): 1379 class subdict(dict): 1380 pass 1381 d = subdict(a=1, b=2, c=3) 1382 self._ok(d) 1383 1384 if util.py2k: 1385 def test_UserDict(self): 1386 import UserDict 1387 d = UserDict.UserDict(a=1, b=2, c=3) 1388 self._ok(d) 1389 1390 def test_object(self): 1391 self._notok(object()) 1392 1393 if util.py2k: 1394 def test_duck_1(self): 1395 class duck1(object): 1396 def iteritems(duck): 1397 return iter(self.baseline) 1398 self._ok(duck1()) 1399 1400 def test_duck_2(self): 1401 class duck2(object): 1402 def items(duck): 1403 return list(self.baseline) 1404 self._ok(duck2()) 1405 1406 if util.py2k: 1407 def test_duck_3(self): 1408 class duck3(object): 1409 def iterkeys(duck): 1410 return iter(['a', 'b', 'c']) 1411 1412 def __getitem__(duck, key): 1413 return dict(a=1, b=2, c=3).get(key) 1414 self._ok(duck3()) 1415 1416 def test_duck_4(self): 1417 class duck4(object): 1418 def iterkeys(duck): 1419 return iter(['a', 'b', 'c']) 1420 self._notok(duck4()) 1421 1422 def test_duck_5(self): 1423 class duck5(object): 1424 def keys(duck): 1425 return ['a', 'b', 'c'] 1426 1427 def get(duck, key): 1428 return dict(a=1, b=2, c=3).get(key) 1429 self._ok(duck5()) 1430 1431 def test_duck_6(self): 1432 class duck6(object): 1433 def keys(duck): 1434 return ['a', 'b', 'c'] 1435 self._notok(duck6()) 1436 1437 1438class DuckTypeCollectionTest(fixtures.TestBase): 1439 1440 def test_sets(self): 1441 class SetLike(object): 1442 def add(self): 1443 pass 1444 1445 class ForcedSet(list): 1446 __emulates__ = set 1447 1448 for type_ in (set, 1449 SetLike, 1450 ForcedSet): 1451 eq_(util.duck_type_collection(type_), set) 1452 instance = type_() 1453 eq_(util.duck_type_collection(instance), set) 1454 1455 for type_ in (frozenset, ): 1456 is_(util.duck_type_collection(type_), None) 1457 instance = type_() 1458 is_(util.duck_type_collection(instance), None) 1459 1460 1461class PublicFactoryTest(fixtures.TestBase): 1462 1463 def _fixture(self): 1464 class Thingy(object): 1465 def __init__(self, value): 1466 "make a thingy" 1467 self.value = value 1468 1469 @classmethod 1470 def foobar(cls, x, y): 1471 "do the foobar" 1472 return Thingy(x + y) 1473 1474 return Thingy 1475 1476 def test_classmethod(self): 1477 Thingy = self._fixture() 1478 foob = langhelpers.public_factory( 1479 Thingy.foobar, ".sql.elements.foob") 1480 eq_(foob(3, 4).value, 7) 1481 eq_(foob(x=3, y=4).value, 7) 1482 eq_(foob.__doc__, "do the foobar") 1483 eq_(foob.__module__, "sqlalchemy.sql.elements") 1484 assert Thingy.foobar.__doc__.startswith("This function is mirrored;") 1485 1486 def test_constructor(self): 1487 Thingy = self._fixture() 1488 foob = langhelpers.public_factory( 1489 Thingy, ".sql.elements.foob") 1490 eq_(foob(7).value, 7) 1491 eq_(foob(value=7).value, 7) 1492 eq_(foob.__doc__, "make a thingy") 1493 eq_(foob.__module__, "sqlalchemy.sql.elements") 1494 assert Thingy.__init__.__doc__.startswith( 1495 "Construct a new :class:`.Thingy` object.") 1496 1497 1498class ArgInspectionTest(fixtures.TestBase): 1499 1500 def test_get_cls_kwargs(self): 1501 1502 class A(object): 1503 def __init__(self, a): 1504 pass 1505 1506 class A1(A): 1507 def __init__(self, a1): 1508 pass 1509 1510 class A11(A1): 1511 def __init__(self, a11, **kw): 1512 pass 1513 1514 class B(object): 1515 def __init__(self, b, **kw): 1516 pass 1517 1518 class B1(B): 1519 def __init__(self, b1, **kw): 1520 pass 1521 1522 class B2(B): 1523 def __init__(self, b2): 1524 pass 1525 1526 class AB(A, B): 1527 def __init__(self, ab): 1528 pass 1529 1530 class BA(B, A): 1531 def __init__(self, ba, **kwargs): 1532 pass 1533 1534 class BA1(BA): 1535 pass 1536 1537 class CAB(A, B): 1538 pass 1539 1540 class CBA(B, A): 1541 pass 1542 1543 class CB1A1(B1, A1): 1544 pass 1545 1546 class CAB1(A, B1): 1547 pass 1548 1549 class CB1A(B1, A): 1550 pass 1551 1552 class CB2A(B2, A): 1553 pass 1554 1555 class D(object): 1556 pass 1557 1558 class BA2(B, A): 1559 pass 1560 1561 class A11B1(A11, B1): 1562 pass 1563 1564 def test(cls, *expected): 1565 eq_(set(util.get_cls_kwargs(cls)), set(expected)) 1566 1567 test(A, 'a') 1568 test(A1, 'a1') 1569 test(A11, 'a11', 'a1') 1570 test(B, 'b') 1571 test(B1, 'b1', 'b') 1572 test(AB, 'ab') 1573 test(BA, 'ba', 'b', 'a') 1574 test(BA1, 'ba', 'b', 'a') 1575 test(CAB, 'a') 1576 test(CBA, 'b', 'a') 1577 test(CAB1, 'a') 1578 test(CB1A, 'b1', 'b', 'a') 1579 test(CB2A, 'b2') 1580 test(CB1A1, "a1", "b1", "b") 1581 test(D) 1582 test(BA2, "a", "b") 1583 test(A11B1, "a1", "a11", "b", "b1") 1584 1585 def test_get_func_kwargs(self): 1586 1587 def f1(): 1588 pass 1589 1590 def f2(foo): 1591 pass 1592 1593 def f3(*foo): 1594 pass 1595 1596 def f4(**foo): 1597 pass 1598 1599 def test(fn, *expected): 1600 eq_(set(util.get_func_kwargs(fn)), set(expected)) 1601 1602 test(f1) 1603 test(f2, 'foo') 1604 test(f3) 1605 test(f4) 1606 1607 def test_callable_argspec_fn(self): 1608 def foo(x, y, **kw): 1609 pass 1610 eq_( 1611 get_callable_argspec(foo), 1612 (['x', 'y'], None, 'kw', None) 1613 ) 1614 1615 def test_callable_argspec_fn_no_self(self): 1616 def foo(x, y, **kw): 1617 pass 1618 eq_( 1619 get_callable_argspec(foo, no_self=True), 1620 (['x', 'y'], None, 'kw', None) 1621 ) 1622 1623 def test_callable_argspec_fn_no_self_but_self(self): 1624 def foo(self, x, y, **kw): 1625 pass 1626 eq_( 1627 get_callable_argspec(foo, no_self=True), 1628 (['self', 'x', 'y'], None, 'kw', None) 1629 ) 1630 1631 @fails_if(lambda: util.pypy, "pypy returns plain *arg, **kw") 1632 def test_callable_argspec_py_builtin(self): 1633 import datetime 1634 assert_raises( 1635 TypeError, 1636 get_callable_argspec, datetime.datetime.now 1637 ) 1638 1639 @fails_if(lambda: util.pypy, "pypy returns plain *arg, **kw") 1640 def test_callable_argspec_obj_init(self): 1641 assert_raises( 1642 TypeError, 1643 get_callable_argspec, object 1644 ) 1645 1646 def test_callable_argspec_method(self): 1647 class Foo(object): 1648 def foo(self, x, y, **kw): 1649 pass 1650 eq_( 1651 get_callable_argspec(Foo.foo), 1652 (['self', 'x', 'y'], None, 'kw', None) 1653 ) 1654 1655 def test_callable_argspec_instance_method_no_self(self): 1656 class Foo(object): 1657 def foo(self, x, y, **kw): 1658 pass 1659 eq_( 1660 get_callable_argspec(Foo().foo, no_self=True), 1661 (['x', 'y'], None, 'kw', None) 1662 ) 1663 1664 def test_callable_argspec_unbound_method_no_self(self): 1665 class Foo(object): 1666 def foo(self, x, y, **kw): 1667 pass 1668 eq_( 1669 get_callable_argspec(Foo.foo, no_self=True), 1670 (['self', 'x', 'y'], None, 'kw', None) 1671 ) 1672 1673 def test_callable_argspec_init(self): 1674 class Foo(object): 1675 def __init__(self, x, y): 1676 pass 1677 1678 eq_( 1679 get_callable_argspec(Foo), 1680 (['self', 'x', 'y'], None, None, None) 1681 ) 1682 1683 def test_callable_argspec_init_no_self(self): 1684 class Foo(object): 1685 def __init__(self, x, y): 1686 pass 1687 1688 eq_( 1689 get_callable_argspec(Foo, no_self=True), 1690 (['x', 'y'], None, None, None) 1691 ) 1692 1693 def test_callable_argspec_call(self): 1694 class Foo(object): 1695 def __call__(self, x, y): 1696 pass 1697 eq_( 1698 get_callable_argspec(Foo()), 1699 (['self', 'x', 'y'], None, None, None) 1700 ) 1701 1702 def test_callable_argspec_call_no_self(self): 1703 class Foo(object): 1704 def __call__(self, x, y): 1705 pass 1706 eq_( 1707 get_callable_argspec(Foo(), no_self=True), 1708 (['x', 'y'], None, None, None) 1709 ) 1710 1711 @fails_if(lambda: util.pypy, "pypy returns plain *arg, **kw") 1712 def test_callable_argspec_partial(self): 1713 from functools import partial 1714 1715 def foo(x, y, z, **kw): 1716 pass 1717 bar = partial(foo, 5) 1718 1719 assert_raises( 1720 TypeError, 1721 get_callable_argspec, bar 1722 ) 1723 1724 1725class SymbolTest(fixtures.TestBase): 1726 1727 def test_basic(self): 1728 sym1 = util.symbol('foo') 1729 assert sym1.name == 'foo' 1730 sym2 = util.symbol('foo') 1731 1732 assert sym1 is sym2 1733 assert sym1 == sym2 1734 1735 sym3 = util.symbol('bar') 1736 assert sym1 is not sym3 1737 assert sym1 != sym3 1738 1739 def test_pickle(self): 1740 sym1 = util.symbol('foo') 1741 sym2 = util.symbol('foo') 1742 1743 assert sym1 is sym2 1744 1745 # default 1746 s = util.pickle.dumps(sym1) 1747 sym3 = util.pickle.loads(s) 1748 1749 for protocol in 0, 1, 2: 1750 print(protocol) 1751 serial = util.pickle.dumps(sym1) 1752 rt = util.pickle.loads(serial) 1753 assert rt is sym1 1754 assert rt is sym2 1755 1756 def test_bitflags(self): 1757 sym1 = util.symbol('sym1', canonical=1) 1758 sym2 = util.symbol('sym2', canonical=2) 1759 1760 assert sym1 & sym1 1761 assert not sym1 & sym2 1762 assert not sym1 & sym1 & sym2 1763 1764 def test_composites(self): 1765 sym1 = util.symbol('sym1', canonical=1) 1766 sym2 = util.symbol('sym2', canonical=2) 1767 sym3 = util.symbol('sym3', canonical=4) 1768 sym4 = util.symbol('sym4', canonical=8) 1769 1770 assert sym1 & (sym2 | sym1 | sym4) 1771 assert not sym1 & (sym2 | sym3) 1772 1773 assert not (sym1 | sym2) & (sym3 | sym4) 1774 assert (sym1 | sym2) & (sym2 | sym4) 1775 1776 1777class TestFormatArgspec(fixtures.TestBase): 1778 1779 def test_specs(self): 1780 def test(fn, wanted, grouped=None): 1781 if grouped is None: 1782 parsed = util.format_argspec_plus(fn) 1783 else: 1784 parsed = util.format_argspec_plus(fn, grouped=grouped) 1785 eq_(parsed, wanted) 1786 1787 test(lambda: None, 1788 {'args': '()', 'self_arg': None, 1789 'apply_kw': '()', 'apply_pos': '()'}) 1790 1791 test(lambda: None, 1792 {'args': '', 'self_arg': None, 1793 'apply_kw': '', 'apply_pos': ''}, 1794 grouped=False) 1795 1796 test(lambda self: None, 1797 {'args': '(self)', 'self_arg': 'self', 1798 'apply_kw': '(self)', 'apply_pos': '(self)'}) 1799 1800 test(lambda self: None, 1801 {'args': 'self', 'self_arg': 'self', 1802 'apply_kw': 'self', 'apply_pos': 'self'}, 1803 grouped=False) 1804 1805 test(lambda *a: None, 1806 {'args': '(*a)', 'self_arg': 'a[0]', 1807 'apply_kw': '(*a)', 'apply_pos': '(*a)'}) 1808 1809 test(lambda **kw: None, 1810 {'args': '(**kw)', 'self_arg': None, 1811 'apply_kw': '(**kw)', 'apply_pos': '(**kw)'}) 1812 1813 test(lambda *a, **kw: None, 1814 {'args': '(*a, **kw)', 'self_arg': 'a[0]', 1815 'apply_kw': '(*a, **kw)', 'apply_pos': '(*a, **kw)'}) 1816 1817 test(lambda a, *b: None, 1818 {'args': '(a, *b)', 'self_arg': 'a', 1819 'apply_kw': '(a, *b)', 'apply_pos': '(a, *b)'}) 1820 1821 test(lambda a, **b: None, 1822 {'args': '(a, **b)', 'self_arg': 'a', 1823 'apply_kw': '(a, **b)', 'apply_pos': '(a, **b)'}) 1824 1825 test(lambda a, *b, **c: None, 1826 {'args': '(a, *b, **c)', 'self_arg': 'a', 1827 'apply_kw': '(a, *b, **c)', 'apply_pos': '(a, *b, **c)'}) 1828 1829 test(lambda a, b=1, **c: None, 1830 {'args': '(a, b=1, **c)', 'self_arg': 'a', 1831 'apply_kw': '(a, b=b, **c)', 'apply_pos': '(a, b, **c)'}) 1832 1833 test(lambda a=1, b=2: None, 1834 {'args': '(a=1, b=2)', 'self_arg': 'a', 1835 'apply_kw': '(a=a, b=b)', 'apply_pos': '(a, b)'}) 1836 1837 test(lambda a=1, b=2: None, 1838 {'args': 'a=1, b=2', 'self_arg': 'a', 1839 'apply_kw': 'a=a, b=b', 'apply_pos': 'a, b'}, 1840 grouped=False) 1841 1842 @testing.fails_if(lambda: util.pypy, 1843 "pypy doesn't report Obj.__init__ as object.__init__") 1844 def test_init_grouped(self): 1845 object_spec = { 1846 'args': '(self)', 'self_arg': 'self', 1847 'apply_pos': '(self)', 'apply_kw': '(self)'} 1848 wrapper_spec = { 1849 'args': '(self, *args, **kwargs)', 'self_arg': 'self', 1850 'apply_pos': '(self, *args, **kwargs)', 1851 'apply_kw': '(self, *args, **kwargs)'} 1852 custom_spec = { 1853 'args': '(slef, a=123)', 'self_arg': 'slef', # yes, slef 1854 'apply_pos': '(slef, a)', 'apply_kw': '(slef, a=a)'} 1855 1856 self._test_init(None, object_spec, wrapper_spec, custom_spec) 1857 self._test_init(True, object_spec, wrapper_spec, custom_spec) 1858 1859 @testing.fails_if(lambda: util.pypy, 1860 "pypy doesn't report Obj.__init__ as object.__init__") 1861 def test_init_bare(self): 1862 object_spec = { 1863 'args': 'self', 'self_arg': 'self', 1864 'apply_pos': 'self', 'apply_kw': 'self'} 1865 wrapper_spec = { 1866 'args': 'self, *args, **kwargs', 'self_arg': 'self', 1867 'apply_pos': 'self, *args, **kwargs', 1868 'apply_kw': 'self, *args, **kwargs'} 1869 custom_spec = { 1870 'args': 'slef, a=123', 'self_arg': 'slef', # yes, slef 1871 'apply_pos': 'slef, a', 'apply_kw': 'slef, a=a'} 1872 1873 self._test_init(False, object_spec, wrapper_spec, custom_spec) 1874 1875 def _test_init(self, grouped, object_spec, wrapper_spec, custom_spec): 1876 def test(fn, wanted): 1877 if grouped is None: 1878 parsed = util.format_argspec_init(fn) 1879 else: 1880 parsed = util.format_argspec_init(fn, grouped=grouped) 1881 eq_(parsed, wanted) 1882 1883 class Obj(object): 1884 pass 1885 1886 test(Obj.__init__, object_spec) 1887 1888 class Obj(object): 1889 def __init__(self): 1890 pass 1891 1892 test(Obj.__init__, object_spec) 1893 1894 class Obj(object): 1895 def __init__(slef, a=123): 1896 pass 1897 1898 test(Obj.__init__, custom_spec) 1899 1900 class Obj(list): 1901 pass 1902 1903 test(Obj.__init__, wrapper_spec) 1904 1905 class Obj(list): 1906 def __init__(self, *args, **kwargs): 1907 pass 1908 1909 test(Obj.__init__, wrapper_spec) 1910 1911 class Obj(list): 1912 def __init__(self): 1913 pass 1914 1915 test(Obj.__init__, object_spec) 1916 1917 class Obj(list): 1918 def __init__(slef, a=123): 1919 pass 1920 1921 test(Obj.__init__, custom_spec) 1922 1923 1924class GenericReprTest(fixtures.TestBase): 1925 1926 def test_all_positional(self): 1927 class Foo(object): 1928 def __init__(self, a, b, c): 1929 self.a = a 1930 self.b = b 1931 self.c = c 1932 eq_( 1933 util.generic_repr(Foo(1, 2, 3)), 1934 "Foo(1, 2, 3)" 1935 ) 1936 1937 def test_positional_plus_kw(self): 1938 class Foo(object): 1939 def __init__(self, a, b, c=5, d=4): 1940 self.a = a 1941 self.b = b 1942 self.c = c 1943 self.d = d 1944 eq_( 1945 util.generic_repr(Foo(1, 2, 3, 6)), 1946 "Foo(1, 2, c=3, d=6)" 1947 ) 1948 1949 def test_kw_defaults(self): 1950 class Foo(object): 1951 def __init__(self, a=1, b=2, c=3, d=4): 1952 self.a = a 1953 self.b = b 1954 self.c = c 1955 self.d = d 1956 eq_( 1957 util.generic_repr(Foo(1, 5, 3, 7)), 1958 "Foo(b=5, d=7)" 1959 ) 1960 1961 def test_multi_kw(self): 1962 class Foo(object): 1963 def __init__(self, a, b, c=3, d=4): 1964 self.a = a 1965 self.b = b 1966 self.c = c 1967 self.d = d 1968 1969 class Bar(Foo): 1970 def __init__(self, e, f, g=5, **kw): 1971 self.e = e 1972 self.f = f 1973 self.g = g 1974 super(Bar, self).__init__(**kw) 1975 1976 eq_( 1977 util.generic_repr( 1978 Bar('e', 'f', g=7, a=6, b=5, d=9), 1979 to_inspect=[Bar, Foo] 1980 ), 1981 "Bar('e', 'f', g=7, a=6, b=5, d=9)" 1982 ) 1983 1984 eq_( 1985 util.generic_repr( 1986 Bar('e', 'f', a=6, b=5), 1987 to_inspect=[Bar, Foo] 1988 ), 1989 "Bar('e', 'f', a=6, b=5)" 1990 ) 1991 1992 def test_multi_kw_repeated(self): 1993 class Foo(object): 1994 def __init__(self, a=1, b=2): 1995 self.a = a 1996 self.b = b 1997 1998 class Bar(Foo): 1999 def __init__(self, b=3, c=4, **kw): 2000 self.c = c 2001 super(Bar, self).__init__(b=b, **kw) 2002 2003 eq_( 2004 util.generic_repr( 2005 Bar(a='a', b='b', c='c'), 2006 to_inspect=[Bar, Foo] 2007 ), 2008 "Bar(b='b', c='c', a='a')" 2009 ) 2010 2011 def test_discard_vargs(self): 2012 class Foo(object): 2013 def __init__(self, a, b, *args): 2014 self.a = a 2015 self.b = b 2016 self.c, self.d = args[0:2] 2017 eq_( 2018 util.generic_repr(Foo(1, 2, 3, 4)), 2019 "Foo(1, 2)" 2020 ) 2021 2022 def test_discard_vargs_kwargs(self): 2023 class Foo(object): 2024 def __init__(self, a, b, *args, **kw): 2025 self.a = a 2026 self.b = b 2027 self.c, self.d = args[0:2] 2028 eq_( 2029 util.generic_repr(Foo(1, 2, 3, 4, x=7, y=4)), 2030 "Foo(1, 2)" 2031 ) 2032 2033 def test_significant_vargs(self): 2034 class Foo(object): 2035 def __init__(self, a, b, *args): 2036 self.a = a 2037 self.b = b 2038 self.args = args 2039 eq_( 2040 util.generic_repr(Foo(1, 2, 3, 4)), 2041 "Foo(1, 2, 3, 4)" 2042 ) 2043 2044 def test_no_args(self): 2045 class Foo(object): 2046 def __init__(self): 2047 pass 2048 eq_( 2049 util.generic_repr(Foo()), 2050 "Foo()" 2051 ) 2052 2053 def test_no_init(self): 2054 class Foo(object): 2055 pass 2056 eq_( 2057 util.generic_repr(Foo()), 2058 "Foo()" 2059 ) 2060 2061 2062class AsInterfaceTest(fixtures.TestBase): 2063 2064 class Something(object): 2065 2066 def _ignoreme(self): 2067 pass 2068 2069 def foo(self): 2070 pass 2071 2072 def bar(self): 2073 pass 2074 2075 class Partial(object): 2076 2077 def bar(self): 2078 pass 2079 2080 class Object(object): 2081 pass 2082 2083 def test_instance(self): 2084 obj = object() 2085 assert_raises(TypeError, util.as_interface, obj, 2086 cls=self.Something) 2087 2088 assert_raises(TypeError, util.as_interface, obj, 2089 methods=('foo')) 2090 2091 assert_raises(TypeError, util.as_interface, obj, 2092 cls=self.Something, required=('foo')) 2093 2094 obj = self.Something() 2095 eq_(obj, util.as_interface(obj, cls=self.Something)) 2096 eq_(obj, util.as_interface(obj, methods=('foo',))) 2097 eq_( 2098 obj, util.as_interface(obj, cls=self.Something, 2099 required=('outofband',))) 2100 partial = self.Partial() 2101 2102 slotted = self.Object() 2103 slotted.bar = lambda self: 123 2104 2105 for obj in partial, slotted: 2106 eq_(obj, util.as_interface(obj, cls=self.Something)) 2107 assert_raises(TypeError, util.as_interface, obj, 2108 methods=('foo')) 2109 eq_(obj, util.as_interface(obj, methods=('bar',))) 2110 eq_(obj, util.as_interface(obj, cls=self.Something, 2111 required=('bar',))) 2112 assert_raises(TypeError, util.as_interface, obj, 2113 cls=self.Something, required=('foo',)) 2114 2115 assert_raises(TypeError, util.as_interface, obj, 2116 cls=self.Something, required=self.Something) 2117 2118 def test_dict(self): 2119 obj = {} 2120 assert_raises(TypeError, util.as_interface, obj, 2121 cls=self.Something) 2122 assert_raises(TypeError, util.as_interface, obj, methods='foo') 2123 assert_raises(TypeError, util.as_interface, obj, 2124 cls=self.Something, required='foo') 2125 2126 def assertAdapted(obj, *methods): 2127 assert isinstance(obj, type) 2128 found = set([m for m in dir(obj) if not m.startswith('_')]) 2129 for method in methods: 2130 assert method in found 2131 found.remove(method) 2132 assert not found 2133 2134 def fn(self): return 123 2135 obj = {'foo': fn, 'bar': fn} 2136 res = util.as_interface(obj, cls=self.Something) 2137 assertAdapted(res, 'foo', 'bar') 2138 res = util.as_interface(obj, cls=self.Something, 2139 required=self.Something) 2140 assertAdapted(res, 'foo', 'bar') 2141 res = util.as_interface(obj, cls=self.Something, required=('foo',)) 2142 assertAdapted(res, 'foo', 'bar') 2143 res = util.as_interface(obj, methods=('foo', 'bar')) 2144 assertAdapted(res, 'foo', 'bar') 2145 res = util.as_interface(obj, methods=('foo', 'bar', 'baz')) 2146 assertAdapted(res, 'foo', 'bar') 2147 res = util.as_interface(obj, methods=('foo', 'bar'), required=('foo',)) 2148 assertAdapted(res, 'foo', 'bar') 2149 assert_raises(TypeError, util.as_interface, obj, methods=('foo',)) 2150 assert_raises(TypeError, util.as_interface, obj, 2151 methods=('foo', 'bar', 'baz'), required=('baz', )) 2152 obj = {'foo': 123} 2153 assert_raises(TypeError, util.as_interface, obj, cls=self.Something) 2154 2155 2156class TestClassHierarchy(fixtures.TestBase): 2157 2158 def test_object(self): 2159 eq_(set(util.class_hierarchy(object)), set((object,))) 2160 2161 def test_single(self): 2162 class A(object): 2163 pass 2164 2165 class B(object): 2166 pass 2167 2168 eq_(set(util.class_hierarchy(A)), set((A, object))) 2169 eq_(set(util.class_hierarchy(B)), set((B, object))) 2170 2171 class C(A, B): 2172 pass 2173 2174 eq_(set(util.class_hierarchy(A)), set((A, B, C, object))) 2175 eq_(set(util.class_hierarchy(B)), set((A, B, C, object))) 2176 2177 if util.py2k: 2178 def test_oldstyle_mixin(self): 2179 class A(object): 2180 pass 2181 2182 class Mixin: 2183 pass 2184 2185 class B(A, Mixin): 2186 pass 2187 2188 eq_(set(util.class_hierarchy(B)), set((A, B, object))) 2189 eq_(set(util.class_hierarchy(Mixin)), set()) 2190 eq_(set(util.class_hierarchy(A)), set((A, B, object))) 2191 2192 2193class ReraiseTest(fixtures.TestBase): 2194 @testing.requires.python3 2195 def test_raise_from_cause_same_cause(self): 2196 class MyException(Exception): 2197 pass 2198 2199 def go(): 2200 try: 2201 raise MyException("exc one") 2202 except Exception as err: 2203 util.raise_from_cause(err) 2204 2205 try: 2206 go() 2207 assert False 2208 except MyException as err: 2209 is_(err.__cause__, None) 2210 2211 def test_reraise_disallow_same_cause(self): 2212 class MyException(Exception): 2213 pass 2214 2215 def go(): 2216 try: 2217 raise MyException("exc one") 2218 except Exception as err: 2219 type_, value, tb = sys.exc_info() 2220 util.reraise(type_, err, tb, value) 2221 2222 assert_raises_message( 2223 AssertionError, 2224 "Same cause emitted", 2225 go 2226 ) 2227 2228 def test_raise_from_cause(self): 2229 class MyException(Exception): 2230 pass 2231 2232 class MyOtherException(Exception): 2233 pass 2234 2235 me = MyException("exc on") 2236 2237 def go(): 2238 try: 2239 raise me 2240 except Exception: 2241 util.raise_from_cause(MyOtherException("exc two")) 2242 2243 try: 2244 go() 2245 assert False 2246 except MyOtherException as moe: 2247 if testing.requires.python3.enabled: 2248 is_(moe.__cause__, me) 2249 2250 @testing.requires.python2 2251 def test_safe_reraise_py2k_warning(self): 2252 class MyException(Exception): 2253 pass 2254 2255 class MyOtherException(Exception): 2256 pass 2257 2258 m1 = MyException("exc one") 2259 m2 = MyOtherException("exc two") 2260 2261 def go2(): 2262 raise m2 2263 2264 def go(): 2265 try: 2266 raise m1 2267 except Exception: 2268 with util.safe_reraise(): 2269 go2() 2270 2271 with expect_warnings( 2272 "An exception has occurred during handling of a previous " 2273 "exception. The previous exception " 2274 "is:.*MyException.*exc one" 2275 ): 2276 try: 2277 go() 2278 assert False 2279 except MyOtherException: 2280 pass 2281 2282 2283class TestClassProperty(fixtures.TestBase): 2284 2285 def test_simple(self): 2286 class A(object): 2287 something = {'foo': 1} 2288 2289 class B(A): 2290 2291 @classproperty 2292 def something(cls): 2293 d = dict(super(B, cls).something) 2294 d.update({'bazz': 2}) 2295 return d 2296 2297 eq_(B.something, {'foo': 1, 'bazz': 2}) 2298 2299 2300class TestProperties(fixtures.TestBase): 2301 2302 def test_pickle(self): 2303 data = {'hello': 'bla'} 2304 props = util.Properties(data) 2305 2306 for loader, dumper in picklers(): 2307 s = dumper(props) 2308 p = loader(s) 2309 2310 eq_(props._data, p._data) 2311 eq_(props.keys(), p.keys()) 2312 2313 def test_pickle_immuatbleprops(self): 2314 data = {'hello': 'bla'} 2315 props = util.Properties(data).as_immutable() 2316 2317 for loader, dumper in picklers(): 2318 s = dumper(props) 2319 p = loader(s) 2320 2321 eq_(props._data, p._data) 2322 eq_(props.keys(), p.keys()) 2323 2324 def test_pickle_orderedprops(self): 2325 data = {'hello': 'bla'} 2326 props = util.OrderedProperties() 2327 props.update(data) 2328 2329 for loader, dumper in picklers(): 2330 s = dumper(props) 2331 p = loader(s) 2332 2333 eq_(props._data, p._data) 2334 eq_(props.keys(), p.keys()) 2335