@@ -956,6 +956,7 @@ class NEI(NamedInt, Enum):
956956 test_pickle_dump_load (self .assertEqual , NI5 , 5 )
957957 self .assertEqual (NEI .y .value , 2 )
958958 test_pickle_dump_load (self .assertIs , NEI .y )
959+ test_pickle_dump_load (self .assertIs , NEI )
959960
960961 def test_subclasses_with_getnewargs_ex (self ):
961962 class NamedInt (int ):
@@ -1012,6 +1013,7 @@ class NEI(NamedInt, Enum):
10121013 test_pickle_dump_load (self .assertEqual , NI5 , 5 , protocol = (4 , 4 ))
10131014 self .assertEqual (NEI .y .value , 2 )
10141015 test_pickle_dump_load (self .assertIs , NEI .y , protocol = (4 , 4 ))
1016+ test_pickle_dump_load (self .assertIs , NEI )
10151017
10161018 def test_subclasses_with_reduce (self ):
10171019 class NamedInt (int ):
@@ -1068,6 +1070,7 @@ class NEI(NamedInt, Enum):
10681070 test_pickle_dump_load (self .assertEqual , NI5 , 5 )
10691071 self .assertEqual (NEI .y .value , 2 )
10701072 test_pickle_dump_load (self .assertIs , NEI .y )
1073+ test_pickle_dump_load (self .assertIs , NEI )
10711074
10721075 def test_subclasses_with_reduce_ex (self ):
10731076 class NamedInt (int ):
@@ -1124,8 +1127,9 @@ class NEI(NamedInt, Enum):
11241127 test_pickle_dump_load (self .assertEqual , NI5 , 5 )
11251128 self .assertEqual (NEI .y .value , 2 )
11261129 test_pickle_dump_load (self .assertIs , NEI .y )
1130+ test_pickle_dump_load (self .assertIs , NEI )
11271131
1128- def test_subclasses_without_getnewargs (self ):
1132+ def test_subclasses_without_direct_pickle_support (self ):
11291133 class NamedInt (int ):
11301134 __qualname__ = 'NamedInt'
11311135 def __new__ (cls , * args ):
@@ -1178,6 +1182,61 @@ class NEI(NamedInt, Enum):
11781182 test_pickle_exception (self .assertRaises , TypeError , NEI .x )
11791183 test_pickle_exception (self .assertRaises , PicklingError , NEI )
11801184
1185+ def test_subclasses_without_direct_pickle_support_using_name (self ):
1186+ class NamedInt (int ):
1187+ __qualname__ = 'NamedInt'
1188+ def __new__ (cls , * args ):
1189+ _args = args
1190+ name , * args = args
1191+ if len (args ) == 0 :
1192+ raise TypeError ("name and value must be specified" )
1193+ self = int .__new__ (cls , * args )
1194+ self ._intname = name
1195+ self ._args = _args
1196+ return self
1197+ @property
1198+ def __name__ (self ):
1199+ return self ._intname
1200+ def __repr__ (self ):
1201+ # repr() is updated to include the name and type info
1202+ return "{}({!r}, {})" .format (type (self ).__name__ ,
1203+ self .__name__ ,
1204+ int .__repr__ (self ))
1205+ def __str__ (self ):
1206+ # str() is unchanged, even if it relies on the repr() fallback
1207+ base = int
1208+ base_str = base .__str__
1209+ if base_str .__objclass__ is object :
1210+ return base .__repr__ (self )
1211+ return base_str (self )
1212+ # for simplicity, we only define one operator that
1213+ # propagates expressions
1214+ def __add__ (self , other ):
1215+ temp = int (self ) + int ( other )
1216+ if isinstance (self , NamedInt ) and isinstance (other , NamedInt ):
1217+ return NamedInt (
1218+ '({0} + {1})' .format (self .__name__ , other .__name__ ),
1219+ temp )
1220+ else :
1221+ return temp
1222+
1223+ class NEI (NamedInt , Enum ):
1224+ __qualname__ = 'NEI'
1225+ x = ('the-x' , 1 )
1226+ y = ('the-y' , 2 )
1227+ def __reduce_ex__ (self , proto ):
1228+ return getattr , (self .__class__ , self ._name_ )
1229+
1230+ self .assertIs (NEI .__new__ , Enum .__new__ )
1231+ self .assertEqual (repr (NEI .x + NEI .y ), "NamedInt('(the-x + the-y)', 3)" )
1232+ globals ()['NamedInt' ] = NamedInt
1233+ globals ()['NEI' ] = NEI
1234+ NI5 = NamedInt ('test' , 5 )
1235+ self .assertEqual (NI5 , 5 )
1236+ self .assertEqual (NEI .y .value , 2 )
1237+ test_pickle_dump_load (self .assertIs , NEI .y )
1238+ test_pickle_dump_load (self .assertIs , NEI )
1239+
11811240 def test_tuple_subclass (self ):
11821241 class SomeTuple (tuple , Enum ):
11831242 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
0 commit comments