diff --git a/changes/1541-shawnwall.md b/changes/1541-shawnwall.md new file mode 100644 index 0000000000..02936f02e0 --- /dev/null +++ b/changes/1541-shawnwall.md @@ -0,0 +1 @@ +Added support for UUID instantiation through 16 byte strings such as `b'\x12\x34\x56\x78' * 4`. This was done to support `BINARY(16)` columns in sqlalchemy. diff --git a/docs/usage/types.md b/docs/usage/types.md index 6e7dbddd67..97853dd07a 100644 --- a/docs/usage/types.md +++ b/docs/usage/types.md @@ -145,7 +145,7 @@ with custom properties and validation. see [Pydantic Types](#pydantic-types) for other more strict path types `uuid.UUID` -: strings and bytes (converted to strings) are passed to `UUID(v)`; +: strings and bytes (converted to strings) are passed to `UUID(v)`, with a fallback to `UUID(bytes=v)` for `bytes` and `bytearray`; see [Pydantic Types](#pydantic-types) for other stricter UUID types `ByteSize` diff --git a/pydantic/validators.py b/pydantic/validators.py index 7249849dc1..f79e785d9f 100644 --- a/pydantic/validators.py +++ b/pydantic/validators.py @@ -252,7 +252,12 @@ def uuid_validator(v: Any, field: 'ModelField') -> UUID: if isinstance(v, str): v = UUID(v) elif isinstance(v, (bytes, bytearray)): - v = UUID(v.decode()) + try: + v = UUID(v.decode()) + except ValueError: + # 16 bytes in big-endian order as the bytes argument fail + # the above check + v = UUID(bytes=v) except ValueError: raise errors.UUIDError() diff --git a/tests/test_types.py b/tests/test_types.py index 1b720d528f..28af56652a 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -392,6 +392,7 @@ def __bool__(self) -> bool: ('uuid_check', 'ebcdab58-6eb8-46fb-a190-d07a33e9eac8', UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8')), ('uuid_check', UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8'), UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8')), ('uuid_check', b'ebcdab58-6eb8-46fb-a190-d07a33e9eac8', UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8')), + ('uuid_check', b'\x12\x34\x56\x78' * 4, UUID('12345678-1234-5678-1234-567812345678')), ('uuid_check', 'ebcdab58-6eb8-46fb-a190-', ValidationError), ('uuid_check', 123, ValidationError), ('decimal_check', 42.24, Decimal('42.24')),