Package: enum34-custom
WhatCustom Enum classes for the Python 3.4 enum module.Install$pipinstallenum34-customUsageMultiValueEnumEnum subclass where a member can be any iterable (even a generator, except str).
You can reference a member by any of its element in the associated iterable.
It might be usable for e.g. Equivalence Class Partitioning (ECP/EC testing).fromenum_customimportMultiValueEnumclassSuit(MultiValueEnum):CLUBS='♣','c','C'DIAMONDS='♦','d','D'HEARTS='♥','h','H'SPADES='♠','s','S'>>>print(Suit.CLUBS)Suit.CLUBS>>>Suit.CLUBS<Suit.CLUBS:('♣','c','C')>>>>Suit('c')<Suit.CLUBS:('♣','c','C')>>>>Suit('c')isSuit('C')isSuit('♣')isSuit.CLUBSTrue>>>importpickle>>>pickle.loads(pickle.dumps(Suit('c')))isSuit('♣')True>>>Suit('L')Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"/Users/walkman/Projects/enum34-custom/enum_custom.py",line19,in__call__returnsuper().__call__(suit)File"/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/enum.py",line222,in__call__returncls.__new__(cls,value)File"/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/enum.py",line457,in__new__raiseValueError("%sis not a valid%s"%(value,cls.__name__))ValueError:LisnotavalidSuit>>>list(Suit)[<Suit.CLUBS:('♣','c','C')>,<Suit.DIAMONDS:('♦','d','D')>,<Suit.HEARTS:('♥','h','H')>,<Suit.SPADES:('♠','s','S')>]WarningYou need to keep a couple of things in mind when using MultiValueEnum:Generators will immediately be exhausted at class creation time!To conform to the standard library behavior, overlapping iterables are
considered aliases, and works the same way as in stdlib
(lookup will match the first declared element):>>>classMyOverLappingMVE(MultiValueEnum):...A=(0,1,2,3,4)...B=(4,5,6,7,8)>>>MyOverLappingMVE(4)<MyOverLappingMVE.A:(0,1,2,3,4)>If you want to make sure, no overlapping elements are present between members,
you can use the no_overlap decorator:>>>fromenum_customimportMultiValueEnum,no_overlap>>>@no_overlap...classNoOverLappingEnum(MultiValueEnum):...A=(1,2,3)...B=(3,4,5).../Users/walkman/Projects/enum34-custom/enum_custom.pyinno_overlap(multienum)55(alias,name,intersection)induplicates])56raiseValueError('common element found in{!r}:{}'--->57.format(multienum,alias_details))58returnmultienum59ValueError:commonelementfoundin<enum'NoOverLappingEnum'>:B&A->{3}Beware with storing lots of data, every value will stored twice
(MultiValueEnum stores values internally in a set for faster lookups)If you declare a dict as a value, keys will be looked up (as expected)CaseInsensitiveMultiValueEnumThis works the same way as MultiValueEnum except if a member’s value contains
a str, those will be compared in a case-insensitive member.Consider the following example:classSimpleMultiValueEnum(MultiValueEnum):one=1,'one'two=2,'two'>>>SimpleMultiValueEnum('One')/usr/local/Cellar/python3/3.4.1_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/enum.pyin__new__(cls,value)455ifmember.value==value:456returnmember-->457raiseValueError("%sis not a valid%s"%(value,cls.__name__))458459def__repr__(self):ValueError:OneisnotavalidSimpleMultiValueEnumWhile:classCaseInsensitiveMVE(CaseInsensitiveMultiValueEnum):one=1,'one'two=2,'two'>>>CaseInsensitiveMVE('One')<CaseInsensitiveMVE.one:(1,'one')>StrEnumMembers of this enum are also instances of str and directly comparable to strings.
str type is forced at declaration. Works the same way as described in Python
Enum documentation, except for checking type.WarningIt’s not possible to use StrEnum with OrderableMixin, because the members of
StrEnum are also instances of str and ordering members will happen beased on
str ordering (e.g. ‘1’ < ‘2’, ‘A’ < ‘B’, etc.)
If you want ordering by declaration, use OrderableMixin without typed
subclass.CaseInsensitiveStrEnumSame as StrEnum, but members stored as uppercase, and comparing to them is
case insensitive also:fromenum_customimportCaseInsensitiveStrEnumclassMyCaseInsensitiveStrEnum(CaseInsensitiveStrEnum):one='a'two='b'>>>MyCaseInsensitiveStrEnum('a')=='A'True>>>MyCaseInsensitiveStrEnum.one=='a'TrueTesting$pythonsetup.pytestOr install package in development mode and test with py.test:$ pip install -e .
$ py.testDifferences between Python 2 and 3There are differences in how Python 2 and 3 creates classes, there are a couple of
things that doesn’t work very well on 2, which you should be aware:xrange(5) != xrange(5)
This is the opposit in Python 3, because range(5) == range(5), however you can use
range(5) == range(5) in Python 2 in this case.Python 2 have no definition order of members. This means youhave tomanually define
__order__ attribute to be able to compare members by definition order (e.g. with
OrderableMixin). See the details inenum34 package dokumentation:str vs unicode: This library doesn’t mix and match str types either in Python2
it uses unicode in Python2 and str in Python3 and also enforces the type in
StrEnum, CaseInsensitiveStrEnum and ckeck for text type only in
CaseInsensitiveMultiValueEnum. (So if you pass str in Python2, it will not be case
insensitive!)Python 2 leaks variables from list comprehensions, so if you define your class
like this:On pypy you always have to set __order__ because if you use different types, because
it would sort the member values, but can’t compare set to other type.classMyList(MultiValueEnum):A=[nforninrange(5)]MyList will have ‘MyList.n’ also!!!Changesv0.7.0Python 2.7 supportRenamed module to enum_custom for consistency (enum34 package is called enum also).