Source code for pyx12.decorators

from __future__ import annotations

import collections.abc
import functools
from collections.abc import Callable
from typing import Any

# See https://wiki.python.org/moin/PythonDecoratorLibrary


[docs] def dump_args(func: Callable[..., Any]) -> Callable[..., Any]: "This decorator dumps out the arguments passed to a function before calling it" argnames = func.__code__.co_varnames[: func.__code__.co_argcount] fname = func.__name__ def echo_func(*args: Any, **kwargs: Any) -> Any: print( ( fname, ":", ", ".join( "%s=%r" % entry for entry in list(zip(argnames, args)) + list(kwargs.items()) ), ) ) return func(*args, **kwargs) return echo_func
[docs] def memoize(obj: Callable[..., Any]) -> Callable[..., Any]: cache: dict[Any, Any] = {} obj.cache = cache # type: ignore[attr-defined] @functools.wraps(obj) def memoizer(*args: Any, **kwargs: Any) -> Any: if kwargs: # frozenset is used to ensure hashability key: Any = (args, frozenset(kwargs.items())) else: key = args if key not in cache: cache[key] = obj(*args, **kwargs) return cache[key] return memoizer
[docs] class memoized: """Decorator. Caches a function's return value each time it is called. If called later with the same arguments, the cached value is returned (not reevaluated). """
[docs] func: Callable[..., Any]
[docs] cache: dict[Any, Any]
def __init__(self, func: Callable[..., Any]) -> None: self.func = func self.cache = {} def __call__(self, *args: Any) -> Any: if not isinstance(args, collections.abc.Hashable): # uncacheable. a list, for instance. # better to not cache than blow up. return self.func(*args) if args in self.cache: return self.cache[args] else: value = self.func(*args) self.cache[args] = value return value def __repr__(self) -> str: """Return the function's docstring.""" return self.func.__doc__ or "" def __get__(self, obj: Any, objtype: Any) -> Callable[..., Any]: """Support instance methods.""" return functools.partial(self.__call__, obj)