Skip to content

Commit 3e0db0e

Browse files
authored
Add pytask lock command (#860)
1 parent d644e5e commit 3e0db0e

22 files changed

Lines changed: 1854 additions & 69 deletions

.pre-commit-config.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,21 @@ repos:
2525
- id: python-no-log-warn
2626
- id: text-unicode-replacement-char
2727
- repo: https://github.com/astral-sh/ruff-pre-commit
28-
rev: v0.15.11
28+
rev: v0.15.12
2929
hooks:
3030
- id: ruff-format
3131
- id: ruff-check
3232
- repo: https://github.com/astral-sh/uv-pre-commit
3333
rev: 0.11.7
3434
hooks:
3535
- id: uv-lock
36+
- repo: local
37+
hooks:
38+
- id: check-termynal-line-lengths
39+
name: Check Termynal line lengths
40+
entry: python scripts/check_termynal_line_lengths.py
41+
language: python
42+
files: ^docs/source/_static/md/.*\.md$
3643
- repo: https://github.com/executablebooks/mdformat
3744
rev: 1.0.0
3845
hooks:
@@ -60,7 +67,7 @@ repos:
6067
- id: nbstripout
6168
exclude: (docs)
6269
- repo: https://github.com/crate-ci/typos
63-
rev: v1
70+
rev: v1.45.1
6471
hooks:
6572
- id: typos
6673
exclude: (\.ipynb)

.readthedocs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ build:
1919
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --frozen --group docs
2020
build:
2121
html:
22-
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv run --group docs zensical build
22+
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uvx --from rust-just just docs
2323
post_build:
2424
- mkdir -p "${READTHEDOCS_OUTPUT}/html"
2525
- cp -a docs/build/. "${READTHEDOCS_OUTPUT}/html/"

docs/source/_static/md/commands/build-options.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
| ---------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
33
| <code>-c, --config FILE</code> | - | Path to configuration file. |
44
| <code>--capture [fd\|no\|sys\|tee-sys]</code> | <code>fd</code> | Per task capturing method. |
5-
| <code>--clean-lockfile</code> | <code>false</code> | Rewrite the lockfile with only currently collected tasks. |
65
| <code>--database-url TEXT</code> | - | Url to the database. |
76
| <code>--debug-pytask</code> | <code>false</code> | Trace all function calls in the plugin framework. |
87
| <code>--disable-warnings</code> | <code>false</code> | Disables the summary for warnings. |

docs/source/_static/md/commands/command-list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
| [`clean`](clean.md) | Clean the provided paths by removing files unknown to pytask. |
55
| [`collect`](collect.md) | Collect tasks and report information about them. |
66
| [`dag`](dag.md) | Create a visualization of the directed acyclic graph. |
7+
| [`lock`](lock.md) | Inspect and update recorded task state in the lockfile. |
78
| [`markers`](markers.md) | Show all registered markers. |
89
| [`profile`](profile.md) | Show information about resource consumption. |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div class="termy">
2+
3+
```console
4+
$ pytask lock accept -k train --dry-run
5+
6+
<span class="termynal-dim">──────────────────────────</span> Start pytask session <span class="termynal-dim">──────────────────────────</span>
7+
Platform: win32 -- Python 3.12.0, pytask 0.5.3
8+
Root: C:\Users\pytask-dev\git\my_project
9+
Collected 2 tasks.
10+
<span class="termynal-success">Would accept recorded state for task_train.py::task_train.</span>
11+
<span class="termynal-success">Would accept recorded state for task_evaluate.py::task_evaluate.</span>
12+
13+
<span class="termynal-dim">─────────────────────────────────────────────────────────────────────────</span>
14+
```
15+
16+
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div class="termy">
2+
3+
```console
4+
$ pytask lock accept -k train
5+
<span class="termynal-dim">──────────────────────────</span> Start pytask session <span class="termynal-dim">──────────────────────────</span>
6+
Platform: win32 -- Python 3.12.0, pytask 0.5.3
7+
Root: C:\Users\pytask-dev\git\my_project
8+
Collected 2 tasks.
9+
# Accept recorded state for task_train.py::task_train? [y/N]: $ y
10+
# Accept recorded state for task_evaluate.py::task_evaluate? [y/N]: $ n
11+
<span class="termynal-success">Accept recorded state for task_train.py::task_train.</span>
12+
13+
<span class="termynal-dim">─────────────────────────────────────────────────────────────────────────</span>
14+
```
15+
16+
</div>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="termy">
2+
3+
```console
4+
$ pytask lock clean
5+
<span class="termynal-dim">──────────────────────────</span> Start pytask session <span class="termynal-dim">──────────────────────────</span>
6+
Platform: win32 -- Python 3.12.0, pytask 0.5.3
7+
Root: C:\Users\pytask-dev\git\my_project
8+
Collected 2 tasks.
9+
# Remove recorded state for task_old.py::task_train? [y/N]: $ y
10+
# Remove recorded state for task_old.py::task_evaluate? [y/N]: $ y
11+
<span class="termynal-success">Remove recorded state for task_old.py::task_train.</span>
12+
<span class="termynal-success">Remove recorded state for task_old.py::task_evaluate.</span>
13+
14+
<span class="termynal-dim">─────────────────────────────────────────────────────────────────────────</span>
15+
```
16+
17+
</div>

docs/source/how_to_guides/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ specific tasks with pytask.
1010
- [Migrating From Scripts To Pytask](migrating_from_scripts_to_pytask.md)
1111
- [Interfaces For Dependencies Products](interfaces_for_dependencies_products.md)
1212
- [Portability](portability.md)
13+
- [Update the Lockfile to Match Project State](reconciling_lockfile_state.md)
1314
- [Remote Files](remote_files.md)
1415
- [Functional Interface](functional_interface.md)
1516
- [Capture Warnings](capture_warnings.md)

docs/source/how_to_guides/portability.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ Use this checklist when you move a project to another machine or environment.
1717
Run a normal build with [`pytask build`](../reference_guides/commands.md#pytask-build)
1818
so `pytask.lock` is up to date:
1919

20-
````
2120
```console
2221
$ pytask build
2322
```
2423

2524
If you already have a recent lockfile and up-to-date outputs, you can skip this step.
26-
````
2725

2826
1. **Ship the right files.**
2927

@@ -85,11 +83,10 @@ tasks run. If tasks are removed or renamed, their old entries remain as stale da
8583
are ignored.
8684

8785
To clean up stale entries without deleting the file, run
88-
[`pytask build --clean-lockfile`](../reference_guides/commands.md#pytask-build--clean-lockfile):
86+
[`pytask lock clean`](../reference_guides/commands.md#pytask-lock-clean):
8987

9088
```console
91-
$ pytask build --clean-lockfile
89+
$ pytask lock clean
9290
```
9391

94-
This rewrites the lockfile after a successful build with only the currently collected
95-
tasks and their current state values.
92+
This removes lockfile entries for tasks which are no longer collected.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Update the Lockfile to Match Project State
2+
3+
Use [`pytask lock`](../reference_guides/commands.md#pytask-lock) when the current files
4+
and outputs in the project are already correct, but the recorded state in `pytask.lock`
5+
needs to catch up. This can happen after refactoring task files, moving or renaming
6+
tasks, producing outputs outside of pytask, or deleting tasks.
7+
8+
## Accept current files and outputs
9+
10+
Use [`pytask lock accept`](../reference_guides/commands.md#pytask-lock-accept) when the
11+
current dependencies, products, and task definition are already correct and should
12+
become the new recorded state.
13+
14+
Preview the changes without writing them with `--dry-run`:
15+
16+
--8<-- "docs/source/_static/md/lock-accept-dry-run.md"
17+
18+
Then accept the planned changes interactively:
19+
20+
--8<-- "docs/source/_static/md/lock-accept-interactive.md"
21+
22+
Add `--yes` to apply all planned changes without prompting:
23+
24+
```console
25+
$ pytask lock accept -k train --yes
26+
```
27+
28+
If no selectors are provided, `pytask lock accept` applies to all collected tasks in the
29+
provided paths.
30+
31+
If selectors are provided with `-k` or `-m`, `accept` automatically includes the
32+
ancestors of the selected tasks. This is useful when you target a downstream task and
33+
want the accepted state to stay consistent with its upstream dependencies.
34+
35+
```console
36+
$ pytask lock accept -k evaluate
37+
```
38+
39+
In this example, `pytask` accepts `evaluate` and its ancestors. It does not
40+
automatically include descendants. If you want to accept a wider part of the DAG, widen
41+
the task selection yourself.
42+
43+
```console
44+
$ pytask lock accept -k "train or evaluate"
45+
```
46+
47+
If a selected task is missing a required dependency or product, the command fails
48+
instead of accepting incomplete state.
49+
50+
Run a build afterwards to check that unchanged tasks are skipped according to the
51+
updated lockfile.
52+
53+
```console
54+
$ pytask build
55+
```
56+
57+
## Reset state for selected tasks
58+
59+
Use [`pytask lock reset`](../reference_guides/commands.md#pytask-lock-reset) to remove
60+
recorded state for selected tasks when state was accepted too broadly or when specific
61+
tasks should be reconsidered from scratch.
62+
63+
```console
64+
$ pytask lock reset -k train
65+
```
66+
67+
Unlike `accept`, `reset` with a selector works on the exact selected tasks. It does not
68+
automatically include ancestors.
69+
70+
Preview the reset with `--dry-run` if you want to check the affected tasks first:
71+
72+
```console
73+
$ pytask lock reset -k train --dry-run
74+
```
75+
76+
Add `--yes` to remove all planned entries without prompting:
77+
78+
```console
79+
$ pytask lock reset -k train --yes
80+
```
81+
82+
If no selectors are provided, `pytask lock reset` removes the recorded state for all
83+
collected tasks in the provided paths.
84+
85+
Run a build afterwards so `pytask` determines again whether the selected tasks require
86+
execution.
87+
88+
```console
89+
$ pytask build
90+
```
91+
92+
## Remove stale entries for deleted or moved tasks
93+
94+
Use [`pytask lock clean`](../reference_guides/commands.md#pytask-lock-clean) to remove
95+
entries from the lockfile which no longer correspond to collected tasks in the current
96+
project. This is useful after deleting, renaming, or moving tasks when old entries
97+
should no longer remain in the lockfile.
98+
99+
Preview stale entries without writing them with `--dry-run`:
100+
101+
```console
102+
$ pytask lock clean --dry-run
103+
```
104+
105+
Then remove stale entries interactively:
106+
107+
--8<-- "docs/source/_static/md/lock-clean.md"
108+
109+
Add `--yes` to remove all stale entries without prompting:
110+
111+
```console
112+
$ pytask lock clean --yes
113+
```
114+
115+
`clean` only removes entries for tasks which are no longer collected. It does not accept
116+
or update the current state of collected tasks.
117+
118+
## Related
119+
120+
- [`pytask lock`](../reference_guides/commands.md#pytask-lock)
121+
- [`pytask build`](../reference_guides/commands.md#pytask-build)
122+
- [Portability](portability.md)
123+
- [The lockfile](../reference_guides/lockfile.md)

0 commit comments

Comments
 (0)