Passed
Push — dependabot/pip/flake8-bugbear-... ( 16d864...b4f9fc )
by
unknown
01:45
created

CtdGeneSearch._if_match()   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nop 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
import re
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
from dataclasses import dataclass
3
from typing import Sequence, Optional
4
5
from mandos.search.pubchem import PubchemHit, PubchemSearch
6
7
8
@dataclass(frozen=True, order=True, repr=True)
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
9
class CtdGeneHit(PubchemHit):
10
    """"""
11
12
    taxon_id: Optional[int]
13
    taxon_name: Optional[str]
14
15
16
class CtdGeneSearch(PubchemSearch[CtdGeneHit]):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
17
    """"""
18
19
    @property
20
    def data_source(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
21
        return "Comparative Toxicogenomics Database (CTD)"
22
23
    def find(self, inchikey: str) -> Sequence[CtdGeneHit]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
24
        data = self.api.fetch_data(inchikey)
25
        results = []
26
        for dd in data.biomolecular_interactions_and_pathways.chemical_gene_interactions:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "dd" 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...
27
            for interaction in dd.interactions:
28
                for predicate in self._predicate(data.name, dd.gene_name, interaction):
29
                    results.append(
30
                        CtdGeneHit(
31
                            record_id=None,
32
                            origin_inchikey=inchikey,
33
                            matched_inchikey=data.names_and_identifiers.inchikey,
34
                            compound_id=str(data.cid),
35
                            compound_name=data.name,
36
                            predicate=predicate,
37
                            object_id=dd.gene_name,
38
                            object_name=dd.gene_name,
39
                            search_key=self.key,
40
                            search_class=self.search_class,
41
                            data_source=self.data_source,
42
                            taxon_id=dd.tax_id,
43
                            taxon_name=dd.tax_name,
44
                        )
45
                    )
46
        return results
47
48
    def _predicate(self, compound: str, gene: str, interaction: str) -> Sequence[str]:
49
        # TODO: Sometimes synonyms of the compound are used (e.g. "Crack Cocaine")
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
50
        if (
51
            "co-treated" in interaction
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
52
            or "co-treatment" in interaction
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
53
            or "mutant" in interaction
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
54
            or "modified form" in interaction
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
55
            or "alternative form" in interaction
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
56
        ):
57
            return []
58
        expression = {
59
            "results in increased ((?:expression)|(?:activity)|(?:phosphorylation))": "increases $1 of",
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

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

Loading history...
60
            "results in decreased ((?:expression)|(?:activity)|(?:phosphorylation))": "decreases $1 of",
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

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

Loading history...
61
            "affects the ((?:expression)|(?:activity)|(?:phosphorylation))": "affects $1 of",
62
            "affects the localization": "affects localization",
63
        }
64
        results = []
65
        for txt, effect in expression.items():
66
            result = self._if_match(
67
                interaction,
68
                re.escape(compound)
69
                + " "
70
                + txt
71
                + " "
72
                + gene
73
                + "(?: (?:mRNA)|(?:protein)|(?:exon))?",
74
                effect,
75
            )
76
            if result is not None:
77
                results.append(result)
78
            else:
79
                # catches "affects the activity of and affects the expression of"
80
                # TODO: could this catch something weird:
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
81
                if result is None:
82
                    result = self._if_match(
83
                        interaction, re.escape(compound) + " " + txt + " of and .+", effect
84
                    )
85
                if result is not None:
86
                    results.append(result)
87
        if len(results) > 0:
88
            return results
89
        result = self._if_match(
90
            interaction,
91
            compound + " ((?:affects)|(?:promotes)|(?:inhibits)) the reaction",
92
            "affects a reaction involving",
93
        )
94
        return [] if result is None else [result]
95
96
    def _if_match(self, interaction: str, pattern: str, result: str) -> Optional[str]:
0 ignored issues
show
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...
97
        pat = re.compile("^" + pattern + "$", flags=re.IGNORECASE)
98
        match = pat.fullmatch(interaction)
99
        if match is None:
100
            return None
101
        for i, group in enumerate(match.groupdict()):
102
            result = result.replace("$" + str(i + 1), group)
103
        return result
104
105
106
__all__ = ["CtdGeneHit", "CtdGeneSearch"]
107