1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
import uuid
from datetime import datetime, timezone
from typing import Any
import pytest
from pydantic import BaseModel, ValidationError
from pydantic_extra_types.uuid_types import UUID6, UUID7, UUID8, uuid7, uuid7_to_datetime
class ModelUUID7(BaseModel):
id: UUID7
class ModelUUID6(BaseModel):
id: UUID6
class ModelUUID8(BaseModel):
id: UUID8
VALID_UUID7_STR = '018f0e8c-7a6a-7b1c-a3e4-fdf3e0ef7a4a'
VALID_UUID7_OBJ = uuid.UUID(VALID_UUID7_STR)
VALID_UUID4_STR = 'a7b3d4e1-1c2d-4f3e-8a5b-6c7d8e9f0a1b'
@pytest.mark.parametrize(
'value, valid',
[
(VALID_UUID7_STR, True),
(VALID_UUID7_OBJ, True),
(VALID_UUID4_STR, False),
('6ba7b810-9dad-11d1-80b4-00c04fd430c8', False),
('not-a-uuid', False),
('', False),
],
)
def test_uuid7_validation(value: Any, valid: bool) -> None:
if valid:
m = ModelUUID7(id=value)
assert m.id.version == 7
assert isinstance(m.id, uuid.UUID)
else:
with pytest.raises(ValidationError):
ModelUUID7(id=value)
def test_uuid7_serialization() -> None:
m = ModelUUID7(id=VALID_UUID7_STR)
dumped = m.model_dump()
assert dumped['id'] == VALID_UUID7_OBJ
json_str = m.model_dump_json()
assert VALID_UUID7_STR in json_str
def test_uuid7_json_schema() -> None:
schema = ModelUUID7.model_json_schema()
assert schema['properties']['id']['type'] == 'string'
assert schema['properties']['id']['format'] == 'uuid'
VALID_UUID6_STR = '1ef21d2f-6aa3-6d00-a327-541a2bda5190'
@pytest.mark.parametrize(
'value, valid',
[
(VALID_UUID6_STR, True),
(uuid.UUID(VALID_UUID6_STR), True),
(VALID_UUID4_STR, False),
],
)
def test_uuid6_validation(value: Any, valid: bool) -> None:
if valid:
m = ModelUUID6(id=value)
assert m.id.version == 6
else:
with pytest.raises(ValidationError):
ModelUUID6(id=value)
def test_uuid6_json_schema() -> None:
schema = ModelUUID6.model_json_schema()
assert schema['properties']['id']['type'] == 'string'
assert schema['properties']['id']['format'] == 'uuid'
VALID_UUID8_STR = '00112233-4455-8677-8899-aabbccddeeff'
@pytest.mark.parametrize(
'value, valid',
[
(VALID_UUID8_STR, True),
(uuid.UUID(VALID_UUID8_STR), True),
(VALID_UUID4_STR, False),
],
)
def test_uuid8_validation(value: Any, valid: bool) -> None:
if valid:
m = ModelUUID8(id=value)
assert m.id.version == 8
else:
with pytest.raises(ValidationError):
ModelUUID8(id=value)
def test_uuid8_json_schema() -> None:
schema = ModelUUID8.model_json_schema()
assert schema['properties']['id']['type'] == 'string'
assert schema['properties']['id']['format'] == 'uuid'
def test_uuid7_generation() -> None:
generated = uuid7()
assert isinstance(generated, uuid.UUID)
assert generated.version == 7
def test_uuid7_generation_is_unique() -> None:
ids = {uuid7() for _ in range(100)}
assert len(ids) == 100
def test_uuid7_generation_is_sortable() -> None:
ids = [uuid7() for _ in range(10)]
assert ids == sorted(ids)
def test_uuid7_generation_validates() -> None:
generated = uuid7()
m = ModelUUID7(id=str(generated))
assert m.id.version == 7
def test_uuid7_to_datetime() -> None:
u = uuid.UUID(VALID_UUID7_STR)
dt = uuid7_to_datetime(u)
assert isinstance(dt, datetime)
assert dt.tzinfo == timezone.utc
expected_ms = 0x018F0E8C7A6A
expected_dt = datetime.fromtimestamp(expected_ms / 1000.0, tz=timezone.utc)
assert dt == expected_dt
def test_uuid7_to_datetime_roundtrip() -> None:
generated = uuid7()
dt = uuid7_to_datetime(generated)
now = datetime.now(tz=timezone.utc)
assert abs((now - dt).total_seconds()) < 2
def test_uuid7_to_datetime_wrong_version() -> None:
u4 = uuid.UUID(VALID_UUID4_STR)
with pytest.raises(ValueError, match='Expected UUID version 7'):
uuid7_to_datetime(u4)
|