1 # Copyright (C) 2009-2012 Chris Ball <cjb@laptop.org>
2 # W. Trevor King <wking@tremily.us>
4 # This file is part of Bugs Everywhere.
6 # Bugs Everywhere is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the Free
8 # Software Foundation, either version 2 of the License, or (at your option) any
11 # Bugs Everywhere is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 # You should have received a copy of the GNU General Public License along with
17 # Bugs Everywhere. If not, see <http://www.gnu.org/licenses/>.
25 class Completer (object):
26 def __init__(self, options):
27 self.options = options
28 def __call__(self, bugdirs, fragment=None):
31 def complete_command(command, argument, fragment=None):
33 List possible command completions for fragment.
35 command argument is not used.
37 return list(libbe.command.commands(command_names=True))
39 def comp_path(fragment=None):
40 """List possible path completions for fragment."""
43 comps = glob.glob(fragment+'*') + glob.glob(fragment+'/*')
44 if len(comps) == 1 and os.path.isdir(comps[0]):
45 comps.extend(glob.glob(comps[0]+'/*'))
48 def complete_path(command, argument, fragment=None):
49 """List possible path completions for fragment."""
50 return comp_path(fragment)
52 def complete_status(command, argument, fragment=None):
53 bd = sorted(command._get_bugdirs().items())[1]
55 return libbe.bug.status_values
57 def complete_severity(command, argument, fragment=None):
58 bd = sorted(command._get_bugdirs().items())[1]
60 return libbe.bug.severity_values
62 def assignees(bugdirs):
64 for bugdir in bugdirs.values():
65 bugdir.load_all_bugs()
66 ret.update(set([bug.assigned for bug in bugdir
67 if bug.assigned != None]))
70 def complete_assigned(command, argument, fragment=None):
71 return assignees(command._get_bugdirs())
73 def complete_extra_strings(command, argument, fragment=None):
78 def complete_bugdir_id(command, argument, fragment=None):
79 bugdirs = command._get_bugdirs()
82 def complete_bug_id(command, argument, fragment=None):
83 return complete_bug_comment_id(command, argument, fragment,
86 def complete_bug_comment_id(command, argument, fragment=None,
87 active_only=True, comments=True):
90 bugdirs = command._get_bugdirs()
91 if fragment == None or len(fragment) == 0:
94 p = libbe.util.id.parse_user(bugdirs, fragment)
96 root,residual = (fragment, None)
97 if not root.endswith('/'):
99 except libbe.util.id.InvalidIDStructure, e:
101 except libbe.util.id.NoIDMatches:
103 except libbe.util.id.MultipleIDMatches, e:
105 # choose among bugdirs
109 root,residual = libbe.util.id.residual(common, fragment)
110 p = libbe.util.id.parse_user(bugdirs, e.common)
112 if matches == None: # fragment was complete, get a list of children uuids
113 if p['type'] == 'bugdir':
114 bugdir = bugdirs[p['bugdir']]
115 matches = bugdir.uuids()
116 common = bugdir.id.user()
117 elif p['type'] == 'bug':
118 if comments == False:
120 bugdir = bugdirs[p['bugdir']]
121 bug = bugdir.bug_from_uuid(p['bug'])
122 matches = bug.uuids()
123 common = bug.id.user()
125 assert p['type'] == 'comment', p
127 if p['type'] == 'bugdir':
128 bugdir = bugdirs[p['bugdir']]
129 child_fn = bugdir.bug_from_uuid
130 elif p['type'] == 'bug':
131 if comments == False:
133 bugdir = bugdirs[p['bugdir']]
135 bug = bugdir.bug_from_uuid(p['bug'])
136 child_fn = bug.comment_from_uuid
137 elif p['type'] == 'comment':
138 assert matches == None, matches
145 possible.append(id.replace(common, root))
148 def select_values(string, possible_values, name="unkown"):
150 This function allows the user to select values from a list of
151 possible values. The default is to select all the values:
153 >>> select_values(None, ['abc', 'def', 'hij'])
154 ['abc', 'def', 'hij']
156 The user selects values with a comma-separated limit_string.
157 Prepending a minus sign to such a list denotes blacklist mode:
159 >>> select_values('-abc,hij', ['abc', 'def', 'hij'])
162 Without the leading -, the selection is in whitelist mode:
164 >>> select_values('abc,hij', ['abc', 'def', 'hij'])
167 In either case, appropriate errors are raised if on of the
168 user-values is not in the list of possible values. The name
169 parameter lets you make the error message more clear:
171 >>> select_values('-xyz,hij', ['abc', 'def', 'hij'], name="foobar")
172 Traceback (most recent call last):
174 UserError: Invalid foobar xyz
175 ['abc', 'def', 'hij']
176 >>> select_values('xyz,hij', ['abc', 'def', 'hij'], name="foobar")
177 Traceback (most recent call last):
179 UserError: Invalid foobar xyz
180 ['abc', 'def', 'hij']
182 possible_values = list(possible_values) # don't alter the original
185 elif string.startswith('-'):
186 blacklisted_values = set(string[1:].split(','))
187 for value in blacklisted_values:
188 if value not in possible_values:
189 raise libbe.command.UserError('Invalid %s %s\n %s'
190 % (name, value, possible_values))
191 possible_values.remove(value)
193 whitelisted_values = string.split(',')
194 for value in whitelisted_values:
195 if value not in possible_values:
196 raise libbe.command.UserError(
198 % (name, value, possible_values))
199 possible_values = whitelisted_values
200 return possible_values
202 def bugdir_bug_comment_from_user_id(bugdirs, id):
203 p = libbe.util.id.parse_user(bugdirs, id)
204 if not p['type'] in ['bugdir', 'bug', 'comment']:
205 raise libbe.command.UserError(
206 '{} is a {} id, not a bugdir, bug, or comment id'.format(
208 if p['bugdir'] not in bugdirs:
209 raise libbe.command.UserError(
210 "{} doesn't belong to any bugdirs in {}".format(
211 id, sorted(bugdirs.keys())))
212 bugdir = bugdirs[p['bugdir']]
213 if p['bugdir'] != bugdir.uuid:
214 raise libbe.command.UserError(
215 "%s doesn't belong to this bugdir (%s)"
218 bug = bugdir.bug_from_uuid(p['bug'])
220 comment = bug.comment_from_uuid(p['comment'])
222 comment = bug.comment_root
225 return (bugdir, bug, comment)
227 def bug_from_uuid(bugdirs, uuid):
229 for bugdir in bugdirs.values():
231 bug = bugdir.bug_from_uuid(uuid)
232 except libbe.bugdir.NoBugMatches as e: