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
|
from __future__ import annotations
from dataclasses import MISSING, fields, is_dataclass
from typing import Any, Generic
from typing_extensions import TypeGuard, get_type_hints
from polyfactory.factories.base import BaseFactory, T
from polyfactory.field_meta import FieldMeta, Null
class DataclassFactory(Generic[T], BaseFactory[T]):
"""Dataclass base factory"""
__is_base_factory__ = True
@classmethod
def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]:
"""Determine whether the given value is supported by the factory.
:param value: An arbitrary value.
:returns: A typeguard
"""
return bool(is_dataclass(value))
@classmethod
def get_model_fields(cls) -> list["FieldMeta"]:
"""Retrieve a list of fields from the factory's model.
:returns: A list of field MetaData instances.
"""
fields_meta: list["FieldMeta"] = []
model_type_hints = get_type_hints(cls.__model__, include_extras=True)
for field in fields(cls.__model__): # type: ignore[arg-type]
if not field.init:
continue
if field.default_factory and field.default_factory is not MISSING:
default_value = field.default_factory()
elif field.default is not MISSING:
default_value = field.default
else:
default_value = Null
fields_meta.append(
FieldMeta.from_type(
annotation=model_type_hints[field.name],
name=field.name,
default=default_value,
),
)
return fields_meta
|