Source code for compages._struct_like
import dataclasses
from collections.abc import Callable
from typing import Any, NamedTuple, get_type_hints
from ._common import ExtendedType, is_named_tuple
class StructAdapterError(Exception):
pass
class NoDefault:
pass
class Field(NamedTuple):
name: str
type: type[Any]
default: Any = NoDefault
default_factory: None | Callable[[], Any] = None
metadata: Any = None
def get_default(self) -> Any:
if self.default is not NoDefault:
return self.default
if self.default_factory is not None:
return self.default_factory()
return NoDefault
def get_fields_named_tuple(tp: ExtendedType[Any]) -> list[Field]:
try:
field_types = get_type_hints(tp)
except NameError as exc:
raise StructAdapterError(f"Field type annotation cannot be resolved: {exc}") from exc
if not is_named_tuple(tp):
raise StructAdapterError(f"Expected a named tuple, got {tp}")
# Because of the check above we know we have a named tuple on our hands,
# but `mypy` cannot assert that.
defaults = tp._field_defaults # type: ignore[union-attr]
field_names = tp._fields # type: ignore[union-attr]
fields = []
for field_name in field_names:
fields.append(
Field(
name=field_name,
type=field_types[field_name],
default=defaults.get(field_name, NoDefault),
)
)
return fields
def get_fields_dataclass(tp: ExtendedType[Any]) -> list[Field]:
try:
field_types = get_type_hints(tp)
except NameError as exc:
raise StructAdapterError(f"Field type annotation cannot be resolved: {exc}") from exc
if not dataclasses.is_dataclass(tp):
raise StructAdapterError(f"Expected a dataclass, got {tp}")
dataclass_fields = dataclasses.fields(tp)
fields = []
for dc_field in dataclass_fields:
if dc_field.default is dataclasses.MISSING:
default = NoDefault
else:
default = dc_field.default
if dc_field.default_factory is dataclasses.MISSING:
default_factory = None
else:
default_factory = dc_field.default_factory
fields.append(
Field(
name=dc_field.name,
type=field_types[dc_field.name],
default=default,
metadata=dc_field.metadata,
default_factory=default_factory,
)
)
return fields
[docs]
@dataclasses.dataclass
class StructLikeOptions:
"""Options for handlers working with struct-like types (dataclasses, named tuples etc)."""
to_unstructured_name: Callable[[str, Any], str] = lambda name, _metadata: name
"""
A function converting a field name of a typed representation
into a field name of the corresponding unstructured representation.
The second argument is the metadata attached to the field (if any).
"""
unstructure_skip_defaults: bool = True
"""If the field value equals to the default when unstructuring, do not output it."""
structure_fill_in_defaults: bool = True
"""
If the field value is missing when structuring, substitute the default.
If this value is ``False``, an error will be raised instead.
"""