mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
committed by
Samuel Colvin
parent
36a20613fb
commit
b4d3a2d544
@@ -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
@@ -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'),
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user