0

如果未提供则默认生成 UUID 的类,如果提供了则验证/创建 UUID 对象str

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'))

在没有提供的情况下,它应该使用默认设置生成一个新的 UUID。

如果提供了值,则应对其进行验证并创建一个 UUID 对象。


我收到一个错误,因为它只会验证一个实例类型,要么str要么UUID

如果我设置instance_of(UUID)它只会在不提供值的情况下工作。

如果我将它设置为instance_of(str)它只会str在提供的情况下工作。


我做错了什么,有没有更好的方法来完成我正在寻找的东西?

4

1 回答 1

1

看来这就是你所追求的:

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)
于 2022-01-20T01:24:45.880 回答