File: test_attrs_factory.py

package info (click to toggle)
python-polyfactory 2.22.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,892 kB
  • sloc: python: 11,338; makefile: 103; sh: 37
file content (266 lines) | stat: -rw-r--r-- 6,103 bytes parent folder | download
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import datetime as dt
from decimal import Decimal
from enum import Enum
from typing import Any, Dict, Generic, List, Optional, Tuple, TypeVar, Union
from uuid import UUID

import attrs
import pytest
from attrs import asdict, define

from polyfactory.factories.attrs_factory import AttrsFactory

pytestmark = [pytest.mark.attrs]


def test_is_supported_type() -> None:
    @define
    class Foo: ...

    assert AttrsFactory.is_supported_type(Foo) is True


def test_is_supported_type_without_struct() -> None:
    class Foo: ...

    assert AttrsFactory.is_supported_type(Foo) is False


def test_with_basic_types_annotated() -> None:
    class SampleEnum(Enum):
        FOO = "foo"
        BAR = "bar"

    @define
    class Foo:
        bool_field: bool
        int_field: int
        float_field: float
        str_field: str
        bytse_field: bytes
        bytearray_field: bytearray
        tuple_field: Tuple[int, str]
        tuple_with_variadic_args: Tuple[int, ...]
        list_field: List[int]
        dict_field: Dict[str, int]
        datetime_field: dt.datetime
        date_field: dt.date
        time_field: dt.time
        uuid_field: UUID
        decimal_field: Decimal
        enum_type: SampleEnum
        any_type: Any

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    foo = FooFactory.build()
    foo_dict = asdict(foo)

    assert foo == Foo(**foo_dict)


def test_with_basic_types_attrs_field() -> None:
    @define
    class Foo:
        bool_field = attrs.field(type=bool)  # pyright: ignore
        int_field = attrs.field(type=int)  # pyright: ignore
        float_field = attrs.field(type=float)  # pyright: ignore
        str_field = attrs.field(type=str)  # pyright: ignore
        bytes_field = attrs.field(type=bytes)  # pyright: ignore
        bytearray_field = attrs.field(type=bytearray)  # pyright: ignore
        tuple_field = attrs.field(type=Tuple[int, str])  # type: ignore
        tuple_with_variadic_args = attrs.field(type=Tuple[int, ...])  # type: ignore
        list_field = attrs.field(type=List[int])  # pyright: ignore
        dict_field = attrs.field(type=Dict[int, str])  # pyright: ignore
        datetime_field = attrs.field(type=dt.datetime)  # pyright: ignore
        date_field = attrs.field(type=dt.date)  # pyright: ignore
        time_field = attrs.field(type=dt.time)  # pyright: ignore
        uuid_field = attrs.field(type=UUID)  # pyright: ignore
        decimal_field = attrs.field(type=Decimal)  # pyright: ignore

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    foo = FooFactory.build()
    foo_dict = asdict(foo)

    assert foo == Foo(**foo_dict)


def test_with_nested_attr_model() -> None:
    @define
    class Foo:
        int_field: int

    @define
    class Bar:
        int_field: int
        foo_field: Foo

    class BarFactory(AttrsFactory[Bar]):
        __model__ = Bar

    bar = BarFactory.build()
    bar_dict = asdict(bar, recurse=False)

    assert bar == Bar(**bar_dict)


def test_with_private_fields() -> None:
    @define
    class Foo:
        _private: int

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    foo = FooFactory.build()

    assert foo == Foo(foo._private)


def test_with_aliased_fields() -> None:
    @define
    class Foo:
        aliased: int = attrs.field(alias="foo")

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    foo = FooFactory.build()

    assert foo == Foo(foo.aliased)


def test_with_generics() -> None:
    T = TypeVar("T")

    @define
    class Foo(Generic[T]):
        x: T

    class FooFactory(AttrsFactory[Foo[str]]):
        __model__ = Foo

    foo = FooFactory.build()
    foo_dict = asdict(foo)

    assert foo == Foo(**foo_dict)


def test_with_inheritance() -> None:
    @define
    class Parent:
        int_field: int

    @define
    class Child(Parent):
        str_field: str

    class ChildFactory(AttrsFactory[Child]):
        __model__ = Child

    child = ChildFactory.build()
    child_dict = asdict(child)

    assert child == Child(**child_dict)


def test_with_stringified_annotations() -> None:
    @define
    class Foo:
        int_field: "int"

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    foo = FooFactory.build()

    assert isinstance(foo.int_field, int)


def test_with_init_false() -> None:
    @define
    class Foo:
        foo: int = attrs.field(init=False)

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo

    assert FooFactory.build()


def test_use_default_with_callable_default() -> None:
    @define
    class Foo:
        default_field: int = attrs.field(default=attrs.Factory(lambda: 10, takes_self=False))

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo
        __use_defaults__ = True

    foo = FooFactory.build()

    assert foo.default_field == 10


def test_use_default_with_non_callable_default() -> None:
    @define
    class Foo:
        default_field: int = attrs.field(default=10)

    class FooFactory(AttrsFactory[Foo]):
        __model__ = Foo
        __use_defaults__ = True

    foo = FooFactory.build()

    assert foo.default_field == 10


def test_union_types() -> None:
    @define
    class A:
        a: Union[List[str], List[int]]
        b: Union[str, List[int]]
        c: List[Union[Tuple[int, int], Tuple[str, int]]]

    AFactory = AttrsFactory.create_factory(A)

    assert AFactory.build()


def test_collection_unions_with_models() -> None:
    @define
    class A:
        a: int

    @define
    class B:
        a: str

    @define
    class C:
        a: Union[List[A], List[B]]
        b: List[Union[A, B]]

    CFactory = AttrsFactory.create_factory(C)

    assert CFactory.build()


@pytest.mark.parametrize("allow_none", (True, False))
def test_optional_type(allow_none: bool) -> None:
    @define
    class A:
        a: Union[str, None]
        b: Optional[str]
        c: Optional[Union[str, int, List[int]]]

    class AFactory(AttrsFactory[A]):
        __model__ = A

        __allow_none_optionals__ = allow_none

    assert AFactory.build()