Source code for hydra_slayer.factory
from typing import Any, Callable, Mapping, Tuple, Type, Union
import copy
import functools
import inspect
__all__ = ["call_meta_factory", "partial_meta_factory", "default_meta_factory"]
Factory = Union[Type, Callable[..., Any]]
MetaFactory = Callable[[Factory, Tuple, Mapping], Any]
DEFAULT_CALL_MODE_KEY = "_mode_"
[docs]def call_meta_factory(factory: Factory, args: Tuple, kwargs: Mapping):
"""Creates a new instance from ``factory``.
Args:
factory: factory to create instance from
args: \*args to pass to the factory
kwargs: \*\*kwargs to pass to the factory
Returns:
Instance.
"""
return factory(*args, **kwargs)
[docs]def partial_meta_factory(factory: Factory, args: Tuple, kwargs: Mapping):
"""
Returns a new partial object which when called will behave like func called
with the positional arguments ``args`` and keyword arguments ``kwargs``.
Args:
factory: factory to create instance from
args: \*args to merge into the factory
kwargs: \*\*kwargs to merge into the factory
Returns:
Partial object.
"""
return functools.partial(factory, *args, **kwargs)
[docs]def default_meta_factory(factory: Factory, args: Tuple, kwargs: Mapping):
"""Returns a new instance or a new partial object.
* _mode_='auto'
Creates a new instance from ``factory`` if ``factory`` is class
(like :py:func:`call_meta_factory`), else returns a new partial object
(like :py:func:`partial_meta_factory`).
* _mode_='call'
Returns a result of the factory called with the positional arguments
``args`` and keyword arguments ``kwargs``.
* _mode_='partial'
Returns a new partial object which when called will behave like factory
called with the positional arguments ``args`` and keyword arguments
``kwargs``.
Args:
factory: factory to create instance from
args: \*args to pass to the factory
kwargs: \*\*kwargs to pass to the factory
Returns:
Instance.
Raises:
ValueError: if mode not in list: ``'auto'``, ``'call'``, ``'partial'``.
Examples:
>>> default_meta_factory(int, (42,))
42
>>> # please note that additional () are used
>>> default_meta_factory(lambda x: x, (42,))()
42
>>> default_meta_factory(int, ('42',), {"base": 16})
66
>>> # please note that additional () are not needed
>>> default_meta_factory(lambda x: x, (42,), {"_mode_": "call"})
42
>>> default_meta_factory(lambda x: x, ('42',), {"_mode_": "partial", "base": 16})()
66
"""
# make a copy of kwargs since we don't want to modify them directly
kwargs = copy.copy(kwargs)
mode = kwargs.pop(DEFAULT_CALL_MODE_KEY, "auto")
if mode not in {"auto", "call", "partial"}:
raise ValueError(f"`{mode}` is not a valid call mode")
if mode == "auto" and inspect.isfunction(factory) or mode == "partial":
return partial_meta_factory(factory, args, kwargs)
return call_meta_factory(factory, args, kwargs)