Bump to 1.1.5
[gonvert] / support / todo.py
1 #!/usr/bin/env python
2
3 from __future__ import with_statement
4 import itertools
5
6
7 verbose = False
8
9
10 def tag_parser(file, tag):
11         """
12         >>> nothing = []
13         >>> for todo in tag_parser(nothing, "@todo"):
14         ...     print todo
15         ...
16         >>> one = ["@todo Help!"]
17         >>> for todo in tag_parser(one, "@todo"):
18         ...     print todo
19         ...
20         1: @todo Help!
21         >>> mixed = ["one", "@todo two", "three"]
22         >>> for todo in tag_parser(mixed, "@todo"):
23         ...     print todo
24         ...
25         2: @todo two
26         >>> embedded = ["one @todo two", "three"]
27         >>> for todo in tag_parser(embedded, "@todo"):
28         ...     print todo
29         ...
30         1: @todo two
31         >>> continuation = ["one", "@todo two", " three"]
32         >>> for todo in tag_parser(continuation, "@todo"):
33         ...     print todo
34         ...
35         2: @todo two three
36         >>> series = ["one", "@todo two", "@todo three"]
37         >>> for todo in tag_parser(series, "@todo"):
38         ...     print todo
39         ...
40         2: @todo two
41         3: @todo three
42         """
43         currentTodo = []
44         prefix = None
45         for lineNumber, line in enumerate(file):
46                 column = line.find(tag)
47                 if column != -1:
48                         if currentTodo:
49                                 yield "\n".join (currentTodo)
50                         prefix = line[0:column]
51                         currentTodo = ["%d: %s" % (lineNumber+1, line[column:].strip())]
52                 elif prefix is not None and len(prefix)+1 < len(line) and line.startswith(prefix) and line[len(prefix)].isspace():
53                         currentTodo.append (line[len(prefix):].rstrip())
54                 elif currentTodo:
55                         yield "\n".join (currentTodo)
56                         currentTodo = []
57                         prefix = None
58         if currentTodo:
59                 yield "\n".join (currentTodo)
60
61
62 def tag_finder(filename, tag):
63         todoList = []
64
65         with open(filename) as file:
66                 body = "\n".join (tag_parser(file, tag))
67         passed = not body
68         if passed:
69                 output = "No %s's for %s" % (tag, filename) if verbose else ""
70         else:
71                 header = "%s's for %s:\n" % (tag, filename) if verbose else ""
72                 output = header + body
73                 output += "\n" if verbose else ""
74
75         return (passed, output)
76
77
78 if __name__ == "__main__":
79         import sys
80         import os
81         import optparse
82
83         opar = optparse.OptionParser()
84         opar.add_option("-v", "--verbose", dest="verbose", help="Toggle verbosity", action="store_true", default=False)
85         options, args = opar.parse_args(sys.argv[1:])
86         verbose = options.verbose
87
88         bugsAsError = True
89         todosAsError = False
90
91         completeOutput = []
92         allPassed = True
93         for filename in args:
94                 bugPassed, bugOutput = tag_finder(filename, "@bug")
95                 todoPassed, todoOutput = tag_finder(filename, "@todo")
96                 output = "\n".join ([bugOutput, todoOutput])
97                 if (not bugPassed and bugsAsError) or (not todoPassed and todosAsError):
98                         allPassed = False
99                 output = output.strip()
100                 if output:
101                         completeOutput.append(filename+":\n"+output+"\n\n")
102         print "\n".join(completeOutput)
103         
104         sys.exit(0 if allPassed else 1);