|
| 1 | +# Reconciling Lockfile State |
| 2 | + |
| 3 | +Use [`pytask lock`](../reference_guides/commands.md#pytask-lock) when the current files |
| 4 | +in the project are already correct and only the recorded state in `pytask.lock` needs to |
| 5 | +catch up. |
| 6 | + |
| 7 | +This is an advanced workflow. Most of the time, |
| 8 | +[`pytask build`](../reference_guides/commands.md#pytask-build) is the right command. |
| 9 | +Reach for `pytask lock` when you want to change the lockfile without executing tasks. |
| 10 | + |
| 11 | +!!! warning |
| 12 | + |
| 13 | + `pytask lock` is a sharp tool. It updates recorded state without proving that the files |
| 14 | + were produced by the current task definitions. |
| 15 | + |
| 16 | +## When is this useful? |
| 17 | + |
| 18 | +Typical situations are: |
| 19 | + |
| 20 | +- You reformatted or reorganized a task file and do not want to rerun an expensive task. |
| 21 | +- You renamed or moved a task and want to accept the current outputs for the new task. |
| 22 | +- You produced outputs manually or elsewhere and now want to register them in the |
| 23 | + lockfile. |
| 24 | +- You deleted or renamed tasks and want to remove their stale lockfile entries. |
| 25 | + |
| 26 | +## Preview changes first |
| 27 | + |
| 28 | +By default, `pytask lock` runs interactively. It shows the planned changes and then asks |
| 29 | +for confirmation one by one. Only entries which would actually change appear in the |
| 30 | +prompt sequence. |
| 31 | + |
| 32 | +To preview changes without writing them, use `--dry-run`: |
| 33 | + |
| 34 | +--8<-- "docs/source/_static/md/lock-accept-dry-run.md" |
| 35 | + |
| 36 | +To apply all planned changes without prompting, use `--yes`: |
| 37 | + |
| 38 | +```console |
| 39 | +$ pytask lock accept -k train --yes |
| 40 | +``` |
| 41 | + |
| 42 | +## Accept the current state |
| 43 | + |
| 44 | +Use [`pytask lock accept`](../reference_guides/commands.md#pytask-lock-accept) when the |
| 45 | +current dependencies, products, and task definition are already correct and should |
| 46 | +become the new recorded state. |
| 47 | + |
| 48 | +--8<-- "docs/source/_static/md/lock-accept-interactive.md" |
| 49 | + |
| 50 | +If no selectors are provided, `pytask lock accept` applies to all collected tasks in the |
| 51 | +provided paths. |
| 52 | + |
| 53 | +If selectors are provided with `-k` or `-m`, `accept` automatically includes the |
| 54 | +ancestors of the selected tasks. This is useful when you target a downstream task and |
| 55 | +want the accepted state to stay consistent with its upstream dependencies. |
| 56 | + |
| 57 | +```console |
| 58 | +$ pytask lock accept -k evaluate |
| 59 | +``` |
| 60 | + |
| 61 | +In this example, `pytask` accepts `evaluate` and its ancestors. It does not |
| 62 | +automatically include descendants. If you want to accept a wider part of the DAG, widen |
| 63 | +the task selection yourself. |
| 64 | + |
| 65 | +```console |
| 66 | +$ pytask lock accept -k "train or evaluate" |
| 67 | +``` |
| 68 | + |
| 69 | +If a selected task is missing a required dependency or product, the command fails |
| 70 | +instead of accepting incomplete state. |
| 71 | + |
| 72 | +## Reset recorded state |
| 73 | + |
| 74 | +Use [`pytask lock reset`](../reference_guides/commands.md#pytask-lock-reset) to remove |
| 75 | +recorded state for selected tasks. |
| 76 | + |
| 77 | +```console |
| 78 | +$ pytask lock reset -k train |
| 79 | +``` |
| 80 | + |
| 81 | +Unlike `accept`, `reset` works on the exact selected tasks. It does not automatically |
| 82 | +include ancestors. |
| 83 | + |
| 84 | +On the next build, `pytask` determines again whether these tasks require execution. This |
| 85 | +is useful when state was accepted too broadly or when you want a specific task to be |
| 86 | +reconsidered from scratch. |
| 87 | + |
| 88 | +## Remove stale lockfile entries |
| 89 | + |
| 90 | +Use [`pytask lock clean`](../reference_guides/commands.md#pytask-lock-clean) to remove |
| 91 | +entries from the lockfile which no longer correspond to collected tasks in the current |
| 92 | +project. |
| 93 | + |
| 94 | +--8<-- "docs/source/_static/md/lock-clean.md" |
| 95 | + |
| 96 | +This is useful after deleting, renaming, or moving tasks when old entries should no |
| 97 | +longer remain in the lockfile. |
| 98 | + |
| 99 | +## Example workflow |
| 100 | + |
| 101 | +One common workflow looks like this: |
| 102 | + |
| 103 | +1. Run a normal build once. |
| 104 | +1. Change a task file in a way that should not force a rerun. |
| 105 | +1. Accept the current state. |
| 106 | +1. Verify that a later build skips the task. |
| 107 | +1. Reset the task if you want `pytask` to reconsider it again. |
| 108 | + |
| 109 | +```console |
| 110 | +$ pytask build |
| 111 | +$ pytask lock accept -k train --yes |
| 112 | +$ pytask build |
| 113 | +$ pytask lock reset -k train --yes |
| 114 | +$ pytask build |
| 115 | +``` |
| 116 | + |
| 117 | +After `accept`, the next build skips unchanged tasks according to the updated lockfile. |
| 118 | +After `reset`, the selected tasks are reconsidered on the next build. |
| 119 | + |
| 120 | +## Be explicit about scope |
| 121 | + |
| 122 | +Start with narrow task selections, preview changes with `--dry-run`, and widen the |
| 123 | +selection only when needed. |
| 124 | + |
| 125 | +This is especially important for `accept`: it is often better to accept a small part of |
| 126 | +the DAG first and then inspect the result than to update the whole project at once. |
| 127 | + |
| 128 | +## Related |
| 129 | + |
| 130 | +- [`pytask lock`](../reference_guides/commands.md#pytask-lock) |
| 131 | +- [`pytask build`](../reference_guides/commands.md#pytask-build) |
| 132 | +- [Portability](portability.md) |
| 133 | +- [The lockfile](../reference_guides/lockfile.md) |
0 commit comments