Passed
Push — dependabot/pip/pyarrow-4.0.1 ( ca09ce...b2836e )
by
unknown
02:18 queued 20s
created

mandos.model.apis._Source.cached_from_url()   F

Complexity

Conditions 14

Size

Total Lines 29
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 24
nop 5
dl 0
loc 29
rs 3.6
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like mandos.model.apis._Source.cached_from_url() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import abc
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
from pathlib import Path
3
from typing import Any, Callable, Mapping, Optional, Sequence
4
5
import defusedxml.ElementTree as Xml
0 ignored issues
show
introduced by
Unable to import 'defusedxml.ElementTree'
Loading history...
6
import orjson
0 ignored issues
show
introduced by
Unable to import 'orjson'
Loading history...
7
from pocketutils.core.dot_dict import NestedDotDict
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.dot_dict'
Loading history...
8
from pocketutils.core.query_utils import QueryExecutor
0 ignored issues
show
introduced by
Unable to import 'pocketutils.core.query_utils'
Loading history...
9
10
11
class _Source:
12
    def __init__(self, *getters: Callable[[], Optional[str]], name: str = "unknown"):
13
        self._getters = getters
14
        self._name = name
15
16
    def _get_txt(self) -> str:
17
        for getter in self._getters:
18
            txt = getter()
19
            if txt is not None:
20
                return txt
21
            raise ValueError(f"Nothing found for {self._name} {self.__class__.__name__} source")
22
23
    @classmethod
24
    def cached_from_url(
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
25
        cls,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
26
        path: Optional[Path],
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
27
        url: Optional[str],
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
28
        query: QueryExecutor,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
29
        query_args: Optional[Mapping[str, Any]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
30
    ):
31
        if path is not None and url is None and query is None:
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
32
            return cls.from_path(path)
33
        elif path is None and url is not None and query is not None:
34
            return cls.from_query(url, query, query_args)
35
        elif path is not None and url is not None and query is not None:
36
            path = Path(path)
37
            query_args = {} if query_args is None else query_args
38
39
            def load():
40
                return path.read_text(encoding="utf8") if path.exists() else None
41
42
            def save():
43
                data = query(url, encoding="utf8", **query_args)
44
                if data is not None:
45
                    if not path.exists():
46
                        path.write_text(data, encoding="utf8")
47
                return data
48
49
            # noinspection PyArgumentList
50
            return cls(load, save, name=f"Cache({path}, {url})")
51
        raise ValueError(f"Cannot create source from path {path}, url {url}, and query {query}")
52
53
    @classmethod
54
    def from_path(cls, path: Path):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
55
        path = Path(path)
56
57
        def one():
58
            return path.read_text(encoding="utf8") if path.exists() else None
59
60
        # noinspection PyArgumentList
61
        return cls(one, name=f"Cache({path})")
62
63
    @classmethod
64
    def from_query(
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
65
        cls, url: str, query: QueryExecutor, query_args: Optional[Mapping[str, Any]] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
66
    ):
67
        def two():
68
            return query(url, encoding="utf8", **query_args)
69
70
        # noinspection PyArgumentList
71
        return cls(two, name=f"Cache({url})")
72
73
74
class TextSource(_Source):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
75
    def get(self) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
76
        return self._get_txt()
77
78
79
class XmlSource(_Source):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
80
    """ """
81
82
    def get(self) -> Xml:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
83
        return Xml.fromstring(self._get_txt())
84
85
86
class JsonSource(_Source):
0 ignored issues
show
Documentation introduced by
Empty class docstring
Loading history...
87
    """ """
88
89
    def get(self) -> NestedDotDict:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
90
        return NestedDotDict(orjson.loads(self._get_txt()))
91
92
93
__all__ = ["TextSource", "XmlSource", "JsonSource"]
94