Source code for eradiate._factory

from __future__ import annotations

import typing as t
from collections.abc import MutableMapping

import attrs
import dessinemoi
import pinttr

from .units import unit_registry as ureg


[docs] @attrs.define class Factory(dessinemoi.Factory): """ Object factory. This factory subclass extends the original :class:`dessinemoi.Factory` type by adding the following functionality to its :meth:`convert` method: * unit interpretation using :func:`pinttr.interpret_units`; * class method constructor selection using the ``"construct"`` key (overrides the default dict constructor if any; reserves the ``"construct"`` parameter). The interface is unchanged. """ def _convert_impl( self, value, allowed_cls: type | tuple[type] | None = None, ) -> t.Any: if isinstance(value, MutableMapping): # Interpret units and copy value to avoid unintended mutation value_copy = pinttr.interpret_units(value, ureg=ureg) # Query registry type_id = value_copy.pop("type") try: entry = self.registry[type_id] except KeyError as e: raise ValueError(f"no type registered as '{type_id}'") from e # Resolve lazy type if necessary cls = ( entry.cls.load() if isinstance(entry.cls, dessinemoi.LazyType) else entry.cls ) # Check if class is allowed if allowed_cls is not None and not issubclass(cls, allowed_cls): raise TypeError( f"conversion to object type '{type_id}' ({cls}) is not allowed" ) # Get constructor from dict, if any dict_constructor = value_copy.pop("construct", entry.dict_constructor) # Construct object return self.create(type_id, construct=dict_constructor, kwargs=value_copy) else: # Check if object has allowed type if allowed_cls is not None: if not isinstance(value, allowed_cls): raise TypeError("value type is not allowed") return value
[docs] def register_lazy_batch( self, specs: list[tuple[str, str, dict]], cls_prefix: str = "", ): """ Register multiple lazy types at once. Parameters ---------- specs : list of tuple[str, str, dict] A list of ``(cls, type_id, kwargs)`` tuples where ``cls`` is the name of the target type (relative to `cls_prefix`), ``type_id`` is the ID for the registered type and ``kwargs`` is a dictionary containing keyword arguments for the :meth:`.Factory.register` method. cls_prefix : str A prefix relative to which lazy type names are expressed. """ for cls, type_id, kwargs in specs: if cls_prefix: cls = f"{cls_prefix}.{cls}" self.register(cls, type_id=type_id, **kwargs)