Source code for tet.decorators

"""
Decorator utilities for Tet applications.

This module provides useful decorators:

- :func:`deprecated` - Mark functions as deprecated
- :class:`reify_attr` - Cached property with configurable attribute name

Example
-------

Marking a function as deprecated::

    from tet.decorators import deprecated

    @deprecated
    def old_function():
        pass

Using reify_attr for cached properties::

    from tet.decorators import reify_attr

    class MyClass:
        @reify_attr
        def expensive_computation(self):
            # This will only be called once per instance
            return compute_something()
"""
import warnings
from functools import update_wrapper


[docs] def deprecated(func): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used.""" def new_func(*args, **kwargs): warnings.warn( "Call to deprecated function {}." .format(func.__qualname__, category=DeprecationWarning, stacklevel=2)) return func(*args, **kwargs) new_func.__name__ = func.__name__ new_func.__doc__ = func.__doc__ new_func.__dict__.update(func.__dict__) return new_func
[docs] class reify_attr(object): """ A cached property descriptor that uses the actual attribute name. Unlike Pyramid's ``reify`` which gets the attribute name from the decorated method, ``reify_attr`` uses the name of the actual attribute it's assigned to. This is determined via ``__set_name__``, falling back to finding the attribute on the class if ``__set_name__`` is not called (e.g., when the descriptor is assigned dynamically). This pattern is useful as a building block for descriptors like ``autowired`` in pyramid_di, where the descriptor needs to know its attribute name to cache the resolved value on the instance. """ def __init__(self, wrapped): self.wrapped = wrapped update_wrapper(self, wrapped) self.names = None def __get__(self, inst, objtype=None): if inst is None: return self val = self.wrapped(inst) if self.names is None: names = [] for name, value in list(objtype.__dict__.items()): if value is self: names.append(name) self.names = names for name in self.names: setattr(inst, name, val) return val def __set_name__(self, owner, name): if self.names is None: self.names = [name] else: self.names.append(name)