支持zope.schema词汇和数据库友好的便利性的枚举。
项目描述
枚举类型主要用于Launchpad代码中的两个不同位置:选择器类型;和数据库类型。
简单的枚举类型没有值,而数据库枚举类型则是从整数值到代码中有意义的映射。
>>> from lazr.enum import ( ... EnumeratedType, DBEnumeratedType, Item, DBItem, use_template)
枚举类型的enum值是Item实例。
>>> class Fruit(EnumeratedType): ... "A choice of fruit." ... APPLE = Item('Apple') ... PEAR = Item('Pear') ... ORANGE = Item('Orange')
IVocabulary支持
枚举类型支持IVocabularyTokenized。
>>> from zope.interface.verify import verifyObject >>> from zope.schema.interfaces import ( ... ITitledTokenizedTerm, IVocabularyTokenized) >>> verifyObject(IVocabularyTokenized, Fruit) True
项目本身不支持任何接口。由词汇方法返回的项目返回包装项目,这些项目支持ITitledTokenizedTerm接口。
用于识别词汇中术语的令牌是Item变量的名称。
>>> item = Fruit.getTermByToken('APPLE') >>> type(item) <class 'lazr.enum...TokenizedItem'> >>> verifyObject(ITitledTokenizedTerm, item) True
TokenizedItems有三个属性(为了支持ITitledTokenizedTerm)
>>> item.value <Item Fruit.APPLE, Apple> >>> item.token 'APPLE' >>> item.title 'Apple'>>> Fruit.getTermByToken('apple').value <Item Fruit.APPLE, Apple>
枚举类型的长度返回它拥有的项目数量。
>>> print(len(Fruit)) 3
枚举类型注册表
创建的所有枚举类型都添加到枚举类型注册表中。
>>> from lazr.enum import enumerated_type_registry
枚举类型注册表将枚举类型的名称映射到该类型本身。
>>> 'Fruit' in enumerated_type_registry True >>> enumerated_type_registry['Fruit'] <EnumeratedType 'Fruit'>
您不能重新定义现有的枚举类型,也不能创建与现有类型具有相同名称的另一个枚举类型。
>>> class BranchType(EnumeratedType): ... BAR = Item('Bar') ... >>> BranchType.name = 'AltBranchType' >>> class BranchType(EnumeratedType): ... FOO = Item('Foo') Traceback (most recent call last): ... TypeError: An enumerated type already exists with the name BranchType (...AltBranchType).
枚举类型基础
枚举类型有一个名称和描述。名称与类名相同,描述是类的docstring。
>>> print(Fruit.name) Fruit >>> print(Fruit.description) A choice of fruit.
如果您没有为枚举类型的项指定显式的sort_order,则会为您创建一个。这是一个令牌的元组。
>>> print(Fruit.sort_order) ('APPLE', 'PEAR', 'ORANGE')
枚举类型的项可以迭代。然而,迭代返回的类型是TokenizedItem,而不是项本身。
>>> for item in Fruit: ... print(item.token, item.title) APPLE Apple PEAR Pear ORANGE Orange
项还可以可选地与它们关联一个url。
>>> class Guitar(EnumeratedType): ... FENDER = Item('Fender', url='http://www.fender.com') ... RICK = Item('Rickenbacker', url='http://www.rickenbacker.com') ... GIBSON = Item('Gibson', url='http://www.gibson.com') ... FRANKENBASS = Item('Home built')>>> print(Guitar.FENDER.url) http://www.fender.com >>> print(Guitar.FRANKENBASS.url) None
枚举器中的项支持比较和相等检查。比较基于项的排序顺序。
>>> apple = Fruit.APPLE >>> pear = Fruit.PEAR >>> orange = Fruit.ORANGE >>> apple < pear True >>> apple == pear False >>> apple == apple True >>> apple != pear True >>> apple > pear False >>> pear < orange True >>> apple < orange True
不在枚举器中的项始终比较为False。
>>> import warnings >>> from lazr.enum import Item >>> with warnings.catch_warnings(): ... warnings.simplefilter('ignore', category=UserWarning) ... Item('a') == Item('b') False
项的字符串表示形式是标题,表示也显示了项所属的枚举。
>>> print(apple) Apple >>> print(repr(apple)) <Item Fruit.APPLE, Apple>
枚举类型的items属性不是一个列表,而是一个提供对项进行迭代和通过项的名称或(如果有)数据库值访问Item属性的类的实例。
此用途主要是为了提供一个向后兼容的访问器,但它也提供了一个适合getattr的合适替代方案。
>>> name = 'APPLE' >>> Fruit.items[name] <Item Fruit.APPLE, Apple> >>> getattr(Fruit, name) <Item Fruit.APPLE, Apple>
数据库枚举类型
枚举类型的一个非常常见用途是为存储在数据库列中的整数值提供语义意义。枚举类型项本身没有任何整数值。
DBEnumeratedType为用于将整数值映射到Python枚举值的类型提供了语义框架。
>>> # Remove the existing reference to BranchType from the registry >>> del enumerated_type_registry['BranchType'] >>> class BranchType(DBEnumeratedType): ... HOSTED = DBItem(1, """ ... Hosted ... ... Hosted braches use the supermirror as the main repository ... for the branch.""") ... ... MIRRORED = DBItem(2, """ ... Mirrored ... ... Mirrored branches are "pulled" from a remote location.""") ... ... IMPORTED = DBItem(3, """ ... Imported ... ... Imported branches are natively maintained in CVS or SVN""")
请注意,DBItem的值是整数表示。但TokenizedItem的值是DBItem本身。
>>> hosted = BranchType.HOSTED >>> hosted.value 1 >>> hosted == BranchType.HOSTED True >>> tokenized_item = BranchType.getTermByToken('HOSTED') >>> tokenized_item.value <DBItem BranchType.HOSTED, (1) Hosted>
DBEnumeratedTypes也支持IVocabularyTokenized
>>> verifyObject(IVocabularyTokenized, BranchType) True
DBEnumeratedTypes的items属性提供了从数据库值到DBItems的映射。
>>> BranchType.items[3] <DBItem BranchType.IMPORTED, (3) Imported>
这些项目也支持URL字段。
>>> class Bass(DBEnumeratedType): ... FENDER = DBItem(10, 'Fender', url='http://www.fender.com') ... RICK = DBItem(20, 'Rickenbacker', ... url='http://www.rickenbacker.com') ... GIBSON = DBItem(30, 'Gibson', url='http://www.gibson.com') ... FRANKENBASS = DBItem(40, 'Home built')>>> print(Bass.FENDER.url) http://www.fender.com >>> print(Bass.FRANKENBASS.url) None
DBEnumeratedType类中的项目必须是DBItem类型。
>>> class BadItemType(DBEnumeratedType): ... TESTING = Item("Testing") Traceback (most recent call last): ... TypeError: Items must be of the appropriate type for the DBEnumeratedType, ...builtin...BadItemType.TESTING
您不能定义一个具有两个不同DBItem映射到相同数字值的DBEnumeratedType。
>>> class TwoMapping(DBEnumeratedType): ... FIRST = DBItem(42, 'First') ... SECOND = DBItem(42, 'Second') Traceback (most recent call last): ... TypeError: Two DBItems with the same value 42 (FIRST, SECOND)
覆盖排序顺序
默认情况下,枚举类型中项目的排序顺序由声明项目的顺序定义。这可以通过在类中指定sort_order属性来覆盖。
如果指定了sort_order,则必须指定枚举中的每个项目。
>>> class AnimalClassification(EnumeratedType): ... sort_order = "REPTILE", "INSECT", "MAMMAL" ... INSECT = Item("Insect") ... MAMMAL = Item("Mammal") ... FISH = Item("Fish") ... REPTILE = Item("Reptile") Traceback (most recent call last): ... TypeError: sort_order for EnumeratedType must contain all and only Item instances ...
sort_order也可以出现在类的定义中的任何位置,尽管惯例是它出现在Item实例之前。
>>> class AnimalClassification(EnumeratedType): ... sort_order = "REPTILE", "FISH", "INSECT", "MAMMAL" ... INSECT = Item("Insect") ... MAMMAL = Item("Mammal") ... FISH = Item("Fish") ... REPTILE = Item("Reptile")
枚举类型的项目属性根据sort_order排序。项目属性还用于通过__iter__控制迭代。
>>> for item in AnimalClassification.items: ... print(item.title) Reptile Fish Insect Mammal
排序顺序还驱动比较操作。
>>> reptile, fish, insect, mammal = AnimalClassification.items >>> reptile < fish < insect < mammal True
扩展枚举类型
扩展类最简单的方法是从它派生。
>>> class AnimalClassificationExtended(AnimalClassification): ... INVERTEBRATE = Item("Invertebrate")>>> for item in AnimalClassificationExtended: ... print(item.title) Reptile Fish Insect Mammal Invertebrate
use_template函数将指定的枚举类型的项目插入到新的枚举类型中。默认情况下,它将获取所有枚举项目。
>>> class UIBranchType(EnumeratedType): ... use_template(BranchType) >>> for item in UIBranchType: ... print(item.title) Hosted Mirrored Imported
您还可以通过在exclude参数中引用属性名称来指定要排除的项目。这可以是一个引用一个名称的字符串,也可以是一个引用多个属性名称的元组或列表。
>>> class UIBranchType2(EnumeratedType): ... use_template(BranchType, exclude='IMPORTED') >>> for item in UIBranchType2: ... print(item.title) Hosted Mirrored
或限制项目为指定的项目
>>> class UIBranchType3(EnumeratedType): ... use_template(BranchType, include=('HOSTED', 'MIRRORED')) >>> for item in UIBranchType3: ... print(item.title) Hosted Mirrored
从项目回到枚举类型
每个Enumertype项目都有一个指向Enumertype的引用。
>>> print(repr(apple)) <Item Fruit.APPLE, Apple> >>> print(repr(apple.enum)) <EnumeratedType 'Fruit'> >>> for item in apple.enum: ... print(item.title) Apple Pear Orange
Item.sortkey
项目的sortkey属性由枚举类型中定义的sort_order定义。该值通常用作列中的隐藏值,以确保适当的排序。
>>> for item in Fruit.items: ... print(item.title, item.sortkey) Apple 0 Pear 1 Orange 2>>> for item in BranchType.items: ... print(item.title, item.sortkey) Hosted 0 Mirrored 1 Imported 2
JSON支持
枚举类型实例可以序列化到/从JSON。此库提供了必要的编码和解码类,可以直接使用或作为lazr.json包的一部分使用,其中它们被注册为lazr枚举的默认处理程序。
枚举实例序列化为包含以下内容的字典:-枚举类型名称按枚举类型注册表的顺序-枚举实例名称
>>> import json >>> from lazr.enum import EnumJSONEncoder>>> json_enum = json.dumps( ... Fruit.APPLE, cls=EnumJSONEncoder, sort_keys=True) >>> print(json_enum) {"name": "APPLE", "type": "Fruit"}
为了反序列化,我们可以指定如下json_object_hook。在使用lazr.json包时,此操作是透明的。
>>> def fruit_enum_decoder(value_dict): ... return EnumJSONDecoder.from_dict(Fruit, value_dict)>>> from lazr.enum import EnumJSONDecoder >>> json.loads(json_enum, object_hook=fruit_enum_decoder) <Item Fruit.APPLE, Apple>
lazr.enum的NEWS
1.2.1 (2021-09-13)
调整版本策略以避免导入pkg_resources,这在大型环境中较慢。
1.2 (2019-11-24)
从buildout切换到tox。
添加Python 3支持。
1.1.4 (2012-04-18)
支持将枚举序列化为/从JSON(lp:984549)
不在枚举器中的项目始终比较为False(lp:524259)
修复_enum.py中的许可证声明为LGPLv3而不是LGPLv3+(lp:526484)
1.1.3 (2011-04-20)
添加了对通过标记值获取术语的区分大小写的支持(lp:154556)
1.1.2 (2009-08-31)
删除了不必要的构建依赖项
1.1.1 (2009-08-06)
从setup.py中删除了sys.path黑客。
1.1 (2009-06-08)
将url参数添加到BaseItem和DBItem构造函数中。
1.0 (2009-03-24)
在PyPI上首次发布