Package: optenum
OptenumA missing Python Option/Enum library which supports enum code, name, text, even (code, name) tuple list and so on.Name "optenum" comes from 'option' + 'enumeration'.Compatible withPython 2.7+andPython 3.0+.InstallPython 3.x, 2.7pipinstalloptenumFor those probably missingsixmodule:pipinstallsixoptenumQuick startSimple as Enum typeSays we define a simple enum:fromoptenumimportOptionsclassFruit(Options):APPLE=1ORANGE=2BANANA=3Try the following in Python command line:>>> from optenum import Option, Options
>>> class Fruit(Options):
...     APPLE = 1
...     ORANGE = 2
...     BANANA = 3
>>> 
>>> Fruit.APPLE
<Option code=1 name=APPLE text=None>
>>> print(Fruit.APPLE)
1
>>> Fruit.APPLE.code
1
>>> Fruit.APPLE.name
'APPLE'
>>> Fruit.APPLE.text
>>> print(Fruit.APPLE.text)
None
>>> Fruit.APPLE.get_text()
'apple'Complex declarationYou may declare your Options (Enums) in many annotations.fromoptenumimportOption,OptionsclassEnumCellPhone(Options):APPLE=1SAMSUNG=Option(2,name='SAMSUNG')HUAWEI=3,'Huawei cellphone'# tuple annotation. name = code, textclassDoorState(Options):OPEN='O','Door is opened'# tuple annotation. name = code, textCLOSED=('C','Door is closed')# tuple annotation, too.IN_OPENING='IO'IN_CLOSING='IC'_FLAG=False# underscore leading name is not an optionx=lambday:y# function/callable is not an optionOperatorsOptionsupport some operators. See more inoperators.md.>>> class Favorite(Options):
...     APPLE = 1
...     BANANA = 3, 'Banana hot'
... 
>>> 
>>> Fruit.APPLE == Favorite.APPLE
True
>>> Fruit.BANANA == Favorite.BANANA
False
>>> Fruit.APPLE + 1 == Fruit.ORANGE
True>>> Fruit.BANANA >> 2
0
>>> Fruit.BANANA << 2
12>>> Fruit.BANANA > Favorite.APPLE
TrueCollectionsOptionsprovides some collections for accessing option and it's fields.
See section "Collections for Options" below for more information.>>> Fruit.codes
[1, 2, 3]
>>> Fruit.names
['ORANGE', 'APPLE', 'BANANA']
>>> Fruit.all
[<Option code=2 name=ORANGE text=None>, <Option code=1 name=APPLE text=None>, <Option code=3 name=BANANA text=None>]
>>> Fruit.tuples
[('ORANGE', 2, None), ('APPLE', 1, None), ('BANANA', 3, None)]
>>> Favorite.items
{'APPLE': <Option code=1 name=APPLE text=None>, 'BANANA': <Option code=3 name=BANANA text=Banana hot>}
>>> Favorite.get_list('code','text')
[(1, None), (3, 'Banana hot')]
>>> Favorite.get_dict('name','text')
{'APPLE': None, 'BANANA': 'Banana hot'}Django model choicesTo be writtenBackgroundOften we need to define some enums or options. But looks python missing this class.
Sometimes we uses class, tuples or dict as the replacement. But they are not convenience.For example, we could define a class as enumeration. We can useMyOption.footo get the enum value1.classMyOption(object):foo=1bar=2But how can we get the enum name foo ? How can we get the list of all enums ? Even list of tuples[ (1, 'foo'), (2, 'bar')](useful in Django model)Although Python 3.7 comes withdata classes. So far it looks like a piece of syntax sugar for me and it can not solve these problems.FeaturesCode - Enumeration/options by different types - e.g. 0, 1, -1 (or 'new', 'running', 'stopped')Name - Name of an enum/option - e.g.  'NEW', 'RUNNING', 'STOPPED'. Support dot access.Text - Meaning or description of the enum/option. support i18n - e.g. _('new'), _('running'), _('stopped') (translated to '新建', '运行中', ‘停止中’)List - Retrieve list of code, name or text[0, 1, -1]Dict - Retrieve dict of{code: name}mapping. even{code: text},{name: text}mapping if required.List of tuples - Retrieve list of[(code, name), ...]tuples. Useful inDjangomodel.Operators support - e.g.Fruit.APPLE == 1,Fruit.BANANA > Fruit.APPLEGrouping - Group a set of enums/options. e.g. IN_PROGRESS_STATE = ['STARTING', 'STOPPING'], but 'STARTED' and 'STOPPED' are not belongs to it.Accessname,textbycodeLookup enum/option byname,codeGuide / TutorType converting forOptionsince v1.1.1AnOptioninstance will be constructed dynamically. Optenum will construct a new sub typeOption(?)class based on your option value(code) to initialize the new instance object.For example,Option(code=1, name='APPLE', text='an apple')will construct a classOption(int).
Theintis yourcode's type. If your option is for a string, e.g.Option('A', 'ADMIN', 'Administration user'),
anOption(str)class will be constructed internally.The internalOption(?)class is derived from eitherOptionand?(e.g.int). That means you can useisinstanceto check your object. For example, says we haveapple = Option(1, 'APPLE', 'an apple'). Thenisinstance(apple, int)isTrue. Andisinstance(apple, Option)isTrue, too. So that you can use
your option as its value(code) is such indictas key and so on.Deprecated since v1.1.0

`str()` or implicit string converting will convert `Option.code` to string type and returns. ~

`repr()` will returns the object as string format of `<Option code=??? name=??? text=???>`.

`int`, `float` will be performed on `Option.code` and returns the value or raises corresponding exception.Boolean forOptionDeprecated since v1.1.0
No special implementation. It behaves as `object` is.Group and tagsSeethis doc.Operators forOptionSince v1.1.1, anOptionbehaves as its value(code) is. So it will support all operators itscodesupports.Deprecated since v1.1.0

`Option.code` is the real value of the enum/option item. Somehow we need to use codes 
like `if active_state == MyOption.RUNNING.code:  # Do something ...` to check the status. For convenience using it, some of the operators
are override. Then we could use `if active_state == MyOption.RUNNING:`, `x = MyOption.RUNNING + 1` and so on to
directly reference to its real value.

See doc [operators.md](https://github.com/samuelchen/optenum/blob/master/docs/operators.md) for override operators.Collections forOptionsOption can be accessed directly as subscribe annotation. For exampleOption['FOO']equals toOption.FOO.We could also access the following collections from within an Options class.Options.codes- list of codesOptions.names- list of namesOptions.all- list of optionsOptions.tuples- list of (name,code,text) tupleOptions.items- dict of {name:Option} mappingOptions.get_list(*fields)- list of *files tuple. *fields are names of Option filed
such ascode, *(name,code) or *(code,name,text)Options.get_dict(key_field, *fields)- dict of{key_filed: (*fields)}({str: tuple}) mapping.key_fieldspecify which Option field is key such asname,code.fieldsspecify the value tuple combined of which Option fields such as (name,text) orname.
if fields is tuple, the value is tuple. if fields is single filed, value is single field.Deprecated since v1.1.0inoperator could check if acodeinOptions. e.g.if Fruit.APPLE in Fruit.
TheOption.namewill not work. e.g.if 'APPLE' in Fruitwill gotFalse.
If you want to check if name inOptions), use collection instead.
e.g.if 'APPLE' in Fruit.names.ConfigurationSome flags can be used to make some simple configuration to your Options.__IGNORE_INVALID_NAME__- Ignore invalidOptionname so that you may add your own attribute/function to class.Underscore_leading attributes and any functions will be ignored so that you can add your own attributes and
functions. The following example is valid definition.fromoptenumimportOptionsclassMyEnum(Options):FOO=1BAR=2_flag=Falsedefswitch(self):passBut if an attributes is not uppercase (all characters), it will be treat as invalidOptionand cause exception.fromoptenumimportOptionsclassMyEnum(Options):FOO=1BAR=2Baz=3# <- Invalid Option name. Exception raised.If you want this available, add__IGNORE_INVALID_NAME__to your class like below. The exception will ignored.
But to be noticed, it still not anOption.fromoptenumimportOptionsclassMyEnum(Options):__IGNORE_INVALID_NAME__=TrueFOO=1BAR=2Baz=3# <- Exception ignored. But still not an Option.__ORDER_BY__Not supported yetFAQWhy not usenamedtuple?namedtupleis also a good way to define enum/options. But it has not enough features
you may required such ascollection,operator,compare,textand so on.Why only uppercase allowed for Option name ?Because you can define other none-option attributes if sets__IGNORE_INVALID_NAME__toTrue.
And enumerations commonly are defined with uppercase identifier.ContributorsList of contributors:Samuel Chen - The project owner and maintainer.