Source code for pygritia.call
"""
Provides :py:class:`CallMixin` mixin class
It provides call support to the :py:class:`Lazy` class
"""
from typing import Any, Mapping, Tuple, TypeVar, cast
from functools import wraps
import operator
from dataclasses import dataclass
from .core import Lazy, LazyAction, LazyMixin, LazyNS, evaluate, repr_
[docs]@dataclass
class Call(LazyAction):
"""Function call"""
__slots__ = ['target', 'args', 'kwargs']
target: Any
args: Tuple[Any, ...]
kwargs: Mapping[str, Any]
def __str__(self) -> str:
if isinstance(self.target, LazyMixin):
name = str(self.target)
elif hasattr(self.target, '__name__'):
name = self.target.__name__
else:
name = repr(self.target)
return '{}({})'.format(
name,
', '.join(
item
for items in (
(repr_(arg) for arg in self.args),
(key + '=' + repr_(value) for key, value in self.kwargs.items())
)
for item in items
)
)
[docs] def evaluate(self, namespace: LazyNS) -> Any:
callable_ = evaluate(self.target, namespace)
args_ = (evaluate(arg, namespace) for arg in self.args)
kwargs_ = {key: evaluate(value, namespace) for key, value in self.kwargs.items()}
return callable_(*args_, **kwargs_)
[docs]class CallMixin(LazyMixin):
"""
Call support
Function call is read only expression
"""
def __call__(self: Lazy, *args: Any, **kwargs: Any) -> Lazy:
return self.__class__(action=Call(self, args, kwargs), origin=self)
_T = TypeVar('_T')
[docs]def lazy_call(func: _T) -> _T:
"""
Make a function to support lazy expression
>>> from pygritia import this, lazy_call, evaluate
>>> @lazy_call
... def hello(obj):
... print(obj)
>>> print(hello(this))
hello(this)
>>> hello("123")
123
>>> evaluate(hello(this), {this: "123"})
123
"""
if callable(func):
func_ = func
@wraps(func)
def wrapped(*args: Any, **kwargs: Any) -> Any:
lazy = any(
isinstance(arg, LazyMixin)
for arglist in (args, kwargs.values())
for arg in arglist
)
if lazy:
return LazyMixin.create(action=Call(func_, args, kwargs))
return func_(*args, **kwargs)
return cast(_T, wrapped)
raise TypeError("lazy_call must be applied to callable")
# pylint: disable=invalid-name
lazy_getitem = lazy_call(operator.getitem)
"Lazy expression version of getitem"
lazy_setitem = lazy_call(operator.setitem)
"Lazy expression version of setitem"
lazy_delitem = lazy_call(operator.delitem)
"Lazy expression version of delitem"
lazy_getattr = lazy_call(getattr)
"Lazy expression version of getattr"
lazy_setattr = lazy_call(setattr)
"Lazy expression version of setattr"
lazy_delattr = lazy_call(delattr)
"Lazy expression version of delattr"
# pylint: enable=invalid-name