@@ -103,6 +103,15 @@ def __getinitargs__(self):
103103class H (object ):
104104 pass
105105
106+ # Hashable mutable key
107+ class K (object ):
108+ def __init__ (self , value ):
109+ self .value = value
110+
111+ def __reduce__ (self ):
112+ # Shouldn't support the recursion itself
113+ return K , (self .value ,)
114+
106115import __main__
107116__main__ .C = C
108117C .__module__ = "__main__"
@@ -112,6 +121,8 @@ class H(object):
112121E .__module__ = "__main__"
113122__main__ .H = H
114123H .__module__ = "__main__"
124+ __main__ .K = K
125+ K .__module__ = "__main__"
115126
116127class myint (int ):
117128 def __init__ (self , x ):
@@ -1041,18 +1052,19 @@ def test_recursive_list(self):
10411052 x = self .loads (s )
10421053 self .assertIsInstance (x , list )
10431054 self .assertEqual (len (x ), 1 )
1044- self .assertTrue ( x is x [0 ])
1055+ self .assertIs ( x [0 ], x )
10451056
1046- def test_recursive_tuple (self ):
1057+ def test_recursive_tuple_and_list (self ):
10471058 t = ([],)
10481059 t [0 ].append (t )
10491060 for proto in protocols :
10501061 s = self .dumps (t , proto )
10511062 x = self .loads (s )
10521063 self .assertIsInstance (x , tuple )
10531064 self .assertEqual (len (x ), 1 )
1065+ self .assertIsInstance (x [0 ], list )
10541066 self .assertEqual (len (x [0 ]), 1 )
1055- self .assertTrue ( x is x [0 ][0 ])
1067+ self .assertIs ( x [0 ][0 ], x )
10561068
10571069 def test_recursive_dict (self ):
10581070 d = {}
@@ -1062,29 +1074,63 @@ def test_recursive_dict(self):
10621074 x = self .loads (s )
10631075 self .assertIsInstance (x , dict )
10641076 self .assertEqual (list (x .keys ()), [1 ])
1065- self .assertTrue (x [1 ] is x )
1077+ self .assertIs (x [1 ], x )
10661078
1067- def test_recursive_set (self ):
1068- h = H ()
1069- y = set ({ h } )
1070- h . attr = y
1079+ def test_recursive_dict_key (self ):
1080+ d = {}
1081+ k = K ( d )
1082+ d [ k ] = 1
10711083 for proto in protocols :
1084+ s = self .dumps (d , proto )
1085+ x = self .loads (s )
1086+ self .assertIsInstance (x , dict )
1087+ self .assertEqual (len (x .keys ()), 1 )
1088+ self .assertIsInstance (list (x .keys ())[0 ], K )
1089+ self .assertIs (list (x .keys ())[0 ].value , x )
1090+
1091+ def test_recursive_set (self ):
1092+ y = set ()
1093+ k = K (y )
1094+ y .add (k )
1095+ for proto in range (4 , pickle .HIGHEST_PROTOCOL + 1 ):
10721096 s = self .dumps (y , proto )
10731097 x = self .loads (s )
10741098 self .assertIsInstance (x , set )
1075- self .assertIs (list (x )[0 ].attr , x )
10761099 self .assertEqual (len (x ), 1 )
1100+ self .assertIsInstance (list (x )[0 ], K )
1101+ self .assertIs (list (x )[0 ].value , x )
10771102
1078- def test_recursive_frozenset (self ):
1079- h = H ()
1080- y = frozenset ({h })
1081- h .attr = y
1082- for proto in protocols :
1103+ def test_recursive_list_subclass (self ):
1104+ y = MyList ()
1105+ y .append (y )
1106+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
10831107 s = self .dumps (y , proto )
10841108 x = self .loads (s )
1085- self .assertIsInstance (x , frozenset )
1086- self .assertIs (list (x )[0 ].attr , x )
1109+ self .assertIsInstance (x , MyList )
10871110 self .assertEqual (len (x ), 1 )
1111+ self .assertIs (x [0 ], x )
1112+
1113+ def test_recursive_dict_subclass (self ):
1114+ d = MyDict ()
1115+ d [1 ] = d
1116+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
1117+ s = self .dumps (d , proto )
1118+ x = self .loads (s )
1119+ self .assertIsInstance (x , MyDict )
1120+ self .assertEqual (list (x .keys ()), [1 ])
1121+ self .assertIs (x [1 ], x )
1122+
1123+ def test_recursive_dict_subclass_key (self ):
1124+ d = MyDict ()
1125+ k = K (d )
1126+ d [k ] = 1
1127+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
1128+ s = self .dumps (d , proto )
1129+ x = self .loads (s )
1130+ self .assertIsInstance (x , MyDict )
1131+ self .assertEqual (len (list (x .keys ())), 1 )
1132+ self .assertIsInstance (list (x .keys ())[0 ], K )
1133+ self .assertIs (list (x .keys ())[0 ].value , x )
10881134
10891135 def test_recursive_inst (self ):
10901136 i = C ()
@@ -1111,6 +1157,48 @@ def test_recursive_multi(self):
11111157 self .assertEqual (list (x [0 ].attr .keys ()), [1 ])
11121158 self .assertTrue (x [0 ].attr [1 ] is x )
11131159
1160+ def check_recursive_collection_and_inst (self , factory ):
1161+ h = H ()
1162+ y = factory ([h ])
1163+ h .attr = y
1164+ for proto in protocols :
1165+ s = self .dumps (y , proto )
1166+ x = self .loads (s )
1167+ self .assertIsInstance (x , type (y ))
1168+ self .assertEqual (len (x ), 1 )
1169+ self .assertIsInstance (list (x )[0 ], H )
1170+ self .assertIs (list (x )[0 ].attr , x )
1171+
1172+ def test_recursive_list_and_inst (self ):
1173+ self .check_recursive_collection_and_inst (list )
1174+
1175+ def test_recursive_tuple_and_inst (self ):
1176+ self .check_recursive_collection_and_inst (tuple )
1177+
1178+ def test_recursive_dict_and_inst (self ):
1179+ self .check_recursive_collection_and_inst (dict .fromkeys )
1180+
1181+ def test_recursive_set_and_inst (self ):
1182+ self .check_recursive_collection_and_inst (set )
1183+
1184+ def test_recursive_frozenset_and_inst (self ):
1185+ self .check_recursive_collection_and_inst (frozenset )
1186+
1187+ def test_recursive_list_subclass_and_inst (self ):
1188+ self .check_recursive_collection_and_inst (MyList )
1189+
1190+ def test_recursive_tuple_subclass_and_inst (self ):
1191+ self .check_recursive_collection_and_inst (MyTuple )
1192+
1193+ def test_recursive_dict_subclass_and_inst (self ):
1194+ self .check_recursive_collection_and_inst (MyDict .fromkeys )
1195+
1196+ def test_recursive_set_subclass_and_inst (self ):
1197+ self .check_recursive_collection_and_inst (MySet )
1198+
1199+ def test_recursive_frozenset_subclass_and_inst (self ):
1200+ self .check_recursive_collection_and_inst (MyFrozenSet )
1201+
11141202 def test_unicode (self ):
11151203 endcases = ['' , '<\\ u>' , '<\\ \u1234 >' , '<\n >' ,
11161204 '<\\ >' , '<\\ \U00012345 >' ,
0 commit comments