Код: Выделить всё
models.py
Код: Выделить всё
from pydantic import BaseModel
class Widget(BaseModel):
name: str
value: float
Для этого в моем файле conftest.py сейчас есть такая неуклюжая конструкция:
Код: Выделить всё
conftest.py
Код: Выделить всё
from typing import NotRequired, Protocol, TypedDict, Unpack
import pytest
from models import Widget
class WidgetFactoryKwargs(TypedDict):
name: NotRequired[str]
value: NotRequired[float]
class WidgetFactory(Protocol):
def __call__(self, **kwargs: Unpack[WidgetFactoryKwargs]) -> Widget: ...
@pytest.fixture
def widget_factory() -> WidgetFactory:
def _widget_factory(**kwargs: Unpack[WidgetFactoryKwargs]) -> Widget:
defaults = WidgetFactoryKwargs(name="foo", value=42)
kwargs = defaults | kwargs
return Widget(**kwargs)
return _widget_factory
Код: Выделить всё
test_widgets.py
Код: Выделить всё
from typing import assert_type
from conftest import WidgetFactory
def test_widget_creation(widget_factory: WidgetFactory) -> None:
widget = widget_factory()
assert_type(widget, Widget) # during type checking
assert isinstance(widget, Widget) # during run time
assert widget.name == "foo"
assert widget.value == 42
widget = widget_factory(name="foobar")
assert widget.name == "foobar"
assert widget.value == 42
widget = widget_factory(value=1337)
assert widget.name == "foo"
assert widget.value == 1337
widget = widget_factory(name="foobar", value=1337)
assert widget.name == "foobar"
assert widget.value == 1337
widget = widget_factory(mode="maintenance") # type checker error
Вопрос:< /p>
Есть ли лучший способ обеспечить безопасность такого типа? В идеале я мог бы создать WidgetFactoryKwargs TypedDict «динамически» на основе модели Pydantic. Это, по крайней мере, позволит избавиться от TypedDict (и связанных с этим затрат на поддержание его в соответствии с любыми изменениями в полях модели Pydantic). Но динамическое построение TypedDict явно не поддерживается для статической проверки типов.
Модель Widget, хотя технически динамическая, можно считать статической (нет странное исправление моих моделей после их определения).
Подробнее здесь: https://stackoverflow.com/questions/792 ... -for-tests