Source code for sequince.utils.callables
from __future__ import annotations
import inspect
from typing import TYPE_CHECKING, Any, Callable
if TYPE_CHECKING:
from ..steps.base import StepContext
[docs]
def call_with_optional_context(
fn: Callable[..., Any],
base_args: tuple[Any, ...],
context: StepContext,
) -> Any:
"""Call fn with base_args and append context only if required."""
signature = inspect.signature(fn)
params = signature.parameters.values()
positional = [
parameter
for parameter in params
if parameter.kind
in (
inspect.Parameter.POSITIONAL_ONLY,
inspect.Parameter.POSITIONAL_OR_KEYWORD,
)
]
required = sum(
parameter.default is inspect._empty for parameter in positional
)
has_varargs = any(
parameter.kind == inspect.Parameter.VAR_POSITIONAL
for parameter in params
)
max_positional = float("inf") if has_varargs else len(positional)
base_count = len(base_args)
if required <= base_count + 1 <= max_positional:
return fn(*base_args, context)
if required <= base_count <= max_positional:
return fn(*base_args)
raise TypeError(
"Function cannot accept the provided positional arguments."
)