add `UUID1, UUID3, UUID4 and UUID5` types (#167) (#167)

This commit is contained in:
Nikita Grishko
2018-05-03 00:49:55 +03:00
committed by Samuel Colvin
parent 36a20613fb
commit b4d3a2d544
5 changed files with 83 additions and 14 deletions
+4
View File
@@ -3,6 +3,10 @@
History
-------
v0.9.1 (2018-XX-XX)
...................
* add ``UUID1``, ``UUID3``, ``UUID4`` and ``UUID5`` types #167
v0.9.0 (2018-04-28)
...................
* tweak email-validator import error message #145
+18 -5
View File
@@ -1,8 +1,9 @@
import uuid
from pathlib import Path
from uuid import UUID
from pydantic import (DSN, BaseModel, EmailStr, NameEmail, NegativeFloat, NegativeInt, PositiveFloat, PositiveInt,
PyObject, confloat, conint, constr)
from pydantic import (DSN, UUID1, UUID3, UUID4, UUID5, BaseModel, EmailStr, NameEmail, NegativeFloat, NegativeInt,
PositiveFloat, PositiveInt, PyObject, confloat, conint, constr)
class Model(BaseModel):
@@ -32,7 +33,11 @@ class Model(BaseModel):
db_driver = 'postgres'
db_query: dict = None
dsn: DSN = None
uuid: UUID = None
uuid_any: UUID = None
uuid_v1: UUID1 = None
uuid_v3: UUID3 = None
uuid_v4: UUID4 = None
uuid_v5: UUID5 = None
m = Model(
cos_function='math.cos',
@@ -48,7 +53,11 @@ m = Model(
neg_float=-2.3,
email_address='Samuel Colvin <s@muelcolvin.com >',
email_and_name='Samuel Colvin <s@muelcolvin.com >',
uuid='ebcdab58-6eb8-46fb-a190-d07a33e9eac8'
uuid_any=uuid.uuid4(),
uuid_v1=uuid.uuid1(),
uuid_v3=uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org'),
uuid_v4=uuid.uuid4(),
uuid_v5=uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
)
print(m.dict())
"""
@@ -68,6 +77,10 @@ print(m.dict())
'email_and_name': <NameEmail("Samuel Colvin <s@muelcolvin.com>")>,
...
'dsn': 'postgres://postgres@localhost:5432/foobar',
'uuid': UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8'),
'uuid_any': UUID('ebcdab58-6eb8-46fb-a190-d07a33e9eac8'),
'uuid_v1': UUID('c96e505c-4c62-11e8-a27c-dca90496b483'),
'uuid_v3': UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e'),
'uuid_v4': UUID('22209f7a-aad1-491c-bb83-ea19b906d210'),
'uuid_v5': UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d'),
}
"""
+21
View File
@@ -1,5 +1,6 @@
import re
from typing import Optional, Type, Union
from uuid import UUID
from .utils import import_string, make_dsn, validate_email
from .validators import str_validator
@@ -29,6 +30,10 @@ __all__ = [
'confloat',
'PositiveFloat',
'NegativeFloat',
'UUID1',
'UUID3',
'UUID4',
'UUID5',
]
NoneStr = Optional[str]
@@ -237,4 +242,20 @@ class NegativeFloat(ConstrainedFloat):
lt = 0
class UUID1(UUID):
_required_version = 1
class UUID3(UUID):
_required_version = 3
class UUID4(UUID):
_required_version = 4
class UUID5(UUID):
_required_version = 5
# TODO, JsonEither, JsonList, JsonDict
+11 -7
View File
@@ -114,16 +114,20 @@ def enum_validator(v, field, config, **kwargs) -> Enum:
return enum_v.value if config.use_enum_values else enum_v
def uuid_validator(v) -> UUID:
if isinstance(v, UUID):
return v
elif isinstance(v, str):
return UUID(v)
def uuid_validator(v, field, config, **kwargs) -> UUID:
if isinstance(v, str):
v = UUID(v)
elif isinstance(v, (bytes, bytearray)):
return UUID(v.decode())
else:
v = UUID(v.decode())
elif not isinstance(v, UUID):
raise ValueError(f'str, byte or native UUID type expected not {type(v)}')
required_version = getattr(field.type_, '_required_version', None)
if required_version and v.version != required_version:
raise ValueError(f'uuid version {required_version} expected, not {v.version}')
return v
# order is important here, for example: bool is a subclass of int so has to come first, datetime before date same
_VALIDATORS = [
+29 -2
View File
@@ -1,4 +1,5 @@
import os
import uuid
from collections import OrderedDict
from datetime import date, datetime, time, timedelta
from enum import Enum, IntEnum
@@ -6,8 +7,8 @@ from uuid import UUID
import pytest
from pydantic import (DSN, BaseModel, EmailStr, NameEmail, NegativeFloat, NegativeInt, PositiveFloat, PositiveInt,
PyObject, StrictStr, ValidationError, confloat, conint, constr)
from pydantic import (DSN, UUID1, UUID3, UUID4, UUID5, BaseModel, EmailStr, NameEmail, NegativeFloat, NegativeInt,
PositiveFloat, PositiveInt, PyObject, StrictStr, ValidationError, confloat, conint, constr)
try:
import email_validator
@@ -461,6 +462,32 @@ v:
Model(v=None)
class UUIDModel(BaseModel):
a: UUID1
b: UUID3
c: UUID4
d: UUID5
def test_uuid_validation():
a = uuid.uuid1()
b = uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
c = uuid.uuid4()
d = uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
m = UUIDModel(a=a, b=b, c=c, d=d)
assert m.dict() == {
'a': a,
'b': b,
'c': c,
'd': d,
}
with pytest.raises(ValidationError) as exc_info:
UUIDModel(a=d, b=c, c=b, d=a)
assert exc_info.value.message == '4 errors validating input'
def test_anystr_strip_whitespace_enabled():
class Model(BaseModel):
str_check: str