Issues (931)

mandos/chembl_api.py (41 issues)

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
import logging
9
from typing import Any, Callable, Iterator, Mapping, Optional, Sequence, Set, List, Union, Iterable
0 ignored issues
show
Unused Set imported from typing
Loading history...
Unused List imported from typing
Loading history...
Unused Union imported from typing
Loading history...
Unused Iterable imported from typing
Loading history...
10
11
from pocketutils.core.dot_dict import NestedDotDict
0 ignored issues
show
Unable to import 'pocketutils.core.dot_dict'
Loading history...
12
13
logger = logging.getLogger("mandos")
14
15
from mandos import MandosResources
0 ignored issues
show
Import "from mandos import MandosResources" should be placed at the top of the module
Loading history...
Unused MandosResources imported from mandos
Loading history...
16
17
18
class ChemblFilterQuery(metaclass=abc.ABCMeta):
19
    """
20
    Wraps the result of calling ``filter`` on a ChEMBL query.
21
    Supports iterating over results (``__iter__`), getting a single item (``__getitem__`), and calling ``only(lst)``.
0 ignored issues
show
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...
22
    """
23
24
    def only(self, items: Sequence[str]) -> ChemblFilterQuery:
25
        """
26
        Turns this into a query for a single record.
27
28
        Args:
29
            items:
30
31
        Returns:
32
33
        """
34
        raise NotImplementedError()
35
36
    def __getitem__(self, item: int) -> NestedDotDict:
37
        raise NotImplementedError()
38
39
    def __len__(self) -> int:
40
        raise NotImplementedError()
41
42
    def __iter__(self) -> Iterator[NestedDotDict]:
43
        raise NotImplementedError()
44
45
    @classmethod
46
    def mock(cls, items: Sequence[dict]):
47
        """
48
        Mocks.
49
50
        Args:
51
            items:
52
53
        Returns:
54
55
        """
56
57
        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...
Missing class docstring
Loading history...
58
            def only(self, _: Sequence[str]) -> ChemblFilterQuery:
59
                return self
60
61
            def __getitem__(self, item: int) -> NestedDotDict:
62
                return NestedDotDict(items[item])
63
64
            def __len__(self) -> int:
65
                return len(items)
66
67
            def __iter__(self) -> Iterator[NestedDotDict]:
68
                return iter([NestedDotDict(x) for x in items])
69
70
        return F()
71
72
    @classmethod
73
    def wrap(cls, query):
74
        """
75
        Wraps.
76
77
        Args:
78
            query:
79
80
        Returns:
81
82
        """
83
84
        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...
Missing class docstring
Loading history...
85
            def only(self, items: Sequence[str]) -> ChemblFilterQuery:
86
                # TODO technically not returning this
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
87
                return getattr(query, "only")(items)
88
89
            def __getitem__(self, item: int) -> NestedDotDict:
90
                return NestedDotDict(query[item])
91
92
            def __len__(self) -> int:
93
                return len(query)
94
95
            def __iter__(self) -> Iterator[NestedDotDict]:
96
                return iter([NestedDotDict(x) for x in query])
97
98
        return F()
99
100
101
class ChemblEntrypoint:
102
    """
103
    Wraps just part of a node in the ChEMBL REST API.
104
    Ex ``Chembl.target``.
105
    """
106
107
    def filter(self, **kwargs) -> ChemblFilterQuery:
0 ignored issues
show
Missing function or method docstring
Loading history...
108
        raise NotImplementedError()
109
110
    def get(self, arg: str) -> Optional[NestedDotDict]:
0 ignored issues
show
Missing function or method docstring
Loading history...
111
        raise NotImplementedError()
112
113
    @classmethod
114
    def mock(
115
        cls,
0 ignored issues
show
Wrong hanging indentation before block (add 4 spaces).
Loading history...
116
        get_items: Mapping[str, dict],
0 ignored issues
show
Wrong hanging indentation before block (add 4 spaces).
Loading history...
117
        filter_items: Optional[Callable[[Mapping[str, Any]], Sequence[dict]]] = None,
0 ignored issues
show
Wrong hanging indentation before block (add 4 spaces).
Loading history...
118
    ) -> ChemblEntrypoint:
119
        """
120
121
        Args:
122
            get_items: Map from single arg for calling ``get`` to the item to return
123
            filter_items: Map from kwarg-set for calling ``filter`` to the list of items to return;
124
                          If None, returns ``items`` in all cases
125
126
        Returns:
127
128
        """
129
130
        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...
Missing class docstring
Loading history...
131
            def filter(self, **kwargs) -> ChemblFilterQuery:
132
                if filter_items is None:
133
                    return ChemblFilterQuery.mock(list(get_items.values()))
134
                items = filter_items(kwargs)
135
                return ChemblFilterQuery.mock(items)
136
137
            def get(self, arg: str) -> Optional[NestedDotDict]:
138
                return NestedDotDict(get_items[arg])
139
140
        return X()
141
142
    @classmethod
143
    def wrap(cls, obj) -> ChemblEntrypoint:
144
        """
145
146
        Args:
147
            obj:
148
149
        Returns:
150
151
        """
152
153
        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...
Missing class docstring
Loading history...
154
            def filter(self, **kwargs) -> ChemblFilterQuery:
155
                query = getattr(obj, "filter")(**kwargs)
156
                return ChemblFilterQuery.wrap(query)
157
158
            def get(self, arg: str) -> Optional[NestedDotDict]:
159
                return NestedDotDict(getattr(obj, "get")(arg))
160
161
        return X()
162
163
164
class ChemblApi(metaclass=abc.ABCMeta):
165
    """
166
    Wraps the whole ChEMBL API.
167
    """
168
169
    @property
170
    def activity(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
171
        return self.__dict__["activity"]
172
173
    @property
174
    def assay(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
175
        return self.__dict__["assay"]
176
177
    @property
178
    def atc_class(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
179
        return self.__dict__["atc_class"]
180
181
    @property
182
    def drug(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
183
        return self.__dict__["drug"]
184
185
    @property
186
    def drug_indication(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
187
        return self.__dict__["drug_indication"]
188
189
    @property
190
    def mechanism(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
191
        return self.__dict__["mechanism"]
192
193
    @property
194
    def molecule(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
195
        return self.__dict__["molecule"]
196
197
    @property
198
    def molecule_form(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
199
        return self.__dict__["molecule_form"]
200
201
    @property
202
    def organism(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
203
        return self.__dict__["mechanism"]
204
205
    @property
206
    def go_slim(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
207
        return self.__dict__["go_slim"]
208
209
    @property
210
    def target(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
211
        return self.__dict__["target"]
212
213
    @property
214
    def target_relation(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
215
        return self.__dict__["target_relation"]
216
217
    @property
218
    def protein_class(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
219
        return self.__dict__["protein_class"]
220
221
    @property
222
    def target_component(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
223
        return self.__dict__["target_component"]
224
225
    @property
226
    def target_prediction(self) -> ChemblEntrypoint:
0 ignored issues
show
Missing function or method docstring
Loading history...
227
        return self.__dict__["target_prediction"]
228
229
    def __getattribute__(self, item: str) -> ChemblEntrypoint:
230
        raise NotImplementedError()
231
232
    @classmethod
233
    def mock(cls, entrypoints: Mapping[str, ChemblEntrypoint]) -> ChemblApi:
234
        """
235
        Mocks.
236
237
        Args:
238
            entrypoints:
239
240
        Returns:
241
242
        """
243
244
        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...
Missing class docstring
Loading history...
245
            def __getattribute__(self, item: str) -> ChemblEntrypoint:
246
                return entrypoints[item]
247
248
        return X()
249
250
    @classmethod
251
    def wrap(cls, obj) -> ChemblApi:
252
        """
253
        Wraps.
254
255
        Args:
256
            obj:
257
258
        Returns:
259
260
        """
261
262
        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...
Missing class docstring
Loading history...
263
            def __getattribute__(self, item: str) -> ChemblEntrypoint:
264
                return ChemblEntrypoint.wrap(getattr(obj, item))
265
266
        return X()
267
268
269
__all__ = [
270
    "ChemblApi",
271
    "ChemblEntrypoint",
272
    "ChemblFilterQuery",
273
]
274