7 from test
.test_support
import TestFailed
, have_unicode
, TESTFN
, \
10 # Tests that try a number of pickle protocols should have a
11 # for proto in protocols:
13 assert pickle
.HIGHEST_PROTOCOL
== cPickle
.HIGHEST_PROTOCOL
== 2
14 protocols
= range(pickle
.HIGHEST_PROTOCOL
+ 1)
17 # Return True if opcode code appears in the pickle, else False.
18 def opcode_in_pickle(code
, pickle
):
19 for op
, dummy
, dummy
in pickletools
.genops(pickle
):
24 # Return the number of times opcode code appears in pickle.
25 def count_opcode(code
, pickle
):
27 for op
, dummy
, dummy
in pickletools
.genops(pickle
):
32 # We can't very well test the extension registry without putting known stuff
33 # in it, but we have to be careful to restore its original state. Code
36 # e = ExtensionSaver(extension_code)
38 # fiddle w/ the extension registry's stuff for extension_code
43 # Remember current registration for code (if any), and remove it (if
45 def __init__(self
, code
):
47 if code
in copyreg
._inverted
_registry
:
48 self
.pair
= copyreg
._inverted
_registry
[code
]
49 copyreg
.remove_extension(self
.pair
[0], self
.pair
[1], code
)
53 # Restore previous registration for code.
56 curpair
= copyreg
._inverted
_registry
.get(code
)
57 if curpair
is not None:
58 copyreg
.remove_extension(curpair
[0], curpair
[1], code
)
61 copyreg
.add_extension(pair
[0], pair
[1], code
)
64 def __cmp__(self
, other
):
65 return cmp(self
.__dict
__, other
.__dict
__)
69 C
.__module
__ = "__main__"
72 def __init__(self
, x
):
77 def __init__(self
, a
, b
):
81 def __getinitargs__(self
):
84 class metaclass(type):
87 class use_metaclass(object):
88 __metaclass__
= metaclass
90 # DATA0 .. DATA2 are the pickles we expect under the various protocols, for
91 # the object returned by create_data().
93 # break into multiple strings to avoid confusing font-lock-mode
139 # Disassembly of DATA0.
142 1: l LIST (MARK at 0)
150 18: c GLOBAL '__builtin__ complex'
155 49: t TUPLE (MARK at 42)
175 110: I INT 2147483647
177 123: I INT -2147483647
179 137: I INT -2147483648
186 166: i INST '__main__ C' (MARK at 165)
189 182: d DICT (MARK at 181)
201 218: t TUPLE (MARK at 151)
209 highest protocol among opcodes = 0
212 DATA1
= (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
213 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
214 '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
215 '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
216 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
217 '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
218 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
222 # Disassembly of DATA1.
230 19: c GLOBAL '__builtin__ complex'
235 61: t TUPLE (MARK at 42)
246 97: J BININT 2147483647
247 102: J BININT -2147483647
248 107: J BININT -2147483648
250 113: U SHORT_BINSTRING 'abc'
254 123: c GLOBAL '__main__ C'
256 137: o OBJ (MARK at 122)
261 144: U SHORT_BINSTRING 'foo'
264 153: U SHORT_BINSTRING 'bar'
267 162: u SETITEMS (MARK at 143)
270 166: t TUPLE (MARK at 112)
274 173: e APPENDS (MARK at 3)
276 highest protocol among opcodes = 1
279 DATA2
= ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'
280 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'
281 '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'
282 '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'
283 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'
284 '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'
285 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')
287 # Disassembly of DATA2.
296 20: c GLOBAL '__builtin__ complex'
311 97: J BININT 2147483647
312 102: J BININT -2147483647
313 107: J BININT -2147483648
315 113: U SHORT_BINSTRING 'abc'
319 123: c GLOBAL '__main__ C'
321 137: o OBJ (MARK at 122)
326 144: U SHORT_BINSTRING 'foo'
329 153: U SHORT_BINSTRING 'bar'
332 162: u SETITEMS (MARK at 143)
335 166: t TUPLE (MARK at 112)
339 173: e APPENDS (MARK at 5)
341 highest protocol among opcodes = 2
348 x
= [0, 1L, 2.0, 3.0+0j
]
349 # Append some integer test cases at cPickle.c's internal size
355 uint1max
, -uint1max
, -uint1max
-1,
356 uint2max
, -uint2max
, -uint2max
-1,
357 int4max
, -int4max
, -int4max
-1])
358 y
= ('abc', 'abc', c
, c
)
364 class AbstractPickleTests(unittest
.TestCase
):
365 # Subclass must define self.dumps, self.loads, self.error.
367 _testdata
= create_data()
373 # test various datatypes not tested by testdata
374 for proto
in protocols
:
376 s
= self
.dumps(x
, proto
)
378 self
.assertEqual(x
, y
)
381 s
= self
.dumps(x
, proto
)
383 self
.assertEqual(x
, y
)
386 s
= self
.dumps(x
, proto
)
388 self
.assertEqual(x
, y
)
390 # XXX test __reduce__ protocol?
392 def test_roundtrip_equality(self
):
393 expected
= self
._testdata
394 for proto
in protocols
:
395 s
= self
.dumps(expected
, proto
)
397 self
.assertEqual(expected
, got
)
399 def test_load_from_canned_string(self
):
400 expected
= self
._testdata
401 for canned
in DATA0
, DATA1
, DATA2
:
402 got
= self
.loads(canned
)
403 self
.assertEqual(expected
, got
)
405 # There are gratuitous differences between pickles produced by
406 # pickle and cPickle, largely because cPickle starts PUT indices at
407 # 1 and pickle starts them at 0. See XXX comment in cPickle's put2() --
408 # there's a comment with an exclamation point there whose meaning
409 # is a mystery. cPickle also suppresses PUT for objects with a refcount
411 def dont_test_disassembly(self
):
412 from cStringIO
import StringIO
413 from pickletools
import dis
415 for proto
, expected
in (0, DATA0_DIS
), (1, DATA1_DIS
):
416 s
= self
.dumps(self
._testdata
, proto
)
417 filelike
= StringIO()
419 got
= filelike
.getvalue()
420 self
.assertEqual(expected
, got
)
422 def test_recursive_list(self
):
425 for proto
in protocols
:
426 s
= self
.dumps(l
, proto
)
428 self
.assertEqual(len(x
), 1)
429 self
.assert_(x
is x
[0])
431 def test_recursive_dict(self
):
434 for proto
in protocols
:
435 s
= self
.dumps(d
, proto
)
437 self
.assertEqual(x
.keys(), [1])
438 self
.assert_(x
[1] is x
)
440 def test_recursive_inst(self
):
443 for proto
in protocols
:
446 self
.assertEqual(dir(x
), dir(i
))
447 self
.assert_(x
.attr
is x
)
449 def test_recursive_multi(self
):
455 for proto
in protocols
:
456 s
= self
.dumps(l
, proto
)
458 self
.assertEqual(len(x
), 1)
459 self
.assertEqual(dir(x
[0]), dir(i
))
460 self
.assertEqual(x
[0].attr
.keys(), [1])
461 self
.assert_(x
[0].attr
[1] is x
)
463 def test_garyp(self
):
464 self
.assertRaises(self
.error
, self
.loads
, 'garyp')
466 def test_insecure_strings(self
):
467 insecure
= ["abc", "2 + 2", # not quoted
468 #"'abc' + 'def'", # not a single quoted string
469 "'abc", # quote is not closed
470 "'abc\"", # open quote and close quote don't match
471 "'abc' ?", # junk after close quote
472 "'\\'", # trailing backslash
473 # some tests of the quoting rules
475 #"'\\\\a\'\'\'\\\'\\\\\''",
478 buf
= "S" + s
+ "\012p0\012."
479 self
.assertRaises(ValueError, self
.loads
, buf
)
482 def test_unicode(self
):
483 endcases
= [unicode(''), unicode('<\\u>'), unicode('<\\\u1234>'),
484 unicode('<\n>'), unicode('<\\>')]
485 for proto
in protocols
:
487 p
= self
.dumps(u
, proto
)
489 self
.assertEqual(u2
, u
)
493 for proto
in protocols
:
496 for expected
in (-n
, n
):
497 s
= self
.dumps(expected
, proto
)
499 self
.assertEqual(expected
, n2
)
502 def test_maxint64(self
):
503 maxint64
= (1L << 63) - 1
504 data
= 'I' + str(maxint64
) + '\n.'
505 got
= self
.loads(data
)
506 self
.assertEqual(got
, maxint64
)
508 # Try too with a bogus literal.
509 data
= 'I' + str(maxint64
) + 'JUNK\n.'
510 self
.assertRaises(ValueError, self
.loads
, data
)
513 for proto
in protocols
:
514 # 256 bytes is where LONG4 begins.
515 for nbits
in 1, 8, 8*254, 8*255, 8*256, 8*257:
517 for npos
in nbase
-1, nbase
, nbase
+1:
518 for n
in npos
, -npos
:
519 pickle
= self
.dumps(n
, proto
)
520 got
= self
.loads(pickle
)
521 self
.assertEqual(n
, got
)
522 # Try a monster. This is quadratic-time in protos 0 & 1, so don't
524 nbase
= long("deadbeeffeedface", 16)
525 nbase
+= nbase
<< 1000000
526 for n
in nbase
, -nbase
:
529 self
.assertEqual(n
, got
)
531 @run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
532 def test_float_format(self
):
533 # make sure that floats are formatted locale independent
534 self
.assertEqual(self
.dumps(1.2)[0:3], 'F1.')
536 def test_reduce(self
):
539 def test_getinitargs(self
):
542 def test_metaclass(self
):
544 for proto
in protocols
:
545 s
= self
.dumps(a
, proto
)
547 self
.assertEqual(a
.__class
__, b
.__class
__)
549 def test_structseq(self
):
554 for proto
in protocols
:
555 s
= self
.dumps(t
, proto
)
557 self
.assertEqual(t
, u
)
558 if hasattr(os
, "stat"):
559 t
= os
.stat(os
.curdir
)
560 s
= self
.dumps(t
, proto
)
562 self
.assertEqual(t
, u
)
563 if hasattr(os
, "statvfs"):
564 t
= os
.statvfs(os
.curdir
)
565 s
= self
.dumps(t
, proto
)
567 self
.assertEqual(t
, u
)
569 # Tests for protocol 2
571 def test_proto(self
):
572 build_none
= pickle
.NONE
+ pickle
.STOP
573 for proto
in protocols
:
574 expected
= build_none
576 expected
= pickle
.PROTO
+ chr(proto
) + expected
577 p
= self
.dumps(None, proto
)
578 self
.assertEqual(p
, expected
)
580 oob
= protocols
[-1] + 1 # a future protocol
581 badpickle
= pickle
.PROTO
+ chr(oob
) + build_none
583 self
.loads(badpickle
)
584 except ValueError, detail
:
585 self
.failUnless(str(detail
).startswith(
586 "unsupported pickle protocol"))
588 self
.fail("expected bad protocol number to raise ValueError")
590 def test_long1(self
):
591 x
= 12345678910111213141516178920L
592 for proto
in protocols
:
593 s
= self
.dumps(x
, proto
)
595 self
.assertEqual(x
, y
)
596 self
.assertEqual(opcode_in_pickle(pickle
.LONG1
, s
), proto
>= 2)
598 def test_long4(self
):
599 x
= 12345678910111213141516178920L << (256*8)
600 for proto
in protocols
:
601 s
= self
.dumps(x
, proto
)
603 self
.assertEqual(x
, y
)
604 self
.assertEqual(opcode_in_pickle(pickle
.LONG4
, s
), proto
>= 2)
606 def test_short_tuples(self
):
607 # Map (proto, len(tuple)) to expected opcode.
608 expected_opcode
= {(0, 0): pickle
.TUPLE
,
609 (0, 1): pickle
.TUPLE
,
610 (0, 2): pickle
.TUPLE
,
611 (0, 3): pickle
.TUPLE
,
612 (0, 4): pickle
.TUPLE
,
614 (1, 0): pickle
.EMPTY_TUPLE
,
615 (1, 1): pickle
.TUPLE
,
616 (1, 2): pickle
.TUPLE
,
617 (1, 3): pickle
.TUPLE
,
618 (1, 4): pickle
.TUPLE
,
620 (2, 0): pickle
.EMPTY_TUPLE
,
621 (2, 1): pickle
.TUPLE1
,
622 (2, 2): pickle
.TUPLE2
,
623 (2, 3): pickle
.TUPLE3
,
624 (2, 4): pickle
.TUPLE
,
631 for proto
in protocols
:
632 for x
in a
, b
, c
, d
, e
:
633 s
= self
.dumps(x
, proto
)
635 self
.assertEqual(x
, y
, (proto
, x
, s
, y
))
636 expected
= expected_opcode
[proto
, len(x
)]
637 self
.assertEqual(opcode_in_pickle(expected
, s
), True)
639 def test_singletons(self
):
640 # Map (proto, singleton) to expected opcode.
641 expected_opcode
= {(0, None): pickle
.NONE
,
642 (1, None): pickle
.NONE
,
643 (2, None): pickle
.NONE
,
645 (0, True): pickle
.INT
,
646 (1, True): pickle
.INT
,
647 (2, True): pickle
.NEWTRUE
,
649 (0, False): pickle
.INT
,
650 (1, False): pickle
.INT
,
651 (2, False): pickle
.NEWFALSE
,
653 for proto
in protocols
:
654 for x
in None, False, True:
655 s
= self
.dumps(x
, proto
)
657 self
.assert_(x
is y
, (proto
, x
, s
, y
))
658 expected
= expected_opcode
[proto
, x
]
659 self
.assertEqual(opcode_in_pickle(expected
, s
), True)
661 def test_newobj_tuple(self
):
662 x
= MyTuple([1, 2, 3])
665 for proto
in protocols
:
666 s
= self
.dumps(x
, proto
)
668 self
.assertEqual(tuple(x
), tuple(y
))
669 self
.assertEqual(x
.__dict
__, y
.__dict
__)
671 def test_newobj_list(self
):
672 x
= MyList([1, 2, 3])
675 for proto
in protocols
:
676 s
= self
.dumps(x
, proto
)
678 self
.assertEqual(list(x
), list(y
))
679 self
.assertEqual(x
.__dict
__, y
.__dict
__)
681 def test_newobj_generic(self
):
682 for proto
in protocols
:
687 s
= self
.dumps(x
, proto
)
689 detail
= (proto
, C
, B
, x
, y
, type(y
))
690 self
.assertEqual(B(x
), B(y
), detail
)
691 self
.assertEqual(x
.__dict
__, y
.__dict
__, detail
)
693 # Register a type with copyreg, with extension code extcode. Pickle
694 # an object of that type. Check that the resulting pickle uses opcode
695 # (EXT[124]) under proto 2, and not in proto 1.
697 def produce_global_ext(self
, extcode
, opcode
):
698 e
= ExtensionSaver(extcode
)
700 copyreg
.add_extension(__name__
, "MyList", extcode
)
701 x
= MyList([1, 2, 3])
705 # Dump using protocol 1 for comparison.
706 s1
= self
.dumps(x
, 1)
707 self
.assert_(__name__
in s1
)
708 self
.assert_("MyList" in s1
)
709 self
.assertEqual(opcode_in_pickle(opcode
, s1
), False)
712 self
.assertEqual(list(x
), list(y
))
713 self
.assertEqual(x
.__dict
__, y
.__dict
__)
715 # Dump using protocol 2 for test.
716 s2
= self
.dumps(x
, 2)
717 self
.assert_(__name__
not in s2
)
718 self
.assert_("MyList" not in s2
)
719 self
.assertEqual(opcode_in_pickle(opcode
, s2
), True)
722 self
.assertEqual(list(x
), list(y
))
723 self
.assertEqual(x
.__dict
__, y
.__dict
__)
728 def test_global_ext1(self
):
729 self
.produce_global_ext(0x00000001, pickle
.EXT1
) # smallest EXT1 code
730 self
.produce_global_ext(0x000000ff, pickle
.EXT1
) # largest EXT1 code
732 def test_global_ext2(self
):
733 self
.produce_global_ext(0x00000100, pickle
.EXT2
) # smallest EXT2 code
734 self
.produce_global_ext(0x0000ffff, pickle
.EXT2
) # largest EXT2 code
735 self
.produce_global_ext(0x0000abcd, pickle
.EXT2
) # check endianness
737 def test_global_ext4(self
):
738 self
.produce_global_ext(0x00010000, pickle
.EXT4
) # smallest EXT4 code
739 self
.produce_global_ext(0x7fffffff, pickle
.EXT4
) # largest EXT4 code
740 self
.produce_global_ext(0x12abcdef, pickle
.EXT4
) # check endianness
742 def test_list_chunking(self
):
743 n
= 10 # too small to chunk
745 for proto
in protocols
:
746 s
= self
.dumps(x
, proto
)
748 self
.assertEqual(x
, y
)
749 num_appends
= count_opcode(pickle
.APPENDS
, s
)
750 self
.assertEqual(num_appends
, proto
> 0)
752 n
= 2500 # expect at least two chunks when proto > 0
754 for proto
in protocols
:
755 s
= self
.dumps(x
, proto
)
757 self
.assertEqual(x
, y
)
758 num_appends
= count_opcode(pickle
.APPENDS
, s
)
760 self
.assertEqual(num_appends
, 0)
762 self
.failUnless(num_appends
>= 2)
764 def test_dict_chunking(self
):
765 n
= 10 # too small to chunk
766 x
= dict.fromkeys(range(n
))
767 for proto
in protocols
:
768 s
= self
.dumps(x
, proto
)
770 self
.assertEqual(x
, y
)
771 num_setitems
= count_opcode(pickle
.SETITEMS
, s
)
772 self
.assertEqual(num_setitems
, proto
> 0)
774 n
= 2500 # expect at least two chunks when proto > 0
775 x
= dict.fromkeys(range(n
))
776 for proto
in protocols
:
777 s
= self
.dumps(x
, proto
)
779 self
.assertEqual(x
, y
)
780 num_setitems
= count_opcode(pickle
.SETITEMS
, s
)
782 self
.assertEqual(num_setitems
, 0)
784 self
.failUnless(num_setitems
>= 2)
786 def test_simple_newobj(self
):
787 x
= object.__new
__(SimpleNewObj
) # avoid __init__
789 for proto
in protocols
:
790 s
= self
.dumps(x
, proto
)
791 self
.assertEqual(opcode_in_pickle(pickle
.NEWOBJ
, s
), proto
>= 2)
792 y
= self
.loads(s
) # will raise TypeError if __init__ called
793 self
.assertEqual(y
.abc
, 666)
794 self
.assertEqual(x
.__dict
__, y
.__dict
__)
796 def test_newobj_list_slots(self
):
797 x
= SlotList([1, 2, 3])
802 self
.assertEqual(list(x
), list(y
))
803 self
.assertEqual(x
.__dict
__, y
.__dict
__)
804 self
.assertEqual(x
.foo
, y
.foo
)
805 self
.assertEqual(x
.bar
, y
.bar
)
807 def test_reduce_overrides_default_reduce_ex(self
):
808 for proto
in 0, 1, 2:
810 self
.assertEqual(x
._reduce
_called
, 0)
811 s
= self
.dumps(x
, proto
)
812 self
.assertEqual(x
._reduce
_called
, 1)
814 self
.assertEqual(y
._reduce
_called
, 0)
816 def test_reduce_ex_called(self
):
817 for proto
in 0, 1, 2:
819 self
.assertEqual(x
._proto
, None)
820 s
= self
.dumps(x
, proto
)
821 self
.assertEqual(x
._proto
, proto
)
823 self
.assertEqual(y
._proto
, None)
825 def test_reduce_ex_overrides_reduce(self
):
826 for proto
in 0, 1, 2:
828 self
.assertEqual(x
._proto
, None)
829 s
= self
.dumps(x
, proto
)
830 self
.assertEqual(x
._proto
, proto
)
832 self
.assertEqual(y
._proto
, None)
834 def test_reduce_ex_calls_base(self
):
835 for proto
in 0, 1, 2:
837 self
.assertEqual(x
._proto
, None)
838 s
= self
.dumps(x
, proto
)
839 self
.assertEqual(x
._proto
, proto
)
841 self
.assertEqual(y
._proto
, proto
)
843 def test_reduce_calls_base(self
):
844 for proto
in 0, 1, 2:
846 self
.assertEqual(x
._reduce
_called
, 0)
847 s
= self
.dumps(x
, proto
)
848 self
.assertEqual(x
._reduce
_called
, 1)
850 self
.assertEqual(y
._reduce
_called
, 1)
852 # Test classes for reduce_ex
854 class REX_one(object):
856 def __reduce__(self
):
857 self
._reduce
_called
= 1
859 # No __reduce_ex__ here, but inheriting it from object
861 class REX_two(object):
863 def __reduce_ex__(self
, proto
):
866 # No __reduce__ here, but inheriting it from object
868 class REX_three(object):
870 def __reduce_ex__(self
, proto
):
873 def __reduce__(self
):
874 raise TestFailed
, "This __reduce__ shouldn't be called"
876 class REX_four(object):
878 def __reduce_ex__(self
, proto
):
880 return object.__reduce
_ex
__(self
, proto
)
881 # Calling base class method should succeed
883 class REX_five(object):
885 def __reduce__(self
):
886 self
._reduce
_called
= 1
887 return object.__reduce
__(self
)
888 # This one used to fail with infinite recursion
890 # Test classes for newobj
898 class MyFloat(float):
901 class MyComplex(complex):
907 class MyUnicode(unicode):
908 sample
= u
"hello \u1234"
910 class MyTuple(tuple):
917 sample
= {"a": 1, "b": 2}
919 myclasses
= [MyInt
, MyLong
, MyFloat
,
922 MyTuple
, MyList
, MyDict
]
925 class SlotList(MyList
):
928 class SimpleNewObj(object):
929 def __init__(self
, a
, b
, c
):
930 # raise an error, to make sure this isn't called
931 raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
933 class AbstractPickleModuleTests(unittest
.TestCase
):
935 def test_dump_closed_file(self
):
937 f
= open(TESTFN
, "w")
940 self
.assertRaises(ValueError, self
.module
.dump
, 123, f
)
944 def test_load_closed_file(self
):
946 f
= open(TESTFN
, "w")
949 self
.assertRaises(ValueError, self
.module
.dump
, 123, f
)
953 def test_highest_protocol(self
):
954 # Of course this needs to be changed when HIGHEST_PROTOCOL changes.
955 self
.assertEqual(self
.module
.HIGHEST_PROTOCOL
, 2)
957 def test_callapi(self
):
958 from cStringIO
import StringIO
960 # With and without keyword arguments
961 self
.module
.dump(123, f
, -1)
962 self
.module
.dump(123, file=f
, protocol
=-1)
963 self
.module
.dumps(123, -1)
964 self
.module
.dumps(123, protocol
=-1)
965 self
.module
.Pickler(f
, -1)
966 self
.module
.Pickler(f
, protocol
=-1)
968 class AbstractPersistentPicklerTests(unittest
.TestCase
):
970 # This class defines persistent_id() and persistent_load()
971 # functions that should be used by the pickler. All even integers
972 # are pickled using persistent ids.
974 def persistent_id(self
, object):
975 if isinstance(object, int) and object % 2 == 0:
981 def persistent_load(self
, oid
):
984 assert object % 2 == 0
987 def test_persistence(self
):
991 self
.assertEqual(self
.loads(self
.dumps(L
)), L
)
992 self
.assertEqual(self
.id_count
, 5)
993 self
.assertEqual(self
.load_count
, 5)
995 def test_bin_persistence(self
):
999 self
.assertEqual(self
.loads(self
.dumps(L
, 1)), L
)
1000 self
.assertEqual(self
.id_count
, 5)
1001 self
.assertEqual(self
.load_count
, 5)