doit is built to be extended and this can be done in several levels. So far we have seen:
Apart from those doit also expose it’s internal API so you can create new applications on top of doit.
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:
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 and DOIT_CONFIG
Returns: | (tuple) list of Task, dict with DOIT_CONFIG options |
---|---|
Parameters: |
|
The main program is implemented in the DoitMain. It’s constructor takes an instance of the task loader to be used.
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:]))
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:]))
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.
third-party should subclass this for commands that do no use tasks
Variables: |
|
---|
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.
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:]))