@@ -145,7 +145,7 @@ def create_dynamic_class(name, bases):
145
145
result .reduce_args = (name , bases )
146
146
return result
147
147
148
- # DATA0 .. DATA2 are the pickles we expect under the various protocols, for
148
+ # DATA0 .. DATA4 are the pickles we expect under the various protocols, for
149
149
# the object returned by create_data().
150
150
151
151
DATA0 = (
@@ -401,27 +401,176 @@ def create_dynamic_class(name, bases):
401
401
highest protocol among opcodes = 2
402
402
"""
403
403
404
+ DATA3 = (
405
+ b'\x80 \x03 ]q\x00 (K\x00 K\x01 G@\x00 \x00 \x00 \x00 \x00 \x00 \x00 c'
406
+ b'builtins\n complex\n q\x01 G'
407
+ b'@\x08 \x00 \x00 \x00 \x00 \x00 \x00 G\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x86 q\x02 '
408
+ b'Rq\x03 K\x01 J\xff \xff \xff \xff K\xff J\x01 \xff \xff \xff J\x00 \xff '
409
+ b'\xff \xff M\xff \xff J\x01 \x00 \xff \xff J\x00 \x00 \xff \xff J\xff \xff \xff \x7f '
410
+ b'J\x01 \x00 \x00 \x80 J\x00 \x00 \x00 \x80 (X\x03 \x00 \x00 \x00 abcq'
411
+ b'\x04 h\x04 c__main__\n C\n q\x05 )\x81 q'
412
+ b'\x06 }q\x07 (X\x03 \x00 \x00 \x00 barq\x08 K\x02 X\x03 \x00 '
413
+ b'\x00 \x00 fooq\t K\x01 ubh\x06 tq\n h\n K\x05 '
414
+ b'e.'
415
+ )
416
+
417
+ # Disassembly of DATA3
418
+ DATA3_DIS = """\
419
+ 0: \x80 PROTO 3
420
+ 2: ] EMPTY_LIST
421
+ 3: q BINPUT 0
422
+ 5: ( MARK
423
+ 6: K BININT1 0
424
+ 8: K BININT1 1
425
+ 10: G BINFLOAT 2.0
426
+ 19: c GLOBAL 'builtins complex'
427
+ 37: q BINPUT 1
428
+ 39: G BINFLOAT 3.0
429
+ 48: G BINFLOAT 0.0
430
+ 57: \x86 TUPLE2
431
+ 58: q BINPUT 2
432
+ 60: R REDUCE
433
+ 61: q BINPUT 3
434
+ 63: K BININT1 1
435
+ 65: J BININT -1
436
+ 70: K BININT1 255
437
+ 72: J BININT -255
438
+ 77: J BININT -256
439
+ 82: M BININT2 65535
440
+ 85: J BININT -65535
441
+ 90: J BININT -65536
442
+ 95: J BININT 2147483647
443
+ 100: J BININT -2147483647
444
+ 105: J BININT -2147483648
445
+ 110: ( MARK
446
+ 111: X BINUNICODE 'abc'
447
+ 119: q BINPUT 4
448
+ 121: h BINGET 4
449
+ 123: c GLOBAL '__main__ C'
450
+ 135: q BINPUT 5
451
+ 137: ) EMPTY_TUPLE
452
+ 138: \x81 NEWOBJ
453
+ 139: q BINPUT 6
454
+ 141: } EMPTY_DICT
455
+ 142: q BINPUT 7
456
+ 144: ( MARK
457
+ 145: X BINUNICODE 'bar'
458
+ 153: q BINPUT 8
459
+ 155: K BININT1 2
460
+ 157: X BINUNICODE 'foo'
461
+ 165: q BINPUT 9
462
+ 167: K BININT1 1
463
+ 169: u SETITEMS (MARK at 144)
464
+ 170: b BUILD
465
+ 171: h BINGET 6
466
+ 173: t TUPLE (MARK at 110)
467
+ 174: q BINPUT 10
468
+ 176: h BINGET 10
469
+ 178: K BININT1 5
470
+ 180: e APPENDS (MARK at 5)
471
+ 181: . STOP
472
+ highest protocol among opcodes = 2
473
+ """
474
+
475
+ DATA4 = (
476
+ b'\x80 \x04 \x95 \xa8 \x00 \x00 \x00 \x00 \x00 \x00 \x00 ]\x94 (K\x00 K\x01 G@'
477
+ b'\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x8c \x08 builtins\x94 \x8c \x07 '
478
+ b'complex\x94 \x93 \x94 G@\x08 \x00 \x00 \x00 \x00 \x00 \x00 G'
479
+ b'\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x86 \x94 R\x94 K\x01 J\xff \xff \xff \xff K'
480
+ b'\xff J\x01 \xff \xff \xff J\x00 \xff \xff \xff M\xff \xff J\x01 \x00 \xff \xff J'
481
+ b'\x00 \x00 \xff \xff J\xff \xff \xff \x7f J\x01 \x00 \x00 \x80 J\x00 \x00 \x00 \x80 ('
482
+ b'\x8c \x03 abc\x94 h\x06 \x8c \x08 __main__\x94 \x8c '
483
+ b'\x01 C\x94 \x93 \x94 )\x81 \x94 }\x94 (\x8c \x03 bar\x94 K\x02 \x8c '
484
+ b'\x03 foo\x94 K\x01 ubh\n t\x94 h\x0e K\x05 e.'
485
+ )
486
+
487
+ # Disassembly of DATA4
488
+ DATA4_DIS = """\
489
+ 0: \x80 PROTO 4
490
+ 2: \x95 FRAME 168
491
+ 11: ] EMPTY_LIST
492
+ 12: \x94 MEMOIZE
493
+ 13: ( MARK
494
+ 14: K BININT1 0
495
+ 16: K BININT1 1
496
+ 18: G BINFLOAT 2.0
497
+ 27: \x8c SHORT_BINUNICODE 'builtins'
498
+ 37: \x94 MEMOIZE
499
+ 38: \x8c SHORT_BINUNICODE 'complex'
500
+ 47: \x94 MEMOIZE
501
+ 48: \x93 STACK_GLOBAL
502
+ 49: \x94 MEMOIZE
503
+ 50: G BINFLOAT 3.0
504
+ 59: G BINFLOAT 0.0
505
+ 68: \x86 TUPLE2
506
+ 69: \x94 MEMOIZE
507
+ 70: R REDUCE
508
+ 71: \x94 MEMOIZE
509
+ 72: K BININT1 1
510
+ 74: J BININT -1
511
+ 79: K BININT1 255
512
+ 81: J BININT -255
513
+ 86: J BININT -256
514
+ 91: M BININT2 65535
515
+ 94: J BININT -65535
516
+ 99: J BININT -65536
517
+ 104: J BININT 2147483647
518
+ 109: J BININT -2147483647
519
+ 114: J BININT -2147483648
520
+ 119: ( MARK
521
+ 120: \x8c SHORT_BINUNICODE 'abc'
522
+ 125: \x94 MEMOIZE
523
+ 126: h BINGET 6
524
+ 128: \x8c SHORT_BINUNICODE '__main__'
525
+ 138: \x94 MEMOIZE
526
+ 139: \x8c SHORT_BINUNICODE 'C'
527
+ 142: \x94 MEMOIZE
528
+ 143: \x93 STACK_GLOBAL
529
+ 144: \x94 MEMOIZE
530
+ 145: ) EMPTY_TUPLE
531
+ 146: \x81 NEWOBJ
532
+ 147: \x94 MEMOIZE
533
+ 148: } EMPTY_DICT
534
+ 149: \x94 MEMOIZE
535
+ 150: ( MARK
536
+ 151: \x8c SHORT_BINUNICODE 'bar'
537
+ 156: \x94 MEMOIZE
538
+ 157: K BININT1 2
539
+ 159: \x8c SHORT_BINUNICODE 'foo'
540
+ 164: \x94 MEMOIZE
541
+ 165: K BININT1 1
542
+ 167: u SETITEMS (MARK at 150)
543
+ 168: b BUILD
544
+ 169: h BINGET 10
545
+ 171: t TUPLE (MARK at 119)
546
+ 172: \x94 MEMOIZE
547
+ 173: h BINGET 14
548
+ 175: K BININT1 5
549
+ 177: e APPENDS (MARK at 13)
550
+ 178: . STOP
551
+ highest protocol among opcodes = 4
552
+ """
553
+
404
554
# set([1,2]) pickled from 2.x with protocol 2
405
- DATA3 = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 (K\x01 K\x02 e\x85 q\x02 Rq\x03 .'
555
+ DATA_SET = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 (K\x01 K\x02 e\x85 q\x02 Rq\x03 .'
406
556
407
557
# xrange(5) pickled from 2.x with protocol 2
408
- DATA4 = b'\x80 \x02 c__builtin__\n xrange\n q\x00 K\x00 K\x05 K\x01 \x87 q\x01 Rq\x02 .'
558
+ DATA_XRANGE = b'\x80 \x02 c__builtin__\n xrange\n q\x00 K\x00 K\x05 K\x01 \x87 q\x01 Rq\x02 .'
409
559
if stackless :
410
- DATA4_SLP = b'\x80 \x02 cstackless._wrap\n range\n q\x00 K\x00 K\x05 K\x01 \x87 q\x01 Rq\x02 )b.'
560
+ DATA_XRANGE_SLP = b'\x80 \x02 cstackless._wrap\n range\n q\x00 K\x00 K\x05 K\x01 \x87 q\x01 Rq\x02 )b.'
411
561
else :
412
- DATA4_SLP = DATA4
413
-
562
+ DATA_XRANGE_SLP = DATA_XRANGE
414
563
415
564
# a SimpleCookie() object pickled from 2.x with protocol 2
416
- DATA5 = (b'\x80 \x02 cCookie\n SimpleCookie\n q\x00 )\x81 q\x01 U\x03 key'
417
- b'q\x02 cCookie\n Morsel\n q\x03 )\x81 q\x04 (U\x07 commentq\x05 U'
418
- b'\x00 q\x06 U\x06 domainq\x07 h\x06 U\x06 secureq\x08 h\x06 U\x07 '
419
- b'expiresq\t h\x06 U\x07 max-ageq\n h\x06 U\x07 versionq\x0b h\x06 U'
420
- b'\x04 pathq\x0c h\x06 U\x08 httponlyq\r h\x06 u}q\x0e (U\x0b '
421
- b'coded_valueq\x0f U\x05 valueq\x10 h\x10 h\x10 h\x02 h\x02 ubs}q\x11 b.' )
565
+ DATA_COOKIE = (b'\x80 \x02 cCookie\n SimpleCookie\n q\x00 )\x81 q\x01 U\x03 key'
566
+ b'q\x02 cCookie\n Morsel\n q\x03 )\x81 q\x04 (U\x07 commentq\x05 U'
567
+ b'\x00 q\x06 U\x06 domainq\x07 h\x06 U\x06 secureq\x08 h\x06 U\x07 '
568
+ b'expiresq\t h\x06 U\x07 max-ageq\n h\x06 U\x07 versionq\x0b h\x06 U'
569
+ b'\x04 pathq\x0c h\x06 U\x08 httponlyq\r h\x06 u}q\x0e (U\x0b '
570
+ b'coded_valueq\x0f U\x05 valueq\x10 h\x10 h\x10 h\x02 h\x02 ubs}q\x11 b.' )
422
571
423
572
# set([3]) pickled from 2.x with protocol 2
424
- DATA6 = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 K\x03 a\x85 q\x02 Rq\x03 .'
573
+ DATA_SET2 = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 K\x03 a\x85 q\x02 Rq\x03 .'
425
574
426
575
python2_exceptions_without_args = (
427
576
ArithmeticError ,
@@ -473,20 +622,10 @@ def create_dynamic_class(name, bases):
473
622
474
623
exception_pickle = b'\x80 \x02 cexceptions\n ?\n q\x00 )Rq\x01 .'
475
624
476
- # Exception objects without arguments pickled from 2.x with protocol 2
477
- DATA7 = {
478
- exception :
479
- exception_pickle .replace (b'?' , exception .__name__ .encode ("ascii" ))
480
- for exception in python2_exceptions_without_args
481
- }
482
-
483
- # StandardError is mapped to Exception, test that separately
484
- DATA8 = exception_pickle .replace (b'?' , b'StandardError' )
485
-
486
625
# UnicodeEncodeError object pickled from 2.x with protocol 2
487
- DATA9 = (b'\x80 \x02 cexceptions\n UnicodeEncodeError\n '
488
- b'q\x00 (U\x05 asciiq\x01 X\x03 \x00 \x00 \x00 fooq\x02 K\x00 K\x01 '
489
- b'U\x03 badq\x03 tq\x04 Rq\x05 .' )
626
+ DATA_UEERR = (b'\x80 \x02 cexceptions\n UnicodeEncodeError\n '
627
+ b'q\x00 (U\x05 asciiq\x01 X\x03 \x00 \x00 \x00 fooq\x02 K\x00 K\x01 '
628
+ b'U\x03 badq\x03 tq\x04 Rq\x05 .' )
490
629
491
630
492
631
def create_data ():
@@ -542,6 +681,12 @@ def test_load_from_data1(self):
542
681
def test_load_from_data2 (self ):
543
682
self .assert_is_copy (self ._testdata , self .loads (DATA2 ))
544
683
684
+ def test_load_from_data3 (self ):
685
+ self .assert_is_copy (self ._testdata , self .loads (DATA3 ))
686
+
687
+ def test_load_from_data4 (self ):
688
+ self .assert_is_copy (self ._testdata , self .loads (DATA4 ))
689
+
545
690
def test_load_classic_instance (self ):
546
691
# See issue5180. Test loading 2.x pickles that
547
692
# contain an instance of old style class.
@@ -599,11 +744,6 @@ def test_load_classic_instance(self):
599
744
b'q\x00 oq\x01 }q\x02 b.' ).replace (b'X' , xname )
600
745
self .assert_is_copy (X (* args ), self .loads (pickle2 ))
601
746
602
- def test_get (self ):
603
- self .assertRaises (KeyError , self .loads , b'g0\n p0' )
604
- self .assert_is_copy ([(100 ,), (100 ,)],
605
- self .loads (b'((Kdtp0\n h\x00 l.))' ))
606
-
607
747
def test_maxint64 (self ):
608
748
maxint64 = (1 << 63 ) - 1
609
749
data = b'I' + str (maxint64 ).encode ("ascii" ) + b'\n .'
@@ -621,24 +761,29 @@ def test_pop_empty_stack(self):
621
761
622
762
def test_unpickle_from_2x (self ):
623
763
# Unpickle non-trivial data from Python 2.x.
624
- loaded = self .loads (DATA3 )
764
+ loaded = self .loads (DATA_SET )
625
765
self .assertEqual (loaded , set ([1 , 2 ]))
626
- loaded = self .loads (DATA4 )
627
- self .assertEqual (type (loaded ), type (range (0 )))
766
+ loaded = self .loads (DATA_XRANGE_SLP )
767
+ if not stackless :
768
+ # Stackless-Python provides a fake range for unpickling
769
+ self .assertEqual (type (loaded ), type (range (0 )))
628
770
self .assertEqual (list (loaded ), list (range (5 )))
629
- loaded = self .loads (DATA5 )
771
+ loaded = self .loads (DATA_COOKIE )
630
772
self .assertEqual (type (loaded ), SimpleCookie )
631
773
self .assertEqual (list (loaded .keys ()), ["key" ])
632
774
self .assertEqual (loaded ["key" ].value , "value" )
633
775
634
- for (exc , data ) in DATA7 .items ():
776
+ # Exception objects without arguments pickled from 2.x with protocol 2
777
+ for exc in python2_exceptions_without_args :
778
+ data = exception_pickle .replace (b'?' , exc .__name__ .encode ("ascii" ))
635
779
loaded = self .loads (data )
636
780
self .assertIs (type (loaded ), exc )
637
781
638
- loaded = self .loads (DATA8 )
782
+ # StandardError is mapped to Exception, test that separately
783
+ loaded = self .loads (exception_pickle .replace (b'?' , b'StandardError' ))
639
784
self .assertIs (type (loaded ), Exception )
640
785
641
- loaded = self .loads (DATA9 )
786
+ loaded = self .loads (DATA_UEERR )
642
787
self .assertIs (type (loaded ), UnicodeEncodeError )
643
788
self .assertEqual (loaded .object , "foo" )
644
789
self .assertEqual (loaded .encoding , "ascii" )
@@ -675,11 +820,26 @@ def test_load_long_python2_str_as_bytes(self):
675
820
b'x' * 300 + pickle .STOP ,
676
821
encoding = 'bytes' ), b'x' * 300 )
677
822
823
+ def test_constants (self ):
824
+ self .assertIsNone (self .loads (b'N.' ))
825
+ self .assertIs (self .loads (b'\x88 .' ), True )
826
+ self .assertIs (self .loads (b'\x89 .' ), False )
827
+ self .assertIs (self .loads (b'I01\n .' ), True )
828
+ self .assertIs (self .loads (b'I00\n .' ), False )
829
+
678
830
def test_empty_bytestring (self ):
679
831
# issue 11286
680
832
empty = self .loads (b'\x80 \x03 U\x00 q\x00 .' , encoding = 'koi8-r' )
681
833
self .assertEqual (empty , '' )
682
834
835
+ def test_short_binbytes (self ):
836
+ dumped = b'\x80 \x03 C\x04 \xe2 \x82 \xac \x00 .'
837
+ self .assertEqual (self .loads (dumped ), b'\xe2 \x82 \xac \x00 ' )
838
+
839
+ def test_binbytes (self ):
840
+ dumped = b'\x80 \x03 B\x04 \x00 \x00 \x00 \xe2 \x82 \xac \x00 .'
841
+ self .assertEqual (self .loads (dumped ), b'\xe2 \x82 \xac \x00 ' )
842
+
683
843
@requires_32b
684
844
def test_negative_32b_binbytes (self ):
685
845
# On 32-bit builds, a BINBYTES of 2**31 or more is refused
@@ -694,6 +854,39 @@ def test_negative_32b_binunicode(self):
694
854
with self .assertRaises ((pickle .UnpicklingError , OverflowError )):
695
855
self .loads (dumped )
696
856
857
+ def test_short_binunicode (self ):
858
+ dumped = b'\x80 \x04 \x8c \x04 \xe2 \x82 \xac \x00 .'
859
+ self .assertEqual (self .loads (dumped ), '\u20ac \x00 ' )
860
+
861
+ def test_misc_get (self ):
862
+ self .assertRaises (KeyError , self .loads , b'g0\n p0' )
863
+ self .assert_is_copy ([(100 ,), (100 ,)],
864
+ self .loads (b'((Kdtp0\n h\x00 l.))' ))
865
+
866
+ def test_get (self ):
867
+ pickled = b'((lp100000\n g100000\n t.'
868
+ unpickled = self .loads (pickled )
869
+ self .assertEqual (unpickled , ([],)* 2 )
870
+ self .assertIs (unpickled [0 ], unpickled [1 ])
871
+
872
+ def test_binget (self ):
873
+ pickled = b'(]q\xff h\xff t.'
874
+ unpickled = self .loads (pickled )
875
+ self .assertEqual (unpickled , ([],)* 2 )
876
+ self .assertIs (unpickled [0 ], unpickled [1 ])
877
+
878
+ def test_long_binget (self ):
879
+ pickled = b'(]r\x00 \x00 \x01 \x00 j\x00 \x00 \x01 \x00 t.'
880
+ unpickled = self .loads (pickled )
881
+ self .assertEqual (unpickled , ([],)* 2 )
882
+ self .assertIs (unpickled [0 ], unpickled [1 ])
883
+
884
+ def test_dup (self ):
885
+ pickled = b'((l2t.'
886
+ unpickled = self .loads (pickled )
887
+ self .assertEqual (unpickled , ([],)* 2 )
888
+ self .assertIs (unpickled [0 ], unpickled [1 ])
889
+
697
890
def test_negative_put (self ):
698
891
# Issue #12847
699
892
dumped = b'Va\n p-1\n .'
@@ -1506,9 +1699,9 @@ def test_pickle_to_2x(self):
1506
1699
# NOTE: this test is a bit too strong since we can produce different
1507
1700
# bytecode that 2.x will still understand.
1508
1701
dumped = self .dumps (range (5 ), 2 )
1509
- self .assertEqual (dumped , DATA4 )
1702
+ self .assertEqual (dumped , DATA_XRANGE )
1510
1703
dumped = self .dumps (set ([3 ]), 2 )
1511
- self .assertEqual (dumped , DATA6 )
1704
+ self .assertEqual (dumped , DATA_SET2 )
1512
1705
1513
1706
def test_large_pickles (self ):
1514
1707
# Test the correctness of internal buffering routines when handling
@@ -2405,7 +2598,7 @@ def reduce_2(obj):
2405
2598
# Print some stuff that can be used to rewrite DATA{0,1,2}
2406
2599
from pickletools import dis
2407
2600
x = create_data ()
2408
- for i in range (3 ):
2601
+ for i in range (pickle . HIGHEST_PROTOCOL + 1 ):
2409
2602
p = pickle .dumps (x , i )
2410
2603
print ("DATA{0} = (" .format (i ))
2411
2604
for j in range (0 , len (p ), 20 ):
0 commit comments