change to match Enum in Python 3.5
diff --git a/enum/README b/enum/README
index 511af98..aa2333d 100644
--- a/enum/README
+++ b/enum/README
@@ -1,2 +1,3 @@
enum34 is the new Python stdlib enum module available in Python 3.4
backported for previous versions of Python from 2.4 to 3.3.
+tested on 2.6, 2.7, and 3.3+
diff --git a/enum/__init__.py b/enum/__init__.py
index 6a327a8..ee64342 100644
--- a/enum/__init__.py
+++ b/enum/__init__.py
@@ -77,7 +77,7 @@
def _is_sunder(name):
"""Returns True if a _sunder_ name, False otherwise."""
- return (name[0] == name[-1] == '_' and
+ return (name[0] == name[-1] == '_' and
name[1:2] != '_' and
name[-2:-1] != '_' and
len(name) > 2)
@@ -310,7 +310,7 @@
setattr(enum_class, '__new__', Enum.__dict__['__new__'])
return enum_class
- def __call__(cls, value, names=None, module=None, type=None):
+ def __call__(cls, value, names=None, module=None, type=None, start=1):
"""Either returns an existing member, or creates a new enum class.
This method is used both when an enum class is given a value to match
@@ -329,7 +329,7 @@
if names is None: # simple value lookup
return cls.__new__(cls, value)
# otherwise, functional API: we're creating a new Enum type
- return cls._create_(value, names, module=module, type=type)
+ return cls._create_(value, names, module=module, type=type, start=start)
def __contains__(cls, member):
return isinstance(member, cls) and member.name in cls._member_map_
@@ -400,7 +400,7 @@
raise AttributeError('Cannot reassign members.')
super(EnumMeta, cls).__setattr__(name, value)
- def _create_(cls, class_name, names=None, module=None, type=None):
+ def _create_(cls, class_name, names=None, module=None, type=None, start=1):
"""Convenience method to create a new Enum class.
`names` can be:
@@ -431,7 +431,7 @@
if isinstance(names, basestring):
names = names.replace(',', ' ').split()
if isinstance(names, (tuple, list)) and isinstance(names[0], basestring):
- names = [(e, i+1) for (i, e) in enumerate(names)]
+ names = [(e, i+start) for (i, e) in enumerate(names)]
# Here, names is either an iterable of (name, value) or a mapping.
for item in names:
@@ -470,7 +470,7 @@
"""
if not bases or Enum is None:
return object, Enum
-
+
# double check that we are not subclassing a class with existing
# enumeration members; while we're at it, see if any other data
@@ -719,7 +719,7 @@
raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__))
temp_enum_dict['__gt__'] = __gt__
del __gt__
-
+
def __eq__(self, other):
if type(other) is self.__class__:
@@ -740,6 +740,14 @@
temp_enum_dict['__hash__'] = __hash__
del __hash__
+def __bool__(self):
+ return bool(self._value_)
+if pyver < 3.0:
+ temp_enum_dict['__nonzero__'] = __bool__
+else:
+ temp_enum_dict['__bool__'] = __bool__
+ del __bool__
+
def __reduce_ex__(self, proto):
return self.__class__, (self._value_, )
temp_enum_dict['__reduce_ex__'] = __reduce_ex__
@@ -764,6 +772,30 @@
temp_enum_dict['value'] = value
del value
+@classmethod
+def _convert(cls, name, module, filter, source=None):
+ """
+ Create a new Enum subclass that replaces a collection of global constants
+ """
+ # convert all constants from source (or module) that pass filter() to
+ # a new Enum called name, and export the enum and its members back to
+ # module;
+ # also, replace the __reduce_ex__ method so unpickling works in
+ # previous Python versions
+ module_globals = vars(_sys.modules[module])
+ if source:
+ source = vars(source)
+ else:
+ source = module_globals
+ members = dict((name, value) for name, value in source.items() if filter(name))
+ cls = cls(name, members, module=module)
+ cls.__reduce_ex__ = _reduce_ex_by_name
+ module_globals.update(cls.__members__)
+ module_globals[name] = cls
+ return cls
+temp_enum_dict['_convert'] = _convert
+del _convert
+
Enum = EnumMeta('Enum', (object, ), temp_enum_dict)
del temp_enum_dict
@@ -773,6 +805,8 @@
class IntEnum(int, Enum):
"""Enum where members are also (and must be) ints"""
+def _reduce_ex_by_name(self, proto):
+ return self.name
def unique(enumeration):
"""Class decorator that ensures only unique members exist in an enumeration."""
diff --git a/enum/test_enum.py b/enum/test_enum.py
index d7a9794..92ae3dc 100644
--- a/enum/test_enum.py
+++ b/enum/test_enum.py
@@ -194,6 +194,21 @@
set(['__class__', '__doc__', '__module__', 'name', 'value']),
)
+ def test_dir_with_added_behavior(self):
+ class Test(Enum):
+ this = 'that'
+ these = 'those'
+ def wowser(self):
+ return ("Wowser! I'm %s!" % self.name)
+ self.assertEqual(
+ set(dir(Test)),
+ set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
+ )
+ self.assertEqual(
+ set(dir(Test.this)),
+ set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
+ )
+
def test_dir_on_sub_with_behavior_on_super(self):
# see issue22506
class SuperEnum(Enum):
@@ -244,7 +259,7 @@
self.assertNotEqual(Season.SPRING, Part.SPRING)
def bad_compare():
Season.SPRING < Part.CLIP
- self.assertRaises(TypeError, bad_compare)
+ self.assertRaises(TypeError, bad_compare)
def test_enum_in_enum_out(self):
Season = self.Season
@@ -320,6 +335,13 @@
self.assertRaises(ValueError, create_bad_class_1)
self.assertRaises(ValueError, create_bad_class_2)
+ def test_bool(self):
+ class Logic(Enum):
+ true = True
+ false = False
+ self.assertTrue(Logic.true)
+ self.assertFalse(Logic.false)
+
def test_contains(self):
Season = self.Season
self.assertTrue(Season.AUTUMN in Season)
@@ -599,7 +621,7 @@
test_pickle_dump_load(self.assertTrue, Question.who)
test_pickle_dump_load(self.assertTrue, Question)
- if pyver >= 3.4:
+ if pyver == 3.4:
def test_class_nested_enum_and_pickle_protocol_four(self):
# would normally just have this directly in the class namespace
class NestedEnum(Enum):
@@ -614,6 +636,18 @@
test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
protocol=(4, HIGHEST_PROTOCOL))
+ elif pyver == 3.5:
+ def test_class_nested_enum_and_pickle_protocol_four(self):
+ # would normally just have this directly in the class namespace
+ class NestedEnum(Enum):
+ twigs = 'common'
+ shiny = 'rare'
+
+ self.__class__.NestedEnum = NestedEnum
+ self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
+ test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
+ protocol=(0, HIGHEST_PROTOCOL))
+
def test_exploding_pickle(self):
BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter')
enum._make_class_unpicklable(BadPickle)
@@ -654,6 +688,13 @@
[Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
)
+ def test_iteration_order_reversed(self):
+ self.assertEqual(
+ list(reversed(self.Season)),
+ [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
+ self.Season.SPRING]
+ )
+
def test_iteration_order_with_unorderable_values(self):
class Complex(Enum):
a = complex(7, 9)
@@ -683,6 +724,23 @@
self.assertTrue(e in SummerMonth)
self.assertTrue(type(e) is SummerMonth)
+ def test_programatic_function_string_with_start(self):
+ SummerMonth = Enum('SummerMonth', 'june july august', start=10)
+ lst = list(SummerMonth)
+ self.assertEqual(len(lst), len(SummerMonth))
+ self.assertEqual(len(SummerMonth), 3, SummerMonth)
+ self.assertEqual(
+ [SummerMonth.june, SummerMonth.july, SummerMonth.august],
+ lst,
+ )
+ for i, month in enumerate('june july august'.split(), 10):
+ e = SummerMonth(i)
+ self.assertEqual(int(e.value), i)
+ self.assertNotEqual(e, i)
+ self.assertEqual(e.name, month)
+ self.assertTrue(e in SummerMonth)
+ self.assertTrue(type(e) is SummerMonth)
+
def test_programatic_function_string_list(self):
SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
lst = list(SummerMonth)
@@ -701,6 +759,23 @@
self.assertTrue(e in SummerMonth)
self.assertTrue(type(e) is SummerMonth)
+ def test_programatic_function_string_list_with_start(self):
+ SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
+ lst = list(SummerMonth)
+ self.assertEqual(len(lst), len(SummerMonth))
+ self.assertEqual(len(SummerMonth), 3, SummerMonth)
+ self.assertEqual(
+ [SummerMonth.june, SummerMonth.july, SummerMonth.august],
+ lst,
+ )
+ for i, month in enumerate('june july august'.split(), 20):
+ e = SummerMonth(i)
+ self.assertEqual(int(e.value), i)
+ self.assertNotEqual(e, i)
+ self.assertEqual(e.name, month)
+ self.assertTrue(e in SummerMonth)
+ self.assertTrue(type(e) is SummerMonth)
+
def test_programatic_function_iterable(self):
SummerMonth = Enum(
'SummerMonth',
@@ -761,6 +836,22 @@
self.assertTrue(e in SummerMonth)
self.assertTrue(type(e) is SummerMonth)
+ def test_programatic_function_type_with_start(self):
+ SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
+ lst = list(SummerMonth)
+ self.assertEqual(len(lst), len(SummerMonth))
+ self.assertEqual(len(SummerMonth), 3, SummerMonth)
+ self.assertEqual(
+ [SummerMonth.june, SummerMonth.july, SummerMonth.august],
+ lst,
+ )
+ for i, month in enumerate('june july august'.split(), 30):
+ e = SummerMonth(i)
+ self.assertEqual(e, i)
+ self.assertEqual(e.name, month)
+ self.assertTrue(e in SummerMonth)
+ self.assertTrue(type(e) is SummerMonth)
+
def test_programatic_function_type_from_subclass(self):
SummerMonth = IntEnum('SummerMonth', 'june july august')
lst = list(SummerMonth)
@@ -778,6 +869,22 @@
self.assertTrue(e in SummerMonth)
self.assertTrue(type(e) is SummerMonth)
+ def test_programatic_function_type_from_subclass_with_start(self):
+ SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
+ lst = list(SummerMonth)
+ self.assertEqual(len(lst), len(SummerMonth))
+ self.assertEqual(len(SummerMonth), 3, SummerMonth)
+ self.assertEqual(
+ [SummerMonth.june, SummerMonth.july, SummerMonth.august],
+ lst,
+ )
+ for i, month in enumerate('june july august'.split(), 40):
+ e = SummerMonth(i)
+ self.assertEqual(e, i)
+ self.assertEqual(e.name, month)
+ self.assertTrue(e in SummerMonth)
+ self.assertTrue(type(e) is SummerMonth)
+
def test_programatic_function_unicode(self):
SummerMonth = Enum('SummerMonth', unicode('june july august'))
lst = list(SummerMonth)
@@ -1496,6 +1603,15 @@
Color.green
Color.blue
+ def test_equality(self):
+ class AlwaysEqual:
+ def __eq__(self, other):
+ return True
+ class OrdinaryEnum(Enum):
+ a = 1
+ self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
+ self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
+
def test_ordered_mixin(self):
class OrderedEnum(Enum):
def __ge__(self, other):
@@ -1578,13 +1694,6 @@
grene = 2
self.assertRaises(ValueError, bad_duplicates)
- def test_reversed(self):
- self.assertEqual(
- list(reversed(self.Season)),
- [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
- self.Season.SPRING]
- )
-
def test_init(self):
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)