Passed
Push — master ( 812b05...176334 )
by Konstantinos
02:19 queued 01:50
created

Delegate.__new__()   A

Complexity

Conditions 5

Size

Total Lines 10
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nop 3
dl 0
loc 10
rs 9.3333
c 0
b 0
f 0
1
import inspect
2
import types
3
import attr
4
5
from so_magic.data.backend.engine_specs import EngineTabularRetriever, EngineTabularIterator, EngineTabularMutator
6
from .client_code import PDTabularRetrieverDelegate, PDTabularIteratorDelegate, PDTabularMutatorDelegate
7
8
9
__all__ = ['PDTabularRetriever', 'PDTabularIterator', 'PDTabularMutator']
10
11
12
# INFRASTRUCTURE
13
14
def with_self(function):
15
    # foo_code = compile(f'def {f_name}({arg_string}): return f({params_str})', "<string>", "exec")
16
    # foo_func1 = types.FunctionType(foo_code.co_consts[0], globals(), f_name)
17
18
    def _function(_self, *args, **kwargs):
19
        return function(*args, **kwargs)
20
    return _function
21
22
23
class Delegate:
24
    def __new__(cls, *args, **kwargs):
25
        delegate_ins = super().__new__(cls)
26
        tabular_operator = args[0]
27
        for _member_name, member in inspect.getmembers(
28
                tabular_operator, predicate=lambda x: any([inspect.ismethod(x), inspect.isfunction(x)])):
29
            if isinstance(member, types.FunctionType):  # if no decorator is used
30
                setattr(delegate_ins, member.__name__, types.MethodType(member, delegate_ins))
31
            if isinstance(member, types.MethodType):  # if @classmethod is used
32
                setattr(delegate_ins, member.__name__, types.MethodType(with_self(member), delegate_ins))
33
        return delegate_ins
34
35
36
def validate_delegate(tabular_operator, required_members):
37
    for member_name, required_signature in required_members:
38
        sig = str(inspect.signature(getattr(tabular_operator, member_name)))
39
        if sig != required_signature:
40
            raise ValueError(f"Expected signature {required_signature} for {member_name} member of object "
41
                             f"{tabular_operator} with type {type(tabular_operator)}. Instead got {sig}.")
42
43
44
RETRIEVER_REQUIRED_SIGNATURES = {
45
        'column': '(identifier, data)',
46
        'row': '(identifier, data)',
47
        'nb_columns': '(data)',
48
        'nb_rows': '(data)',
49
        'get_numerical_attributes': '(data)',
50
    }
51
52
53
# CONCRETE IMPLEMENTATIONS
54
55
@attr.s
56
@EngineTabularRetriever.register_as_subclass('pd')
57
class PDTabularRetriever(EngineTabularRetriever):
58
    """The observation object is the same as the one your return from 'from_json_lines'"""
59
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularRetrieverDelegate)),
60
                        # validator=lambda x, y, z: validate_delegate(z, RETRIEVER_REQUIRED_SIGNATURES)
61
                        )
62
63
    def column(self, identifier, data):
64
        return self._delegate.column(identifier, data)
65
66
    def row(self, identifier, data):
67
        return self._delegate.row(identifier, data)
68
69
    def nb_columns(self, data):
70
        return self._delegate.nb_columns(data)
71
72
    def nb_rows(self, data):
73
        return self._delegate.nb_rows(data)
74
75
    def get_numerical_attributes(self, data):
76
        return self._delegate.get_numerical_attributes(data)
77
78
79
@attr.s
80
@EngineTabularIterator.register_as_subclass('pd')
81
class PDTabularIterator(EngineTabularIterator):
82
    """The observation object is the same as the one your return from 'from_json_lines'"""
83
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularIteratorDelegate)))
84
85
    def columnnames(self, data):
86
        return self._delegate.columnnames(data)
87
88
    def iterrows(self, data):
89
        return self._delegate.iterrows(data)
90
91
    def itercolumns(self, data):
92
        return self._delegate.itercolumns(data)
93
94
95
@attr.s
96
@EngineTabularMutator.register_as_subclass('pd')
97
class PDTabularMutator(EngineTabularMutator):
98
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularMutatorDelegate)))
99
100
    def add_column(self, datapoints, values, new_attribute, **kwargs):
101
        self._delegate.add_column(datapoints, values, new_attribute, **kwargs)
102