Passed
Push — main ( fad324...4074a3 )
by Douglas
04:07 queued 02:06
created

mandos.model.apis.hmdb_api._is_float()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
import abc
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
import gzip
0 ignored issues
show
Unused Code introduced by
The import gzip seems to be unused.
Loading history...
3
from dataclasses import dataclass
4
from pathlib import Path
5
from typing import Optional, Sequence, Union
6
7
import decorateme
0 ignored issues
show
introduced by
Unable to import 'decorateme'
Loading history...
8
import orjson
0 ignored issues
show
introduced by
Unable to import 'orjson'
Loading history...
Unused Code introduced by
The import orjson seems to be unused.
Loading history...
9
from pocketutils.core.dot_dict import NestedDotDict
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.dot_dict'
Loading history...
10
from pocketutils.core.query_utils import QueryExecutor
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.query_utils'
Loading history...
11
from pocketutils.tools.common_tools import CommonTools
0 ignored issues
show
introduced by
Unable to import 'pocketutils.tools.common_tools'
Loading history...
12
13
from mandos.model import Api
14
from mandos.model.settings import QUERY_EXECUTORS, SETTINGS
15
16
17
@dataclass(frozen=True, repr=True, order=True)
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
18
class HmdbProperty:
19
    name: str
20
    source: str
21
    value: Union[None, str, int, float, bool]
22
    experimental: bool
23
24
25
@decorateme.auto_repr_str()
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
26
class HmdbApi(Api, metaclass=abc.ABCMeta):
27
    def fetch(self, hmdb_id: str) -> NestedDotDict:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
28
        raise NotImplementedError()
29
30
    def fetch_properties(self, hmdb_id: str) -> Sequence[HmdbProperty]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
31
        raise NotImplementedError()
32
33
    def fetch_tissues(self, hmdb_id: str) -> Sequence[HmdbProperty]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
34
        raise NotImplementedError()
35
36
37
class JsonBackedHmdbApi(HmdbApi, metaclass=abc.ABCMeta):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
38
    def fetch_properties(self, hmdb_id: str) -> Sequence[HmdbProperty]:
39
        data = self.fetch(hmdb_id)
40
        pred = data.sub("metabolite.predicted_properties.property")
41
        exp = data.sub("metabolite.experimental_properties.property")
42
        items = [self._prop(x, True) for x in exp]
43
        items += [self._prop(x, False) for x in pred]
44
        return items
45
46
    def fetch_tissues(self, hmdb_id: str) -> Sequence[str]:
47
        data = self.fetch(hmdb_id)
48
        tissues = data.get_list_as("metabolite.biological_properties.tissue_locations.tissue", str)
49
        return [] if tissues is None else tissues
50
51
    def _prop(self, x: NestedDotDict, experimental: bool):
0 ignored issues
show
Coding Style Naming introduced by
Argument name "x" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' 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...
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
52
        value = x.req_as("value", str)
53
        if value.isdigit():
54
            value = int(value)
55
        elif value.lower() == "true":
56
            value = True
57
        elif value.lower() == "false":
58
            value = False
59
        elif CommonTools.is_probable_null(value):
60
            value = None
61
        elif CommonTools.is_float(value):
62
            value = float(value)
63
        return HmdbProperty(
64
            name=x["kind"], value=value, source=x["source"], experimental=experimental
65
        )
66
67
68
class QueryingHmdbApi(JsonBackedHmdbApi):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
69
    def __init__(self, executor: QueryExecutor = QUERY_EXECUTORS.hmdb):
70
        self._executor = executor
71
72
    def fetch(self, hmdb_id: str) -> NestedDotDict:
73
        # e.g. https://hmdb.ca/metabolites/HMDB0001925.xml
74
        url = f"https://hmdb.ca/metabolites/{hmdb_id}.xml"
75
        data = self._executor(url)
76
        data = self._to_json(data)
77
        return NestedDotDict(data)
78
79
    def _to_json(self, xml):
80
        response = {}
81
        for child in list(xml):
82
            if len(list(child)) > 0:
83
                response[child.tag] = self._to_json(child)
84
            else:
85
                response[child.tag] = child.text or ""
86
        return response
87
88
89
class CachingHmdbApi(JsonBackedHmdbApi):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
90
    def __init__(
91
        self, query: Optional[QueryingHmdbApi], cache_dir: Path = SETTINGS.hmdb_cache_path
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
92
    ):
93
        self._query = query
94
        self._cache_dir = cache_dir
95
96
    def fetch(self, hmdb_id: str) -> NestedDotDict:
97
        path = self.path(hmdb_id)
0 ignored issues
show
Bug introduced by
The Instance of CachingHmdbApi does not seem to have a member named path.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
98
        if not path.exists():
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
99
            return NestedDotDict.read_json(path)
100
        else:
101
            data = self._query.fetch(hmdb_id)
102
            data.write_json(path, mkdirs=True)
103
            self._write_json(data, path)
0 ignored issues
show
Bug introduced by
The Instance of CachingHmdbApi does not seem to have a member named _write_json.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
104
            return data
105
106
107
__all__ = ["HmdbApi", "QueryingHmdbApi", "HmdbProperty"]
108