Passed
Push — master ( 154bfb...1be8b2 )
by sosei
06:13 queued 05:00
created

check_self_class_call_of_meta_package.check_self_class_call_of_meta_module   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 51
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 6
eloc 28
dl 0
loc 51
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A check_self_class_call_of_meta.__new__() 0 5 3
A check_self_class_call_of_meta.__class_function_wrapper() 0 15 2
A check_self_class_call_of_meta.__call__() 0 3 1
1
'''
2
multivalued_dict - This is a multi-valued dictionary package.
3
Copyright (C) 2019  sosei
4
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Affero General Public License as published
7
by the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU Affero General Public License for more details.
14
15
You should have received a copy of the GNU Affero General Public License
16
along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
'''
18
19
import inspect
20
from functools import wraps
21
22
__all__ = ['check_self_class_call_of_meta']
23
24
class check_self_class_call_of_meta(type):
25
    '''Check the class name pattern of the class instance method called the self.'''
26
    @staticmethod
27
    def __class_function_wrapper(func):
28
        @wraps(func)
29
        def wrapper(*args, **kwargs):
30
            first_arg = args[0]
31
            class_of_first_arg = type(first_arg)
32
            func_of_module = func.__module__
33
            func_of_class = func.__qualname__.rpartition('.')[0]
34
            exec('from '+func_of_module+' import '+func_of_class)
35
            original_class = eval(func_of_class)
36
            if issubclass(class_of_first_arg, original_class):
37
                return func(*args, **kwargs)
38
            else:
39
                raise TypeError(f"descriptor '{func.__name__}' requires a '{original_class.__name__}' object but received a '{class_of_first_arg.__name__}'")
40
        return wrapper
41
    
42
    def __new__(cls, name, bases, namespace, **kwargs):
43
        for key, value in namespace.items():
44
            if inspect.isfunction(value):
45
                namespace.__setitem__(key, cls.__class_function_wrapper(value))
46
        return type.__new__(cls, name, bases, namespace)
47
    
48
    def __call__(self, *args, **kwargs):
49
        self.__instance = super().__call__(*args, **kwargs)
50
        return self.__instance
51