Source code for doitoml.actors.py
"""Declarative actions for ``doitoml``."""
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
from doitoml.types import ExecutionContext
from doitoml.utils.py import (
base_py_schema,
make_py_function,
parse_dotted_py,
resolve_py_args,
)
if TYPE_CHECKING:
from doitoml.sources._config import ConfigSource
from ._actor import Actor
CallableAction = Callable[[], Optional[bool]]
[docs]
class PyActor(Actor):
"""An actor for user-defined Python functions."""
[docs]
def knows(self, action: Dict[str, Any]) -> bool:
"""Only handles ``py`` actions."""
if "py" not in action:
return False
path_dotted_func = list(action["py"].items())[0][0]
py_path, dotted, func_name = parse_dotted_py(path_dotted_func)
return None not in [dotted, func_name]
[docs]
def transform_action(
self,
source: "ConfigSource",
action: Dict[str, Any],
) -> List[Dict[str, Any]]:
"""Expand a dict containing `py`."""
args_kwargs = list(action["py"].items())[0][1]
args, kwargs = resolve_py_args(
self.doitoml,
source,
args_kwargs.pop("args", []),
args_kwargs.pop("kwargs", {}),
)
args_kwargs.update(args=args, kwargs=kwargs)
return [action]
[docs]
def perform_action(
self,
action: Dict[str, Any],
execution_context: ExecutionContext,
) -> List[CallableAction]:
"""Build a python callable."""
path_dotted_func, args_kwargs = list(action["py"].items())[0]
args, kwargs = args_kwargs["args"], args_kwargs["kwargs"]
return [
make_py_function(path_dotted_func, args, kwargs, execution_context),
]
[docs]
@staticmethod
def schema() -> Dict[str, Any]:
"""Describe the structure of an at-rest ``py`` action."""
return base_py_schema(description="a custom python action")