Skip to content

Commit a425c2a

Browse files
Merge pull request #17 from angrybayblade/test/coverage
Test coverage
2 parents a874474 + d8246a6 commit a425c2a

32 files changed

+851
-97
lines changed

.github/workflows/workflow.yml

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ jobs:
1111
runs-on: ${{ matrix.os }}
1212
strategy:
1313
matrix:
14-
os: [ ubuntu-latest ]
14+
os: [ubuntu-latest]
1515
python-version: ["3.10.9"]
1616
timeout-minutes: 5
1717
steps:
18-
- uses: actions/checkout@v2
19-
- uses: actions/setup-python@master
20-
with:
21-
python-version: ${{ matrix.python-version }}
22-
- if: matrix.os != 'windows-latest'
23-
name: Lock check
24-
run: |
25-
pip install poetry
26-
rm -rf poetry.lock
27-
time poetry lock
18+
- uses: actions/checkout@v2
19+
- uses: actions/setup-python@master
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
- if: matrix.os != 'windows-latest'
23+
name: Lock check
24+
run: |
25+
pip install poetry
26+
rm -rf poetry.lock
27+
time poetry lock
2828
2929
linter_checks:
3030
continue-on-error: False
@@ -35,31 +35,70 @@ jobs:
3535
python-version: ["3.10.9"]
3636
timeout-minutes: 30
3737
steps:
38-
- uses: actions/checkout@v2
39-
- uses: actions/setup-python@master
40-
with:
41-
python-version: ${{ matrix.python-version }}
42-
- name: Install dependencies
43-
run: |
44-
sudo apt-get update --fix-missing
45-
sudo apt-get autoremove
46-
sudo apt-get autoclean
47-
pip install --user --upgrade setuptools
48-
pip install tox==4.6.3
49-
# TODO
50-
# - name: Security checks
51-
# run: |
52-
# tox -e bandit
53-
# tox -e safety
54-
- name: Code style check
55-
run: |
56-
tox -e black-check
57-
tox -e isort-check
58-
tox -e flake8
59-
# TODO
60-
# tox -e vulture
61-
# tox -e darglint
62-
- name: Static type check
63-
run: tox -e mypy
64-
- name: Pylint
65-
run: tox -e pylint
38+
- uses: actions/checkout@v2
39+
- uses: actions/setup-python@master
40+
with:
41+
python-version: ${{ matrix.python-version }}
42+
- name: Install dependencies
43+
run: |
44+
sudo apt-get update --fix-missing
45+
sudo apt-get autoremove
46+
sudo apt-get autoclean
47+
pip install --user --upgrade setuptools
48+
pip install tox==4.6.3
49+
# TODO
50+
# - name: Security checks
51+
# run: |
52+
# tox -e bandit
53+
# tox -e safety
54+
- name: Code style check
55+
run: |
56+
tox -e black-check
57+
tox -e isort-check
58+
tox -e flake8
59+
# TODO
60+
# tox -e vulture
61+
# tox -e darglint
62+
- name: Static type check
63+
run: tox -e mypy
64+
- name: Pylint
65+
run: tox -e pylint
66+
67+
test:
68+
continue-on-error: True
69+
needs:
70+
- lock_check
71+
- linter_checks
72+
runs-on: ${{ matrix.os }}
73+
strategy:
74+
matrix:
75+
os: [ubuntu-latest]
76+
python-version: ["3.8", "3.9", "3.10.9", "3.11"]
77+
timeout-minutes: 15
78+
steps:
79+
- uses: actions/checkout@v2
80+
with:
81+
submodules: recursive
82+
fetch-depth: 0
83+
- uses: actions/setup-python@master
84+
with:
85+
python-version: ${{ matrix.python-version }}
86+
- name: Install Dependencies
87+
run: |
88+
sudo apt-get update --fix-missing
89+
sudo apt-get autoremove
90+
sudo apt-get autoclean
91+
pip install --user --upgrade setuptools
92+
pip install tox==4.6.3
93+
- name: Unittests
94+
run: |
95+
tox -e unittests
96+
- if: matrix.python-version == '3.10.9'
97+
name: Upload coverage to Codecov
98+
uses: codecov/codecov-action@v3
99+
with:
100+
token: ${{ secrets.CODECOV_TOKEN }}
101+
file: ./coverage.xml
102+
flags: unittests
103+
name: codecov-umbrella
104+
fail_ci_if_error: false

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ temp/
22
build/
33
dist/
44
site/
5+
htmlcov/
6+
7+
.coverage
8+
coverage.xml
59

610
.tox/
711
.mypy_cache/

clea/__init__.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
11
"""
2-
A lightweight clea for writing CLI tools in python.
2+
A lightweight framework for writing CLI tools in python.
33
"""
4+
5+
from .context import Context # noqa: F401
6+
from .params import ( # noqa: F401
7+
Boolean,
8+
Choice,
9+
ChoiceByFlag,
10+
ContextParameter,
11+
Directory,
12+
File,
13+
Float,
14+
Integer,
15+
String,
16+
StringList,
17+
VersionParameter,
18+
)
19+
from .runner import run # noqa: F401
20+
from .wrappers import command, group # noqa: F401

clea/params.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ def short_flag(self) -> t.Optional[str]:
4747
return self._short_flag
4848

4949
@property
50-
def long_flag(self) -> str:
50+
def long_flag(self) -> t.Optional[str]:
5151
"""FLag"""
52-
if self._long_flag is not None:
53-
return self._long_flag
54-
return "--" + t.cast(str, self.name).replace("_", "-")
52+
return self._long_flag
53+
54+
def create_long_flag(self) -> str:
55+
"""Set the value of long flag."""
56+
self._long_flag = "--" + t.cast(str, self.name).replace("_", "-")
57+
return self._long_flag
5558

5659
@property
5760
def default(self) -> t.Optional[ParameterType]:
@@ -106,7 +109,7 @@ def help(self) -> str:
106109
"""Help string."""
107110
if self.short_flag is not None:
108111
help_string = f"{self.short_flag}, "
109-
else:
112+
else: # pragma: nocover
110113
help_string = ""
111114
help_string += f"{self.long_flag}"
112115
if self._help is not None:
@@ -183,7 +186,7 @@ def help(self) -> str:
183186
if self.short_flag is not None:
184187
help_string = f"{self.short_flag}, "
185188
else:
186-
help_string = ""
189+
help_string = "" # pragma: nocover
187190
help_string += f"{self.long_flag}"
188191
if self._help is not None:
189192
help_string += " " * (HELP_COL_LENGTH - len(help_string))
@@ -228,7 +231,7 @@ def help(self) -> str:
228231
if self.short_flag is not None:
229232
help_string = f"{self.short_flag}, "
230233
else:
231-
help_string = ""
234+
help_string = "" # pragma: nocover
232235
help_string += f"{self.long_flag}"
233236
choices = "|".join(list(map(lambda x: x.value, self.enum)))
234237
help_string += f" [{choices}]"
@@ -237,7 +240,7 @@ def help(self) -> str:
237240
if str_len < HELP_COL_LENGTH:
238241
help_string += " " * (HELP_COL_LENGTH - str_len)
239242
help_string += self._help
240-
else:
243+
else: # pragma: nocover # TODO
241244
help_string += "\n"
242245
help_string += " " * HELP_COL_LENGTH
243246
help_string += f" {self._help}"
@@ -287,7 +290,7 @@ def help(self) -> str:
287290
if str_len < HELP_COL_LENGTH:
288291
help_string += " " * (HELP_COL_LENGTH - str_len)
289292
help_string += self._help
290-
else:
293+
else: # pragma: nocover # TODO
291294
help_string += "\n"
292295
help_string += " " * HELP_COL_LENGTH
293296
help_string += f" {self._help}"

clea/parser.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
class BaseParser:
2121
"""Argument parser."""
2222

23-
_args: deque[Parameter]
23+
_args: t.Deque[Parameter]
2424
_kwargs: t.Dict[str, Parameter]
2525

2626
def __init__(self) -> None:
@@ -49,21 +49,28 @@ def add(self, defintion: Parameter) -> None:
4949
self._kwargs[long_flag] = defintion
5050
return
5151

52-
if defintion.default is not None:
52+
if (
53+
defintion.default is None
54+
and defintion.short_flag is None
55+
and defintion.long_flag is None
56+
):
57+
self._args.append(defintion)
58+
return
59+
60+
if defintion.default is not None and defintion.long_flag is None:
61+
self._kwargs[defintion.create_long_flag()] = defintion
62+
63+
if defintion.long_flag is not None:
5364
self._kwargs[defintion.long_flag] = defintion
5465

5566
if defintion.short_flag is not None:
5667
self._kwargs[defintion.short_flag] = defintion
57-
return
58-
59-
if defintion.default is None:
60-
self._args.append(defintion)
6168

6269
def parse( # pylint: disable=unused-argument
6370
self, argv: Argv, commands: t.Optional[t.Dict[str, t.Any]] = None
6471
) -> t.Tuple:
6572
"""Parse and return kwargs."""
66-
return NotImplemented
73+
return NotImplemented # pragma: nocover
6774

6875

6976
class CommandParser(BaseParser):
@@ -93,6 +100,9 @@ def parse( # pylint: disable=too-many-branches
93100
kwargs[definition.name] = definition.parse(value=value)
94101
if definition.is_container:
95102
self._kwargs[flag] = definition
103+
else:
104+
self._kwargs.pop(definition.short_flag or "", None)
105+
self._kwargs.pop(definition.long_flag or "", None)
96106
else:
97107
if len(self._args) == 0:
98108
raise ExtraArgumentProvided(f"Extra argument provided `{arg}`")
@@ -105,7 +115,7 @@ def parse( # pylint: disable=too-many-branches
105115
if len(self._kwargs) > 0:
106116
for kwarg in self._kwargs.values():
107117
if kwarg.name == "version":
108-
continue
118+
continue # pragma: nocover
109119
if kwarg.is_container:
110120
kwargs[kwarg.name] = kwarg.container
111121
else:
@@ -155,6 +165,9 @@ def parse( # pylint: disable=too-many-branches
155165
kwargs[definition.name] = definition.parse(value=value)
156166
if definition.is_container:
157167
self._kwargs[flag] = definition
168+
else:
169+
self._kwargs.pop(definition.short_flag or "", None)
170+
self._kwargs.pop(definition.long_flag or "", None)
158171
else:
159172
if len(self._args) == 0:
160173
raise ExtraArgumentProvided(f"Extra argument provided `{arg}`")
@@ -167,7 +180,7 @@ def parse( # pylint: disable=too-many-branches
167180
if len(self._kwargs) > 0:
168181
for kwarg in self._kwargs.values():
169182
if kwarg.name == "version":
170-
continue
183+
continue # pragma: nocover
171184
if kwarg.is_container:
172185
kwargs[kwarg.name] = kwarg.container
173186
else:

clea/runner.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def run(
6363
argv = argv if argv is not None else sys.argv[1:].copy()
6464
result = _run_isolated(cli=cli, argv=argv) if isolated else _run(cli=cli, argv=argv)
6565
if not isolated:
66-
sys.stderr.write(result.stderr)
66+
if result.stderr != "": # pragma: nocover
67+
sys.stderr.write(result.stderr + "\n")
6768
sys.exit(result.exit_code)
6869
return result

clea/wrappers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def help(self) -> int:
9595
self._parser._kwargs.values() # pylint: disable=protected-access
9696
):
9797
if parameter.name == "context":
98-
continue
98+
continue # pragma: nocover
9999
print(f" {parameter.help()}")
100100
print(" --help Show help and exit.")
101101
return 0
@@ -113,7 +113,7 @@ def invoke( # pylint: disable=unused-argument
113113
self, argv: Argv, isolated: bool = False
114114
) -> int:
115115
"""Run the command."""
116-
return NotImplemented
116+
return NotImplemented # pragma: nocover
117117

118118

119119
class Command(BaseWrapper):
@@ -448,7 +448,7 @@ def help(self) -> int:
448448
self._parser._kwargs.values() # pylint: disable=protected-access
449449
):
450450
if parameter.name == "context":
451-
continue
451+
continue # pragma: nocover
452452
print(f" {parameter.help()}")
453453
print(" --help Show help and exit.")
454454
print("\nCommands:\n")

docs/command.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,9 @@ Usage: add-numbers [OPTIONS] N1 N2
7777
Options:
7878

7979
--help Show help and exit.
80-
```
80+
```
81+
82+
## Next steps
83+
84+
- [Group](/clea/group)
85+
- [Parameters](/clea/parameters)

docs/context.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,7 @@ def home(context: Context) -> None:
6262
if __name__ == "__main__":
6363
run(cli=home)
6464
```
65+
66+
## Next steps
67+
68+
- [Testing](/clea/testing)

docs/group.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,10 @@ Options:
9191
Commands:
9292

9393
add Add two numbers.
94-
```
94+
```
95+
96+
## Next steps
97+
98+
- [Parameters](/clea/parameters)
99+
- [Context](/clea/context)
100+
- [Testing](/clea/testing)

docs/parameters.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,9 @@ As before the input will be parsed as enum value
294294
$ python command.py --tcp
295295
296296
ctype=<ConnectionType.TCP: 'tcp'>
297-
```
297+
```
298+
299+
## Next steps
300+
301+
- [Context](/clea/context)
302+
- [Testing](/clea/testing)

0 commit comments

Comments
 (0)