| t | from inspect import getfullargspec | t | from inspect import getfullargspec |
| | | |
| class Absolute(type): | | class Absolute(type): |
| | | |
| def __new__(mcls, cls_name, bases_tuple, cls_dict, **kwargs): | | def __new__(mcls, cls_name, bases_tuple, cls_dict, **kwargs): |
| attr_w = kwargs.get('width', 'width') | | attr_w = kwargs.get('width', 'width') |
| attr_h = kwargs.get('height', 'height') | | attr_h = kwargs.get('height', 'height') |
| | | |
| def is_paramless_method(func): | | def is_paramless_method(func): |
| if not callable(func): | | if not callable(func): |
| return False | | return False |
| try: | | try: |
| args = getfullargspec(func).args | | args = getfullargspec(func).args |
| return len(args) == 1 | | return len(args) == 1 |
| except TypeError: | | except TypeError: |
| return False | | return False |
| orig_abs = cls_dict.get('abs') | | orig_abs = cls_dict.get('abs') |
| orig_len = cls_dict.get('__len__') | | orig_len = cls_dict.get('__len__') |
| orig_w = cls_dict.get(attr_w) | | orig_w = cls_dict.get(attr_w) |
| orig_h = cls_dict.get(attr_h) | | orig_h = cls_dict.get(attr_h) |
| if '__abs__' not in cls_dict or not callable(cls_dict['__abs__'] | | if '__abs__' not in cls_dict or not callable(cls_dict['__abs__'] |
| ): | | ): |
| abs_implementation = lambda self: self | | abs_implementation = lambda self: self |
| if is_paramless_method(orig_abs): | | if is_paramless_method(orig_abs): |
| abs_implementation = lambda self: orig_abs(self) | | abs_implementation = lambda self: orig_abs(self) |
| elif is_paramless_method(orig_len): | | elif is_paramless_method(orig_len): |
| abs_implementation = lambda self: len(self) | | abs_implementation = lambda self: len(self) |
| elif is_paramless_method(orig_w) and is_paramless_method(ori | | elif is_paramless_method(orig_w) and is_paramless_method(ori |
| g_h): | | g_h): |
| abs_implementation = lambda self: getattr(self, attr_w)( | | abs_implementation = lambda self: getattr(self, attr_w)( |
| ) * getattr(self, attr_h)() | | ) * getattr(self, attr_h)() |
| elif attr_w in cls_dict and (not callable(orig_w)) and (attr | | elif attr_w in cls_dict and (not callable(orig_w)) and (attr |
| _h in cls_dict) and (not callable(orig_h)): | | _h in cls_dict) and (not callable(orig_h)): |
| abs_implementation = lambda self: getattr(self, attr_w) | | abs_implementation = lambda self: getattr(self, attr_w) |
| * getattr(self, attr_h) | | * getattr(self, attr_h) |
| cls_dict['__abs__'] = abs_implementation | | cls_dict['__abs__'] = abs_implementation |
| | | |
| class AbsProxy: | | class AbsProxy: |
| | | |
| def __get__(self, instance, owner): | | def __get__(self, instance, owner): |
| if instance is None: | | if instance is None: |
| return self | | return self |
| return instance.__abs__() | | return instance.__abs__() |
| cls_dict['abs'] = AbsProxy() | | cls_dict['abs'] = AbsProxy() |
| return super().__new__(mcls, cls_name, bases_tuple, cls_dict) | | return super().__new__(mcls, cls_name, bases_tuple, cls_dict) |