/usr/share/doc/python-doit-doc/html/_sources/dependencies.txt is in python-doit-doc 0.25.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | =====================
More on dependencies
=====================
.. _attr-uptodate:
uptodate
----------
Apart from file dependencies you can extend `doit` to support other ways
to determine if a task is up-to-date through the attribute ``uptodate``.
This can be used in cases where you need to some kind of calculation to
determine if the task is up-to-date or not.
``uptodate`` is a list where each element can be True, False, None, a callable
or a command(string).
* ``False`` indicates that the task is NOT up-to-date
* ``True`` indicates that the task is up-to-date
* ``None`` values will just be ignored. This is used when the value is dynamically calculated
.. note::
An ``uptodate`` value equal to ``True`` does not override others
up-to-date checks. It is one more way to check if task is **not** up-to-date.
i.e. if uptodate==True but a file_dep changes the task is still
considered **not** up-to-date.
If an ``uptodate`` item is a string it will be executed on the shell.
If the process exits with the code ``0``, it is considered as up-to-date.
All other values would be considered as not up-to-date.
``uptodate`` elements can also be a callable that will be executed on runtime
(not when the task is being created).
The section ``custom-uptodate`` will explain in details how to extend `doit`
writing your own callables for ``uptodate``. This callables will typically
compare a value on the present time with a value calculated on the last
successful execution.
`doit` includes several implementations to be used as ``uptodate``.
They are all included in module `doit.tools` and will be discussed in detail
later:
* ``result_dep``: check if the result of another task has changed
* ``run_once``: execute a task only once (used for tasks without dependencies)
* ``timeout``: indicate that a task should "expire" after a certain time interval
* ``config_changed``: check for changes in a "configuration" string or dictionary
* ``check_timestamp_unchanged``: check access, status change/create or modify timestamp of a given file/directory
.. _up-to-date-def:
doit up-to-date definition
-----------------------------
A task is **not** up-to-date if any of `file_dep` or `uptodate` is not up-to-date
or there is a missing `target`.
If a task does not define any of these dependencies it will always be executed.
Apart from these dependencies used to determine if a task is up-to-date or not.
``doit`` also includes other kind of dependencies to help you combine tasks
so they are executed in appropriate order.
task-dependency
---------------
It is used to enforce tasks are executed on the desired order.
By default tasks are executed on the same order as they were defined in
the `dodo` file. To define a dependency on another task use the
task name (whatever comes after ``task_`` on the function name) in the
"task_dep" attribute.
.. note::
A *task-dependency* **only** indicates that another task should be "executed"
before itself. The task-dependency might not really be executed if it
is *up-to-date*.
.. note::
*task-dependencies* are **not** used to determine if a task is up-to-date or
not. If a task defines only *task-dependency* it will always be executed.
This example we make sure we include a file with the latest revision number of
the mercurial repository on the tar file.
.. literalinclude:: tutorial/tar.py
.. code-block:: console
$ doit
. version
. tar
groups
^^^^^^^
You can define a group of tasks by adding tasks as dependencies and setting
its `actions` to ``None``.
.. literalinclude:: tutorial/group.py
Note that tasks are never executed twice in the same "run".
.. _attr-calc_dep:
calculated-dependencies
------------------------
Calculation of dependencies might be an expensive operation, so not suitable
to be done on load time by task-creators.
For this situation it is better to delegate
the calculation of dependencies to another task.
The task calculating dependencies must have a python-action returning a
dictionary with `file_dep`, `task_dep`, `uptodate` or another `calc_dep`.
On the example below ``mod_deps`` prints on the screen all direct dependencies
from a module. The dependencies itself are calculated on task ``get_dep``
(note: get_dep has a fake implementation where the results are taken from a dict).
.. literalinclude:: tutorial/calc_dep.py
setup-task
-------------
Some tasks may require some kind of environment setup.
In this case they can define a list of "setup" tasks.
* the setup-task will be executed only if the task is to be executed (not up-to-date)
* setup-tasks are just normal tasks that follow all other task behavior
.. note::
A *task-dependency* is executed before checking if the task is up-to-date.
A *setup-task* is executed after the checking if the task is up-to-date and
it is executed only if the task is not up-to-date and will be executed.
teardown
^^^^^^^^^^^
Task may also define 'teardown' actions.
These actions are executed after all tasks have finished their execution.
They are executed in reverse order their tasks were executed.
Example:
.. literalinclude:: tutorial/tsetup.py
.. code-block:: console
$ doit withenvX
. setup_sample:setupX
start setupX
. withenvX:c
x c
. withenvX:b
x b
. withenvX:a
x a
stop setupX
$ doit withenvY
. setup_sample:setupY
start setupY
. withenvY
y
stop setupY
saving computed values
------------------------
Tasks can save computed values by returning a dictionary on it's python-actions.
The values must be JSON encodable.
A cmd-action can also save it's output.
But for this you will need to explicitly import `CmdAction` and set its `save_out`
parameter with the *name* used to save the output in *values*
.. literalinclude:: tutorial/save_out.py
These values can be used on uptodate_ and getargs_.
Check those sections for examples.
getargs
--------
`getargs` provides a way to use values computed from one task in another task.
The values are taken from "saved computed values"
(returned dict from a python-action).
For *cmd-action* use dictionary-based string formatting.
For *python-action* the action callable parameter names must match with keys
from `getargs`.
`getargs` is a dictionary where the key is the argument name used on actions,
and the value is a tuple with 2 strings: task name, "value name".
.. literalinclude:: tutorial/getargs.py
The values are being passed on to a python-action you can pass the whole dict
by specifying the value name as ``None``.
.. literalinclude:: tutorial/getargs_dict.py
If a group-task is used, the values from all its sub-tasks are passed as a dict.
.. literalinclude:: tutorial/getargs_group.py
.. note::
``getargs`` creates an implicit setup-task.
keywords on actions
--------------------
It is common situation to use task information such as *targets*,
*dependencies*, or *changed* in its own actions.
Note: Dependencies here refers only to *file-dependencies*.
For *cmd-action* you can use the python notation for keyword substitution
on strings. The string will contain all values separated by a space (" ").
For *python-action* create a parameter in the function, `doit` will take care
of passing the value when the function is called.
The values are passed as list of strings.
.. literalinclude:: tutorial/hello.py
You can also pass the keyword *task* to have a reference to all task
metadata.
.. literalinclude:: tutorial/meta.py
|