doit logo

Table Of Contents

Sponsors

Your logo here

Sponsor/Donate


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

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

Hire me

Looking for a python developer with a proven record of designing and developing robust and well tested applications? The creator and maintainer of doit is available for hire. Full-time, part-time or one-off job.
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:

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.

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:]))