Python attr.s 多类型验证
Python attr.s multiple type validation
如果提供 none,则默认生成 UUID 的 class,如果提供 str
,则 validates/creates 生成 UUID 对象。
import attr
from attrs import validators
from uuid import UUID, uuid1
def _validate(instance, attribute, value) -> None:
try:
if isinstance(value, str):
instance.uuid = UUID(value)
return
except Exception as e:
raise BadUUID() from e
@attr.s(slots=True)
class Private:
uuid = attr.ib(type=[str, UUID], validator=[validators.optional([validators.instance_of(UUID), validators.instance_of(str)]), _validate], default=uuid1())
它应该提供和不提供值:
print(Private())
print(Private('d283a713-9f4b-1c15-ab8d-8d95d7ce8999'))
如果有none,它应该使用默认设置生成一个新的 UUID。
如果提供了值,它应该验证它并创建一个 UUID 对象。
我收到一个错误,因为它只会验证一种实例类型,str
或 UUID
。
如果我设置 instance_of(UUID)
它只会在不提供值的情况下工作。
如果我将它设置为 instance_of(str)
,它只会在提供 str
的情况下工作。
我做错了什么吗,有没有更好的方法来完成我正在寻找的东西?
看来这就是你想要的:
import attr
from uuid import UUID, uuid1
def _convert(value) -> UUID:
return value if isinstance(value, UUID) else UUID(value)
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p1 = Private()
print(p1.uuid)
p2 = Private('c53358b3-798e-11ec-a49b-cf6d4243e811')
print(p2.uuid)
示例结果:
d5e2d087-798e-11ec-9d59-cf6d4243e811
c53358b3-798e-11ec-a49b-cf6d4243e811
如果您更喜欢 仅 字符串被转换,并且如果传递了任何其他内容则引发您自己的异常(尽管我可能只是将其保留到 UUID()
本身),这有效:
import attr
from uuid import UUID, uuid1
class BadUUID(Exception):
...
def _convert(value) -> UUID:
if isinstance(value, str):
return UUID(value)
elif isinstance(value, UUID):
return value
else:
raise BadUUID(f'{value} is neither a string nor a UUID')
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p = Private(42)
或者,如果您的目的是从 UUID 捕获异常并添加一些内容:
import attr
from uuid import UUID, uuid1
class BadUUID(Exception):
...
def _convert(value) -> UUID:
try:
return value if isinstance(value, UUID) else UUID(value)
except Exception as e:
raise BadUUID (f'{value} is not a good UUID') from e
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p = Private(42)
如果提供 none,则默认生成 UUID 的 class,如果提供 str
,则 validates/creates 生成 UUID 对象。
import attr
from attrs import validators
from uuid import UUID, uuid1
def _validate(instance, attribute, value) -> None:
try:
if isinstance(value, str):
instance.uuid = UUID(value)
return
except Exception as e:
raise BadUUID() from e
@attr.s(slots=True)
class Private:
uuid = attr.ib(type=[str, UUID], validator=[validators.optional([validators.instance_of(UUID), validators.instance_of(str)]), _validate], default=uuid1())
它应该提供和不提供值:
print(Private())
print(Private('d283a713-9f4b-1c15-ab8d-8d95d7ce8999'))
如果有none,它应该使用默认设置生成一个新的 UUID。
如果提供了值,它应该验证它并创建一个 UUID 对象。
我收到一个错误,因为它只会验证一种实例类型,str
或 UUID
。
如果我设置 instance_of(UUID)
它只会在不提供值的情况下工作。
如果我将它设置为 instance_of(str)
,它只会在提供 str
的情况下工作。
我做错了什么吗,有没有更好的方法来完成我正在寻找的东西?
看来这就是你想要的:
import attr
from uuid import UUID, uuid1
def _convert(value) -> UUID:
return value if isinstance(value, UUID) else UUID(value)
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p1 = Private()
print(p1.uuid)
p2 = Private('c53358b3-798e-11ec-a49b-cf6d4243e811')
print(p2.uuid)
示例结果:
d5e2d087-798e-11ec-9d59-cf6d4243e811
c53358b3-798e-11ec-a49b-cf6d4243e811
如果您更喜欢 仅 字符串被转换,并且如果传递了任何其他内容则引发您自己的异常(尽管我可能只是将其保留到 UUID()
本身),这有效:
import attr
from uuid import UUID, uuid1
class BadUUID(Exception):
...
def _convert(value) -> UUID:
if isinstance(value, str):
return UUID(value)
elif isinstance(value, UUID):
return value
else:
raise BadUUID(f'{value} is neither a string nor a UUID')
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p = Private(42)
或者,如果您的目的是从 UUID 捕获异常并添加一些内容:
import attr
from uuid import UUID, uuid1
class BadUUID(Exception):
...
def _convert(value) -> UUID:
try:
return value if isinstance(value, UUID) else UUID(value)
except Exception as e:
raise BadUUID (f'{value} is not a good UUID') from e
@attr.s(slots=True)
class Private:
uuid = attr.ib(default=uuid1(), converter=_convert)
p = Private(42)