diff options
Diffstat (limited to 'tools/cru-py/cru/_func.py')
-rw-r--r-- | tools/cru-py/cru/_func.py | 262 |
1 files changed, 90 insertions, 172 deletions
diff --git a/tools/cru-py/cru/_func.py b/tools/cru-py/cru/_func.py index ef3da72..1b437be 100644 --- a/tools/cru-py/cru/_func.py +++ b/tools/cru-py/cru/_func.py @@ -10,59 +10,77 @@ from typing import ( ParamSpec, TypeAlias, TypeVar, - cast, ) + from ._cru import CRU from ._const import CruPlaceholder _P = ParamSpec("_P") +_P1 = ParamSpec("_P1") _T = TypeVar("_T") -_ArgsChainableCallable: TypeAlias = Callable[..., Iterable[Any]] -_KwargsChainableCallable: TypeAlias = Callable[..., Iterable[tuple[str, Any]]] -_ChainableCallable: TypeAlias = Callable[ - ..., tuple[Iterable[Any], Iterable[tuple[str, Any]]] -] +class _Dec: + @staticmethod + def wrap( + origin: Callable[_P, Callable[_P1, _T]] + ) -> Callable[_P, _Wrapper[_P1, _T]]: + def _wrapped(*args: _P.args, **kwargs: _P.kwargs) -> _Wrapper[_P1, _T]: + return _Wrapper(origin(*args, **kwargs)) + return _wrapped -class CruFunctionMeta: - class Base: - @staticmethod - def none(*_v, **_kwargs) -> None: - return None - @staticmethod - def true(*_v, **_kwargs) -> Literal[True]: - return True +class _RawBase: + @staticmethod + def none(*_v, **_kwargs) -> None: + return None - @staticmethod - def false(*_v, **_kwargs) -> Literal[False]: - return False + @staticmethod + def true(*_v, **_kwargs) -> Literal[True]: + return True - @staticmethod - def identity(v: _T) -> _T: - return v + @staticmethod + def false(*_v, **_kwargs) -> Literal[False]: + return False - @staticmethod - def only_you(v: _T, *_v, **_kwargs) -> _T: - return v + @staticmethod + def identity(v: _T) -> _T: + return v - @staticmethod - def equal(a: Any, b: Any) -> bool: - return a == b + @staticmethod + def only_you(v: _T, *_v, **_kwargs) -> _T: + return v - @staticmethod - def not_equal(a: Any, b: Any) -> bool: - return a != b + @staticmethod + def equal(a: Any, b: Any) -> bool: + return a == b - @staticmethod - def not_(v: Any) -> Any: - return not v + @staticmethod + def not_equal(a: Any, b: Any) -> bool: + return a != b @staticmethod - def bind(func: Callable[..., _T], *bind_args, **bind_kwargs) -> Callable[..., _T]: + def not_(v: Any) -> Any: + return not v + + +class _Wrapper(Generic[_P, _T]): + def __init__(self, f: Callable[_P, _T]): + self._f = f + + @property + def me(self) -> Callable[_P, _T]: + return self._f + + def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _T: + return self._f(*args, **kwargs) + + @_Dec.wrap + def bind(self, *bind_args, **bind_kwargs) -> Callable[..., _T]: + func = self.me + def bound_func(*args, **kwargs): popped = 0 real_args = [] @@ -82,174 +100,74 @@ class CruFunctionMeta: KWARGS = auto() BOTH = ARGS | KWARGS - ArgsChainableCallable = _ArgsChainableCallable - KwargsChainableCallable = _KwargsChainableCallable - ChainableCallable = _ChainableCallable + ArgsChainableCallable: TypeAlias = Callable[..., Iterable[Any]] + KwargsChainableCallable: TypeAlias = Callable[..., Iterable[tuple[str, Any]]] + ChainableCallable: TypeAlias = Callable[ + ..., tuple[Iterable[Any], Iterable[tuple[str, Any]]] + ] - @staticmethod + @_Dec.wrap def chain_with_args( - funcs: Iterable[_ArgsChainableCallable], *bind_args, **bind_kwargs - ) -> _ArgsChainableCallable: + self, funcs: Iterable[ArgsChainableCallable], *bind_args, **bind_kwargs + ) -> ArgsChainableCallable: def chained_func(*args): + args = self.bind(*bind_args, **bind_kwargs)(*args) + for func in funcs: - args = CruFunctionMeta.bind(func, *bind_args, **bind_kwargs)(*args) + args = _Wrapper(func).bind(*bind_args, **bind_kwargs)(*args) return args return chained_func - @staticmethod + @_Dec.wrap def chain_with_kwargs( - funcs: Iterable[_KwargsChainableCallable], *bind_args, **bind_kwargs - ) -> _KwargsChainableCallable: + self, funcs: Iterable[KwargsChainableCallable], *bind_args, **bind_kwargs + ) -> KwargsChainableCallable: def chained_func(**kwargs): + kwargs = self.bind(*bind_args, **bind_kwargs)(**kwargs) for func in funcs: - kwargs = CruFunctionMeta.bind(func, *bind_args, **bind_kwargs)(**kwargs) + kwargs = _Wrapper(func).bind(func, *bind_args, **bind_kwargs)(**kwargs) return kwargs return chained_func - @staticmethod + @_Dec.wrap def chain_with_both( - funcs: Iterable[_ChainableCallable], *bind_args, **bind_kwargs - ) -> _ChainableCallable: + self, funcs: Iterable[ChainableCallable], *bind_args, **bind_kwargs + ) -> ChainableCallable: def chained_func(*args, **kwargs): for func in funcs: - args, kwargs = CruFunctionMeta.bind(func, *bind_args, **bind_kwargs)( + args, kwargs = _Wrapper(func).bind(func, *bind_args, **bind_kwargs)( *args, **kwargs ) return args, kwargs return chained_func - @staticmethod - def chain( - mode: ChainMode, - funcs: Iterable[ - _ArgsChainableCallable | _KwargsChainableCallable | _ChainableCallable - ], - *bind_args, - **bind_kwargs, - ) -> _ArgsChainableCallable | _KwargsChainableCallable | _ChainableCallable: - if mode == CruFunctionMeta.ChainMode.ARGS: - return CruFunctionMeta.chain_with_args( - cast(Iterable[_ArgsChainableCallable], funcs), - *bind_args, - **bind_kwargs, - ) - elif mode == CruFunctionMeta.ChainMode.KWARGS: - return CruFunctionMeta.chain_with_kwargs( - cast(Iterable[_KwargsChainableCallable], funcs), - *bind_args, - **bind_kwargs, - ) - elif mode == CruFunctionMeta.ChainMode.BOTH: - return CruFunctionMeta.chain_with_both( - cast(Iterable[_ChainableCallable], funcs), *bind_args, **bind_kwargs - ) - - -class CruFunction(Generic[_P, _T]): - - def __init__(self, f: Callable[_P, _T]): - self._f = f - - @property - def me(self) -> Callable[_P, _T]: - return self._f - def bind(self, *bind_args, **bind_kwargs) -> CruFunction[..., _T]: - return CruFunction(CruFunctionMeta.bind(self._f, *bind_args, **bind_kwargs)) +class _Base: + none = _Wrapper(_RawBase.none) + true = _Wrapper(_RawBase.true) + false = _Wrapper(_RawBase.false) + identity = _Wrapper(_RawBase.identity) + only_you = _Wrapper(_RawBase.only_you) + equal = _Wrapper(_RawBase.equal) + not_equal = _Wrapper(_RawBase.not_equal) + not_ = _Wrapper(_RawBase.not_) - def _iter_with_self( - self, funcs: Iterable[Callable[..., Any]] - ) -> Iterable[Callable[..., Any]]: - yield self - yield from funcs +class _Creators: @staticmethod - def chain_with_args( - self, - funcs: Iterable[_ArgsChainableCallable], - *bind_args, - **bind_kwargs, - ) -> _ArgsChainableCallable: - return CruFunction( - CruFunctionMeta.chain_with_args( - self._iter_with_self(funcs), *bind_args, **bind_kwargs - ) - ) + def make_isinstance_of_types(*types: type) -> Callable: + return _Wrapper(lambda v: type(v) in types) - def chain_with_kwargs( - self, funcs: Iterable[_KwargsChainableCallable], *bind_args, **bind_kwargs - ) -> _KwargsChainableCallable: - return CruFunction( - CruFunctionMeta.chain_with_kwargs( - self._iter_with_self(funcs), *bind_args, **bind_kwargs - ) - ) - def chain_with_both( - self, funcs: Iterable[_ChainableCallable], *bind_args, **bind_kwargs - ) -> _ChainableCallable: - return CruFunction( - CruFunctionMeta.chain_with_both( - self._iter_with_self(funcs), *bind_args, **bind_kwargs - ) - ) - - def chain( - self, - mode: CruFunctionChainMode, - funcs: Iterable[ - _ArgsChainableCallable | _KwargsChainableCallable | _ChainableCallable - ], - *bind_args, - **bind_kwargs, - ) -> _ArgsChainableCallable | _KwargsChainableCallable | _ChainableCallable: - return CruFunction( - CruFunctionMeta.chain( - mode, self._iter_with_self(funcs), *bind_args, **bind_kwargs - ) - ) +class CruFunction: + RawBase = _RawBase + Base = _Base + Creators = _Creators + Wrapper = _Wrapper + Decorators = _Dec - def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _T: - return self._f(*args, **kwargs) - @staticmethod - def make_chain( - mode: CruFunctionChainMode, - funcs: Iterable[ - _ArgsChainableCallable | _KwargsChainableCallable | _ChainableCallable - ], - *bind_args, - **bind_kwargs, - ) -> CruFunction: - return CruFunction( - CruFunctionMeta.chain(mode, funcs, *bind_args, **bind_kwargs) - ) - - -class CruWrappedFunctions: - none = CruFunction(CruRawFunctions.none) - true = CruFunction(CruRawFunctions.true) - false = CruFunction(CruRawFunctions.false) - identity = CruFunction(CruRawFunctions.identity) - only_you = CruFunction(CruRawFunctions.only_you) - equal = CruFunction(CruRawFunctions.equal) - not_equal = CruFunction(CruRawFunctions.not_equal) - not_ = CruFunction(CruRawFunctions.not_) - - -class CruFunctionGenerators: - @staticmethod - def make_isinstance_of_types(*types: type) -> Callable: - return CruFunction(lambda v: type(v) in types) - - -CRU.add_objects( - CruRawFunctions, - CruFunctionMeta, - CruFunction, - CruWrappedFunctions, - CruFunctionGenerators, -) +CRU.add_objects(CruFunction) |