@@ -2800,7 +2800,7 @@ def test_recursive_multi(self):
28002800 self .assertEqual (list (x [0 ].attr .keys ()), [1 ])
28012801 self .assertIs (x [0 ].attr [1 ], x )
28022802
2803- def _test_recursive_collection_and_inst (self , factory ):
2803+ def _test_recursive_collection_and_inst (self , factory , oldminproto = 0 ):
28042804 # Mutable object containing a collection containing the original
28052805 # object.
28062806 o = Object ()
@@ -2818,6 +2818,8 @@ def _test_recursive_collection_and_inst(self, factory):
28182818 # collection.
28192819 o = o .attr
28202820 for proto in protocols :
2821+ if self .py_version < (3 , 4 ) and proto < oldminproto :
2822+ continue
28212823 s = self .dumps (o , proto )
28222824 x = self .loads (s )
28232825 self .assertIsInstance (x , t )
@@ -2835,25 +2837,25 @@ def test_recursive_dict_and_inst(self):
28352837 self ._test_recursive_collection_and_inst (dict .fromkeys )
28362838
28372839 def test_recursive_set_and_inst (self ):
2838- self ._test_recursive_collection_and_inst (set )
2840+ self ._test_recursive_collection_and_inst (set , oldminproto = 4 )
28392841
28402842 def test_recursive_frozenset_and_inst (self ):
2841- self ._test_recursive_collection_and_inst (frozenset )
2843+ self ._test_recursive_collection_and_inst (frozenset , oldminproto = 4 )
28422844
28432845 def test_recursive_list_subclass_and_inst (self ):
2844- self ._test_recursive_collection_and_inst (MyList )
2846+ self ._test_recursive_collection_and_inst (MyList , oldminproto = 2 )
28452847
28462848 def test_recursive_tuple_subclass_and_inst (self ):
2847- self ._test_recursive_collection_and_inst (MyTuple )
2849+ self ._test_recursive_collection_and_inst (MyTuple , oldminproto = 4 )
28482850
28492851 def test_recursive_dict_subclass_and_inst (self ):
2850- self ._test_recursive_collection_and_inst (MyDict .fromkeys )
2852+ self ._test_recursive_collection_and_inst (MyDict .fromkeys , oldminproto = 2 )
28512853
28522854 def test_recursive_set_subclass_and_inst (self ):
2853- self ._test_recursive_collection_and_inst (MySet )
2855+ self ._test_recursive_collection_and_inst (MySet , oldminproto = 4 )
28542856
28552857 def test_recursive_frozenset_subclass_and_inst (self ):
2856- self ._test_recursive_collection_and_inst (MyFrozenSet )
2858+ self ._test_recursive_collection_and_inst (MyFrozenSet , oldminproto = 4 )
28572859
28582860 def test_recursive_inst_state (self ):
28592861 # Mutable object containing itself.
@@ -2926,8 +2928,11 @@ def test_bytes(self):
29262928 self .assert_is_copy (s , self .loads (p ))
29272929
29282930 def test_bytes_memoization (self ):
2931+ array_types = [bytes ]
2932+ if self .py_version >= (3 , 4 ):
2933+ array_types += [ZeroCopyBytes ]
29292934 for proto in protocols :
2930- for array_type in [ bytes , ZeroCopyBytes ] :
2935+ for array_type in array_types :
29312936 for s in b'' , b'xyz' , b'xyz' * 100 :
29322937 with self .subTest (proto = proto , array_type = array_type , s = s , independent = False ):
29332938 b = array_type (s )
@@ -2964,8 +2969,11 @@ def test_bytearray(self):
29642969 self .assertTrue (opcode_in_pickle (pickle .BYTEARRAY8 , p ))
29652970
29662971 def test_bytearray_memoization (self ):
2972+ array_types = [bytearray ]
2973+ if self .py_version >= (3 , 4 ):
2974+ array_types += [ZeroCopyBytearray ]
29672975 for proto in protocols :
2968- for array_type in [ bytearray , ZeroCopyBytearray ] :
2976+ for array_type in array_types :
29692977 for s in b'' , b'xyz' , b'xyz' * 100 :
29702978 with self .subTest (proto = proto , array_type = array_type , s = s , independent = False ):
29712979 b = array_type (s )
@@ -3039,10 +3047,13 @@ def test_float_format(self):
30393047
30403048 def test_reduce (self ):
30413049 for proto in protocols :
3042- inst = AAA ()
3043- dumped = self .dumps (inst , proto )
3044- loaded = self .loads (dumped )
3045- self .assertEqual (loaded , REDUCE_A )
3050+ if self .py_version < (3 , 4 ) and proto < 3 :
3051+ continue
3052+ with self .subTest (proto = proto ):
3053+ inst = AAA ()
3054+ dumped = self .dumps (inst , proto )
3055+ loaded = self .loads (dumped )
3056+ self .assertEqual (loaded , REDUCE_A )
30463057
30473058 def test_getinitargs (self ):
30483059 for proto in protocols :
@@ -3076,6 +3087,8 @@ def test_structseq(self):
30763087 s = self .dumps (t , proto )
30773088 u = self .loads (s )
30783089 self .assert_is_copy (t , u )
3090+ if self .py_version < (3 , 4 ):
3091+ continue
30793092 t = os .stat (os .curdir )
30803093 s = self .dumps (t , proto )
30813094 u = self .loads (s )
@@ -3087,19 +3100,25 @@ def test_structseq(self):
30873100 self .assert_is_copy (t , u )
30883101
30893102 def test_ellipsis (self ):
3103+ if self .py_version < (3 , 3 ):
3104+ self .skipTest ('not supported in Python < 3.3' )
30903105 for proto in protocols :
30913106 s = self .dumps (..., proto )
30923107 u = self .loads (s )
30933108 self .assertIs (..., u )
30943109
30953110 def test_notimplemented (self ):
3111+ if self .py_version < (3 , 3 ):
3112+ self .skipTest ('not supported in Python < 3.3' )
30963113 for proto in protocols :
30973114 s = self .dumps (NotImplemented , proto )
30983115 u = self .loads (s )
30993116 self .assertIs (NotImplemented , u )
31003117
31013118 def test_singleton_types (self ):
31023119 # Issue #6477: Test that types of built-in singletons can be pickled.
3120+ if self .py_version < (3 , 3 ):
3121+ self .skipTest ('not supported in Python < 3.3' )
31033122 singletons = [None , ..., NotImplemented ]
31043123 for singleton in singletons :
31053124 for proto in protocols :
@@ -3110,12 +3129,34 @@ def test_singleton_types(self):
31103129 def test_builtin_types (self ):
31113130 for t in builtins .__dict__ .values ():
31123131 if isinstance (t , type ) and not issubclass (t , BaseException ):
3132+ if t is str and self .py_version < (3 , 4 ):
3133+ continue
3134+ if t .__name__ == 'BuiltinImporter' and self .py_version < (3 , 3 ):
3135+ continue
31133136 for proto in protocols :
3114- s = self .dumps (t , proto )
3115- self .assertIs (self .loads (s ), t )
3137+ with self .subTest (name = t .__name__ , proto = proto ):
3138+ s = self .dumps (t , proto )
3139+ self .assertIs (self .loads (s ), t )
31163140
31173141 def test_builtin_exceptions (self ):
31183142 new_names = {
3143+ 'BlockingIOError' : (3 , 3 ),
3144+ 'BrokenPipeError' : (3 , 3 ),
3145+ 'ChildProcessError' : (3 , 3 ),
3146+ 'ConnectionError' : (3 , 3 ),
3147+ 'ConnectionAbortedError' : (3 , 3 ),
3148+ 'ConnectionRefusedError' : (3 , 3 ),
3149+ 'ConnectionResetError' : (3 , 3 ),
3150+ 'FileExistsError' : (3 , 3 ),
3151+ 'FileNotFoundError' : (3 , 3 ),
3152+ 'InterruptedError' : (3 , 3 ),
3153+ 'IsADirectoryError' : (3 , 3 ),
3154+ 'NotADirectoryError' : (3 , 3 ),
3155+ 'PermissionError' : (3 , 3 ),
3156+ 'ProcessLookupError' : (3 , 3 ),
3157+ 'TimeoutError' : (3 , 3 ),
3158+ 'RecursionError' : (3 , 5 ),
3159+ 'StopAsyncIteration' : (3 , 5 ),
31193160 'ModuleNotFoundError' : (3 , 6 ),
31203161 'EncodingWarning' : (3 , 10 ),
31213162 'BaseExceptionGroup' : (3 , 11 ),
@@ -3128,14 +3169,17 @@ def test_builtin_exceptions(self):
31283169 if t .__name__ in new_names and self .py_version < new_names [t .__name__ ]:
31293170 continue
31303171 for proto in protocols :
3131- s = self .dumps (t , proto )
3132- u = self .loads (s )
3133- if proto <= 2 and issubclass (t , OSError ) and t is not BlockingIOError :
3134- self .assertIs (u , OSError )
3135- elif proto <= 2 and issubclass (t , ImportError ):
3136- self .assertIs (u , ImportError )
3137- else :
3138- self .assertIs (u , t )
3172+ if self .py_version < (3 , 3 ) and proto < 3 :
3173+ continue
3174+ with self .subTest (name = t .__name__ , proto = proto ):
3175+ s = self .dumps (t , proto )
3176+ u = self .loads (s )
3177+ if proto <= 2 and issubclass (t , OSError ) and t is not BlockingIOError :
3178+ self .assertIs (u , OSError )
3179+ elif proto <= 2 and issubclass (t , ImportError ):
3180+ self .assertIs (u , ImportError )
3181+ else :
3182+ self .assertIs (u , t )
31393183
31403184 def test_builtin_functions (self ):
31413185 new_names = {'breakpoint' : (3 , 7 ), 'aiter' : (3 , 10 ), 'anext' : (3 , 10 )}
@@ -3144,8 +3188,9 @@ def test_builtin_functions(self):
31443188 if t .__name__ in new_names and self .py_version < new_names [t .__name__ ]:
31453189 continue
31463190 for proto in protocols :
3147- s = self .dumps (t , proto )
3148- self .assertIs (self .loads (s ), t )
3191+ with self .subTest (name = t .__name__ , proto = proto ):
3192+ s = self .dumps (t , proto )
3193+ self .assertIs (self .loads (s ), t )
31493194
31503195 # Tests for protocol 2
31513196
@@ -3160,7 +3205,7 @@ def test_proto(self):
31603205
31613206 def test_bad_proto (self ):
31623207 if self .py_version < (3 , 8 ):
3163- self .skipTest ('No protocol validation in this version ' )
3208+ self .skipTest ('no protocol validation in Python < 3.8 ' )
31643209 oob = protocols [- 1 ] + 1 # a future protocol
31653210 build_none = pickle .NONE + pickle .STOP
31663211 badpickle = pickle .PROTO + bytes ([oob ]) + build_none
@@ -3272,6 +3317,8 @@ def test_newobj_list(self):
32723317 def test_newobj_generic (self ):
32733318 for proto in protocols :
32743319 for C in myclasses :
3320+ if self .py_version < (3 , 4 ) and proto < 3 and C in (MyStr , MyUnicode ):
3321+ continue
32753322 B = C .__base__
32763323 x = C (C .sample )
32773324 x .foo = 42
@@ -3290,6 +3337,8 @@ def test_newobj_proxies(self):
32903337 classes .remove (c )
32913338 for proto in protocols :
32923339 for C in classes :
3340+ if self .py_version < (3 , 4 ) and proto < 3 and C in (MyStr , MyUnicode ):
3341+ continue
32933342 B = C .__base__
32943343 x = C (C .sample )
32953344 x .foo = 42
@@ -3314,6 +3363,8 @@ def test_newobj_overridden_new(self):
33143363
33153364 def test_newobj_not_class (self ):
33163365 # Issue 24552
3366+ if self .py_version < (3 , 4 ):
3367+ self .skipTest ('not supported in Python < 3.4' )
33173368 o = SimpleNewObj .__new__ (SimpleNewObj )
33183369 b = self .dumps (o , 4 )
33193370 with support .swap_attr (picklecommon , 'SimpleNewObj' , 42 ):
@@ -3448,9 +3499,10 @@ def test_simple_newobj(self):
34483499 self .assertIn (b'64206' , s ) # INT or LONG
34493500 else :
34503501 self .assertIn (b'M\xce \xfa ' , s ) # BININT2
3451- self .assertEqual (opcode_in_pickle (pickle .NEWOBJ , s ),
3452- 2 <= proto )
3453- self .assertFalse (opcode_in_pickle (pickle .NEWOBJ_EX , s ))
3502+ if not (self .py_version < (3 , 5 ) and proto == 4 ):
3503+ self .assertEqual (opcode_in_pickle (pickle .NEWOBJ , s ),
3504+ 2 <= proto )
3505+ self .assertFalse (opcode_in_pickle (pickle .NEWOBJ_EX , s ))
34543506 y = self .loads (s ) # will raise TypeError if __init__ called
34553507 self .assert_is_copy (x , y )
34563508
@@ -3471,9 +3523,10 @@ def test_complex_newobj(self):
34713523 self .assertIn (b'X\x04 \x00 \x00 \x00 FACE' , s ) # BINUNICODE
34723524 else :
34733525 self .assertIn (b'\x8c \x04 FACE' , s ) # SHORT_BINUNICODE
3474- self .assertEqual (opcode_in_pickle (pickle .NEWOBJ , s ),
3475- 2 <= proto )
3476- self .assertFalse (opcode_in_pickle (pickle .NEWOBJ_EX , s ))
3526+ if not (self .py_version < (3 , 5 ) and proto == 4 ):
3527+ self .assertEqual (opcode_in_pickle (pickle .NEWOBJ , s ),
3528+ 2 <= proto )
3529+ self .assertFalse (opcode_in_pickle (pickle .NEWOBJ_EX , s ))
34773530 y = self .loads (s ) # will raise TypeError if __init__ called
34783531 self .assert_is_copy (x , y )
34793532
@@ -3608,6 +3661,8 @@ def test_large_pickles(self):
36083661
36093662 def test_int_pickling_efficiency (self ):
36103663 # Test compacity of int representation (see issue #12744)
3664+ if self .py_version < (3 , 3 ):
3665+ self .skipTest ('not supported in Python < 3.3' )
36113666 for proto in protocols :
36123667 with self .subTest (proto = proto ):
36133668 pickles = [self .dumps (2 ** n , proto ) for n in range (70 )]
@@ -3852,7 +3907,12 @@ def concatenate_chunks(self):
38523907 chunk_sizes )
38533908
38543909 def test_nested_names (self ):
3910+ if self .py_version < (3 , 4 ):
3911+ self .skipTest ('not supported in Python < 3.4' )
3912+ # required protocol 4 in Python 3.4
38553913 for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
3914+ if self .py_version < (3 , 5 ) and proto < 4 :
3915+ continue
38563916 for obj in [Nested .A , Nested .A .B , Nested .A .B .C ]:
38573917 with self .subTest (proto = proto , obj = obj ):
38583918 unpickled = self .loads (self .dumps (obj , proto ))
@@ -3883,10 +3943,21 @@ class Recursive:
38833943 del Recursive .ref # break reference loop
38843944
38853945 def test_py_methods (self ):
3946+ if self .py_version < (3 , 4 ):
3947+ self .skipTest ('not supported in Python < 3.4' )
38863948 py_methods = (
3887- PyMethodsTest .cheese ,
38883949 PyMethodsTest .wine ,
38893950 PyMethodsTest ().biscuits ,
3951+ )
3952+ for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
3953+ for method in py_methods :
3954+ with self .subTest (proto = proto , method = method ):
3955+ unpickled = self .loads (self .dumps (method , proto ))
3956+ self .assertEqual (method (), unpickled ())
3957+
3958+ # required protocol 4 in Python 3.4
3959+ py_methods = (
3960+ PyMethodsTest .cheese ,
38903961 PyMethodsTest .Nested .ketchup ,
38913962 PyMethodsTest .Nested .maple ,
38923963 PyMethodsTest .Nested ().pie
@@ -3896,6 +3967,8 @@ def test_py_methods(self):
38963967 (PyMethodsTest .Nested .pie , PyMethodsTest .Nested )
38973968 )
38983969 for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
3970+ if self .py_version < (3 , 5 ) and proto < 4 :
3971+ continue
38993972 for method in py_methods :
39003973 with self .subTest (proto = proto , method = method ):
39013974 unpickled = self .loads (self .dumps (method , proto ))
@@ -3916,6 +3989,8 @@ def test_py_methods(self):
39163989 self .assertRaises (TypeError , self .dumps , descr , proto )
39173990
39183991 def test_c_methods (self ):
3992+ if self .py_version < (3 , 4 ):
3993+ self .skipTest ('not supported in Python < 3.4' )
39193994 c_methods = (
39203995 # bound built-in method
39213996 ("abcd" .index , ("c" ,)),
@@ -3936,7 +4011,6 @@ def test_c_methods(self):
39364011 # subclass methods
39374012 (Subclass ([1 ,2 ,2 ]).count , (2 ,)),
39384013 (Subclass .count , (Subclass ([1 ,2 ,2 ]), 2 )),
3939- (Subclass .Nested ("sweet" ).count , ("e" ,)),
39404014 (Subclass .Nested .count , (Subclass .Nested ("sweet" ), "e" )),
39414015 )
39424016 for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
@@ -3945,6 +4019,18 @@ def test_c_methods(self):
39454019 unpickled = self .loads (self .dumps (method , proto ))
39464020 self .assertEqual (method (* args ), unpickled (* args ))
39474021
4022+ # required protocol 4 in Python 3.4
4023+ c_methods = (
4024+ (Subclass .Nested ("sweet" ).count , ("e" ,)),
4025+ )
4026+ for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
4027+ if self .py_version < (3 , 5 ) and proto < 4 :
4028+ continue
4029+ for method , args in c_methods :
4030+ with self .subTest (proto = proto , method = method ):
4031+ unpickled = self .loads (self .dumps (method , proto ))
4032+ self .assertEqual (method (* args ), unpickled (* args ))
4033+
39484034 descriptors = (
39494035 bytearray .__dict__ ['maketrans' ], # built-in static method descriptor
39504036 dict .__dict__ ['fromkeys' ], # built-in class method descriptor
@@ -3955,6 +4041,8 @@ def test_c_methods(self):
39554041 self .assertRaises (TypeError , self .dumps , descr , proto )
39564042
39574043 def test_compat_pickle (self ):
4044+ if self .py_version < (3 , 4 ):
4045+ self .skipTest ("doesn't work in Python < 3.4'" )
39584046 tests = [
39594047 (range (1 , 7 ), '__builtin__' , 'xrange' ),
39604048 (map (int , '123' ), 'itertools' , 'imap' ),
0 commit comments