Skip to content

Commit 4cb04b8

Browse files
authored
Improve the documentation. (#509)
1 parent 6f51e61 commit 4cb04b8

25 files changed

+412
-255
lines changed

docs/source/explanations/index.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ systems in general as well as its design.
88
maxdepth: 1
99
---
1010
why_pytask
11-
interfaces_for_dependencies_products
1211
comparison_to_other_tools
1312
pluggy
1413
```

docs/source/explanations/interfaces_for_dependencies_products.md

Lines changed: 0 additions & 30 deletions
This file was deleted.

docs/source/how_to_guides/functional_interface.ipynb

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/source/how_to_guides/how_to_write_a_plugin.md

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,40 @@ This section explains some steps which are required for all plugins.
3232

3333
pytask discovers plugins via `setuptools` entry-points. Following the approach advocated
3434
for by [setuptools_scm](https://github.com/pypa/setuptools_scm), the entry-point is
35-
specified in `setup.cfg`.
35+
specified in `pyproject.toml`.
3636

37-
```cfg
38-
# Content of setup.cfg
37+
```toml
38+
[project]
39+
name = "pytask-plugin"
3940

40-
[metadata]
41-
name = pytask-plugin
41+
[tool.setuptools.package-dir]
42+
"" = "src"
4243

43-
[options.packages.find]
44-
where = src
44+
[tool.setuptools.packages.find]
45+
where = ["src"]
46+
namespaces = false
4547

46-
[options.entry_points]
47-
pytask =
48-
pytask_plugin = pytask_plugin.plugin
48+
[project.entry-points.pytask]
49+
pytask_plugin = "pytask_plugin.plugin"
4950
```
5051

51-
For `setuptools_scm` you also need a `pyproject.toml` with the following content.
52+
For `setuptools_scm` you also need the following additions in `pyproject.toml`.
5253

5354
```toml
54-
# Content of pyproject.toml
55-
5655
[build-system]
5756
requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.0"]
5857

5958
[tool.setuptools_scm]
6059
write_to = "src/pytask_plugin/_version.py"
6160
```
6261

63-
For a complete example with `setuptools_scm` and `setup.cfg` see the
64-
[pytask-parallel repo](https://github.com/pytask-dev/pytask-parallel/blob/main/setup.cfg).
62+
For a complete example with `setuptools_scm` and `pyproject.toml` see the
63+
[pytask-parallel repo](https://github.com/pytask-dev/pytask-parallel/blob/main/pyproject.toml).
6564

6665
The entry-point for pytask is called `"pytask"` and points to a module called
6766
`pytask_plugin.plugin`.
6867

69-
### plugin.py
68+
### `plugin.py`
7069

7170
`plugin.py` is the entrypoint for pytask to your package. You can put all of your hook
7271
implementations in this module, but it is recommended to imitate the structure of pytask

docs/source/how_to_guides/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ specific tasks with pytask.
1212
maxdepth: 1
1313
---
1414
migrating_from_scripts_to_pytask
15+
interfaces_for_dependencies_products
1516
functional_interface
1617
capture_warnings
1718
how_to_influence_build_order
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Interfaces for dependencies and products
2+
3+
Different interfaces exist for dependencies and products, and it might not be obvious
4+
when to use what. This guide gives you an overview of the different strengths of each
5+
approach.
6+
7+
## Legend
8+
9+
- ✅ = True
10+
- ❌ = False
11+
- ➖ = Does not apply
12+
13+
## Dependencies
14+
15+
In general, pytask regards everything as a task dependency if it is not marked as a
16+
product. Thus, you can also think of the following examples as how to inject values into
17+
a task. When we talk about products later, the same interfaces will be used.
18+
19+
| | `def task(arg: ... = ...)` | `Annotated[..., value]` | `@task(kwargs=...)` | `@pytask.mark.depends_on(...)` |
20+
| --------------------------------------- | :------------------------: | :---------------------: | :-----------------: | :----------------------------: |
21+
| Not deprecated |||||
22+
| No type annotations required |||||
23+
| Flexible choice of argument name |||||
24+
| Supports third-party functions as tasks |||||
25+
26+
(default-argument)=
27+
28+
### Default argument
29+
30+
You can pass a value to a task as a default argument.
31+
32+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/dependencies_default.py
33+
```
34+
35+
(annotation)=
36+
37+
### Annotation with value
38+
39+
It is possible to include the value in the type annotation.
40+
41+
It is especially helpful if you pass a {class}`~pytask.PNode` to the task. If you passed
42+
a node as the default argument, type checkers like mypy would expect the node to enter
43+
the task, but the value injected into the task depends on the nodes
44+
{meth}`~pytask.PNode.load` method. For a {class}`~pytask.PathNode`
45+
46+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/dependencies_annotation.py
47+
```
48+
49+
(task-kwargs)=
50+
51+
### `@task(kwargs=...)`
52+
53+
You can use the `kwargs` argument of the {func}`@task <pytask.task>` decorator to pass a
54+
dictionary. It applies to dependencies and products alike.
55+
56+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/dependencies_task_kwargs.py
57+
```
58+
59+
## Products
60+
61+
| | `def task(arg: Annotated[..., Product] = ...)` | `Annotated[..., value, Product]` | `produces` | `@task(produces=...)` | `def task() -> Annotated[..., value]` | `@pytask.mark.produces(...)` |
62+
| --------------------------------------------------------- | :--------------------------------------------: | :------------------------------: | :--------: | :-------------------: | :-----------------------------------: | :--------------------------: |
63+
| Not deprecated |||||||
64+
| No type annotations required |||||||
65+
| Flexible choice of argument name |||||||
66+
| Supports third-party functions as tasks |||||||
67+
| Allows to pass custom node while preserving type of value |||||||
68+
69+
### `Product` annotation
70+
71+
The syntax is the same as {ref}`default-argument`, but the {class}`~pytask.Product`
72+
annotation turns the argument into a task product.
73+
74+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/products_annotation.py
75+
```
76+
77+
### `Product` annotation with value
78+
79+
The syntax is the same as {ref}`annotation`, but the {class}`~pytask.Product` annotation
80+
turns the argument into a task product.
81+
82+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/products_annotation_with_pnode.py
83+
```
84+
85+
### `produces`
86+
87+
Without using any type annotation, you can use `produces` as a magical argument name to
88+
treat every value passed to it as a task product.
89+
90+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/products_produces.py
91+
```
92+
93+
(return-annotation)=
94+
95+
### Return annotation
96+
97+
You can also add a node or a value that will be parsed to a node to the annotation of
98+
the return type. It allows us to treat the returns of the task function as products.
99+
100+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/products_return_annotation.py
101+
```
102+
103+
(task-produces)=
104+
105+
### `@task(produces=...)`
106+
107+
In situations where the task return is the product like {ref}`return-annotation`, but
108+
you cannot modify the type annotation of the return, use the argument `produces` of the
109+
{func}`@task <pytask.task>` decorator.
110+
111+
Pass the node or value you otherwise include in the type annotation to `produces`.
112+
113+
```{literalinclude} ../../../docs_src/how_to_guides/interfaces/products_task_produces.py
114+
```

docs/source/how_to_guides/writing_custom_nodes.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ your own to improve your workflows.
99

1010
## Use-case
1111

12-
A typical task operation is to load data like a {class}`pandas.DataFrame` from a pickle
12+
A typical task operation is to load data like a {class}`~pandas.DataFrame` from a pickle
1313
file, transform it, and store it on disk. The usual way would be to use paths to point
14-
to inputs and outputs and call {func}`pandas.read_pickle` and
15-
{meth}`pandas.DataFrame.to_pickle`.
14+
to inputs and outputs and call {func}`~pandas.read_pickle` and
15+
{meth}`~pandas.DataFrame.to_pickle`.
1616

1717
```{literalinclude} ../../../docs_src/how_to_guides/writing_custom_nodes_example_1.py
1818
```
1919

2020
To remove IO operations from the task and delegate them to pytask, we will write a
2121
`PickleNode` that automatically loads and stores Python objects.
2222

23-
And we pass the value to `df` via {obj}`Annotated` to preserve the type hint.
23+
And we pass the value to `df` via {obj}`~typing.Annotated` to preserve the type hint.
2424

2525
The result will be the following task.
2626

0 commit comments

Comments
 (0)