Passed
Push — main ( ddff4b...7b3fbc )
by Douglas
04:33
created

mandos.model.apis.chembl_api   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 270
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 131
dl 0
loc 270
rs 10
c 0
b 0
f 0
wmc 29

28 Methods

Rating   Name   Duplication   Size   Complexity  
A ChemblApi.molecule_form() 0 3 1
A ChemblEntrypoint.filter() 0 2 1
A ChemblApi.target_relation() 0 3 1
A ChemblFilterQuery.__len__() 0 2 1
A ChemblApi.go_slim() 0 3 1
A ChemblApi.wrap() 0 17 1
A ChemblApi.drug() 0 3 1
A ChemblEntrypoint.wrap() 0 20 1
A ChemblFilterQuery.only() 0 11 1
A ChemblApi.activity() 0 3 1
A ChemblFilterQuery.mock() 0 26 1
A ChemblFilterQuery.wrap() 0 27 1
A ChemblApi.drug_indication() 0 3 1
A ChemblApi.protein_class() 0 3 1
A ChemblApi.target_component() 0 3 1
A ChemblApi.mock() 0 17 1
A ChemblApi.target() 0 3 1
A ChemblApi.atc_class() 0 3 1
A ChemblFilterQuery.__getitem__() 0 2 1
A ChemblFilterQuery.__iter__() 0 2 1
A ChemblApi.__getattribute__() 0 2 1
A ChemblApi.molecule() 0 3 1
A ChemblApi.organism() 0 3 1
A ChemblEntrypoint.mock() 0 28 2
A ChemblEntrypoint.get() 0 2 1
A ChemblApi.assay() 0 3 1
A ChemblApi.target_prediction() 0 3 1
A ChemblApi.mechanism() 0 3 1
1
"""
2
An abstraction for the ChEMBL REST API.
3
Designed to facilitate testing, but also improves static type checking.
4
"""
5
from __future__ import annotations
6
7
import abc
8
from typing import Any, Callable, Iterator, Mapping, Optional, Sequence
9
10
from pocketutils.core.dot_dict import NestedDotDict
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.dot_dict'
Loading history...
11
12
from mandos import logger
0 ignored issues
show
Unused Code introduced by
Unused logger imported from mandos
Loading history...
13
14
15
class ChemblFilterQuery(metaclass=abc.ABCMeta):
16
    """
17
    Wraps the result of calling ``filter`` on a ChEMBL query.
18
    Supports iterating over results (``__iter__`), getting a single item (``__getitem__`), and calling ``only(lst)``.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (117/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
19
    """
20
21
    def only(self, items: Sequence[str]) -> ChemblFilterQuery:
22
        """
23
        Turns this into a query for a single record.
24
25
        Args:
26
            items:
27
28
        Returns:
29
30
        """
31
        raise NotImplementedError()
32
33
    def __getitem__(self, item: int) -> NestedDotDict:
34
        raise NotImplementedError()
35
36
    def __len__(self) -> int:
37
        raise NotImplementedError()
38
39
    def __iter__(self) -> Iterator[NestedDotDict]:
40
        raise NotImplementedError()
41
42
    @classmethod
43
    def mock(cls, items: Sequence[dict]):
44
        """
45
        Mocks.
46
47
        Args:
48
            items:
49
50
        Returns:
51
52
        """
53
54
        class F(ChemblFilterQuery):
0 ignored issues
show
Coding Style Naming introduced by
Class name "F" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing class docstring
Loading history...
55
            def only(self, _: Sequence[str]) -> ChemblFilterQuery:
56
                return self
57
58
            def __getitem__(self, item: int) -> NestedDotDict:
59
                return NestedDotDict(items[item])
60
61
            def __len__(self) -> int:
62
                return len(items)
63
64
            def __iter__(self) -> Iterator[NestedDotDict]:
65
                return iter([NestedDotDict(x) for x in items])
66
67
        return F()
68
69
    @classmethod
70
    def wrap(cls, query):
71
        """
72
        Wraps.
73
74
        Args:
75
            query:
76
77
        Returns:
78
79
        """
80
81
        class F(ChemblFilterQuery):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
Coding Style Naming introduced by
Class name "F" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
82
            def only(self, items: Sequence[str]) -> ChemblFilterQuery:
83
                # TODO technically not returning this
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
84
                return getattr(query, "only")(items)
85
86
            def __getitem__(self, item: int) -> NestedDotDict:
87
                return NestedDotDict(query[item])
88
89
            def __len__(self) -> int:
90
                return len(query)
91
92
            def __iter__(self) -> Iterator[NestedDotDict]:
93
                return iter([NestedDotDict(x) for x in query])
94
95
        return F()
96
97
98
class ChemblEntrypoint:
99
    """
100
    Wraps just part of a node in the ChEMBL REST API.
101
    Ex ``Chembl.target``.
102
    """
103
104
    def filter(self, **kwargs) -> ChemblFilterQuery:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
105
        raise NotImplementedError()
106
107
    def get(self, arg: str) -> Optional[NestedDotDict]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
108
        raise NotImplementedError()
109
110
    @classmethod
111
    def mock(
112
        cls,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
113
        get_items: Mapping[str, dict],
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
114
        filter_items: Optional[Callable[[Mapping[str, Any]], Sequence[dict]]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
115
    ) -> ChemblEntrypoint:
116
        """
117
118
        Args:
119
            get_items: Map from single arg for calling ``get`` to the item to return
120
            filter_items: Map from kwarg-set for calling ``filter`` to the list of items to return;
121
                          If None, returns ``items`` in all cases
122
123
        Returns:
124
125
        """
126
127
        class X(ChemblEntrypoint):
0 ignored issues
show
Coding Style Naming introduced by
Class name "X" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing class docstring
Loading history...
128
            def filter(self, **kwargs) -> ChemblFilterQuery:
129
                if filter_items is None:
130
                    return ChemblFilterQuery.mock(list(get_items.values()))
131
                items = filter_items(kwargs)
132
                return ChemblFilterQuery.mock(items)
133
134
            def get(self, arg: str) -> Optional[NestedDotDict]:
135
                return NestedDotDict(get_items[arg])
136
137
        return X()
138
139
    @classmethod
140
    def wrap(cls, obj) -> ChemblEntrypoint:
141
        """
142
143
        Args:
144
            obj:
145
146
        Returns:
147
148
        """
149
150
        class X(ChemblEntrypoint):
0 ignored issues
show
Coding Style Naming introduced by
Class name "X" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing class docstring
Loading history...
151
            def filter(self, **kwargs) -> ChemblFilterQuery:
152
                query = getattr(obj, "filter")(**kwargs)
153
                return ChemblFilterQuery.wrap(query)
154
155
            def get(self, arg: str) -> Optional[NestedDotDict]:
156
                return NestedDotDict(getattr(obj, "get")(arg))
157
158
        return X()
159
160
161
class ChemblApi(metaclass=abc.ABCMeta):
162
    """
163
    Wraps the whole ChEMBL API.
164
    """
165
166
    @property
167
    def activity(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
168
        return self.__dict__["activity"]
169
170
    @property
171
    def assay(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
172
        return self.__dict__["assay"]
173
174
    @property
175
    def atc_class(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
176
        return self.__dict__["atc_class"]
177
178
    @property
179
    def drug(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
180
        return self.__dict__["drug"]
181
182
    @property
183
    def drug_indication(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
184
        return self.__dict__["drug_indication"]
185
186
    @property
187
    def mechanism(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
188
        return self.__dict__["mechanism"]
189
190
    @property
191
    def molecule(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
192
        return self.__dict__["molecule"]
193
194
    @property
195
    def molecule_form(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
196
        return self.__dict__["molecule_form"]
197
198
    @property
199
    def organism(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
200
        return self.__dict__["mechanism"]
201
202
    @property
203
    def go_slim(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
204
        return self.__dict__["go_slim"]
205
206
    @property
207
    def target(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
208
        return self.__dict__["target"]
209
210
    @property
211
    def target_relation(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
212
        return self.__dict__["target_relation"]
213
214
    @property
215
    def protein_class(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
216
        return self.__dict__["protein_class"]
217
218
    @property
219
    def target_component(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
220
        return self.__dict__["target_component"]
221
222
    @property
223
    def target_prediction(self) -> ChemblEntrypoint:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
224
        return self.__dict__["target_prediction"]
225
226
    def __getattribute__(self, item: str) -> ChemblEntrypoint:
227
        raise NotImplementedError()
228
229
    @classmethod
230
    def mock(cls, entrypoints: Mapping[str, ChemblEntrypoint]) -> ChemblApi:
231
        """
232
        Mocks.
233
234
        Args:
235
            entrypoints:
236
237
        Returns:
238
239
        """
240
241
        class X(ChemblApi):
0 ignored issues
show
Coding Style Naming introduced by
Class name "X" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing class docstring
Loading history...
242
            def __getattribute__(self, item: str) -> ChemblEntrypoint:
243
                return entrypoints[item]
244
245
        return X()
246
247
    @classmethod
248
    def wrap(cls, obj) -> ChemblApi:
249
        """
250
        Wraps.
251
252
        Args:
253
            obj:
254
255
        Returns:
256
257
        """
258
259
        class X(ChemblApi):
0 ignored issues
show
Coding Style Naming introduced by
Class name "X" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
introduced by
Missing class docstring
Loading history...
260
            def __getattribute__(self, item: str) -> ChemblEntrypoint:
261
                return ChemblEntrypoint.wrap(getattr(obj, item))
262
263
        return X()
264
265
266
__all__ = [
267
    "ChemblApi",
268
    "ChemblEntrypoint",
269
    "ChemblFilterQuery",
270
]
271