-
Notifications
You must be signed in to change notification settings - Fork 0
/
self.py
47 lines (37 loc) · 1.6 KB
/
self.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Decorators for class methods."""
import logging
from typing import Union, Iterable, Callable
from functools import wraps
logger = logging.getLogger(__name__)
class Self:
"""Decorator to allow passing an object itself to methods that actually take some attribute of that object."""
def __init__(self, attr: str, cls: Union[Iterable, str] = None):
self.attr = attr
self.cls = {cls,} if isinstance(cls, str) else cls
def _filter(self, cls: type):
return bool({c.__name__ for c in cls.mro()} & set(self.cls))
def __call__(self, func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*[getattr(arg, self.attr) if self._filter(arg.__class__) else arg for arg in args], **kwargs)
return wrapper
@staticmethod
def inplace(attr: str):
def decorator(func: Callable):
@wraps(func)
def wrapper(self, *args, inplace=True, return_self=False, **kwargs):
r = func(self, *args, **kwargs)
if inplace:
setattr(self, attr, r)
if return_self:
return self
return r
return wrapper
return decorator
# class SelfMixin(Self):
# """Mixin class that provides a class method as decorator to allow passing the object itself to the wrapped functions that actually take some attribute of that object."""
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# @classmethod
# def _filter(self, cls: type):
# return issubclass(cls, self)