Passed
Pull Request — dev (#30)
by Konstantinos
02:57 queued 01:32
created

PDTabularMutator.add_column()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 5
dl 0
loc 2
rs 10
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
    members_list = list(inspect.getmembers(tabular_operator,
38
                                           predicate=lambda x: any([inspect.ismethod(x), inspect.isfunction(x)])))
39
    assert all(x in (_[0] for _ in members_list) for x in required_members)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable _ does not seem to be defined.
Loading history...
40
    for member_name, required_signature in required_members:
41
        sig = str(inspect.signature(getattr(tabular_operator, member_name)))
42
        if sig != required_signature:
43
            raise ValueError(f"Expected signature {required_signature} for {member_name} member of object "
44
                             f"{tabular_operator} with type {type(tabular_operator)}. Instead got {sig}.")
45
46
47
def validate_retriever_delegate(_self, _attribute, value):
48
    validate_delegate(value, {
49
        'column': '(identifier, data)',
50
        'row': '(identifier, data)',
51
        'nb_columns': '(data)',
52
        'nb_rows': '(data)',
53
        'get_numerical_attributes': '(data)',
54
    })
55
56
57
# CONCRETE IMPLEMENTATIONS
58
59
@attr.s
60
@EngineTabularRetriever.register_as_subclass('pd')
61
class PDTabularRetriever(EngineTabularRetriever):
62
    """The observation object is the same as the one your return from 'from_json_lines'"""
63
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularRetrieverDelegate)),
64
    # validator=validate_retriever_delegate
65
    )
66
67
    def column(self, identifier, data):
68
        return self._delegate.column(identifier, data)
69
70
    def row(self, identifier, data):
71
        return self._delegate.row(identifier, data)
72
73
    def nb_columns(self, data):
74
        return self._delegate.nb_columns(data)
75
76
    def nb_rows(self, data):
77
        return self._delegate.nb_rows(data)
78
79
    def get_numerical_attributes(self, data):
80
        return self._delegate.get_numerical_attributes(data)
81
82
83
@attr.s
84
@EngineTabularIterator.register_as_subclass('pd')
85
class PDTabularIterator(EngineTabularIterator):
86
    """The observation object is the same as the one your return from 'from_json_lines'"""
87
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularIteratorDelegate)))
88
89
    def columnnames(self, data):
90
        return self._delegate.columnnames(data)
91
92
    def iterrows(self, data):
93
        return self._delegate.iterrows(data)
94
95
    def itercolumns(self, data):
96
        return self._delegate.itercolumns(data)
97
98
99
@attr.s
100
@EngineTabularMutator.register_as_subclass('pd')
101
class PDTabularMutator(EngineTabularMutator):
102
    _delegate = attr.ib(default=attr.Factory(lambda: Delegate(PDTabularMutatorDelegate)))
103
104
    def add_column(self, datapoints, values, new_attribute, **kwargs):
105
        self._delegate.add_column(datapoints, values, new_attribute, **kwargs)
106