@@ -1184,6 +1184,101 @@ def some_classmethod(cls):
11841184 def some_staticmethod ():
11851185 """A staticmethod"""
11861186
1187+ @property
1188+ @abc .abstractmethod
1189+ def some_property ():
1190+ """A property"""
1191+
1192+ class ConcreteClass (AbstractClass ):
1193+ def some_method (self ):
1194+ return 'it works!'
1195+
1196+ @classmethod
1197+ def some_classmethod (cls ):
1198+ assert cls == ConcreteClass
1199+ return 'it works!'
1200+
1201+ @staticmethod
1202+ def some_staticmethod ():
1203+ return 'it works!'
1204+
1205+ @property
1206+ def some_property (self ):
1207+ return 'it works!'
1208+
1209+ # This abstract class is locally defined so we can safely register
1210+ # tuple in it to verify the unpickled class also register tuple.
1211+ AbstractClass .register (tuple )
1212+
1213+ concrete_instance = ConcreteClass ()
1214+ depickled_base = pickle_depickle (AbstractClass , protocol = self .protocol )
1215+ depickled_class = pickle_depickle (ConcreteClass ,
1216+ protocol = self .protocol )
1217+ depickled_instance = pickle_depickle (concrete_instance )
1218+
1219+ assert issubclass (tuple , AbstractClass )
1220+ assert issubclass (tuple , depickled_base )
1221+
1222+ self .assertEqual (depickled_class ().some_method (), 'it works!' )
1223+ self .assertEqual (depickled_instance .some_method (), 'it works!' )
1224+
1225+ self .assertEqual (depickled_class .some_classmethod (), 'it works!' )
1226+ self .assertEqual (depickled_instance .some_classmethod (), 'it works!' )
1227+
1228+ self .assertEqual (depickled_class ().some_staticmethod (), 'it works!' )
1229+ self .assertEqual (depickled_instance .some_staticmethod (), 'it works!' )
1230+
1231+ self .assertEqual (depickled_class ().some_property , 'it works!' )
1232+ self .assertEqual (depickled_instance .some_property , 'it works!' )
1233+ self .assertRaises (TypeError , depickled_base )
1234+
1235+ class DepickledBaseSubclass (depickled_base ):
1236+ def some_method (self ):
1237+ return 'it works for realz!'
1238+
1239+ @classmethod
1240+ def some_classmethod (cls ):
1241+ assert cls == DepickledBaseSubclass
1242+ return 'it works for realz!'
1243+
1244+ @staticmethod
1245+ def some_staticmethod ():
1246+ return 'it works for realz!'
1247+
1248+ @property
1249+ def some_property ():
1250+ return 'it works for realz!'
1251+
1252+ self .assertEqual (DepickledBaseSubclass ().some_method (),
1253+ 'it works for realz!' )
1254+
1255+ class IncompleteBaseSubclass (depickled_base ):
1256+ def some_method (self ):
1257+ return 'this class lacks some concrete methods'
1258+
1259+ self .assertRaises (TypeError , IncompleteBaseSubclass )
1260+
1261+ def test_abstracts (self ):
1262+ # Same as `test_abc` but using deprecated `abc.abstract*` methods.
1263+ # See https://github.com/cloudpipe/cloudpickle/issues/367
1264+
1265+ class AbstractClass (abc .ABC ):
1266+ @abc .abstractmethod
1267+ def some_method (self ):
1268+ """A method"""
1269+
1270+ @abc .abstractclassmethod
1271+ def some_classmethod (cls ):
1272+ """A classmethod"""
1273+
1274+ @abc .abstractstaticmethod
1275+ def some_staticmethod ():
1276+ """A staticmethod"""
1277+
1278+ @abc .abstractproperty
1279+ def some_property (self ):
1280+ """A property"""
1281+
11871282 class ConcreteClass (AbstractClass ):
11881283 def some_method (self ):
11891284 return 'it works!'
@@ -1197,6 +1292,10 @@ def some_classmethod(cls):
11971292 def some_staticmethod ():
11981293 return 'it works!'
11991294
1295+ @property
1296+ def some_property (self ):
1297+ return 'it works!'
1298+
12001299 # This abstract class is locally defined so we can safely register
12011300 # tuple in it to verify the unpickled class also register tuple.
12021301 AbstractClass .register (tuple )
@@ -1218,6 +1317,9 @@ def some_staticmethod():
12181317
12191318 self .assertEqual (depickled_class ().some_staticmethod (), 'it works!' )
12201319 self .assertEqual (depickled_instance .some_staticmethod (), 'it works!' )
1320+
1321+ self .assertEqual (depickled_class ().some_property , 'it works!' )
1322+ self .assertEqual (depickled_instance .some_property , 'it works!' )
12211323 self .assertRaises (TypeError , depickled_base )
12221324
12231325 class DepickledBaseSubclass (depickled_base ):
@@ -1233,6 +1335,10 @@ def some_classmethod(cls):
12331335 def some_staticmethod ():
12341336 return 'it works for realz!'
12351337
1338+ @property
1339+ def some_property (self ):
1340+ return 'it works for realz!'
1341+
12361342 self .assertEqual (DepickledBaseSubclass ().some_method (),
12371343 'it works for realz!' )
12381344
0 commit comments