doit logo

Table Of Contents

Sponsors

Your logo here

Sponsor/Donate to doit


Why Donate? Donations will be used to sponsor futher development of the project.

For coorporate donations the logo of your company will be placed on this website side-bar (see above). For more information please contact schettino72@gmail.com



Extending doit

doit is built to be extended and this can be done in several levels. So far we have seen:

  1. User’s can create new ways to define when a task is up-to-date using the uptodate task parameter (more)
  2. Tasks can be created in different styles by creating a custom task creators (more)
  3. The output can be configured by creating custom reports (more)
  4. You can customize how tasks are executed by creating new Action types (more)

Apart from those doit also expose it’s internal API so you can create new applications on top of doit.

task loader customization

The task loader controls the source/creation of tasks. Normally doit tasks are defined in a dodo.py file. This file is loaded, and the list of tasks is created from the dict containing task meta-data from the task-creator functions.

Subclass TaskLoader to create a custom loader:

class doit.cmd_base.TaskLoader[source]

task-loader interface responsible of creating Task objects

Subclasses must implement the method load_tasks

Variables:cmd_options – (list of dict) see cmdparse.CmdOption for dict format
load_tasks(cmd, opt_values, pos_args)[source]

load tasks and DOIT_CONFIG

Returns:

(tuple) list of Task, dict with DOIT_CONFIG options

Parameters:
  • cmd – (doit.cmd_base.Command) current command being executed
  • opt_values – (dict) with values for cmd_options
  • pos_args – (list str) positional arguments from command line

The main program is implemented in the DoitMain. It’s constructor takes an instance of the task loader to be used.

Example: pre-defined task

In the full example below a application is created where the only task available is defined using a dict (so no dodo.py will be used).

#! /usr/bin/env python

import sys

from doit.task import dict_to_task
from doit.cmd_base import TaskLoader
from doit.doit_cmd import DoitMain

my_builtin_task = {
    'name': 'sample_task',
    'actions': ['echo hello from built in'],
    'doc': 'sample doc',
    }

class MyLoader(TaskLoader):
    @staticmethod
    def load_tasks(cmd, opt_values, pos_args):
        task_list = [dict_to_task(my_builtin_task)]
        config = {'verbosity': 2}
        return task_list, config


if __name__ == "__main__":
    sys.exit(DoitMain(MyLoader()).run(sys.argv[1:]))

Example: load tasks from a module

The ModuleTaskLoader can be used to load tasks from a specified module, where this module specifies tasks in the same way as in dodo.py. ModuleTaskLoader is included in doit source.

#! /usr/bin/env python

import sys

from doit.cmd_base import ModuleTaskLoader
from doit.doit_cmd import DoitMain

if __name__ == "__main__":
    import my_module_with_tasks
    sys.exit(DoitMain(ModuleTaskLoader(my_module_with_tasks)).run(sys.argv[1:]))

sub-command customization

The doit command line has several sub-commands: run, help, list, clean... By sub-classing DoitMain.get_commands it is possible to add/remove commands.

To create a new sub-cmd, subclass doit.cmd_base.Command set some class variables and implement the execute method.

class doit.cmd_base.Command[source]

third-party should subclass this for commands that do no use tasks

Variables:
  • name – (str) name of sub-cmd to be use from cmdline
  • doc_purpose – (str) single line cmd description
  • doc_usage – (str) describe accepted parameters
  • doc_description – (str) long description/help for cmd
  • cmd_options – (list of dict) see cmdparse.CmdOption for dict format
execute(opt_values, pos_args)[source]

execute command :param opt_values: (dict) with cmd_options values :param pos_args: (list) of cmd-line positinal arguments

cmd_options uses the same format as task parameters.

Example: scaffolding

A common example is applications that provide some kind of scaffolding when creating new projects.

#! /usr/bin/env python

import sys

from doit.cmd_base import Command
from doit.doit_cmd import DoitMain


class MyCmd(Command):
    doc_purpose = 'test extending doit commands'
    doc_usage = '[XXX]'
    doc_description = 'my command description'

    def execute(self, opt_values, pos_args):
        print "this command does nothing!"


class MyTool(DoitMain):
    def get_commands(self):
        cmds = DoitMain.get_commands(self)
        my_cmd = MyCmd()
        cmds[my_cmd.name] = my_cmd
        return cmds


if __name__ == "__main__":
    sys.exit(MyTool().run(sys.argv[1:]))