Skip to content

Commit 6258670

Browse files
authored
Refactor CLI. (#33)
1 parent 741a42d commit 6258670

File tree

11 files changed

+77
-97
lines changed

11 files changed

+77
-97
lines changed

docs/changes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ all releases are available on `Anaconda.org <https://anaconda.org/pytask/pytask>
1111

1212
- :gh:`31` adds ``pytask collect`` to show information on collected tasks.
1313
- :gh:`32` fixes ``pytask clean``.
14+
- :gh:`33` adds a module to apply common parameters to the command line interface.
1415

1516

1617
0.0.8 - 2020-10-04

src/_pytask/build.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from _pytask.exceptions import ResolvingDependenciesError
1313
from _pytask.pluginmanager import get_plugin_manager
1414
from _pytask.session import Session
15-
from _pytask.shared import falsy_to_none_callback
1615

1716

1817
@hookimpl(tryfirst=True)
@@ -85,28 +84,12 @@ def main(config_from_cli):
8584

8685

8786
@click.command()
88-
@click.argument(
89-
"paths", nargs=-1, type=click.Path(exists=True), callback=falsy_to_none_callback
90-
)
91-
@click.option(
92-
"--ignore",
93-
type=str,
94-
multiple=True,
95-
help=(
96-
"A pattern to ignore files or directories. For example, ``task_example.py`` or "
97-
"``src/*``."
98-
),
99-
callback=falsy_to_none_callback,
100-
)
10187
@click.option(
10288
"--debug-pytask",
10389
is_flag=True,
10490
default=None,
10591
help="Trace all function calls in the plugin framework. [default: False]",
10692
)
107-
@click.option(
108-
"-c", "--config", type=click.Path(exists=True), help="Path to configuration file."
109-
)
11093
def build(**config_from_cli):
11194
"""Collect and execute tasks and report the results.
11295

src/_pytask/clean.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from _pytask.exceptions import CollectionError
1515
from _pytask.pluginmanager import get_plugin_manager
1616
from _pytask.session import Session
17-
from _pytask.shared import falsy_to_none_callback
1817
from _pytask.shared import get_first_non_none_value
1918

2019

@@ -55,9 +54,6 @@ def pytask_post_parse(config):
5554

5655

5756
@click.command()
58-
@click.argument(
59-
"paths", nargs=-1, type=click.Path(exists=True), callback=falsy_to_none_callback
60-
)
6157
@click.option(
6258
"-m",
6359
"--mode",
@@ -68,19 +64,6 @@ def pytask_post_parse(config):
6864
@click.option(
6965
"-q", "--quiet", is_flag=True, help="Do not print the names of the removed paths."
7066
)
71-
@click.option(
72-
"--ignore",
73-
type=str,
74-
multiple=True,
75-
help=(
76-
"A pattern to ignore files or directories. For example, ``task_example.py`` or "
77-
"``src/*``."
78-
),
79-
callback=falsy_to_none_callback,
80-
)
81-
@click.option(
82-
"-c", "--config", type=click.Path(exists=True), help="Path to configuration file."
83-
)
8467
def clean(**config_from_cli):
8568
"""Clean provided paths by removing files unknown to pytask."""
8669
config_from_cli["command"] = "clean"

src/_pytask/cli.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
1111

1212

13-
def _extend_command_line_interface(cli):
13+
def _extend_command_line_interface(command_line_interface):
1414
"""Add parameters from plugins to the commandline interface."""
1515
pm = _prepare_plugin_manager()
16-
pm.hook.pytask_extend_command_line_interface(cli=cli)
17-
_sort_options_for_each_command_alphabetically(cli)
18-
return cli
16+
pm.hook.pytask_extend_command_line_interface(cli=command_line_interface)
17+
_sort_options_for_each_command_alphabetically(command_line_interface)
18+
return command_line_interface
1919

2020

2121
def _prepare_plugin_manager():
@@ -46,6 +46,7 @@ def pytask_add_hooks(pm):
4646
from _pytask import execute
4747
from _pytask import logging
4848
from _pytask import mark
49+
from _pytask import parameters
4950
from _pytask import parametrize
5051
from _pytask import persist
5152
from _pytask import resolve_dependencies
@@ -61,6 +62,7 @@ def pytask_add_hooks(pm):
6162
pm.register(execute)
6263
pm.register(logging)
6364
pm.register(mark)
65+
pm.register(parameters)
6466
pm.register(parametrize)
6567
pm.register(persist)
6668
pm.register(resolve_dependencies)

src/_pytask/collect_command.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from _pytask.exceptions import CollectionError
99
from _pytask.pluginmanager import get_plugin_manager
1010
from _pytask.session import Session
11-
from _pytask.shared import falsy_to_none_callback
1211

1312

1413
@hookimpl(tryfirst=True)
@@ -23,23 +22,7 @@ def pytask_parse_config(config, config_from_cli):
2322

2423

2524
@click.command()
26-
@click.argument(
27-
"paths", nargs=-1, type=click.Path(exists=True), callback=falsy_to_none_callback
28-
)
2925
@click.option("--nodes", is_flag=True, help="Show a task's dependencies and products.")
30-
@click.option(
31-
"--ignore",
32-
type=str,
33-
multiple=True,
34-
help=(
35-
"A pattern to ignore files or directories. For example, ``task_example.py`` or "
36-
"``src/*``."
37-
),
38-
callback=falsy_to_none_callback,
39-
)
40-
@click.option(
41-
"-c", "--config", type=click.Path(exists=True), help="Path to configuration file."
42-
)
4326
def collect(**config_from_cli):
4427
"""Collect tasks from paths."""
4528
config_from_cli["command"] = "collect"

src/_pytask/mark/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@
3737

3838

3939
@click.command()
40-
@click.option(
41-
"-c", "--config", type=click.Path(exists=True), help="Path to configuration file."
42-
)
4340
def markers(**config_from_cli):
4441
"""Show all registered markers."""
4542
config_from_cli["command"] = "markers"

src/_pytask/mark/expression.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,11 @@ def __init__(self, code: types.CodeType) -> None:
202202
def compile_(cls, input_: str) -> "Expression":
203203
"""Compile a match expression.
204204
205-
:param input: The input expression - one line.
205+
Parameters
206+
----------
207+
input_: str
208+
The input expression - one line.
209+
206210
"""
207211
astexpr = expression(Scanner(input_))
208212
code = compile(

src/_pytask/parameters.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Contains common parameters for the commands of the command line interface."""
2+
import click
3+
from _pytask.config import hookimpl
4+
from _pytask.shared import falsy_to_none_callback
5+
6+
7+
_CONFIG_OPTION = click.Option(
8+
["-c", "--config"], type=click.Path(exists=True), help="Path to configuration file."
9+
)
10+
11+
_IGNORE_OPTION = click.Option(
12+
["--ignore"],
13+
type=str,
14+
multiple=True,
15+
help=(
16+
"A pattern to ignore files or directories. For example, ``task_example.py`` or "
17+
"``src/*``."
18+
),
19+
callback=falsy_to_none_callback,
20+
)
21+
22+
_PATH_ARGUMENT = click.Argument(
23+
["paths"], nargs=-1, type=click.Path(exists=True), callback=falsy_to_none_callback
24+
)
25+
26+
27+
@hookimpl(trylast=True)
28+
def pytask_extend_command_line_interface(cli):
29+
for command in ["build", "clean", "collect", "markers"]:
30+
cli.commands[command].params.append(_CONFIG_OPTION)
31+
for command in ["build", "clean", "collect"]:
32+
cli.commands[command].params.append(_IGNORE_OPTION)
33+
for command in ["build", "clean", "collect"]:
34+
cli.commands[command].params.append(_PATH_ARGUMENT)

src/_pytask/parametrize.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ def pytask_parametrize_task(session, name, obj):
7575
:func:`zip`, multiple ``@pytask.mark.parametrize`` decorators form a Cartesian
7676
product.
7777
78+
We cannot raise an error if the function does not use parametrized arguments since
79+
some plugins will replace functions with their own implementation like pytask-r.
80+
7881
"""
7982
if callable(obj):
8083
obj, markers = _remove_parametrize_markers_from_func(obj)
@@ -125,11 +128,11 @@ def pytask_parametrize_task(session, name, obj):
125128

126129
def _remove_parametrize_markers_from_func(obj):
127130
"""Remove parametrize markers from the object."""
128-
parametrize = [i for i in obj.pytaskmark if i.name == "parametrize"]
131+
parametrize_markers = [i for i in obj.pytaskmark if i.name == "parametrize"]
129132
others = [i for i in obj.pytaskmark if i.name != "parametrize"]
130133
obj.pytaskmark = others
131134

132-
return obj, parametrize
135+
return obj, parametrize_markers
133136

134137

135138
def _parse_parametrize_marker(marker):
@@ -336,9 +339,9 @@ def _copy_func(func: Callable[[Any], Any]) -> Callable[[Any], Any]:
336339
337340
Example
338341
-------
339-
>>> def func(): pass
340-
>>> copied_func = _copy_func(func)
341-
>>> func == copied_func
342+
>>> def _func(): pass
343+
>>> copied_func = _copy_func(_func)
344+
>>> _func == copied_func
342345
False
343346
344347
"""

src/_pytask/traceback.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def _filter_internal_traceback_frames(frame):
4646
"""
4747
for frame in _yield_traceback_frames(frame):
4848
if frame is None or not _is_internal_traceback_frame(frame):
49-
return frame
49+
break
50+
return frame
5051

5152

5253
def _yield_traceback_frames(frame):

0 commit comments

Comments
 (0)