Skip to content

Commit

Permalink
refs #14. delayed-task-creation. fix command that dont execute tasks...
Browse files Browse the repository at this point in the history
  • Loading branch information
schettino72 committed Jan 6, 2015
1 parent 8d390e3 commit 3eacff4
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 30 deletions.
1 change: 1 addition & 0 deletions doit/cmd_auto.py
Expand Up @@ -32,6 +32,7 @@ class Auto(DoitCmdBase):
doc_purpose = "automatically execute tasks when a dependency changes"
doc_usage = "[TASK ...]"
doc_description = None
execute_tasks = True

cmd_options = (opt_verbosity, opt_reporter)

Expand Down
13 changes: 9 additions & 4 deletions doit/cmd_base.py
Expand Up @@ -47,6 +47,11 @@ class Command(object):
# sequence of dicts
cmd_options = tuple()

# `execute_tasks` indicates wheather this command execute task's actions.
# This is used by the loader to indicate when delayed task creation
# should be used.
execute_tasks = False

def __init__(self):
self.name = self.name or self.__class__.__name__.lower()
Command.CMD_LIST.append(self.name)
Expand Down Expand Up @@ -172,13 +177,13 @@ def load_tasks(self, cmd, opt_values, pos_args): # pragma: no cover
raise NotImplementedError()

@staticmethod
def _load_from(namespace, cmd_list):
def _load_from(cmd, namespace, cmd_list):
"""load task from a module or dict with module members"""
if inspect.ismodule(namespace):
members = dict(inspect.getmembers(namespace))
else:
members = namespace
task_list = loader.load_tasks(members, cmd_list)
task_list = loader.load_tasks(members, cmd_list, cmd.execute_tasks)
doit_config = loader.load_doit_config(members)
return task_list, doit_config

Expand All @@ -193,7 +198,7 @@ def __init__(self, mod_dict):
self.mod_dict = mod_dict

def load_tasks(self, cmd, params, args):
return self._load_from(self.mod_dict, cmd.CMD_LIST)
return self._load_from(cmd, self.mod_dict, cmd.CMD_LIST)


class DodoTaskLoader(TaskLoader):
Expand All @@ -203,7 +208,7 @@ class DodoTaskLoader(TaskLoader):
def load_tasks(self, cmd, params, args):
dodo_module = loader.get_module(params['dodoFile'], params['cwdPath'],
params['seek_file'])
return self._load_from(dodo_module, cmd.CMD_LIST)
return self._load_from(cmd, dodo_module, cmd.CMD_LIST)



Expand Down
1 change: 1 addition & 0 deletions doit/cmd_run.py
Expand Up @@ -123,6 +123,7 @@ class Run(DoitCmdBase):
doc_purpose = "run tasks"
doc_usage = "[TASK/TARGET...]"
doc_description = None
execute_tasks = True

cmd_options = (opt_always, opt_continue, opt_verbosity,
opt_reporter, opt_outfile, opt_num_process,
Expand Down
69 changes: 43 additions & 26 deletions doit/loader.py
Expand Up @@ -42,7 +42,7 @@ def decorated(func):

def get_module(dodo_file, cwd=None, seek_parent=False):
"""
The python file defining tasks is called "dodo" file.
Find python module defining tasks, it is called "dodo" file.
@param dodo_file(str): path to file containing the tasks
@param cwd(str): path to be used cwd, if None use path from dodo_file
Expand Down Expand Up @@ -102,21 +102,53 @@ def exist_or_raise(path):
return __import__(os.path.splitext(file_name)[0])


def load_tasks(task_creators, command_names=()):
"""Get task generators and generate tasks
def load_tasks(namespace, command_names=(), allow_delayed=False):
"""Find task-creators and create tasks
@param task_creators: (dict) containing the task creators, it might
@param namespace: (dict) containing the task creators, it might
contain other stuff
@param command_names: (list - str) blacklist for task names
@param load_all: (bool) if True ignore doit_crate_after['executed']
`load_all == False` is used by the runner to delay the creation of
tasks until a dependent task is executed. This is only used by the `run`
command, other commands should always load all tasks since it wont execute
any task.
@return task_list (list) of Tasks in the order they were defined on the file
"""
funcs = _get_task_creators(namespace, command_names)
# sort by the order functions were defined (line number)
# TODO: this ordering doesnt make sense when generators come
# from different modules
funcs.sort(key=lambda obj:obj[2])

task_list = []
for name, ref, line in funcs:
dep_task = (allow_delayed and
hasattr(ref, 'doit_create_after') and
ref.doit_create_after.get('executed'))

if dep_task:
task_list.append(Task(name, None, loader=(ref, dep_task)))
else:
task_list.extend(generate_tasks(name, ref(), ref.__doc__))
return task_list


# get functions defined in the module and select the task generators
# a task generator function name starts with the string TASK_STRING
def _get_task_creators(namespace, command_names):
"""get functions defined in the `namespace` and select the task-creators
A task-creator is a function that:
- name starts with the string TASK_STRING
- has the attribute `create_doit_tasks`
@return (list - func) task-creators
"""
funcs = []
prefix_len = len(TASK_STRING)
# get all functions that are task_creators
for name, ref in six.iteritems(task_creators):
# get all functions that are task-creators
for name, ref in six.iteritems(namespace):

# function is a task creator because of its name
if ((inspect.isfunction(ref) or inspect.ismethod(ref)) and
Expand All @@ -139,7 +171,7 @@ def load_tasks(task_creators, command_names=()):
elif True: # coverage can't get "else: continue"
continue

# tasks cant have name of commands
# tasks can't have the same name of a commands
if task_name in command_names:
msg = ("Task can't be called '%s' because this is a command name."+
" Please choose another name.")
Expand All @@ -149,22 +181,7 @@ def load_tasks(task_creators, command_names=()):
# add to list task generator functions
funcs.append((task_name, ref, line))

# sort by the order functions were defined (line number)
# TODO: this ordering doesnt make sense when generators come
# from different modules
funcs.sort(key=lambda obj:obj[2])

task_list = []
for name, ref, line in funcs:
after = None
if hasattr(ref, 'doit_create_after'):
after = ref.doit_create_after.get('executed')

if after:
task_list.append(Task(name, None, loader=(ref, after)))
else:
task_list.extend(generate_tasks(name, ref(), ref.__doc__))
return task_list
return funcs


def load_doit_config(dodo_module):
Expand Down Expand Up @@ -259,7 +276,7 @@ def generate_tasks(func_name, gen_result, gen_doc=None):
@param gen_result: value returned by a task generator function
it can be a dict or generator (generating dicts)
@param gen_doc: (string/None) docstring from the task generator function
@return: (tuple) task, list of subtasks
@return: (list - Task)
"""
# task described as a dictionary
if isinstance(gen_result, dict):
Expand Down

0 comments on commit 3eacff4

Please sign in to comment.