# Optenum
[![Travis](https://img.shields.io/github/languages/top/samuelchen/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)
[![Travis](https://img.shields.io/travis/samuelchen/optenum.svg?branch=master?style=flat-square)](https://travis-ci.org/samuelchen/optenum)
[![Travis](https://img.shields.io/pypi/pyversions/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)
[![Travis](https://img.shields.io/pypi/v/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)
[![Travis](https://img.shields.io/pypi/status/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)
[![Travis](https://img.shields.io/pypi/format/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)
A missing Python Option/Enum library which supports enum code, name, text, even (code, name) tuple list and so on.
Name "**optenum**" comes from '**opt**ion' + '**enum**eration'.
Compatible with `Python 2.7+` and `Python 3.0+`.
# Install
Python 3.x, 2.7
```bash
pip install optenum
```
For those probably missing `six` module:
```bash
pip install six optenum
```
# Quick start
1. Simple as Enum type
Says we define a simple enum:
```python
from optenum import Options
class Fruit(Options):
APPLE = 1
ORANGE = 2
BANANA = 3
```
Try 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'
```
2. Complex declaration
You may declare your Options (Enums) in many annotations.
```python
from optenum import Option, Options
class EnumCellPhone(Options):
APPLE = 1
SAMSUNG = Option(2, name='SAMSUNG')
HUAWEI = 3, 'Huawei cellphone' # tuple annotation. name = code, text
class DoorState(Options):
OPEN = 'O', 'Door is opened' # tuple annotation. name = code, text
CLOSED = ('C', 'Door is closed') # tuple annotation, too.
IN_OPENING = 'IO'
IN_CLOSING = 'IC'
_FLAG = False # underscore leading name is not an option
x = lambda y: y # function/callable is not an option
```
3. Operators
`Option` support some operators. See more in [operators.md](https://github.com/samuelchen/optenum/blob/master/docs/operators.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
True
```
4. Collections
`Options` provides 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'}
```
5. Django model choices
To be written
# Background
Often 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 use `MyOption.foo` to get the enum value `1`.
```python
class MyOption(object):
foo = 1
bar = 2
```
But 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 with [data classes](https://docs.python.org/3/whatsnew/3.7.html#whatsnew37-pep557). So far it looks like a piece of syntax sugar for me and it can not solve these problems.
# Features
* Code - 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 in **Django** model.
* Operators support - e.g. `Fruit.APPLE == 1`, `Fruit.BANANA > Fruit.APPLE`
* Grouping - Group a set of enums/options. e.g. IN_PROGRESS_STATE = ['STARTING', 'STOPPING'], but 'STARTED' and 'STOPPED' are not belongs to it.
* Access **name**, **text** by **code**
* Lookup enum/option by **name**, **code**
# Guide / Tutor
# Type converting for `Option`
since v1.1.1
An `Option` instance will be constructed dynamically. Optenum will construct a new sub type
`Option(?)` 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 class `Option(int)`.
The `int` is your `code`'s type. If your option is for a string, e.g. `Option('A', 'ADMIN', 'Administration user')`,
an `Option(str)` class will be constructed internally.
The internal `Option(?)` class is derived from either `Option` and `?` (e.g. `int`). That means you can use
`isinstance` to check your object. For example, says we have `apple = Option(1, 'APPLE', 'an apple')`. Then
`isinstance(apple, int)` is `True`. And `isinstance(apple, Option)` is `True`, too. So that you can use
your option as its value(`code`) is such in `dict` as 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 for `Option`
Deprecated since v1.1.0
No special implementation. It behaves as `object` is.
# Group and tags
See [this doc](https://github.com/samuelchen/optenum/blob/master/docs/tag-and-group.md).
# Operators for `Option`
Since v1.1.1, an `Option` behaves as its value(`code`) is. So it will support all operators its `code` supports.
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 for `Options`
Option can be accessed directly as subscribe annotation. For example `Option['FOO']`
equals to `Option.FOO`.
We could also access the following collections from within an Options class.
* `Options.codes` - list of codes
* `Options.names` - list of names
* `Options.all` - list of options
* `Options.tuples` - list of (`name`, `code`, `text`) tuple
* `Options.items` - dict of {`name`: `Option`} mapping
* `Options.get_list(*fields)` - list of *files tuple. *fields are names of Option filed
such as `code`, *(`name`, `code`) or *(`code`, `name`, `text`)
* `Options.get_dict(key_field, *fields)` - dict of `{key_filed: (*fields)}` (`{str: tuple}`) mapping.
`key_field` specify which Option field is key such as `name`, `code`.
`fields` specify the value tuple combined of which Option fields such as (`name`, `text`) or `name`.
if fields is tuple, the value is tuple. if fields is single filed, value is single field.
Deprecated since v1.1.0
`in` operator could check if a `code` in `Options`. e.g. `if Fruit.APPLE in Fruit`.
The `Option.name` will not work. e.g. `if 'APPLE' in Fruit` will got `False`.
If you want to check if name in `Options`), use collection instead.
e.g. `if 'APPLE' in Fruit.names`.
# Configuration
Some flags can be used to make some simple configuration to your Options.
* `__IGNORE_INVALID_NAME__` - Ignore invalid `Option` name 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.
```python
from optenum import Options
class MyEnum(Options):
FOO = 1
BAR = 2
_flag = False
def switch(self):
pass
```
But if an attributes is not uppercase (all characters), it will be treat as invalid `Option` and cause exception.
```python
from optenum import Options
class MyEnum(Options):
FOO = 1
BAR = 2
Baz = 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 an `Option`.
```python
from optenum import Options
class MyEnum(Options):
__IGNORE_INVALID_NAME__ = True
FOO = 1
BAR = 2
Baz = 3 # <- Exception ignored. But still not an Option.
```
* `__ORDER_BY__`
Not supported yet
# FAQ
* Why not use *namedtuple* ?
*namedtuple* is also a good way to define enum/options. But it has not enough features
you may required such as *collection*, *operator*, *compare*, *text* and so on.
* Why only uppercase allowed for Option name ?
Because you can define other none-option attributes if sets `__IGNORE_INVALID_NAME__` to `True`.
And enumerations commonly are defined with uppercase identifier.
# Contributors
List of contributors:
* Samuel Chen - The project owner and maintainer.
Raw data
{
"_id": null,
"home_page": "http://en.samuelchen.net/project/optenum/",
"name": "optenum",
"maintainer": "",
"docs_url": null,
"requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4",
"maintainer_email": "",
"keywords": "enum library development",
"author": "Samuel Chen",
"author_email": "samuel.net@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/bb/9e/cb073435923982005663cff4cd996d6d6035f55f4a7a6d31628f6d66c8ce/optenum-1.1.9.tar.gz",
"platform": null,
"description": "# Optenum\r\n\r\n[![Travis](https://img.shields.io/github/languages/top/samuelchen/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)\r\n[![Travis](https://img.shields.io/travis/samuelchen/optenum.svg?branch=master?style=flat-square)](https://travis-ci.org/samuelchen/optenum)\r\n[![Travis](https://img.shields.io/pypi/pyversions/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)\r\n[![Travis](https://img.shields.io/pypi/v/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)\r\n[![Travis](https://img.shields.io/pypi/status/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)\r\n[![Travis](https://img.shields.io/pypi/format/optenum.svg?style=flat-square)](https://pypi.org/project/optenum/)\r\n\r\n\r\n\t\r\nA missing Python Option/Enum library which supports enum code, name, text, even (code, name) tuple list and so on.\r\n\r\nName \"**optenum**\" comes from '**opt**ion' + '**enum**eration'.\r\n\r\nCompatible with `Python 2.7+` and `Python 3.0+`.\r\n\r\n# Install\r\n\r\nPython 3.x, 2.7\r\n\r\n```bash\r\npip install optenum\r\n```\r\n\r\nFor those probably missing `six` module:\r\n\r\n```bash\r\npip install six optenum\r\n```\r\n\r\n# Quick start\r\n\r\n1. Simple as Enum type\r\n\r\n Says we define a simple enum:\r\n \r\n ```python\r\n from optenum import Options\r\n \r\n class Fruit(Options):\r\n APPLE = 1\r\n ORANGE = 2\r\n BANANA = 3 \r\n ```\r\n \r\n Try the following in Python command line:\r\n \r\n ```\r\n >>> from optenum import Option, Options\r\n >>> class Fruit(Options):\r\n ... APPLE = 1\r\n ... ORANGE = 2\r\n ... BANANA = 3\r\n >>> \r\n >>> Fruit.APPLE\r\n <Option code=1 name=APPLE text=None>\r\n >>> print(Fruit.APPLE)\r\n 1\r\n >>> Fruit.APPLE.code\r\n 1\r\n >>> Fruit.APPLE.name\r\n 'APPLE'\r\n >>> Fruit.APPLE.text\r\n >>> print(Fruit.APPLE.text)\r\n None\r\n >>> Fruit.APPLE.get_text()\r\n 'apple'\r\n \r\n ```\r\n\r\n2. Complex declaration\r\n\r\n You may declare your Options (Enums) in many annotations.\r\n\r\n ```python\r\n from optenum import Option, Options\r\n \r\n class EnumCellPhone(Options):\r\n APPLE = 1\r\n SAMSUNG = Option(2, name='SAMSUNG')\r\n HUAWEI = 3, 'Huawei cellphone' # tuple annotation. name = code, text\r\n \r\n \r\n class DoorState(Options):\r\n OPEN = 'O', 'Door is opened' # tuple annotation. name = code, text\r\n CLOSED = ('C', 'Door is closed') # tuple annotation, too.\r\n IN_OPENING = 'IO'\r\n IN_CLOSING = 'IC'\r\n \r\n _FLAG = False # underscore leading name is not an option\r\n x = lambda y: y # function/callable is not an option\r\n ```\r\n\r\n3. Operators\r\n\r\n `Option` support some operators. See more in [operators.md](https://github.com/samuelchen/optenum/blob/master/docs/operators.md).\r\n \r\n ```\r\n >>> class Favorite(Options):\r\n ... APPLE = 1\r\n ... BANANA = 3, 'Banana hot'\r\n ... \r\n >>> \r\n >>> Fruit.APPLE == Favorite.APPLE\r\n True\r\n >>> Fruit.BANANA == Favorite.BANANA\r\n False\r\n >>> Fruit.APPLE + 1 == Fruit.ORANGE\r\n True>>> Fruit.BANANA >> 2\r\n 0\r\n >>> Fruit.BANANA << 2\r\n 12>>> Fruit.BANANA > Favorite.APPLE\r\n True\r\n ```\r\n\r\n4. Collections\r\n\r\n `Options` provides some collections for accessing option and it's fields.\r\n See section \"Collections for Options\" below for more information.\r\n \r\n ```\r\n >>> Fruit.codes\r\n [1, 2, 3]\r\n >>> Fruit.names\r\n ['ORANGE', 'APPLE', 'BANANA']\r\n >>> Fruit.all\r\n [<Option code=2 name=ORANGE text=None>, <Option code=1 name=APPLE text=None>, <Option code=3 name=BANANA text=None>]\r\n >>> Fruit.tuples\r\n [('ORANGE', 2, None), ('APPLE', 1, None), ('BANANA', 3, None)]\r\n >>> Favorite.items\r\n {'APPLE': <Option code=1 name=APPLE text=None>, 'BANANA': <Option code=3 name=BANANA text=Banana hot>}\r\n >>> Favorite.get_list('code','text')\r\n [(1, None), (3, 'Banana hot')]\r\n >>> Favorite.get_dict('name','text')\r\n {'APPLE': None, 'BANANA': 'Banana hot'}\r\n \r\n ```\r\n\r\n5. Django model choices\r\n\r\n To be written\r\n\r\n# Background\r\n\r\nOften we need to define some enums or options. But looks python missing this class.\r\nSometimes we uses class, tuples or dict as the replacement. But they are not convenience.\r\n\r\nFor example, we could define a class as enumeration. We can use `MyOption.foo` to get the enum value `1`.\r\n\r\n```python\r\nclass MyOption(object):\r\n foo = 1\r\n bar = 2\r\n```\r\nBut 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)\r\n\r\nAlthough Python 3.7 comes with [data classes](https://docs.python.org/3/whatsnew/3.7.html#whatsnew37-pep557). So far it looks like a piece of syntax sugar for me and it can not solve these problems.\r\n\r\n# Features\r\n\r\n * Code - Enumeration/options by different types - e.g. 0, 1, -1 (or 'new', 'running', 'stopped')\r\n * Name - Name of an enum/option - e.g. 'NEW', 'RUNNING', 'STOPPED'. Support dot access. \r\n * Text - Meaning or description of the enum/option. support i18n - e.g. _('new'), _('running'), _('stopped') (translated to '\u65b0\u5efa', '\u8fd0\u884c\u4e2d', \u2018\u505c\u6b62\u4e2d\u2019)\r\n * List - Retrieve list of code, name or text `[0, 1, -1]`\r\n * Dict - Retrieve dict of `{code: name}` mapping. even `{code: text}`, `{name: text}` mapping if required.\r\n * List of tuples - Retrieve list of `[(code, name), ...]` tuples. Useful in **Django** model.\r\n * Operators support - e.g. `Fruit.APPLE == 1`, `Fruit.BANANA > Fruit.APPLE`\r\n * Grouping - Group a set of enums/options. e.g. IN_PROGRESS_STATE = ['STARTING', 'STOPPING'], but 'STARTED' and 'STOPPED' are not belongs to it.\r\n * Access **name**, **text** by **code**\r\n * Lookup enum/option by **name**, **code**\r\n \r\n# Guide / Tutor\r\n\r\n# Type converting for `Option`\r\n\r\n since v1.1.1\r\n\r\nAn `Option` instance will be constructed dynamically. Optenum will construct a new sub type \r\n`Option(?)` class based on your option value(`code`) to initialize the new instance object. \r\n\r\nFor example, `Option(code=1, name='APPLE', text='an apple')` will construct a class `Option(int)`.\r\nThe `int` is your `code`'s type. If your option is for a string, e.g. `Option('A', 'ADMIN', 'Administration user')`,\r\nan `Option(str)` class will be constructed internally.\r\n\r\nThe internal `Option(?)` class is derived from either `Option` and `?` (e.g. `int`). That means you can use \r\n`isinstance` to check your object. For example, says we have `apple = Option(1, 'APPLE', 'an apple')`. Then\r\n `isinstance(apple, int)` is `True`. And `isinstance(apple, Option)` is `True`, too. So that you can use\r\n your option as its value(`code`) is such in `dict` as key and so on.\r\n \r\n\r\n Deprecated since v1.1.0\r\n \r\n `str()` or implicit string converting will convert `Option.code` to string type and returns. ~\r\n \r\n `repr()` will returns the object as string format of `<Option code=??? name=??? text=???>`.\r\n \r\n `int`, `float` will be performed on `Option.code` and returns the value or raises corresponding exception.\r\n\r\n# Boolean for `Option`\r\n\r\n Deprecated since v1.1.0\r\n No special implementation. It behaves as `object` is.\r\n\r\n# Group and tags \r\n\r\nSee [this doc](https://github.com/samuelchen/optenum/blob/master/docs/tag-and-group.md).\r\n\r\n# Operators for `Option`\r\n\r\nSince v1.1.1, an `Option` behaves as its value(`code`) is. So it will support all operators its `code` supports.\r\n\r\n Deprecated since v1.1.0\r\n \r\n `Option.code` is the real value of the enum/option item. Somehow we need to use codes \r\n like `if active_state == MyOption.RUNNING.code: # Do something ...` to check the status. For convenience using it, some of the operators\r\n are override. Then we could use `if active_state == MyOption.RUNNING:`, `x = MyOption.RUNNING + 1` and so on to\r\n directly reference to its real value.\r\n \r\n See doc [operators.md](https://github.com/samuelchen/optenum/blob/master/docs/operators.md) for override operators.\r\n\r\n# Collections for `Options`\r\n\r\nOption can be accessed directly as subscribe annotation. For example `Option['FOO']`\r\nequals to `Option.FOO`.\r\n\r\nWe could also access the following collections from within an Options class. \r\n\r\n * `Options.codes` - list of codes\r\n \r\n * `Options.names` - list of names\r\n \r\n * `Options.all` - list of options\r\n\r\n * `Options.tuples` - list of (`name`, `code`, `text`) tuple\r\n\r\n * `Options.items` - dict of {`name`: `Option`} mapping\r\n\r\n * `Options.get_list(*fields)` - list of *files tuple. *fields are names of Option filed \r\n such as `code`, *(`name`, `code`) or *(`code`, `name`, `text`)\r\n \r\n * `Options.get_dict(key_field, *fields)` - dict of `{key_filed: (*fields)}` (`{str: tuple}`) mapping.\r\n `key_field` specify which Option field is key such as `name`, `code`. \r\n `fields` specify the value tuple combined of which Option fields such as (`name`, `text`) or `name`.\r\n if fields is tuple, the value is tuple. if fields is single filed, value is single field.\r\n\r\n Deprecated since v1.1.0\r\n \r\n `in` operator could check if a `code` in `Options`. e.g. `if Fruit.APPLE in Fruit`.\r\n The `Option.name` will not work. e.g. `if 'APPLE' in Fruit` will got `False`. \r\n If you want to check if name in `Options`), use collection instead. \r\n e.g. `if 'APPLE' in Fruit.names`.\r\n\r\n\r\n# Configuration\r\n\r\nSome flags can be used to make some simple configuration to your Options.\r\n\r\n * `__IGNORE_INVALID_NAME__` - Ignore invalid `Option` name so that you may add your own attribute/function to class.\r\n \r\n Underscore `_` leading attributes and any functions will be ignored so that you can add your own attributes and \r\n functions. The following example is valid definition.\r\n \r\n ```python\r\n from optenum import Options\r\n\r\n class MyEnum(Options):\r\n FOO = 1\r\n BAR = 2\r\n \r\n _flag = False\r\n \r\n def switch(self):\r\n pass\r\n ```\r\n \r\n But if an attributes is not uppercase (all characters), it will be treat as invalid `Option` and cause exception.\r\n \r\n ```python\r\n from optenum import Options\r\n\r\n class MyEnum(Options):\r\n FOO = 1\r\n BAR = 2\r\n \r\n Baz = 3 # <- Invalid Option name. Exception raised.\r\n ```\r\n \r\n If you want this available, add `__IGNORE_INVALID_NAME__` to your class like below. The exception will ignored.\r\n But to be noticed, it still not an `Option`.\r\n \r\n ```python\r\n from optenum import Options\r\n\r\n class MyEnum(Options):\r\n __IGNORE_INVALID_NAME__ = True\r\n \r\n FOO = 1\r\n BAR = 2\r\n \r\n Baz = 3 # <- Exception ignored. But still not an Option.\r\n ```\r\n \r\n * `__ORDER_BY__`\r\n \r\n Not supported yet\r\n\r\n# FAQ\r\n\r\n* Why not use *namedtuple* ?\r\n\r\n*namedtuple* is also a good way to define enum/options. But it has not enough features\r\nyou may required such as *collection*, *operator*, *compare*, *text* and so on.\r\n\r\n* Why only uppercase allowed for Option name ?\r\n\r\nBecause you can define other none-option attributes if sets `__IGNORE_INVALID_NAME__` to `True`.\r\nAnd enumerations commonly are defined with uppercase identifier.\r\n\r\n# Contributors\r\n\r\nList of contributors:\r\n\r\n* Samuel Chen - The project owner and maintainer.\r\n",
"bugtrack_url": null,
"license": "",
"summary": "A missing Python Option/Enum library",
"version": "1.1.9",
"split_keywords": [
"enum",
"library",
"development"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "7bc1cd17a89f8eb0ed95b2568b41fa65efc97884ec86987d6101a8fd48bb214f",
"md5": "969701e2088b331eaeac959005b16617",
"sha256": "7d43bd0b64fb5dc02fb204cd138363e357f9a7aa9371c8afefa423b7528eb806"
},
"downloads": -1,
"filename": "optenum-1.1.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "969701e2088b331eaeac959005b16617",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4",
"size": 14596,
"upload_time": "2023-04-18T02:43:15",
"upload_time_iso_8601": "2023-04-18T02:43:15.559252Z",
"url": "https://files.pythonhosted.org/packages/7b/c1/cd17a89f8eb0ed95b2568b41fa65efc97884ec86987d6101a8fd48bb214f/optenum-1.1.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "bb9ecb073435923982005663cff4cd996d6d6035f55f4a7a6d31628f6d66c8ce",
"md5": "3a869d97a5455e0caa2a75dd95682143",
"sha256": "e9127e4b79fd7a62e1808d32f8ae308fb9e576b0c08045b7f700e8a788c99786"
},
"downloads": -1,
"filename": "optenum-1.1.9.tar.gz",
"has_sig": false,
"md5_digest": "3a869d97a5455e0caa2a75dd95682143",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4",
"size": 24152,
"upload_time": "2023-04-18T02:43:17",
"upload_time_iso_8601": "2023-04-18T02:43:17.665131Z",
"url": "https://files.pythonhosted.org/packages/bb/9e/cb073435923982005663cff4cd996d6d6035f55f4a7a6d31628f6d66c8ce/optenum-1.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-18 02:43:17",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "optenum"
}