Merge lp:~javier.collado/doit/bug425811 into lp:doit

Proposed by Javier Collado
Status: Merged
Merged at revision: not available
Proposed branch: lp:~javier.collado/doit/bug425811
Merge into: lp:doit
Diff against target: None lines
To merge this branch: bzr merge lp:~javier.collado/doit/bug425811
Reviewer Review Type Date Requested Status
schettino72 Approve
Review via email: mp+11318@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Javier Collado (javier.collado) wrote :

This branch provides a way to print some documentation when displaying the task list in a dodo file using the 'list' subcommand. To display the documentation the '-v', '--verbose' option must be passed. Otherwise, the same option as in the past will be passed.

The task documentation is extracted from:
- 'doc' key in the task dictionary
- Documentation string in task generator if available

lp:~javier.collado/doit/bug425811 updated
129. By Javier Collado

verbose parameter is now options to avoid breaking test cases

Revision history for this message
schettino72 (schettino72) wrote :

I like the idea :)

* the verbose option should be true by default. so the 'list' should have an option to turn off verbose mode. (the default for the function main.py:doit_list doesn't matter)

* the docstring of the task doesnt work if the task yields sub-tasks.

* please dont put space around "=" for function parameters:
use => def doit_list(task_list, printSubtasks, verbose=False)
instead of => def doit_list(task_list, printSubtasks, verbose = False)

* I think we should get rid of those print statements
print "===== Tasks ====="
print "================="

* you use a ":" right after the task name. please include some space after the task name.

* I would prefer that the printed doc for a task to be limited by a single line. and the task doc be printed in the same line. if you want more lines you can keep it. or maybe create different verbosity levels.

* please write tests

review: Needs Fixing
Revision history for this message
Javier Collado (javier.collado) wrote :

Thanks for your comments. I'll go through them and let you know when code is ready for a new review.

lp:~javier.collado/doit/bug425811 updated
130. By Javier Collado

Verbose option changed to quiet so printing the task documentation now is the default

131. By Javier Collado

Parenthesis removed for default values

132. By Javier Collado

Print statements for headers removed

133. By Javier Collado

Space added between task name and colon mark

134. By Javier Collado

Only first non-empty documentation line is printed

135. By Javier Collado

Updating old tests

136. By Javier Collado

Test cases that check documentation strings output added

137. By Javier Collado

Quiet test cases added to verify that documentation isn't printed in quiet mode

138. By Javier Collado

Merge from trunk

Revision history for this message
Javier Collado (javier.collado) wrote :

Latest branch revision should cover everything except for:

* the docstring of the task doesnt work if the task yields sub-tasks.

I'd say that the doc string from the generator shouldn't be used in the sub-tasks to avoid having multiple tasks with the same documentation string (which isn't very useful). Were you thinking about another solution?

Revision history for this message
schettino72 (schettino72) wrote :

> * the docstring of the task doesnt work if the task yields sub-tasks.
>
> I'd say that the doc string from the generator shouldn't be used in the sub-tasks to avoid having multiple tasks with the same documentation string (which isn't very useful). Were you thinking about another solution?

I have not looked at the branch yet... but what i mean is:

FILES = [file1, ...]
def task_pyflakes():
     """doc for group. execute pyflakes on all files"""
     for f in FILES:
         yield {'actions': ["pyflakes %s " % f],
                 'doc': "doc for sub-task"}

you should get the docstring as documentation for "pyflakes" top task
but not for each sub-task.

$ doit list

pyflakes : doc for group. execute pyflakes on all files

$ doit list --all

pyflakes : doc for group. execute pyflakes on all files
pyflakes:file1 : doc for sub-task
....

Revision history for this message
Javier Collado (javier.collado) wrote :

Ok, we have the same understanding about how should it work. Let me write a few test cases to verify that (I've just realized that pyflakes in your example gets no documentation at all) and I'll ask for another review.

lp:~javier.collado/doit/bug425811 updated
139. By Javier Collado

Added test to make sure that documentation strings are correctly generated either from doc dictionary key or from generator documentation string
Documentation string not being used for generators fixed.

Revision history for this message
Javier Collado (javier.collado) wrote :

Test case added and problem fixed in rev 139. Ready for a new review round.

Revision history for this message
schettino72 (schettino72) wrote :

merged on 131.

there was a bug handling docstrings containing only empty lines.

I am not very happy with the output formating... it is hard to read. I guess 2 columns would look better.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/doit'
2--- bin/doit 2009-09-06 05:01:33 +0000
3+++ bin/doit 2009-09-07 16:57:25 +0000
4@@ -131,12 +131,19 @@
5 'help': "list include all sub-tasks from dodo file"
6 }
7
8+opt_list_verbose = {'name': 'verbose',
9+ 'short': 'v',
10+ 'long': 'verbose',
11+ 'type': bool,
12+ 'default': False,
13+ 'help': 'print tasks documentation'}
14+
15 # TODO list should support "args" as a filter.
16 def cmd_list(params, args):
17 dodo_module = main.get_module(params['dodoFile'])
18 command_names = params['sub'].keys()
19 dodo_tasks = main.load_task_generators(dodo_module, command_names)
20- return main.doit_list(dodo_tasks['task_list'], params['all'])
21+ return main.doit_list(dodo_tasks['task_list'], params['all'], params['verbose'])
22
23
24 ##########################################################
25@@ -304,7 +311,7 @@
26 subCmd['run'] = cmdparse.Command('run', run_options, cmd_run, run_doc)
27
28 # list command
29- list_options = (opt_dodo, opt_listall)
30+ list_options = (opt_dodo, opt_listall, opt_list_verbose)
31 subCmd['list'] = cmdparse.Command('list', list_options, cmd_list, list_doc)
32
33 # forget command
34
35=== modified file 'lib/doit/main.py'
36--- lib/doit/main.py 2009-09-06 05:01:33 +0000
37+++ lib/doit/main.py 2009-09-07 16:57:25 +0000
38@@ -2,6 +2,7 @@
39 import os
40 import sys
41 import inspect
42+import itertools
43
44 from doit.util import isgenerator
45 from doit.task import InvalidTask, Task, dict_to_task
46@@ -79,7 +80,7 @@
47 # generate all tasks
48 task_list = []
49 for name, ref, line in funcs:
50- task_list.extend(generate_tasks(name, ref()))
51+ task_list.extend(generate_tasks(name, ref(), ref.__doc__))
52
53 # get default tasks
54 default_tasks = getattr(dodo_module, 'DEFAULT_TASKS', None)
55@@ -91,7 +92,7 @@
56 return {'task_list': task_list,
57 'default_tasks': default_tasks}
58
59-def generate_tasks(name, gen_result):
60+def generate_tasks(name, gen_result, gen_doc = None):
61 """Create tasks from a task generator result.
62
63 @param name: (string) name of taskgen function
64@@ -104,6 +105,12 @@
65 raise InvalidTask("Task %s. Only subtasks use field name."%name)
66
67 gen_result['name'] = name
68+
69+ # Use task generator documentation
70+ # if no documentation present in task list
71+ if not 'doc' in gen_result:
72+ gen_result['doc'] = gen_doc
73+
74 return [dict_to_task(gen_result)]
75
76 # a generator
77@@ -280,7 +287,7 @@
78
79
80
81-def doit_list(task_list, printSubtasks):
82+def doit_list(task_list, printSubtasks, verbose):
83 """List task generators, in the order they were defined.
84
85 @param printSubtasks: (bool) print subtasks
86@@ -288,7 +295,14 @@
87 print "==== Tasks ===="
88 for task in task_list:
89 if (not task.is_subtask) or printSubtasks:
90- print task.name
91+ task_str = task.name
92+ if verbose and task.doc:
93+ doc_lines = [line.strip()
94+ for line in task.doc.splitlines()]
95+ doc_lines = list(itertools.dropwhile(lambda line: not line, reversed(doc_lines)))
96+ doc_lines = list(itertools.dropwhile(lambda line: not line, reversed(doc_lines)))
97+ task_str += ":\n%s\n" % "\n".join(["\t%s" % line for line in doc_lines])
98+ print task_str
99 print "="*25,"\n"
100 return 0
101
102
103=== modified file 'lib/doit/task.py'
104--- lib/doit/task.py 2009-09-06 05:01:33 +0000
105+++ lib/doit/task.py 2009-09-07 16:57:25 +0000
106@@ -228,10 +228,11 @@
107 @ivar file_dep: (list - string)
108 @ivar run_once: (bool) task without dependencies should run
109 @ivar is_subtask: (bool) indicate this task is a subtask.
110+ @ivar doc: (string) task documentation
111 """
112
113 def __init__(self,name, actions, dependencies=(),targets=(),setup=None,
114- is_subtask=False):
115+ is_subtask=False, doc=None):
116 """Init."""
117 # dependencies parameter must be a list
118 if not ((isinstance(dependencies,list)) or
119@@ -263,6 +264,7 @@
120 self.setup = setup
121 self.run_once = False
122 self.is_subtask = is_subtask
123+ self.doc = doc
124
125 # there are 3 kinds of dependencies: file, task, and folder
126 self.folder_dep = []
127@@ -334,7 +336,7 @@
128 @raise InvalidTask: If unexpected fields were passed in task_dict
129 """
130 # TASK_ATTRS: sequence of know attributes(keys) of a task dict.
131- TASK_ATTRS = ('name','actions','dependencies','targets','setup')
132+ TASK_ATTRS = ('name','actions','dependencies','targets','setup', 'doc')
133 # FIXME check field 'name'
134
135 # === DREPREACATED on 0.4 (to be removed on 0.5): START
136@@ -358,9 +360,4 @@
137 raise InvalidTask("Task %s contain invalid field: %s"%
138 (task_dict['name'],key))
139
140- return Task(task_dict.get('name'),
141- task_dict.get('actions'),
142- task_dict.get('dependencies',[]),
143- task_dict.get('targets',[]),
144- task_dict.get('setup',None),
145- )
146+ return Task(**task_dict)

Subscribers

People subscribed via source and target branches

to all changes: