Passing arguments from the command line

Task action parameters

It is possible to pass option parameters to the task action through the command line.

Just add a params field to the task dictionary. params must be a list of dictionaries where every entry is an option parameter. Each parameter must define a name, and a default value. It can optionally define a “short” and “long” names to be used from the command line (it follows unix command line conventions). It may also specify additional attributes, such as type and help (see below).

See the example:

def task_py_params():
    def show_params(param1, param2):
        print(param1)
        print(5 + param2)
    return {'actions':[(show_params,)],
            'params':[{'name':'param1',
                       'short':'p',
                       'default':'default value'},

                      {'name':'param2',
                       'long':'param2',
                       'type': int,
                       'default':0}],
            'verbosity':2,
            }

def task_py_params_list():
    def print_a_list(list):
        for item in list:
            print(item)
    return {'actions':[(print_a_list,)],
            'params':[{'name':'list',
                       'short':'l',
                       'long': 'list',
                       'type': list,
                       'default': [],
                       'help': 'Collect a list with multiple -l flags'}],
            'verbosity':2,
            }

def task_py_params_choice():
    def print_choice(choice):
        print(choice)

    return {'actions':[(print_choice,)],
            'params':[{'name':'choice',
                       'short':'c',
                       'long': 'choice',
                       'type': str,
                       'choices': (('this', ''), ('that', '')),
                       'default': 'this',
                       'help': 'Choose between this and that'}],
            'verbosity':2,}

def task_cmd_params():
    return {'actions':["echo mycmd %(flag)s xxx"],
            'params':[{'name':'flag',
                       'short':'f',
                       'long': 'flag',
                       'default': '',
                       'help': 'helpful message about this flag'}],
            'verbosity': 2
            }

For python-actions the python function must define arguments with the same name as a task parameter.

$ doit py_params -p abc --param2 4
.  py_params
abc
9

Need a list in your python function? Specify an option with type set to list.

$ doit py_params_list -l milk -l eggs -l bread
.  py_params_list
milk
eggs
bread

Choices can be set by specifying an option with choices set to a sequence of a 2-element tuple. The first element is the choice value. The second element is the choice description, if not required, use an empty string.

$ doit py_params_choice -c that
.  py_params_choice
that

Invalid choices are detected and passed back to the user.

$ doit py_params_choice -c notavalidchoice
ERROR: Error parsing parameter 'choice'. Provided 'notavalidchoice' but available choices are: 'this', 'that'.

For cmd-actions use python string substitution notation:

$ doit cmd_params -f "-c --other value"
.  cmd_params
mycmd -c --other value xxx

All parameters attributes

Here is the list of all attributes param accepts:

name

Name of the parameter, identifier used as name of the the parameter on python code. It should be unique among others.

required

True

type

str

default

Default value used when it is set through command-line.

required

True

short

Short parameter form, used for e.g. -p value.

required

optional

type

str

long

Long parameter form, used for e.g. --parameter value.

required

optional

type

str

type

Actually it can be any python callable. It coverts the string value received from command line to whatever value to be used on python code.

If the type is bool the parameter is treated as an option flag where no value should be specified, value is set to True. Example: doit mytask --flag.

required

optional

type

callable (e.g. a function)

default

str

choices

List of accepted value choices for option. First tuple element is the value name, second tuple element is a help description for value.

required

optional

type

list of 2-tuple strings

help

Help message associated to this parameter, shown when help is called for this task, e.g. doit help mytask.

required

optional

type

str

inverse

[only for bool parameter] Set inverse flag long parameter name, value will be set to False (see example below).

required

optional

type

str

Example, given following code:

def task_with_flag():
    def _task(flag):
        print("Flag {0}".format("On" if flag else "Off"))

    return {
        'params': [{
            'name': 'flag',
            'long': 'flagon',
            'short': 'f',
            'type': bool,
            'default': True,
            'inverse': 'flagoff'}],
        'actions': [(_task, )],
        'verbosity': 2
        }

calls to task with_flag show flag on or off:

$ doit with_flag
.  with_flag
Flag On
$ doit with_flag --flagoff
.  with_flag
Flag Off

positional arguments

Tasks might also get positional arguments from the command line as standard unix commands do, with positional arguments after optional arguments.

def task_pos_args():
    def show_params(param1, pos):
        print('param1 is: {0}'.format(param1))
        for index, pos_arg in enumerate(pos):
            print('positional-{0}: {1}'.format(index, pos_arg))
    return {'actions':[(show_params,)],
            'params':[{'name':'param1',
                       'short':'p',
                       'default':'default value'},
                      ],
            'pos_arg': 'pos',
            'verbosity': 2,
            }
$ doit pos_args -p 4 foo bar
.  pos_args
param1 is: 4
positional-0: foo
positional-1: bar

Warning

If a task accepts positional arguments, it is not allowed to pass other tasks after it in the command line. For example if task1 takes positional arguments you can not call:

$ doit task1 pos1 task2

As the string task2 would be interpreted as positional argument from task1 not as another task name.

command line variables (doit.get_var)

It is possible to pass variable values to be used in dodo.py from the command line.

from doit import get_var

config = {"abc": get_var('abc', 'NO')}

def task_echo():
    return {'actions': ['echo hi %s' % config],
            'verbosity': 2,
            }
$ doit
.  echo
hi {abc: NO}
$ doit abc=xyz x=3
.  echo
hi {abc: xyz}

Task creator parameters

Command line arguments may also be passed to task creators. It uses the same parameter syntax as is used with task action parameters.

from doit import task_params

@task_params([{"name": "howmany", "default": 3, "type": int, "long": "howmany"}])
def task_subtasks(howmany):
    for i in range(howmany):
        yield {"name": i, "actions": [f"echo I can count to {howmany}: {i}"]}

Any argument defined for the task generating function will also be available as an argument for any task actions.

def do_work(foo):
    print(f'Argument foo={foo}')

@task_params([{"name": "foo", "default": "bar", "long": "foo"}])
def task_use_in_action(foo):
    print(f'When the task action runs it will print {foo}')

    return {
        'actions': [do_work],
        'verbosity': 2
    }

Warning

When the @task_params decorator is used, you must not use the params field. The content from params can be easily included in @task_params.

The reason for this limitation is that the command line parsing happens before the task’s dict is returned. Hence impossible to know its value.