Passed
Push — main ( cee75c...37036d )
by Douglas
02:08
created

mandos.entry._arg_utils   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 159
dl 0
loc 210
rs 9.52
c 0
b 0
f 0
wmc 36

24 Methods

Rating   Name   Duplication   Size   Complexity  
A Opt.out_file() 0 4 1
A Opt.out_path() 0 12 1
A _Args._arg() 0 11 2
A Arg.val() 0 3 1
A Opt.in_path() 0 12 1
A Arg.out_path() 0 4 1
A Arg.in_path() 0 4 1
A ArgUtils.parse_taxon_id_or_name() 0 7 4
B ArgUtils.list() 0 18 6
A Opt.in_file() 0 4 1
A _Args._path() 0 18 3
A Opt.out_dir() 0 4 1
A Arg.out_dir() 0 4 1
A Opt.in_dir() 0 4 1
A Opt.val() 0 3 1
A ArgUtils.parse_taxon_id() 0 6 2
A Opt.flag() 0 3 1
A ArgUtils.definition_bullets() 0 5 1
A Arg.out_file() 0 4 1
A ArgUtils.parse_taxa() 0 4 1
A ArgUtils.definition_list() 0 4 1
A Arg.in_dir() 0 4 1
A ArgUtils.df_description() 0 7 1
A Arg.in_file() 0 4 1
1
import enum
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
import os
3
from inspect import cleandoc
4
from typing import Optional, Iterable, Any, Mapping, Union, Callable, Sequence, Type
5
6
import typer
0 ignored issues
show
introduced by
Unable to import 'typer'
Loading history...
7
from typeddfs import TypedDf
0 ignored issues
show
introduced by
Unable to import 'typeddfs'
Loading history...
8
9
from mandos.entry._common_args import T
10
11
12
class _Args:
13
    @staticmethod
14
    def _arg(doc: str, *names, default: Optional[T] = None, req: bool = False, **kwargs):
15
        kwargs = dict(
16
            help=cleandoc(doc),
17
            **kwargs,
18
            allow_dash=True,
19
        )
20
        if req:
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
21
            return typer.Argument(default, **kwargs)
22
        else:
23
            return typer.Option(default, *names, **kwargs)
24
25
    @staticmethod
26
    def _path(
27
        doc: str, *names, default: Optional[str], f: bool, d: bool, out: bool, req: bool, **kwargs
0 ignored issues
show
Coding Style Naming introduced by
Variable name "d" 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 Naming introduced by
Variable name "f" 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
Wrong hanging indentation before block (add 4 spaces).
Loading history...
28
    ):
29
        # if it's None, we're going to have a special default set afterward, so we'll explain it in the doc
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (107/100).

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

Loading history...
30
        if out and default is None:
31
            kwargs = dict(show_default=False, **kwargs)
32
        kwargs = {
33
            **dict(
34
                exists=not out,
35
                dir_okay=d,
36
                file_okay=f,
37
                readable=out,
38
                writable=not out,
39
            ),
40
            **kwargs,
41
        }
42
        return _Args._arg(doc, *names, default=default, req=req, **kwargs)
43
44
45
class Arg(_Args):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
46
    @staticmethod
47
    def out_file(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
48
        return _Args._path(
49
            doc, *names, default=default, f=True, d=False, out=True, req=True, **kwargs
50
        )
51
52
    @staticmethod
53
    def out_dir(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
54
        return _Args._path(
55
            doc, *names, default=default, f=True, d=True, out=True, req=True, **kwargs
56
        )
57
58
    @staticmethod
59
    def out_path(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
60
        return _Args._path(
61
            doc, *names, default=default, f=True, d=True, out=False, req=True, **kwargs
62
        )
63
64
    @staticmethod
65
    def in_file(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
66
        return _Args._path(
67
            doc, *names, default=default, f=True, d=False, out=False, req=True, **kwargs
68
        )
69
70
    @staticmethod
71
    def in_dir(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
72
        return _Args._path(
73
            doc, *names, default=default, f=False, d=True, out=False, req=True, **kwargs
74
        )
75
76
    @staticmethod
77
    def in_path(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
78
        return _Args._path(
79
            doc, *names, default=default, f=True, d=True, out=False, req=True, **kwargs
80
        )
81
82
    @staticmethod
83
    def val(doc: str, *names, default: Optional[T] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
84
        return _Args._arg(doc, *names, default=default, req=True, **kwargs)
85
86
87
class Opt(_Args):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
88
    @staticmethod
89
    def out_file(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
90
        return _Args._path(
91
            doc, *names, default=default, f=True, d=False, out=True, req=False, **kwargs
92
        )
93
94
    @staticmethod
95
    def out_dir(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
96
        return _Args._path(
97
            doc, *names, default=default, f=True, d=True, out=True, req=False, **kwargs
98
        )
99
100
    @staticmethod
101
    def out_path(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
102
        return _Args._path(
103
            doc,
104
            *names,
105
            default=default,
106
            f=True,
107
            d=True,
108
            out=False,
109
            req=False,
110
            exists=False,
111
            **kwargs,
112
        )
113
114
    @staticmethod
115
    def in_file(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
116
        return _Args._path(
117
            doc, *names, default=default, f=True, d=False, out=False, req=False, **kwargs
118
        )
119
120
    @staticmethod
121
    def in_dir(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
122
        return _Args._path(
123
            doc, *names, default=default, f=False, d=True, out=False, req=False, **kwargs
124
        )
125
126
    @staticmethod
127
    def in_path(doc: str, *names, default: Optional[str] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
128
        return _Args._path(
129
            doc,
130
            *names,
131
            default=default,
132
            f=True,
133
            d=True,
134
            out=False,
135
            req=False,
136
            exists=False,
137
            **kwargs,
138
        )
139
140
    @staticmethod
141
    def val(doc: str, *names, default: Optional[T] = None, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
142
        return _Args._arg(doc, *names, default=default, req=False, **kwargs)
143
144
    @staticmethod
145
    def flag(doc: str, *names, **kwargs):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
146
        return _Args._arg(doc, *names, default=False, req=False, **kwargs)
147
148
149
class ArgUtils:
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
150
    @classmethod
151
    def definition_bullets(cls, dct: Mapping[Any, Any], colon: str = ": ", indent: int = 12) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
152
        joiner = os.linesep * 2 + " " * indent
153
        jesus = [f" - {k}{colon}{v}" for k, v in dct.items()]
154
        return joiner.join(jesus)
155
156
    @classmethod
157
    def definition_list(cls, dct: Mapping[Any, Any], colon: str = ": ", sep: str = "; ") -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
158
        jesus = [f"{k}{colon}{v}" for k, v in dct.items()]
159
        return sep.join(jesus)
160
161
    @classmethod
162
    def df_description(cls, tdf: Type[TypedDf]) -> str:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
163
        req = tdf.get_typing().required_columns
164
        res = [*tdf.get_typing().reserved_index_names, *tdf.get_typing().reserved_columns]
165
        line1 = "Required columns: " + ", ".join(req)
166
        line2 = "Optional columns: " + ", ".join(res)
167
        return line1 + "\n\n" + line2
168
169
    @classmethod
170
    def list(
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
171
        cls,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
172
        lst: Iterable[Any],
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
173
        attr: Union[None, str, Callable[[Any], Any]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
174
        sep: str = "; ",
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
175
    ) -> str:
176
        x = []
0 ignored issues
show
Coding Style Naming introduced by
Variable 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...
177
        for v in lst:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "v" 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...
178
            if attr is None and isinstance(v, enum.Enum):
179
                x += [v.name]
0 ignored issues
show
Coding Style Naming introduced by
Variable 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...
180
            elif attr is None:
181
                x += [str(v)]
0 ignored issues
show
Coding Style Naming introduced by
Variable 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...
182
            elif isinstance(attr, str):
183
                x += [str(getattr(v, attr))]
0 ignored issues
show
Coding Style Naming introduced by
Variable 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...
184
            else:
185
                x += [str(attr(v))]
0 ignored issues
show
Coding Style Naming introduced by
Variable 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...
186
        return sep.join(x)
187
188
    @classmethod
189
    def parse_taxon_id_or_name(cls, taxon: Union[int, str]) -> Union[int, str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
190
        if isinstance(taxon, str):
0 ignored issues
show
unused-code introduced by
Unnecessary "elif" after "return"
Loading history...
191
            return taxon
192
        elif isinstance(taxon, str) and taxon.isdigit():
193
            return int(taxon)
194
        raise ValueError(f"Taxon {taxon} must be an ID or name")
195
196
    @classmethod
197
    def parse_taxon_id(cls, taxon: Union[int, str]) -> int:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
198
        try:
199
            return int(taxon)
200
        except ValueError:
201
            raise ValueError(f"Taxon {taxon} must be an exact ID") from None
202
203
    @classmethod
204
    def parse_taxa(cls, taxa: str) -> Sequence[Union[int, str]]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
205
        taxa = [t.strip() for t in taxa.split(",")]
206
        return [ArgUtils.parse_taxon_id_or_name(t) for t in taxa]
207
208
209
__all__ = ["Arg", "Opt", "ArgUtils"]
210