Navigation Menu

Skip to content

Commit

Permalink
add ConstrainedUUID, UUID1, UUID3, UUID4 and `UUID5
Browse files Browse the repository at this point in the history
…` types (#167)
  • Loading branch information
Gr1N committed May 1, 2018
1 parent 36a2061 commit a049fe5
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 8 deletions.
4 changes: 4 additions & 0 deletions HISTORY.rst
Expand Up @@ -3,6 +3,10 @@
History
-------

v0.9.1 (2018-XX-XX)
...................
* add ``ConstrainedUUID``, ``UUID1``, ``UUID3``, ``UUID4`` and ``UUID5`` types #167

v0.9.0 (2018-04-28)
...................
* tweak email-validator import error message #145
Expand Down
23 changes: 18 additions & 5 deletions docs/examples/exotic.py
@@ -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):
Expand Down Expand Up @@ -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',
Expand All @@ -48,7 +53,11 @@ class Model(BaseModel):
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())
"""
Expand All @@ -68,6 +77,10 @@ class Model(BaseModel):
'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'),
}
"""
40 changes: 39 additions & 1 deletion pydantic/types.py
@@ -1,8 +1,9 @@
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
from .validators import str_validator, uuid_validator

try:
import email_validator
Expand All @@ -29,6 +30,11 @@
'confloat',
'PositiveFloat',
'NegativeFloat',
'ConstrainedUUID',
'UUID1',
'UUID3',
'UUID4',
'UUID5',
]

NoneStr = Optional[str]
Expand Down Expand Up @@ -237,4 +243,36 @@ class NegativeFloat(ConstrainedFloat):
lt = 0


class ConstrainedUUID(UUID):
version_: int = None

@classmethod
def get_validators(cls):
yield uuid_validator
yield cls.validate

@classmethod
def validate(cls, value: UUID) -> UUID:
if cls.version_ and value.version != cls.version_:
raise ValueError(f'uuid version {cls.version_} expected, not {value.version}')

return value


class UUID1(ConstrainedUUID):
version_ = 1


class UUID3(ConstrainedUUID):
version_ = 3


class UUID4(ConstrainedUUID):
version_ = 4


class UUID5(ConstrainedUUID):
version_ = 5


# TODO, JsonEither, JsonList, JsonDict
31 changes: 29 additions & 2 deletions tests/test_types.py
@@ -1,13 +1,14 @@
import os
import uuid
from collections import OrderedDict
from datetime import date, datetime, time, timedelta
from enum import Enum, IntEnum
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
Expand Down Expand Up @@ -461,6 +462,32 @@ class Model(BaseModel):
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
Expand Down

0 comments on commit a049fe5

Please sign in to comment.