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
|
from datetime import date
from enum import Enum
from typing import Callable, Literal, Optional
import pytest
from pydantic import AmqpDsn, AnyHttpUrl, AnyUrl, BaseConfig, BaseModel, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn
from polyfactory.exceptions import ParameterException
from polyfactory.factories.pydantic_factory import ModelFactory
from tests.models import Person, PersonFactoryWithDefaults, Pet
def test_enum_parsing() -> None:
class MyStrEnum(str, Enum):
FIRST_NAME = "Moishe Zuchmir"
SECOND_NAME = "Hannah Arendt"
class MyIntEnum(Enum):
ONE_HUNDRED = 100
TWO_HUNDRED = 200
class MyModel(BaseModel):
name: MyStrEnum
worth: MyIntEnum
class MyFactory(ModelFactory):
__model__ = MyModel
result = MyFactory.build()
assert isinstance(result.name, MyStrEnum)
assert isinstance(result.worth, MyIntEnum)
def test_callback_parsing() -> None:
today = date.today()
class MyModel(BaseModel):
name: str
birthday: date
secret: Callable
class MyFactory(ModelFactory):
__model__ = MyModel
name = lambda: "moishe zuchmir" # noqa: E731
birthday = lambda: today # noqa: E731
result = MyFactory.build()
assert result.name == "moishe zuchmir"
assert result.birthday == today
assert callable(result.secret)
def test_literal_parsing() -> None:
class MyModel(BaseModel):
literal_field: "Literal['yoyos']"
multi_literal_field: "Literal['nolos', 'zozos', 'kokos']"
class MyFactory(ModelFactory):
__model__ = MyModel
assert MyFactory.build().literal_field == "yoyos"
batch = MyFactory.batch(30)
values = {v.multi_literal_field for v in batch}
assert values == {"nolos", "zozos", "kokos"}
def test_embedded_models_parsing() -> None:
class MyModel(BaseModel):
pet: Pet
class MyFactory(ModelFactory):
__model__ = MyModel
result = MyFactory.build()
assert isinstance(result.pet, Pet)
def test_embedded_factories_parsing() -> None:
class MyModel(BaseModel):
person: Person
class MyFactory(ModelFactory):
__model__ = MyModel
person = PersonFactoryWithDefaults
result = MyFactory.build()
assert isinstance(result.person, Person)
def test_class_parsing() -> None:
class TestClassWithoutKwargs:
def __init__(self) -> None:
self.flag = "123"
class MyModel(BaseModel):
class Config(BaseConfig):
arbitrary_types_allowed = True
class_field: TestClassWithoutKwargs
# just a few select exceptions, to verify this works
exception_field: Exception
type_error_field: TypeError
attribute_error_field: AttributeError
runtime_error_field: RuntimeError
class MyFactory(ModelFactory):
__model__ = MyModel
result = MyFactory.build()
assert isinstance(result.class_field, TestClassWithoutKwargs)
assert result.class_field.flag == "123"
assert isinstance(result.exception_field, Exception)
assert isinstance(result.type_error_field, TypeError)
assert isinstance(result.attribute_error_field, AttributeError)
assert isinstance(result.runtime_error_field, RuntimeError)
class TestClassWithKwargs:
def __init__(self, _: str) -> None:
self.flag = str
class MyNewModel(BaseModel):
class Config(BaseConfig):
arbitrary_types_allowed = True
class_field: TestClassWithKwargs
class MySecondFactory(ModelFactory):
__model__ = MyNewModel
with pytest.raises(ParameterException):
MySecondFactory.build()
@pytest.mark.parametrize(
"type_",
[AnyUrl, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, AmqpDsn, AnyHttpUrl],
)
def test_optional_url_field_parsed_correctly(type_: type) -> None:
class MyModel(BaseModel):
url: Optional[type_] # type: ignore
class MyFactory(ModelFactory[MyModel]):
__model__ = MyModel
while not (url := MyFactory.build().url):
assert not url
assert MyModel(url=url) # no validation error raised
|