| t | from collections.abc import Callable | t | from collections.abc import Callable |
| | | |
| class Absolute(type): | | class Absolute(type): |
| | | |
| def __new__(mcls, name, bases, namespace, **kwargs): | | def __new__(mcls, name, bases, namespace, **kwargs): |
| width_name = kwargs.pop('width', 'width') | | width_name = kwargs.pop('width', 'width') |
| height_name = kwargs.pop('height', 'height') | | height_name = kwargs.pop('height', 'height') |
| cls = super().__new__(mcls, name, bases, namespace) | | cls = super().__new__(mcls, name, bases, namespace) |
| original_abs = getattr(cls, 'abs', None) | | original_abs = getattr(cls, 'abs', None) |
| existing_abs = getattr(cls, '__abs__', None) | | existing_abs = getattr(cls, '__abs__', None) |
| if not isinstance(existing_abs, Callable): | | if not isinstance(existing_abs, Callable): |
| | | |
| def __abs__(self, _orig_abs=original_abs, _w_name=width_name | | def __abs__(self, _orig_abs=original_abs, _w_name=width_name |
| , _h_name=height_name): | | , _h_name=height_name): |
| if isinstance(_orig_abs, Callable): | | if isinstance(_orig_abs, Callable): |
| func = _orig_abs | | func = _orig_abs |
| if hasattr(func, '__get__'): | | if hasattr(func, '__get__'): |
| func = func.__get__(self, type(self)) | | func = func.__get__(self, type(self)) |
| try: | | try: |
| return func() | | return func() |
| except TypeError: | | except TypeError: |
| pass | | pass |
| len_meth = getattr(self, '__len__', None) | | len_meth = getattr(self, '__len__', None) |
| if isinstance(len_meth, Callable): | | if isinstance(len_meth, Callable): |
| try: | | try: |
| return len_meth() | | return len_meth() |
| except TypeError: | | except TypeError: |
| pass | | pass |
| w_attr = getattr(self, _w_name, None) | | w_attr = getattr(self, _w_name, None) |
| h_attr = getattr(self, _h_name, None) | | h_attr = getattr(self, _h_name, None) |
| if isinstance(w_attr, Callable) and isinstance(h_attr, C | | if isinstance(w_attr, Callable) and isinstance(h_attr, C |
| allable): | | allable): |
| try: | | try: |
| return w_attr() * h_attr() | | return w_attr() * h_attr() |
| except TypeError: | | except TypeError: |
| pass | | pass |
| if w_attr is not None and h_attr is not None and (not is | | if w_attr is not None and h_attr is not None and (not is |
| instance(w_attr, Callable)) and (not isinstance(h_attr, Callable)): | | instance(w_attr, Callable)) and (not isinstance(h_attr, Callable)): |
| return w_attr * h_attr | | return w_attr * h_attr |
| return self | | return self |
| setattr(cls, '__abs__', __abs__) | | setattr(cls, '__abs__', __abs__) |
| | | |
| class _AbsDescriptor: | | class _AbsDescriptor: |
| | | |
| def __get__(self, obj, owner=None): | | def __get__(self, obj, owner=None): |
| if obj is None: | | if obj is None: |
| | | |
| def class_abs(instance): | | def class_abs(instance): |
| return instance.__abs__() | | return instance.__abs__() |
| return class_abs | | return class_abs |
| return obj.__abs__() | | return obj.__abs__() |
| setattr(cls, 'abs', _AbsDescriptor()) | | setattr(cls, 'abs', _AbsDescriptor()) |
| return cls | | return cls |