py-enum


Namepy-enum JSON
Version 1.1.1 PyPI version JSON
download
home_pagehttps://github.com/SkylerHu/py-enum.git
Summaryenums for choices fields
upload_time2024-05-03 16:31:42
maintainerNone
docs_urlNone
authorSkylerHu
requires_python>=2.7
licenseMIT Licence
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # py-enum
A python enum module for python2.7 and django choices fields.

通过改造python3中的enum.py而来,增加对python2的支持,并新增类`ChoiceEnum`用于以下场景:
- argparse使用 `add_argument` 的参数 `choices`
- Django中 `models.CharField` 的参数 `choices`
- Django REST framework `ChoiceField` 的参数 `choices`


## 1. 安装

	pip install py-enum

可查看版本变更记录[ChangeLog](https://github.com/SkylerHu/py-enum/blob/master/docs/CHANGELOG-1.x.md)

## 2. 使用(Usage)

### 2.1 用ChoiceEnum定义枚举

```python
# 导入
from py_enum import ChoiceEnum, unique

# 定义
class Color(ChoiceEnum):
    RED = (1, '红色')
    GREEN = (2, '绿色')
    BLUE = (3, '蓝色', {'value': 'blue'})

@unique
class Status(ChoiceEnum):
    PROCESSING = ('processing', '处理中')
    APPROVED = ('approved', '已审批')
    CANCELED = ('canceled', '已取消')
    CLOSED = ('closed', '已关闭')
```
定义如上,按照`Key = (value, label, extra)`的形式进行定义,value定义的值;label是对值的描述;第三个参数是extra,额外信息,可以任意类型。

### 2.2 基础用法
- `直接根据Key访问value值`,而并不是一个tuple,正是和原生Enum的区别
- get_label方法
- get_extra方法
- `直接遍历枚举类`,这是能够作为Choices Enum的关键

```python
print(Color.RED)  # 1
type(Color.RED)  # <enum 'Color'>
len(colors) == 3  # true
Color.RED in Color  # true
1 in Color  # true
0 not in Color  # true

Color.get_label(Color.RED)  # '红色'
Color.get_extra(Color.BLUE)  # {'value': 'blue'}

for value, label in Color:
    print(value, label)  # 直接遍历value和label
# 1, '红色'
# 2, '绿色'
# 3, '蓝色'

Color.to_js_enum()
# 输出dict数据,可以通过接口序列化后给前端使用,结合js-enumerate前端枚举库
"""
[
    {"key": "RED", "value": 1, "label": "红色"},
    {"key": "GREEN", "value": 2, "label": "绿色"},
    {"key": "BLUE", "value": 3, "label": "蓝色", "extra": {"value": "blue"}}
]
"""
```

### 2.3 枚举对象实例化
```python
member = Color(Color.RED)  # 或者 Color(1)
member.value == 1  # true
member.name == 'RED'  # true
member.label == '红色'  # true
member.option == (1, '红色')  # true
member.extra == None  # true,因为没有定义
# 以上几个属性无法修改,直接赋值会抛出AttributeError异常
member.value in Color  # true
```

### 2.4 在Python argparse中使用
```python
import argparse

parser = argparse.ArgumentParser(description='test ChoiceEnum use in argparse.')
parser.add_argument('--color', type=int, choices=Color, required=True)
args = parser.parse_args(['--color', str(Color.RED)])
# args.color == Color.RED
```

### 2.5 在Django中使用
```python
from django.db import models

class ColorModel(models.Model):
    color = models.IntegerField(verbose_name='颜色', choices=Color, default=Color.RED)

instance = ColorModel.objects.create()
assert instance.color == colors.RED
instance.color = colors.BLUE
instance.save()
```

### 2.6 在DRF中使用
```python
from rest_framework import serializers

class ColorSerializer(serializers.Serializer):
    color = serializers.ChoiceField(help_text='选择颜色', choices=Color, default=Color.RED)

s = ColorSerializer()
s = ColorSerializer(data={'status': status.CLOSED})
assert s.is_valid() is True
s = ColorSerializer(data={'status': 1})
assert s.is_valid() is True
s = ColorSerializer(data={'status': 0})
assert s.is_valid() is False  # 值不在枚举定义范围内,校验不通过
```

### 2.7 类Enum和unique
和python3中原生的Enum并无太大区别,具体可以参考[官方原生开发文档](https://docs.python.org/3.6/library/enum.html)

```python
from py_enum import Enum, unique

@unique
class Season(Enum):
    SPRING = 1
    SUMMER = 2
    AUTUMN = 3
    WINTER = 4
```

## 3. 对比
- `Enum`可以在`Python2`中使用,但需要注意的是:
  - members无序,属性定义时申明的顺序和直接遍历枚举对象时并不一定一致;需通过`_order_`来定义member的顺序
  - python2没有定义__bool__,所以不能直接用class类或者member来做逻辑判断
  - 执行 Season.SPRING > Season.SUMMER 不会报错,但结果也不符合预期
    - py3执行会raise TypeError, 不允许比较
    - 但是ChoiceEnum是直接取值,可以用来做比较运算
  - 枚举类定义时,无法识别多个相同的Key
  - 在多继承方面会受限
- `Enum`和Python3原生enum.py对比,保留了`Enum`类和`unique`方法
- `ChoiceEnum`和Django的 models.Choices 的优势在于低版本Django也能使用,且普通Python项目脚本也能使用
- 新增了额外的特性
  - 额外多出了`ChoiceEnum.extra`的用法,对不同枚举成员做映射配置相关场景可以使用
  - 增加方法`ChoiceEnum.to_js_enum`返回数组数据,可以用于前端枚举库 [js-enumerate](https://github.com/SkylerHu/js-enum) 初始化使用
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/SkylerHu/py-enum.git",
    "name": "py-enum",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=2.7",
    "maintainer_email": null,
    "keywords": null,
    "author": "SkylerHu",
    "author_email": "skylerhu@qq.com",
    "download_url": "https://files.pythonhosted.org/packages/45/cc/79712e9b5e70ed4dcf0773f3a40ff7d40df1e0d3cf3f81042b6ade06fbc7/py-enum-1.1.1.tar.gz",
    "platform": "any",
    "description": "# py-enum\nA python enum module for python2.7 and django choices fields.\n\n\u901a\u8fc7\u6539\u9020python3\u4e2d\u7684enum.py\u800c\u6765\uff0c\u589e\u52a0\u5bf9python2\u7684\u652f\u6301\uff0c\u5e76\u65b0\u589e\u7c7b`ChoiceEnum`\u7528\u4e8e\u4ee5\u4e0b\u573a\u666f\uff1a\n- argparse\u4f7f\u7528 `add_argument` \u7684\u53c2\u6570 `choices`\n- Django\u4e2d `models.CharField` \u7684\u53c2\u6570 `choices`\n- Django REST framework `ChoiceField` \u7684\u53c2\u6570 `choices`\n\n\n## 1. \u5b89\u88c5\n\n\tpip install py-enum\n\n\u53ef\u67e5\u770b\u7248\u672c\u53d8\u66f4\u8bb0\u5f55[ChangeLog](https://github.com/SkylerHu/py-enum/blob/master/docs/CHANGELOG-1.x.md)\n\n## 2. \u4f7f\u7528(Usage)\n\n### 2.1 \u7528ChoiceEnum\u5b9a\u4e49\u679a\u4e3e\n\n```python\n# \u5bfc\u5165\nfrom py_enum import ChoiceEnum, unique\n\n# \u5b9a\u4e49\nclass Color(ChoiceEnum):\n    RED = (1, '\u7ea2\u8272')\n    GREEN = (2, '\u7eff\u8272')\n    BLUE = (3, '\u84dd\u8272', {'value': 'blue'})\n\n@unique\nclass Status(ChoiceEnum):\n    PROCESSING = ('processing', '\u5904\u7406\u4e2d')\n    APPROVED = ('approved', '\u5df2\u5ba1\u6279')\n    CANCELED = ('canceled', '\u5df2\u53d6\u6d88')\n    CLOSED = ('closed', '\u5df2\u5173\u95ed')\n```\n\u5b9a\u4e49\u5982\u4e0a\uff0c\u6309\u7167`Key = (value, label, extra)`\u7684\u5f62\u5f0f\u8fdb\u884c\u5b9a\u4e49\uff0cvalue\u5b9a\u4e49\u7684\u503c\uff1blabel\u662f\u5bf9\u503c\u7684\u63cf\u8ff0\uff1b\u7b2c\u4e09\u4e2a\u53c2\u6570\u662fextra\uff0c\u989d\u5916\u4fe1\u606f\uff0c\u53ef\u4ee5\u4efb\u610f\u7c7b\u578b\u3002\n\n### 2.2 \u57fa\u7840\u7528\u6cd5\n- `\u76f4\u63a5\u6839\u636eKey\u8bbf\u95eevalue\u503c`\uff0c\u800c\u5e76\u4e0d\u662f\u4e00\u4e2atuple\uff0c\u6b63\u662f\u548c\u539f\u751fEnum\u7684\u533a\u522b\n- get_label\u65b9\u6cd5\n- get_extra\u65b9\u6cd5\n- `\u76f4\u63a5\u904d\u5386\u679a\u4e3e\u7c7b`\uff0c\u8fd9\u662f\u80fd\u591f\u4f5c\u4e3aChoices Enum\u7684\u5173\u952e\n\n```python\nprint(Color.RED)  # 1\ntype(Color.RED)  # <enum 'Color'>\nlen(colors) == 3  # true\nColor.RED in Color  # true\n1 in Color  # true\n0 not in Color  # true\n\nColor.get_label(Color.RED)  # '\u7ea2\u8272'\nColor.get_extra(Color.BLUE)  # {'value': 'blue'}\n\nfor value, label in Color:\n    print(value, label)  # \u76f4\u63a5\u904d\u5386value\u548clabel\n# 1, '\u7ea2\u8272'\n# 2, '\u7eff\u8272'\n# 3, '\u84dd\u8272'\n\nColor.to_js_enum()\n# \u8f93\u51fadict\u6570\u636e\uff0c\u53ef\u4ee5\u901a\u8fc7\u63a5\u53e3\u5e8f\u5217\u5316\u540e\u7ed9\u524d\u7aef\u4f7f\u7528\uff0c\u7ed3\u5408js-enumerate\u524d\u7aef\u679a\u4e3e\u5e93\n\"\"\"\n[\n    {\"key\": \"RED\", \"value\": 1, \"label\": \"\u7ea2\u8272\"},\n    {\"key\": \"GREEN\", \"value\": 2, \"label\": \"\u7eff\u8272\"},\n    {\"key\": \"BLUE\", \"value\": 3, \"label\": \"\u84dd\u8272\", \"extra\": {\"value\": \"blue\"}}\n]\n\"\"\"\n```\n\n### 2.3 \u679a\u4e3e\u5bf9\u8c61\u5b9e\u4f8b\u5316\n```python\nmember = Color(Color.RED)  # \u6216\u8005 Color(1)\nmember.value == 1  # true\nmember.name == 'RED'  # true\nmember.label == '\u7ea2\u8272'  # true\nmember.option == (1, '\u7ea2\u8272')  # true\nmember.extra == None  # true\uff0c\u56e0\u4e3a\u6ca1\u6709\u5b9a\u4e49\n# \u4ee5\u4e0a\u51e0\u4e2a\u5c5e\u6027\u65e0\u6cd5\u4fee\u6539\uff0c\u76f4\u63a5\u8d4b\u503c\u4f1a\u629b\u51faAttributeError\u5f02\u5e38\nmember.value in Color  # true\n```\n\n### 2.4 \u5728Python argparse\u4e2d\u4f7f\u7528\n```python\nimport argparse\n\nparser = argparse.ArgumentParser(description='test ChoiceEnum use in argparse.')\nparser.add_argument('--color', type=int, choices=Color, required=True)\nargs = parser.parse_args(['--color', str(Color.RED)])\n# args.color == Color.RED\n```\n\n### 2.5 \u5728Django\u4e2d\u4f7f\u7528\n```python\nfrom django.db import models\n\nclass ColorModel(models.Model):\n    color = models.IntegerField(verbose_name='\u989c\u8272', choices=Color, default=Color.RED)\n\ninstance = ColorModel.objects.create()\nassert instance.color == colors.RED\ninstance.color = colors.BLUE\ninstance.save()\n```\n\n### 2.6 \u5728DRF\u4e2d\u4f7f\u7528\n```python\nfrom rest_framework import serializers\n\nclass ColorSerializer(serializers.Serializer):\n    color = serializers.ChoiceField(help_text='\u9009\u62e9\u989c\u8272', choices=Color, default=Color.RED)\n\ns = ColorSerializer()\ns = ColorSerializer(data={'status': status.CLOSED})\nassert s.is_valid() is True\ns = ColorSerializer(data={'status': 1})\nassert s.is_valid() is True\ns = ColorSerializer(data={'status': 0})\nassert s.is_valid() is False  # \u503c\u4e0d\u5728\u679a\u4e3e\u5b9a\u4e49\u8303\u56f4\u5185\uff0c\u6821\u9a8c\u4e0d\u901a\u8fc7\n```\n\n### 2.7 \u7c7bEnum\u548cunique\n\u548cpython3\u4e2d\u539f\u751f\u7684Enum\u5e76\u65e0\u592a\u5927\u533a\u522b\uff0c\u5177\u4f53\u53ef\u4ee5\u53c2\u8003[\u5b98\u65b9\u539f\u751f\u5f00\u53d1\u6587\u6863](https://docs.python.org/3.6/library/enum.html)\n\n```python\nfrom py_enum import Enum, unique\n\n@unique\nclass Season(Enum):\n    SPRING = 1\n    SUMMER = 2\n    AUTUMN = 3\n    WINTER = 4\n```\n\n## 3. \u5bf9\u6bd4\n- `Enum`\u53ef\u4ee5\u5728`Python2`\u4e2d\u4f7f\u7528\uff0c\u4f46\u9700\u8981\u6ce8\u610f\u7684\u662f\uff1a\n  - members\u65e0\u5e8f\uff0c\u5c5e\u6027\u5b9a\u4e49\u65f6\u7533\u660e\u7684\u987a\u5e8f\u548c\u76f4\u63a5\u904d\u5386\u679a\u4e3e\u5bf9\u8c61\u65f6\u5e76\u4e0d\u4e00\u5b9a\u4e00\u81f4\uff1b\u9700\u901a\u8fc7`_order_`\u6765\u5b9a\u4e49member\u7684\u987a\u5e8f\n  - python2\u6ca1\u6709\u5b9a\u4e49__bool__\uff0c\u6240\u4ee5\u4e0d\u80fd\u76f4\u63a5\u7528class\u7c7b\u6216\u8005member\u6765\u505a\u903b\u8f91\u5224\u65ad\n  - \u6267\u884c Season.SPRING > Season.SUMMER \u4e0d\u4f1a\u62a5\u9519\uff0c\u4f46\u7ed3\u679c\u4e5f\u4e0d\u7b26\u5408\u9884\u671f\n    - py3\u6267\u884c\u4f1araise TypeError, \u4e0d\u5141\u8bb8\u6bd4\u8f83\n    - \u4f46\u662fChoiceEnum\u662f\u76f4\u63a5\u53d6\u503c\uff0c\u53ef\u4ee5\u7528\u6765\u505a\u6bd4\u8f83\u8fd0\u7b97\n  - \u679a\u4e3e\u7c7b\u5b9a\u4e49\u65f6\uff0c\u65e0\u6cd5\u8bc6\u522b\u591a\u4e2a\u76f8\u540c\u7684Key\n  - \u5728\u591a\u7ee7\u627f\u65b9\u9762\u4f1a\u53d7\u9650\n- `Enum`\u548cPython3\u539f\u751fenum.py\u5bf9\u6bd4\uff0c\u4fdd\u7559\u4e86`Enum`\u7c7b\u548c`unique`\u65b9\u6cd5\n- `ChoiceEnum`\u548cDjango\u7684 models.Choices \u7684\u4f18\u52bf\u5728\u4e8e\u4f4e\u7248\u672cDjango\u4e5f\u80fd\u4f7f\u7528\uff0c\u4e14\u666e\u901aPython\u9879\u76ee\u811a\u672c\u4e5f\u80fd\u4f7f\u7528\n- \u65b0\u589e\u4e86\u989d\u5916\u7684\u7279\u6027\n  - \u989d\u5916\u591a\u51fa\u4e86`ChoiceEnum.extra`\u7684\u7528\u6cd5\uff0c\u5bf9\u4e0d\u540c\u679a\u4e3e\u6210\u5458\u505a\u6620\u5c04\u914d\u7f6e\u76f8\u5173\u573a\u666f\u53ef\u4ee5\u4f7f\u7528\n  - \u589e\u52a0\u65b9\u6cd5`ChoiceEnum.to_js_enum`\u8fd4\u56de\u6570\u7ec4\u6570\u636e\uff0c\u53ef\u4ee5\u7528\u4e8e\u524d\u7aef\u679a\u4e3e\u5e93 [js-enumerate](https://github.com/SkylerHu/js-enum) \u521d\u59cb\u5316\u4f7f\u7528",
    "bugtrack_url": null,
    "license": "MIT Licence",
    "summary": "enums for choices fields",
    "version": "1.1.1",
    "project_urls": {
        "Homepage": "https://github.com/SkylerHu/py-enum.git"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "45cc79712e9b5e70ed4dcf0773f3a40ff7d40df1e0d3cf3f81042b6ade06fbc7",
                "md5": "fe45e63c38c660a30eadb6304ea72d80",
                "sha256": "56dc4430eee495a96b671ec975898de3c98a72636b683583e8d88e8b0bf270f6"
            },
            "downloads": -1,
            "filename": "py-enum-1.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "fe45e63c38c660a30eadb6304ea72d80",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=2.7",
            "size": 30670,
            "upload_time": "2024-05-03T16:31:42",
            "upload_time_iso_8601": "2024-05-03T16:31:42.988127Z",
            "url": "https://files.pythonhosted.org/packages/45/cc/79712e9b5e70ed4dcf0773f3a40ff7d40df1e0d3cf3f81042b6ade06fbc7/py-enum-1.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-03 16:31:42",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "SkylerHu",
    "github_project": "py-enum",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": false,
    "tox": true,
    "lcname": "py-enum"
}
        
Elapsed time: 1.60673s