Passed
Push — main ( 65730f...fad324 )
by Douglas
06:54 queued 02:27
created

mandos.model.utils.sources   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 99
rs 10
c 0
b 0
f 0
wmc 24

8 Methods

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