@@ -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,22 +401,172 @@ 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
410
560
# a SimpleCookie() object pickled from 2.x with protocol 2
411
- DATA5 = (b'\x80 \x02 cCookie\n SimpleCookie\n q\x00 )\x81 q\x01 U\x03 key'
412
- b'q\x02 cCookie\n Morsel\n q\x03 )\x81 q\x04 (U\x07 commentq\x05 U'
413
- b'\x00 q\x06 U\x06 domainq\x07 h\x06 U\x06 secureq\x08 h\x06 U\x07 '
414
- b'expiresq\t h\x06 U\x07 max-ageq\n h\x06 U\x07 versionq\x0b h\x06 U'
415
- b'\x04 pathq\x0c h\x06 U\x08 httponlyq\r h\x06 u}q\x0e (U\x0b '
416
- b'coded_valueq\x0f U\x05 valueq\x10 h\x10 h\x10 h\x02 h\x02 ubs}q\x11 b.' )
561
+ DATA_COOKIE = (b'\x80 \x02 cCookie\n SimpleCookie\n q\x00 )\x81 q\x01 U\x03 key'
562
+ b'q\x02 cCookie\n Morsel\n q\x03 )\x81 q\x04 (U\x07 commentq\x05 U'
563
+ b'\x00 q\x06 U\x06 domainq\x07 h\x06 U\x06 secureq\x08 h\x06 U\x07 '
564
+ b'expiresq\t h\x06 U\x07 max-ageq\n h\x06 U\x07 versionq\x0b h\x06 U'
565
+ b'\x04 pathq\x0c h\x06 U\x08 httponlyq\r h\x06 u}q\x0e (U\x0b '
566
+ b'coded_valueq\x0f U\x05 valueq\x10 h\x10 h\x10 h\x02 h\x02 ubs}q\x11 b.' )
417
567
418
568
# set([3]) pickled from 2.x with protocol 2
419
- DATA6 = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 K\x03 a\x85 q\x02 Rq\x03 .'
569
+ DATA_SET2 = b'\x80 \x02 c__builtin__\n set\n q\x00 ]q\x01 K\x03 a\x85 q\x02 Rq\x03 .'
420
570
421
571
python2_exceptions_without_args = (
422
572
ArithmeticError ,
@@ -468,20 +618,10 @@ def create_dynamic_class(name, bases):
468
618
469
619
exception_pickle = b'\x80 \x02 cexceptions\n ?\n q\x00 )Rq\x01 .'
470
620
471
- # Exception objects without arguments pickled from 2.x with protocol 2
472
- DATA7 = {
473
- exception :
474
- exception_pickle .replace (b'?' , exception .__name__ .encode ("ascii" ))
475
- for exception in python2_exceptions_without_args
476
- }
477
-
478
- # StandardError is mapped to Exception, test that separately
479
- DATA8 = exception_pickle .replace (b'?' , b'StandardError' )
480
-
481
621
# UnicodeEncodeError object pickled from 2.x with protocol 2
482
- DATA9 = (b'\x80 \x02 cexceptions\n UnicodeEncodeError\n '
483
- b'q\x00 (U\x05 asciiq\x01 X\x03 \x00 \x00 \x00 fooq\x02 K\x00 K\x01 '
484
- b'U\x03 badq\x03 tq\x04 Rq\x05 .' )
622
+ DATA_UEERR = (b'\x80 \x02 cexceptions\n UnicodeEncodeError\n '
623
+ b'q\x00 (U\x05 asciiq\x01 X\x03 \x00 \x00 \x00 fooq\x02 K\x00 K\x01 '
624
+ b'U\x03 badq\x03 tq\x04 Rq\x05 .' )
485
625
486
626
487
627
def create_data ():
@@ -537,6 +677,12 @@ def test_load_from_data1(self):
537
677
def test_load_from_data2 (self ):
538
678
self .assert_is_copy (self ._testdata , self .loads (DATA2 ))
539
679
680
+ def test_load_from_data3 (self ):
681
+ self .assert_is_copy (self ._testdata , self .loads (DATA3 ))
682
+
683
+ def test_load_from_data4 (self ):
684
+ self .assert_is_copy (self ._testdata , self .loads (DATA4 ))
685
+
540
686
def test_load_classic_instance (self ):
541
687
# See issue5180. Test loading 2.x pickles that
542
688
# contain an instance of old style class.
@@ -594,11 +740,6 @@ def test_load_classic_instance(self):
594
740
b'q\x00 oq\x01 }q\x02 b.' ).replace (b'X' , xname )
595
741
self .assert_is_copy (X (* args ), self .loads (pickle2 ))
596
742
597
- def test_get (self ):
598
- self .assertRaises (KeyError , self .loads , b'g0\n p0' )
599
- self .assert_is_copy ([(100 ,), (100 ,)],
600
- self .loads (b'((Kdtp0\n h\x00 l.))' ))
601
-
602
743
def test_maxint64 (self ):
603
744
maxint64 = (1 << 63 ) - 1
604
745
data = b'I' + str (maxint64 ).encode ("ascii" ) + b'\n .'
@@ -616,24 +757,27 @@ def test_pop_empty_stack(self):
616
757
617
758
def test_unpickle_from_2x (self ):
618
759
# Unpickle non-trivial data from Python 2.x.
619
- loaded = self .loads (DATA3 )
760
+ loaded = self .loads (DATA_SET )
620
761
self .assertEqual (loaded , set ([1 , 2 ]))
621
- loaded = self .loads (DATA4 )
762
+ loaded = self .loads (DATA_XRANGE )
622
763
self .assertEqual (type (loaded ), type (range (0 )))
623
764
self .assertEqual (list (loaded ), list (range (5 )))
624
- loaded = self .loads (DATA5 )
765
+ loaded = self .loads (DATA_COOKIE )
625
766
self .assertEqual (type (loaded ), SimpleCookie )
626
767
self .assertEqual (list (loaded .keys ()), ["key" ])
627
768
self .assertEqual (loaded ["key" ].value , "value" )
628
769
629
- for (exc , data ) in DATA7 .items ():
770
+ # Exception objects without arguments pickled from 2.x with protocol 2
771
+ for exc in python2_exceptions_without_args :
772
+ data = exception_pickle .replace (b'?' , exc .__name__ .encode ("ascii" ))
630
773
loaded = self .loads (data )
631
774
self .assertIs (type (loaded ), exc )
632
775
633
- loaded = self .loads (DATA8 )
776
+ # StandardError is mapped to Exception, test that separately
777
+ loaded = self .loads (exception_pickle .replace (b'?' , b'StandardError' ))
634
778
self .assertIs (type (loaded ), Exception )
635
779
636
- loaded = self .loads (DATA9 )
780
+ loaded = self .loads (DATA_UEERR )
637
781
self .assertIs (type (loaded ), UnicodeEncodeError )
638
782
self .assertEqual (loaded .object , "foo" )
639
783
self .assertEqual (loaded .encoding , "ascii" )
@@ -670,11 +814,26 @@ def test_load_long_python2_str_as_bytes(self):
670
814
b'x' * 300 + pickle .STOP ,
671
815
encoding = 'bytes' ), b'x' * 300 )
672
816
817
+ def test_constants (self ):
818
+ self .assertIsNone (self .loads (b'N.' ))
819
+ self .assertIs (self .loads (b'\x88 .' ), True )
820
+ self .assertIs (self .loads (b'\x89 .' ), False )
821
+ self .assertIs (self .loads (b'I01\n .' ), True )
822
+ self .assertIs (self .loads (b'I00\n .' ), False )
823
+
673
824
def test_empty_bytestring (self ):
674
825
# issue 11286
675
826
empty = self .loads (b'\x80 \x03 U\x00 q\x00 .' , encoding = 'koi8-r' )
676
827
self .assertEqual (empty , '' )
677
828
829
+ def test_short_binbytes (self ):
830
+ dumped = b'\x80 \x03 C\x04 \xe2 \x82 \xac \x00 .'
831
+ self .assertEqual (self .loads (dumped ), b'\xe2 \x82 \xac \x00 ' )
832
+
833
+ def test_binbytes (self ):
834
+ dumped = b'\x80 \x03 B\x04 \x00 \x00 \x00 \xe2 \x82 \xac \x00 .'
835
+ self .assertEqual (self .loads (dumped ), b'\xe2 \x82 \xac \x00 ' )
836
+
678
837
@requires_32b
679
838
def test_negative_32b_binbytes (self ):
680
839
# On 32-bit builds, a BINBYTES of 2**31 or more is refused
@@ -689,6 +848,39 @@ def test_negative_32b_binunicode(self):
689
848
with self .assertRaises ((pickle .UnpicklingError , OverflowError )):
690
849
self .loads (dumped )
691
850
851
+ def test_short_binunicode (self ):
852
+ dumped = b'\x80 \x04 \x8c \x04 \xe2 \x82 \xac \x00 .'
853
+ self .assertEqual (self .loads (dumped ), '\u20ac \x00 ' )
854
+
855
+ def test_misc_get (self ):
856
+ self .assertRaises (KeyError , self .loads , b'g0\n p0' )
857
+ self .assert_is_copy ([(100 ,), (100 ,)],
858
+ self .loads (b'((Kdtp0\n h\x00 l.))' ))
859
+
860
+ def test_get (self ):
861
+ pickled = b'((lp100000\n g100000\n t.'
862
+ unpickled = self .loads (pickled )
863
+ self .assertEqual (unpickled , ([],)* 2 )
864
+ self .assertIs (unpickled [0 ], unpickled [1 ])
865
+
866
+ def test_binget (self ):
867
+ pickled = b'(]q\xff h\xff t.'
868
+ unpickled = self .loads (pickled )
869
+ self .assertEqual (unpickled , ([],)* 2 )
870
+ self .assertIs (unpickled [0 ], unpickled [1 ])
871
+
872
+ def test_long_binget (self ):
873
+ pickled = b'(]r\x00 \x00 \x01 \x00 j\x00 \x00 \x01 \x00 t.'
874
+ unpickled = self .loads (pickled )
875
+ self .assertEqual (unpickled , ([],)* 2 )
876
+ self .assertIs (unpickled [0 ], unpickled [1 ])
877
+
878
+ def test_dup (self ):
879
+ pickled = b'((l2t.'
880
+ unpickled = self .loads (pickled )
881
+ self .assertEqual (unpickled , ([],)* 2 )
882
+ self .assertIs (unpickled [0 ], unpickled [1 ])
883
+
692
884
def test_negative_put (self ):
693
885
# Issue #12847
694
886
dumped = b'Va\n p-1\n .'
@@ -1455,9 +1647,9 @@ def test_pickle_to_2x(self):
1455
1647
# NOTE: this test is a bit too strong since we can produce different
1456
1648
# bytecode that 2.x will still understand.
1457
1649
dumped = self .dumps (range (5 ), 2 )
1458
- self .assertEqual (dumped , DATA4 )
1650
+ self .assertEqual (dumped , DATA_XRANGE )
1459
1651
dumped = self .dumps (set ([3 ]), 2 )
1460
- self .assertEqual (dumped , DATA6 )
1652
+ self .assertEqual (dumped , DATA_SET2 )
1461
1653
1462
1654
def test_large_pickles (self ):
1463
1655
# Test the correctness of internal buffering routines when handling
@@ -2312,7 +2504,7 @@ def reduce_2(obj):
2312
2504
# Print some stuff that can be used to rewrite DATA{0,1,2}
2313
2505
from pickletools import dis
2314
2506
x = create_data ()
2315
- for i in range (3 ):
2507
+ for i in range (pickle . HIGHEST_PROTOCOL + 1 ):
2316
2508
p = pickle .dumps (x , i )
2317
2509
print ("DATA{0} = (" .format (i ))
2318
2510
for j in range (0 , len (p ), 20 ):
0 commit comments