Hello community, here is the log from the commit of package python-aenum for openSUSE:Factory checked in at 2019-12-12 23:17:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-aenum (Old) and /work/SRC/openSUSE:Factory/.python-aenum.new.4691 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-aenum" Thu Dec 12 23:17:57 2019 rev:4 rq:755836 version:2.2.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-aenum/python-aenum.changes 2019-07-30 12:39:02.866937105 +0200 +++ /work/SRC/openSUSE:Factory/.python-aenum.new.4691/python-aenum.changes 2019-12-12 23:18:03.934214008 +0100 @@ -1,0 +2,6 @@ +Wed Dec 11 11:56:29 UTC 2019 - Tomáš Chvátal <tchva...@suse.com> + +- Update to 2.2.3: + * Various minor fixes + +------------------------------------------------------------------- Old: ---- aenum-2.2.1.tar.gz New: ---- aenum-2.2.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-aenum.spec ++++++ --- /var/tmp/diff_new_pack.IjvYEy/_old 2019-12-12 23:18:05.342213882 +0100 +++ /var/tmp/diff_new_pack.IjvYEy/_new 2019-12-12 23:18:05.354213880 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-aenum # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,12 +18,12 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-aenum -Version: 2.2.1 +Version: 2.2.3 Release: 0 Summary: Advanced Enumerations, NamedTuples, and NamedConstants License: BSD-3-Clause Group: Development/Languages/Python -Url: https://bitbucket.org/stoneleaf/aenum +URL: https://bitbucket.org/stoneleaf/aenum Source: https://files.pythonhosted.org/packages/source/a/aenum/aenum-%{version}.tar.gz BuildRequires: %{python_module setuptools} BuildRequires: fdupes ++++++ aenum-2.2.1.tar.gz -> aenum-2.2.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/PKG-INFO new/aenum-2.2.3/PKG-INFO --- old/aenum-2.2.1/PKG-INFO 2019-07-24 23:22:43.000000000 +0200 +++ new/aenum-2.2.3/PKG-INFO 2019-11-10 02:43:09.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: aenum -Version: 2.2.1 +Version: 2.2.3 Summary: Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants Home-page: https://bitbucket.org/stoneleaf/aenum Author: Ethan Furman @@ -46,6 +46,9 @@ - enum: helper class for creating members with keywords + - enum_property: property to enable enum members to have same named attributes + (e.g. `name` and `value`) + - export: helper to insert Enum members into a namespace (usually globals()) - extend_enum: add new members to enumerations after creation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/aenum/CHANGES new/aenum-2.2.3/aenum/CHANGES --- old/aenum-2.2.1/aenum/CHANGES 2019-07-24 23:22:37.000000000 +0200 +++ new/aenum-2.2.3/aenum/CHANGES 2019-11-10 02:43:02.000000000 +0100 @@ -1,3 +1,48 @@ +2.2.3 +===== + +use member type's methods __str__, __repr__, __format__, and +__reduce_ex__ if directly assigned in Enum class body; i.e.: + + --> class Color(str, Enum): + ... red = 'red' + ... green = 'green' + ... blue = 'blue' + ... __str__ = str.__str__ + + --> print(repr(Color.green)) + <Color.green: 'green'> + + --> print(Color.green) + green + + +2.2.2 +===== + +replace _RouteClassAttributeToGetattr with enum_property (it is still +available as an alias) + +support constant() and auto() being used together: + + --> class Fruit(Flag): + ... _order_ = 'apple banana lemon orange' + ... apple = auto() + ... banana = auto() + ... lemon = auto() + ... orange = auto() + ... CitrusTypes = constant(lemon | orange) + + --> list(Fruit) + [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange] + + --> list(Fruit.CitrusTypes) + [Fruit.orange, Fruit.lemon] + + --> Fruit.orange in Fruit.CitrusTypes + True + + 2.2.1 ===== @@ -19,14 +64,14 @@ allow Enum name use while constructing Enum (Python 3.4+ only) - class Color(Enum): - _order_ = 'BLACK WHITE' - BLACK = Color('black', '#000') - WHITE = Color('white', '#fff') - - def __init__(self, label, hex): - self.label = label - self.hex = hex + --> class Color(Enum): + ... _order_ = 'BLACK WHITE' + ... BLACK = Color('black', '#000') + ... WHITE = Color('white', '#fff') + ... # + ... def __init__(self, label, hex): + ... self.label = label + ... self.hex = hex 2.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/aenum/__init__.py new/aenum-2.2.3/aenum/__init__.py --- old/aenum-2.2.1/aenum/__init__.py 2019-07-24 23:22:37.000000000 +0200 +++ new/aenum-2.2.3/aenum/__init__.py 2019-11-10 02:43:03.000000000 +0100 @@ -40,13 +40,13 @@ 'Enum', 'IntEnum', 'AutoNumberEnum', 'OrderedEnum', 'UniqueEnum', 'Flag', 'IntFlag', 'AutoNumber', 'MultiValue', 'NoAlias', 'Unique', - 'enum', 'extend_enum', 'unique', + 'enum', 'extend_enum', 'unique', 'enum_property', 'NamedTuple', 'SqliteEnum', ] if sqlite3 is None: __all__.remove('SqliteEnum') -version = 2, 2, 1 +version = 2, 2, 3 try: any @@ -97,23 +97,32 @@ # will be exported later AutoValue = AutoNumber = MultiValue = NoAlias = Unique = None -class _RouteClassAttributeToGetattr(object): - """Route attribute access on a class to __getattr__. - - This is a descriptor, used to define attributes that act differently when - accessed through an instance and through a class. Instance access remains - normal, but access to an attribute through a class will be routed to the - class's __getattr__ method; this is done by raising AttributeError. +class enum_property(object): + """ + This is a descriptor, used to define attributes that act differently + when accessed through an enum member and through an enum class. + Instance access is the same as property(), but access to an attribute + through the enum class will look in the class' _member_map_. """ + name = None # set by metaclass - def __init__(self, fget=None): + def __init__(self, fget=None, doc=None): self.fget = fget + self.__doc__ = doc or fget.__doc__ + + def __call__(self, func, doc=None): + self.fget = func + self.__doc__ = self.__doc__ or doc or func.__doc__ def __get__(self, instance, ownerclass=None): if instance is None: - raise AttributeError() - return self.fget(instance) + try: + return ownerclass._member_map_[self.name] + except KeyError: + raise AttributeError(self.name) + else: + return self.fget(instance) def __set__(self, instance, value): raise AttributeError("can't set attribute %r" % (self.name, )) @@ -121,6 +130,7 @@ def __delete__(self, instance): raise AttributeError("can't delete attribute %r" % (self.name, )) +_RouteClassAttributeToGetattr = enum_property class NonMember(object): """ @@ -1391,7 +1401,14 @@ _init_.pop(0) self._init = _init_ elif key == '_generate_next_value_': - setattr(self, '_generate_next_value', value) + if isinstance(value, staticmethod): + gnv = value.__func__ + elif isinstance(value, classmethod): + raise TypeError('_generate_next_value should be a staticmethod, not a classmethod') + else: + gnv = value + value = staticmethod(value) + setattr(self, '_generate_next_value', gnv) self._auto_args = _check_auto_args(value) elif _is_dunder(key): if key == '__order__': @@ -1444,8 +1461,6 @@ source_values = len(value) if target_values != source_values: gnv = self._generate_next_value - if isinstance(gnv, staticmethod): - gnv = gnv.__func__ if self._auto_args: value = gnv( key, 1, @@ -1518,6 +1533,12 @@ else: if value.value == _auto_null: gnv = self._generate_next_value + prev_values = [] + for v in self._last_values: + if isinstance(v, auto): + prev_values.append(v.value) + else: + prev_values.append(v) if isinstance(gnv, staticmethod): gnv = gnv.__func__ if self._auto_args: @@ -1525,7 +1546,7 @@ key, 1, len(self._member_names), - self._last_values[:], + prev_values, *value.args, **value.kwds ) @@ -1534,9 +1555,8 @@ key, 1, len(self._member_names), - self._last_values[:], + prev_values, ) - value = value.value elif isinstance(value, enum): value.name = key else: @@ -1754,7 +1774,7 @@ for name, obj in clsdict.items(): if isinstance(obj, nonmember): dict.__setitem__(clsdict, name, obj.value) - elif isinstance(obj, _RouteClassAttributeToGetattr): + elif isinstance(obj, enum_property): obj.name = name # check for illegal enum names (any others?) invalid_names = set(enum_members) & set(['mro', '']) @@ -1787,6 +1807,8 @@ __new__ = enum_class.__new__ for member_name in clsdict._member_names: value = enum_members[member_name] + if isinstance(value, auto): + value = value.value kwds = {} new_args = () init_args = () @@ -1877,9 +1899,19 @@ (cls, '; '.join(message)) ) # performance boost for any member that would not shadow - # a DynamicClassAttribute (aka _RouteClassAttributeToGetattr) + # an enum_property if member_name not in base_attributes: setattr(enum_class, member_name, enum_member) + else: + # otherwise make sure the thing being shadowed /is/ an + # enum_property + for parent in enum_class.mro()[1:]: + if member_name in parent.__dict__: + obj = parent.__dict__[member_name] + if not isinstance(obj, enum_property): + raise TypeError('%r already used: %r' % (member_name, obj)) + # we're good + break # now add to _member_map_ enum_class._member_map_[member_name] = enum_member values = (value, ) + extra_mv_args @@ -1900,8 +1932,10 @@ enum_class._value2member_map_[value] = enum_member except TypeError: enum_class._value2member_seq_ += ((value, enum_member), ) - - + # check for constants with auto() values + for k, v in enum_class.__dict__.items(): + if isinstance(v, constant) and isinstance(v.value, auto): + v.value = enum_class(v.value.value) # If a custom type is mixed into the Enum, and it does not know how # to pickle itself, pickle.dumps will succeed but pickle.loads will # fail. Rather than have the error show up later and possibly far @@ -1921,10 +1955,14 @@ _make_class_unpicklable(enum_class) unpicklable = True - # double check that repr and friends are not the mixin's or various # things break (such as pickle) + for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): + enum_class_method = enum_class.__dict__.get(name, None) + if enum_class_method: + # class has defined/imported/copied the method + continue class_method = getattr(enum_class, name) obj_method = getattr(member_type, name, None) enum_method = getattr(first_enum, name, None) @@ -1933,7 +1971,6 @@ continue setattr(enum_class, name, enum_method) - # method resolution and int's are not playing nice # Python's less than 2.6 use __cmp__ @@ -1977,7 +2014,7 @@ # create ordered list for comparison _order_ = [m.name for m in sorted(enum_class, key=_order_)] if _order_ != enum_class._member_names_: - raise TypeError('member order does not match _order_') + raise TypeError('member order does not match _order_: %r %r' % (enum_class._member_names_, enum_class._member_map_.items())) return enum_class def __bool__(cls): @@ -2039,21 +2076,6 @@ """ return cls._member_map_.copy() - def __getattr__(cls, name): - """Return the enum member matching `name` - - We use __getattr__ instead of descriptors or inserting into the enum - class' __dict__ in order to support `name` and `value` being both - properties for enum members (which live in the class' __dict__) and - enum members themselves. - """ - if _is_dunder(name): - raise AttributeError(name) - try: - return cls._member_map_[name] - except KeyError: - raise AttributeError(name) - def __getitem__(cls, name): try: return cls._member_map_[name] @@ -2569,29 +2591,29 @@ temp_enum_dict['_convert'] = classmethod(_convert) del _convert -# _RouteClassAttributeToGetattr is used to provide access to the `name` -# and `value` properties of enum members while keeping some measure of -# protection from modification, while still allowing for an enumeration -# to have members named `name` and `value`. This works because enumeration -# members are not set directly on the enum class -- __getattr__ is -# used to look them up. +# enum_property is used to provide access to the `name`, `value', etc., +# properties of enum members while keeping some measure of protection +# from modification, while still allowing for an enumeration to have +# members named `name`, `value`, etc.. This works because enumeration +# members are not set directly on the enum class -- enum_property will +# look them up in _member_map_. # -# This method is also very slow, so EnumMeta will add members directly to the -# Enum class if it won't shadow other instance attributes +# This method is also very slow, so EnumMeta will add members directlyi +# to the Enum class if it won't shadow other instance attributes -@_RouteClassAttributeToGetattr +@enum_property def name(self): return self._name_ temp_enum_dict['name'] = name del name -@_RouteClassAttributeToGetattr +@enum_property def value(self): return self._value_ temp_enum_dict['value'] = value del value -@_RouteClassAttributeToGetattr +@enum_property def values(self): return self._values_ temp_enum_dict['values'] = values @@ -2794,14 +2816,27 @@ if _no_alias_: # unless NoAlias was specified _member_names_.append(name) + _member_map_[name] = new_member else: for canonical_member in _member_map_.values(): _values_ = getattr(canonical_member, '_values_', [canonical_member._value_]) for canonical_value in _values_: if canonical_value == new_member._value_: + # name is an alias if _unique_ or _multi_value_: # aliases not allowed if Unique specified raise ValueError('%s is a duplicate of %s' % (name, canonical_member.name)) + if name not in base_attributes: + setattr(enumeration, name, canonical_member) + else: + # check type of name + for parent in enumeration.mro()[1:]: + if name in parent.__dict__: + obj = parent.__dict__[name] + if not isinstance(obj, enum_property): + raise TypeError('%r already used: %r' % (name, obj)) + break + # Aliases don't appear in member names (only in __members__ and _member_map_). _member_map_[new_member._name_] = canonical_member new_member = canonical_member is_alias = True @@ -2809,34 +2844,41 @@ if is_alias: break else: - # Aliases don't appear in member names (only in __members__). + # not an alias + values = (value, ) + more_values + new_member._values_ = values + for value in (value, ) + more_values: + # first check if value has already been used + if _multi_value_ and ( + value in _value2member_map_ + or any(v == value for (v, m) in _value2member_seq_) + ): + raise ValueError('%r has already been used' % (value, )) + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + if _no_alias_: + raise TypeError('cannot use dict to store value') + _value2member_map_[value] = new_member + except TypeError: + _value2member_seq_ += ((value, new_member), ) + if name not in base_attributes: + setattr(enumeration, name, new_member) + else: + # check type of name + for parent in enumeration.mro()[1:]: + if name in parent.__dict__: + obj = parent.__dict__[name] + if not isinstance(obj, enum_property): + raise TypeError('%r already used: %r' % (name, obj)) + break _member_names_.append(name) - if not is_alias: - values = (value, ) + more_values - new_member._values_ = values - for value in (value, ) + more_values: - # first check if value has already been used - if _multi_value_ and ( - value in _value2member_map_ - or any(v == value for (v, m) in _value2member_seq_) - ): - raise ValueError('%r has already been used' % (value, )) + _member_map_[name] = new_member try: - # This may fail if value is not hashable. We can't add the value - # to the map, and by-value lookups for this value will be - # linear. - if _no_alias_: - raise TypeError('cannot use dict to store value') _value2member_map_[value] = new_member except TypeError: - _value2member_seq_ += ((value, new_member), ) - if name not in base_attributes: - setattr(enumeration, name, new_member) - _member_map_[name] = new_member - try: - _value2member_map_[value] = new_member - except TypeError: - pass + pass def unique(enumeration): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/aenum/doc/aenum.pdf new/aenum-2.2.3/aenum/doc/aenum.pdf --- old/aenum-2.2.1/aenum/doc/aenum.pdf 2019-07-24 23:22:43.000000000 +0200 +++ new/aenum-2.2.3/aenum/doc/aenum.pdf 2019-11-10 02:43:09.000000000 +0100 @@ -357,7 +357,7 @@ endobj 45 0 obj << -/Author () /CreationDate (D:20190724142242+08'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20190724142242+08'00') /Producer (ReportLab PDF Library - www.reportlab.com) +/Author () /CreationDate (D:20191109174308+08'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20191109174308+08'00') /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\)) /Title (aenum --- support for advanced enumerations, namedtuples, and constants) /Trapped /False >> endobj @@ -4882,7 +4882,7 @@ trailer << /ID -[<af725aae5768dc69b62d14f1504864a7><af725aae5768dc69b62d14f1504864a7>] +[<82bdf423791213d84b7c3b54f91ad929><82bdf423791213d84b7c3b54f91ad929>] % ReportLab generated PDF document -- digest (http://www.reportlab.com) /Info 45 0 R diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/aenum/test.py new/aenum-2.2.3/aenum/test.py --- old/aenum-2.2.1/aenum/test.py 2019-07-24 23:22:37.000000000 +0200 +++ new/aenum-2.2.3/aenum/test.py 2019-11-10 02:43:02.000000000 +0100 @@ -1990,6 +1990,33 @@ yellow = 6 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') + def test_extending4(self): + class hohum(object): + def cyan(self): + "cyanize a color" + return self.value + with self.assertRaises(TypeError): + class Color(hohum, Enum): + red = 1 + green = 2 + blue = 3 + cyan = 4 + + def test_extending5(self): + class Color(Enum): + _order_ = 'red green blue value' + red = 1 + green = 2 + blue = 3 + value = 4 + self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.value]) + self.assertEqual(Color.value.name, 'value') + self.assertEqual(Color.value.value, 4) + self.assertTrue(Color.value in Color) + self.assertEqual(Color(4), Color.value) + self.assertEqual(Color['value'], Color.value) + self.assertEqual(Color.red.value, 1) + if StdlibEnum is not None: def test_extend_enum_stdlib(self): @@ -2068,6 +2095,20 @@ self.assertEqual(len(Color), 4) self.assertEqual(Color.red.value, 1) + def test_extend_enum_shadow_base(self): + class hohum(object): + def cyan(self): + "cyanize a color" + return self.value + class Color(hohum, UniqueEnum): + red = 1 + green = 2 + blue = 3 + with self.assertRaises(TypeError): + extend_enum(Color, 'cyan', 4) + self.assertEqual(len(Color), 3) + self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) + def test_extend_enum_multivalue(self): class Color(MultiValueEnum): red = 1, 4, 7 @@ -2820,6 +2861,7 @@ def test_member_with_external_functions(self): class Func(Enum): + _order_ = 'an_int a_str' an_int = member(int) a_str = member(str) @classproperty @@ -2837,6 +2879,7 @@ def test_member_with_internal_functions(self): class Func(Enum): + _order_ = 'haha hehe' @member def haha(): return 'haha' @@ -2871,6 +2914,30 @@ self.assertEqual(Universe.PI, 3.141596) self.assertEqual(Universe.TAU, 2 * Universe.PI) + def test_constant_with_auto_is_updated(self): + class Fruit(Flag): + _order_ = 'apple banana lemon orange' + apple = auto() + banana = auto() + lemon = auto() + orange = auto() + CitrusTypes = constant(lemon | orange) + self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]) + self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon]) + self.assertTrue(Fruit.orange in Fruit.CitrusTypes) + + def test_constant_with_enum_is_updated(self): + class Fruit(Flag): + _order_ = 'apple banana lemon orange' + apple = auto() + banana = auto() + lemon = auto() + orange = auto() + CitrusTypes = constant(lemon | orange) + self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]) + self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon]) + self.assertTrue(Fruit.orange in Fruit.CitrusTypes) + def test_order_as_function(self): # first with _init_ class TestSequence(Enum): @@ -3330,6 +3397,64 @@ BLUE = 4 PURPLE = RED|BLUE + class TermColor(str, Flag): + _settings_ = AutoValue + + def __new__(cls, value, code): + str_value = '\x1b[%sm' % code + obj = str.__new__(cls, str_value) + obj._value_ = value + obj.code = code + return obj + + @classmethod + def _create_pseudo_member_values_(cls, members, *values): + code = ';'.join(m.code for m in members) + return values + (code, ) + + AllReset = '0' # ESC [ 0 m # reset all (colors and brightness) + Bright = '1' # ESC [ 1 m # bright + Dim = '2' # ESC [ 2 m # dim (looks same as normal brightness) + Underline = '4' + Normal = '22' # ESC [ 22 m # normal brightness + # + # # FOREGROUND - 30s BACKGROUND - 40s: + FG_Black = '30' # ESC [ 30 m # black + FG_Red = '31' # ESC [ 31 m # red + FG_Green = '32' # ESC [ 32 m # green + FG_Yellow = '33' # ESC [ 33 m # yellow + FG_Blue = '34' # ESC [ 34 m # blue + FG_Magenta = '35' # ESC [ 35 m # magenta + FG_Cyan = '36' # ESC [ 36 m # cyan + FG_White = '37' # ESC [ 37 m # white + FG_Reset = '39' # ESC [ 39 m # reset + # + BG_Black = '40' # ESC [ 30 m # black + BG_Red = '41' # ESC [ 31 m # red + BG_Green = '42' # ESC [ 32 m # green + BG_Yellow = '43' # ESC [ 33 m # yellow + BG_Blue = '44' # ESC [ 34 m # blue + BG_Magenta = '45' # ESC [ 35 m # magenta + BG_Cyan = '46' # ESC [ 36 m # cyan + BG_White = '47' # ESC [ 37 m # white + BG_Reset = '49' # ESC [ 39 m # reset + + __str__ = str.__str__ + + def __repr__(self): + if self._name_ is not None: + return '<%s.%s>' % (self.__class__.__name__, self._name_) + else: + return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)])) + + def __enter__(self): + print(self.AllReset, end='', verbose=0) + return self + + def __exit__(self, *args): + print(self.AllReset, end='', verbose=0) + + class Open(Flag): RO = 0 WO = 1 @@ -3337,6 +3462,15 @@ AC = 3 CE = 1<<19 + def test_str_is_str_str(self): + red, white = self.TermColor.FG_Red, self.TermColor.BG_White + barber = red | white + self.assertEqual(barber, '\x1b[47;31m') + self.assertEqual(barber.value, red.value | white.value) + self.assertEqual(barber.code, ';'.join([white.code, red.code])) + self.assertEqual(repr(barber), '<TermColor: BG_White|FG_Red>') + self.assertEqual(str(barber), '\x1b[47;31m') + def test_membership(self): Color = self.Color Open = self.Open @@ -4087,10 +4221,16 @@ RED = 1 GREEN = 2 BLUE = 4 - extend_enum(Color, 'PURPLE', 5) - self.assertTrue(Color(5) is Color.PURPLE) + extend_enum(Color, 'MAGENTA') + self.assertTrue(Color(8) is Color.MAGENTA) + self.assertTrue(isinstance(Color.MAGENTA, Color)) + self.assertEqual(Color.MAGENTA.value, 8) + extend_enum(Color, 'PURPLE', 11) + self.assertTrue(Color(11) is Color.PURPLE) self.assertTrue(isinstance(Color.PURPLE, Color)) - self.assertEqual(Color.PURPLE.value, 5) + self.assertEqual(Color.PURPLE.value, 11) + self.assertTrue(issubclass(Color, Flag)) + print(list(Color)) def test_extend_flag_subclass(self): class Color(str, Flag): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/aenum.egg-info/PKG-INFO new/aenum-2.2.3/aenum.egg-info/PKG-INFO --- old/aenum-2.2.1/aenum.egg-info/PKG-INFO 2019-07-24 23:22:43.000000000 +0200 +++ new/aenum-2.2.3/aenum.egg-info/PKG-INFO 2019-11-10 02:43:09.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: aenum -Version: 2.2.1 +Version: 2.2.3 Summary: Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants Home-page: https://bitbucket.org/stoneleaf/aenum Author: Ethan Furman @@ -46,6 +46,9 @@ - enum: helper class for creating members with keywords + - enum_property: property to enable enum members to have same named attributes + (e.g. `name` and `value`) + - export: helper to insert Enum members into a namespace (usually globals()) - extend_enum: add new members to enumerations after creation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aenum-2.2.1/setup.py new/aenum-2.2.3/setup.py --- old/aenum-2.2.1/setup.py 2019-07-24 23:22:37.000000000 +0200 +++ new/aenum-2.2.3/setup.py 2019-11-10 02:43:03.000000000 +0100 @@ -46,6 +46,9 @@ - enum: helper class for creating members with keywords +- enum_property: property to enable enum members to have same named attributes + (e.g. `name` and `value`) + - export: helper to insert Enum members into a namespace (usually globals()) - extend_enum: add new members to enumerations after creation @@ -62,7 +65,7 @@ data = dict( name='aenum', - version='2.2.1', + version='2.2.3', url='https://bitbucket.org/stoneleaf/aenum', packages=['aenum'], package_data={ @@ -104,7 +107,7 @@ if __name__ == '__main__': if 'install' in sys.argv: - import os, sys, shutil + import os, sys if sys.version_info[0] != 2: for file in py2_only: try: