Пожалуйста, объясните, как работает, например,
Ge из библиотеки annotated-types. Как-то слишком много магии, что даже просмотр исходного кода не проясняет.
Смотрите сами. Пусть есть модель Pydantic (v2):
from annotated_types import Gt
from pydantic import BaseModel
class Person(BaseModel):
first_name: str
last_name: str
age: Annotated[int, Gt(30)]
Исходный код для Gt:
class BaseMetadata:
"""Base class for all metadata.
This exists mainly so that implementers
can do `isinstance(..., BaseMetadata)` while traversing field annotations.
"""
__slots__ = ()
class SupportsGt(Protocol):
def __gt__(self: T, __other: T) -> bool:
...
@dataclass(frozen=True, **SLOTS)
class Gt(BaseMetadata):
"""Gt(gt=x) implies that the value must be greater than x.
It can be used with any type that supports the ``>`` operator,
including numbers, dates and times, strings, sets, and so on.
"""
gt: SupportsGt
Как Pydantic выполняет сравнивание при валидации? И как вообще он понимает, что нужно сравнить, а не выполнить сравнение по паттерну? Я бы еще понял, что сначала мы инициализируем, а потом вызываем метод `__call__`...
Как написать свой валидатор, скажем, который выполняет сравнение на конкретную строку типа такого:
@dataclass(frozen=True, **SLOTS)
class MyCompare:
the_string: str
?
Если входящая строка равна указанной строке, то это ошибка валидации.