More on Task creation
=====================


importing tasks
---------------

The *doit* loader will look at **all** objects in the namespace of the *dodo*.
It will look for functions staring with ``task_`` and objects with
``create_doit_tasks``.
So it is also possible to load task definitions from other
modules just by importing them into your *dodo* file.

.. literalinclude:: tutorial/import_tasks.py

.. code-block:: console

    $ doit list
    echo
    hello
    sample


.. note::

   Importing tasks from different modules is useful if you want to split
   your task definitions in different modules.

   The best way to create re-usable tasks that can be used in several projects
   is to call functions that return task dict's.
   For example take a look at a reusable *pyflakes*
   `task generator <https://github.com/pydoit/doit-py/blob/master/doitpy/pyflakes.py>`_.
   Check the project `doit-py <https://github.com/pydoit/doit-py>`_
   for more examples.


.. _delayed-task-creation:

delayed task creation
---------------------


`doit` execution model is divided in two phases:

  - *task-loading* : search for task-creator functions (that starts with string `task_`) and create task metadata

  - *task-execution* : check which tasks are out-of-date and execute them

Normally *task-loading* is completed before the *task-execution* starts.
`doit` allows some task metadata to be modified during *task-execution* with
`calc_deps` and on `uptodate`, but those are restricted to modifying
already created tasks...

Sometimes it is not possible to know all tasks that should be created before
some tasks are executed. For these cases `doit` supports
*delayed task creation*, that means *task-execution* starts before
*task-loading* is completed.

When *task-creator* function is decorated with `doit.create_after`,
its evaluation to create the tasks will be delayed to happen after the
execution of the specified task in the `executed` param.

.. literalinclude:: tutorial/delayed.py


.. _specify-target-regex:

.. note::

   To be able to specify targets created by delayed task loaders to `doit run`,
   it is possible to also specify a regular expression (regex) for every
   delayed task loader. If specified, this regex should match any target name
   possibly generated by this delayed task generator. It can be specified via
   the additional *task-generator* argument `target_regex`. In the above example,
   the regex `.*\\.out` matches every target name ending with `.out`.

   It is possible to match every possible target name by specifying `.*`.
   Alternatively, one can use the command line option `--auto-delayed-regex`
   to `doit run`; see :ref:`here <auto-delayed-regex>` for more information.


Parameter: `creates`
++++++++++++++++++++

In case the task created by a `DelayedTask` has a different *basename* than
then creator function, or creates several tasks with different *basenames*,
you should pass the parameter `creates`.

Since `doit` will only execute the body of the task-creator function on demand,
the tasks names must be explicitly specified... Example:

.. literalinclude:: tutorial/delayed_creates.py



.. _create-doit-tasks:

custom task definition
------------------------

Apart from collect functions that start with the name `task_`.
The *doit* loader will also execute the ``create_doit_tasks``
callable from any object that contains this attribute.


.. literalinclude:: tutorial/custom_task_def.py

The `project letsdoit <https://bitbucket.org/takluyver/letsdoit>`_
has some real-world implementations.

For simple examples to help you create your own check this
`blog post <http://blog.schettino72.net/posts/doit-task-creation.html>`_.


