强制正确使用python枚举

问题描述 投票:1回答:2

所以我正在使用一个大型Django代码库,该代码库始终使用python Enums,例如:

from enum import Enum

class Status(Enum):
    active = 'active'

# ... later
assert some_django_model_instance.status == Status.active.value  # so far so good

...但是,“。value”部分当然会被遗忘并保留一直”>。到目前为止,要完全放弃Enums是很困难的,尽管它们存在的问题多于有用。有没有一种方法可以自动检查像这样的行:

assert some_django_model_instance.status == Status.active  # someone forgot ".value" here!

,例如,mypy或pylint,或者可能向基本枚举添加一些代码/断言?问题是,Status.active并没有真正调用任何代码,它只是返回一个类,当然,该类绝不等于some_django_model_instance.status,它是一个字符串。

<<

您可以通过继承

enum.EnumMeta

:来强制实施enum.EnumMeta
现在您不必调用

from enum import EnumMeta, Enum as _Enum class Enum(_Enum, metaclass=EnumMeta): def __eq__(self, arg): if isinstance(arg, self.__class__): return arg is self return self.value == arg 进行比较:

enum.value
这从某种意义上解决了这个问题,即其他人不会忘记调用class Method(Enum):
    GET = 'GET'
    POST = 'POST'

>>> get = 'GET'
>>> Method.GET == get
True
>>> get == Method.GET
True
>>> Method.POST == Method.GET
False
进行比较,但是会产生更大的问题,因为现在插入模型中时,人们更可能会忘记调用.value

要解决此问题,建议您也将

.value

子类化以创建您自己的枚举字段:
models.CharField
现在您也可以在不调用models.CharField的情况下插入模型:

class EnumField(models.CharField): def __init__(self, enum, **kwargs): self.enum = enum def from_db_value(self, value, expression, connection): if value is not None: return self.enum(value) return None def to_python(self, value): if isinstance(value, self.enum): return value.value return None def get_prep_value(self, value): if isinstance(value, self.enum): value = value.value return super().get_prep_value(value) def deconstruct(self): name, path, args, kwargs = super().deconstruct() args.append(self.enum) return name, path, args, kwargs

您可以使用.value命令行标志/配置标志选项使mypy检测这些类型的有问题的比较。启用此标志后,执行class MyModel(models.Model): method = EnumField(enum=Method) >>> MyModel.objects.create(method=Method.GET) 会产生如下错误:

--strict-equality

注意:此标志将检查

all

总是为假的相等比较,而不仅仅是涉及枚举的比较。 但是,对于任何一个操作数都定义了自定义--strict-equality方法的相等比较,它将禁用,因为自定义方法实际上可以做任何事情。
python django pylint mypy
2个回答
2
投票
您可以通过继承

enum.EnumMeta


1
投票
您可以使用.value命令行标志/配置标志选项使mypy检测这些类型的有问题的比较。启用此标志后,执行class MyModel(models.Model): method = EnumField(enum=Method) >>> MyModel.objects.create(method=Method.GET) 会产生如下错误:

--strict-equality

© www.soinside.com 2019 - 2024. All rights reserved.