From 49a7771336ce09f6d42c7699ef32aecea0e83182 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 7 Dec 2009 20:07:55 -0500 Subject: Initial directory restructuring to clarify dependencies --- libbe/command/target.py | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 libbe/command/target.py (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py new file mode 100644 index 0000000..5dd5d38 --- /dev/null +++ b/libbe/command/target.py @@ -0,0 +1,168 @@ +# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. +# Chris Ball +# Gianluca Montecchi +# Marien Zwart +# Thomas Gerigk +# W. Trevor King +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +"""Assorted bug target manipulations and queries""" +from libbe import cmdutil, bugdir +from becommands import depend +__desc__ = __doc__ + +def execute(args, manipulate_encodings=True, restrict_file_access=False, + dir="."): + """ + >>> import os, StringIO, sys + >>> bd = bugdir.SimpleBugDir() + >>> os.chdir(bd.root) + >>> execute(["a"], manipulate_encodings=False) + No target assigned. + >>> execute(["a", "tomorrow"], manipulate_encodings=False) + >>> execute(["a"], manipulate_encodings=False) + tomorrow + + >>> orig_stdout = sys.stdout + >>> tmp_stdout = StringIO.StringIO() + >>> sys.stdout = tmp_stdout + >>> execute(["--resolve", "tomorrow"], manipulate_encodings=False) + >>> sys.stdout = orig_stdout + >>> output = tmp_stdout.getvalue().strip() + >>> target = bd.bug_from_uuid(output) + >>> print target.summary + tomorrow + >>> print target.severity + target + + >>> execute(["a", "none"], manipulate_encodings=False) + >>> execute(["a"], manipulate_encodings=False) + No target assigned. + >>> bd.cleanup() + """ + parser = get_parser() + options, args = parser.parse_args(args) + cmdutil.default_complete(options, args, parser, + bugid_args={0: lambda bug : bug.active==True}) + + if (options.resolve == False and len(args) not in (1, 2)) \ + or (options.resolve == True and len(args) not in (0, 1)): + raise cmdutil.UsageError('Incorrect number of arguments.') + bd = bugdir.BugDir(from_disk=True, + manipulate_encodings=manipulate_encodings, + root=dir) + if options.resolve == True: + if len(args) == 0: + summary = None + else: + summary = args[0] + bug = bug_from_target_summary(bd, summary) + if bug == None: + print 'No target assigned.' + else: + print bug.uuid + return + bug = cmdutil.bug_from_id(bd, args[0]) + if len(args) == 1: + target = bug_target(bd, bug) + if target is None: + print "No target assigned." + else: + print target.summary + else: + if args[1] == "none": + target = remove_target(bd, bug) + else: + target = add_target(bd, bug, args[1]) + +def get_parser(): + parser = cmdutil.CmdOptionParser("be target BUG-ID [TARGET]\nor: be target --resolve [TARGET]") + parser.add_option("-r", "--resolve", action="store_true", dest="resolve", + help="Print the UUID for the target bug whose summary matches TARGET. If TARGET is not given, print the UUID of the current bugdir target. If that is not set, don't print anything.", + default=False) + return parser + +longhelp=""" +Assorted bug target manipulations and queries. + +If no target is specified, the bug's current target is printed. If +TARGET is specified, it will be assigned to the bug, creating a new +target bug if necessary. + +Targets are free-form; any text may be specified. They will generally +be milestone names or release numbers. The value "none" can be used +to unset the target. + +In the alternative `be target --resolve TARGET` form, print the UUID +of the target-bug with summary TARGET. If target is not given, return +use the bugdir's current target (see `be set`). + +If you want to list all bugs blocking the current target, try + $ be depend --status -closed,fixed,wontfix --severity -target \ + $(be target --resolve) + +If you want to set the current bugdir target by summary (rather than +by UUID), try + $ be set target $(be target --resolve SUMMARY) +""" + +def help(): + return get_parser().help_str() + longhelp + +def bug_from_target_summary(bugdir, summary=None): + if summary == None: + if bugdir.target == None: + return None + else: + return bugdir.bug_from_uuid(bugdir.target) + matched = [] + for uuid in bugdir.uuids(): + bug = bugdir.bug_from_uuid(uuid) + if bug.severity == 'target' and bug.summary == summary: + matched.append(bug) + if len(matched) == 0: + return None + if len(matched) > 1: + raise Exception('Several targets with same summary: %s' + % '\n '.join([bug.uuid for bug in matched])) + return matched[0] + +def bug_target(bugdir, bug): + if bug.severity == 'target': + return bug + matched = [] + for blocked in depend.get_blocks(bugdir, bug): + if blocked.severity == 'target': + matched.append(blocked) + if len(matched) == 0: + return None + if len(matched) > 1: + raise Exception('This bug (%s) blocks several targets: %s' + % (bug.uuid, + '\n '.join([b.uuid for b in matched]))) + return matched[0] + +def remove_target(bugdir, bug): + target = bug_target(bugdir, bug) + depend.remove_block(target, bug) + return target + +def add_target(bugdir, bug, summary): + target = bug_from_target_summary(bugdir, summary) + if target == None: + target = bugdir.new_bug(summary=summary) + target.severity = 'target' + depend.add_block(target, bug) + return target -- cgit From 4370270929db62a32d168ae221ecc70a2d80269e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 02:38:51 -0500 Subject: Transitioned target to Command-format --- libbe/command/target.py | 162 +++++++++++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 65 deletions(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 5dd5d38..39e12b2 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -18,83 +18,104 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Assorted bug target manipulations and queries""" -from libbe import cmdutil, bugdir -from becommands import depend -__desc__ = __doc__ -def execute(args, manipulate_encodings=True, restrict_file_access=False, - dir="."): - """ +import libbe +import libbe.command +import libbe.command.util +import libbe.command.depend + + + +class Target (libbe.command.Command): + """Assorted bug target manipulations and queries + >>> import os, StringIO, sys - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a"], manipulate_encodings=False) + >>> import libbe.bugdir + >>> bd = libbe.bugdir.SimpleBugDir(memory=False) + >>> cmd = Target() + >>> cmd._storage = bd.storage + >>> cmd._setup_io = lambda i_enc,o_enc : None + >>> cmd.stdout = sys.stdout + + >>> ret = cmd.run(args=['/a']) No target assigned. - >>> execute(["a", "tomorrow"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) + >>> ret = cmd.run(args=['/a', 'tomorrow']) + >>> ret = cmd.run(args=['/a']) tomorrow - >>> orig_stdout = sys.stdout - >>> tmp_stdout = StringIO.StringIO() - >>> sys.stdout = tmp_stdout - >>> execute(["--resolve", "tomorrow"], manipulate_encodings=False) - >>> sys.stdout = orig_stdout - >>> output = tmp_stdout.getvalue().strip() + >>> cmd.stdout = StringIO.StringIO() + >>> ret = cmd.run({'resolve':True}, ['tomorrow']) + >>> output = cmd.stdout.getvalue().strip() >>> target = bd.bug_from_uuid(output) >>> print target.summary tomorrow >>> print target.severity target - >>> execute(["a", "none"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) + >>> cmd.stdout = sys.stdout + >>> ret = cmd.run(args=['/a', 'none']) + >>> ret = cmd.run(args=['/a']) No target assigned. >>> bd.cleanup() """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - - if (options.resolve == False and len(args) not in (1, 2)) \ - or (options.resolve == True and len(args) not in (0, 1)): - raise cmdutil.UsageError('Incorrect number of arguments.') - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings, - root=dir) - if options.resolve == True: - if len(args) == 0: - summary = None - else: - summary = args[0] - bug = bug_from_target_summary(bd, summary) - if bug == None: - print 'No target assigned.' - else: - print bug.uuid - return - bug = cmdutil.bug_from_id(bd, args[0]) - if len(args) == 1: - target = bug_target(bd, bug) - if target is None: - print "No target assigned." + name = 'target' + + def __init__(self, *args, **kwargs): + libbe.command.Command.__init__(self, *args, **kwargs) + self.options.extend([ + libbe.command.Option(name='resolve', short_name='r', + help="Print the UUID for the target bug whose summary " + "matches TARGET. If TARGET is not given, print the UUID " + "of the current bugdir target."), + ]) + self.args.extend([ + libbe.command.Argument( + name='id', metavar='BUG-ID', default=None, + optional=True, + completion_callback=libbe.command.util.complete_bug_id), + libbe.command.Argument( + name='target', metavar='TARGET', default=None, + optional=True, + completion_callback=complete_target), + ]) + + def _run(self, **params): + if params['resolve'] == False: + if params['id'] == None: + raise libbe.command.UserError('Please specify a bug id.') else: - print target.summary - else: - if args[1] == "none": - target = remove_target(bd, bug) + if params['target'] != None: + raise libbe.command.UserError('Too many arguments') + params['target'] = params.pop('id') + bugdir = self._get_bugdir() + if params['resolve'] == True: + bug = bug_from_target_summary(bugdir, params['target']) + if bug == None: + print >> self.stdout, 'No target assigned.' + else: + print >> self.stdout, bug.uuid + return 0 + bug,dummy_comment = libbe.command.util.bug_comment_from_user_id( + bugdir, params['id']) + if params['target'] == None: + target = bug_target(bugdir, bug) + if target == None: + print >> self.stdout, 'No target assigned.' + else: + print >> self.stdout, target.summary else: - target = add_target(bd, bug, args[1]) + if params['target'] == 'none': + target = remove_target(bugdir, bug) + else: + target = add_target(bugdir, bug, params['target']) + return 0 -def get_parser(): - parser = cmdutil.CmdOptionParser("be target BUG-ID [TARGET]\nor: be target --resolve [TARGET]") - parser.add_option("-r", "--resolve", action="store_true", dest="resolve", - help="Print the UUID for the target bug whose summary matches TARGET. If TARGET is not given, print the UUID of the current bugdir target. If that is not set, don't print anything.", - default=False) - return parser + def _usage(self): + return 'usage: be %(name)s BUG-ID [TARGET]\nor: be %(name)s --resolve [TARGET]' \ + % vars(self) -longhelp=""" + def _long_help(self): + return """ Assorted bug target manipulations and queries. If no target is specified, the bug's current target is printed. If @@ -118,9 +139,6 @@ by UUID), try $ be set target $(be target --resolve SUMMARY) """ -def help(): - return get_parser().help_str() + longhelp - def bug_from_target_summary(bugdir, summary=None): if summary == None: if bugdir.target == None: @@ -143,7 +161,7 @@ def bug_target(bugdir, bug): if bug.severity == 'target': return bug matched = [] - for blocked in depend.get_blocks(bugdir, bug): + for blocked in libbe.command.depend.get_blocks(bugdir, bug): if blocked.severity == 'target': matched.append(blocked) if len(matched) == 0: @@ -156,7 +174,7 @@ def bug_target(bugdir, bug): def remove_target(bugdir, bug): target = bug_target(bugdir, bug) - depend.remove_block(target, bug) + libbe.command.depend.remove_block(target, bug) return target def add_target(bugdir, bug, summary): @@ -164,5 +182,19 @@ def add_target(bugdir, bug, summary): if target == None: target = bugdir.new_bug(summary=summary) target.severity = 'target' - depend.add_block(target, bug) + libbe.command.depend.add_block(target, bug) return target + +def targets(bugdir): + bugdir.load_all_bugs() + for bug in bugdir: + if bug.severity == 'target': + yield bug.summary + +def complete_target(command, argument, fragment=None): + """ + List possible command completions for fragment. + + argument argument is not used. + """ + return targets(command._get_bugdir()) -- cgit From eb26ca7e4a6886f97740c45e9e3b7bdd2d08d76f Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 03:05:34 -0500 Subject: Transitioned set to Command-format --- libbe/command/target.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 39e12b2..034c532 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -25,7 +25,6 @@ import libbe.command.util import libbe.command.depend - class Target (libbe.command.Command): """Assorted bug target manipulations and queries @@ -70,12 +69,10 @@ class Target (libbe.command.Command): ]) self.args.extend([ libbe.command.Argument( - name='id', metavar='BUG-ID', default=None, - optional=True, + name='id', metavar='BUG-ID', optional=True, completion_callback=libbe.command.util.complete_bug_id), libbe.command.Argument( - name='target', metavar='TARGET', default=None, - optional=True, + name='target', metavar='TARGET', optional=True, completion_callback=complete_target), ]) -- cgit From 89b7a1411e4658e831f5d635534b24355dbb941d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 15 Dec 2009 06:44:20 -0500 Subject: Fixed libbe.command.diff + ugly BugDir.duplicate_bugdir implementation duplicate_bugdir() works, but for the vcs backends, it could require shelling out for _every_ file read. This could, and probably will, be horribly slow. Still it works ;). I'm not sure what a better implementation would be. The old implementation checked out the entire earlier state into a temporary directory pros: single shell out, simple upgrade implementation cons: wouldn't work well for HTTP backens I think a good solution would run along the lines of the currently commented out code in duplicate_bugdir(), where a VersionedStorage.changed_since(revision) call would give you a list of changed files. diff could work off of that directly, without the need to generate a whole duplicate bugdir. I'm stuck on how to handle upgrades though... Also removed trailing whitespace from all python files. --- libbe/command/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 034c532..df836db 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -58,7 +58,7 @@ class Target (libbe.command.Command): >>> bd.cleanup() """ name = 'target' - + def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) self.options.extend([ -- cgit From e2b648f2148d7b6550fb3a4bcfde4eff714a7ec6 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 28 Dec 2009 10:56:04 -0500 Subject: Allow external use of Command.usage() and use CmdOptionParser.set_usage() This fixes $ python be diff -2 Usage: be [options] be: error: no such option: -2 and we now get the correct output $ python be diff -2 Usage: be diff [options] [REVISION] be: error: no such option: -2 --- libbe/command/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index df836db..3195f95 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -107,7 +107,7 @@ class Target (libbe.command.Command): target = add_target(bugdir, bug, params['target']) return 0 - def _usage(self): + def usage(self): return 'usage: be %(name)s BUG-ID [TARGET]\nor: be %(name)s --resolve [TARGET]' \ % vars(self) -- cgit From cfae8a8302f06a84196700138d7ddbb25e91ea31 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 31 Dec 2009 14:32:39 -0500 Subject: Added UserInterface and other improved abstractions for command handling --- libbe/command/target.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 3195f95..9f8feae 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -31,30 +31,32 @@ class Target (libbe.command.Command): >>> import os, StringIO, sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Target() - >>> cmd._storage = bd.storage - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Target(ui=ui) - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a']) No target assigned. - >>> ret = cmd.run(args=['/a', 'tomorrow']) - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a', 'tomorrow']) + >>> ret = ui.run(cmd, args=['/a']) tomorrow - >>> cmd.stdout = StringIO.StringIO() - >>> ret = cmd.run({'resolve':True}, ['tomorrow']) - >>> output = cmd.stdout.getvalue().strip() + >>> ui.io.stdout = StringIO.StringIO() + >>> ret = ui.run(cmd, {'resolve':True}, ['tomorrow']) + >>> output = ui.io.get_stdout().strip() >>> target = bd.bug_from_uuid(output) >>> print target.summary tomorrow >>> print target.severity target - >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(args=['/a', 'none']) - >>> ret = cmd.run(args=['/a']) + >>> ui.io.stdout = sys.stdout + >>> ret = ui.run(cmd, args=['/a', 'none']) + >>> ret = ui.run(cmd, args=['/a']) No target assigned. + >>> ui.cleanup() >>> bd.cleanup() """ name = 'target' -- cgit From 4d4283ecd654f1efb058cd7f7dba6be88b70ee92 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 1 Jan 2010 08:11:08 -0500 Subject: Updated copyright information --- libbe/command/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 9f8feae..0161772 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -1,4 +1,4 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. +# Copyright (C) 2005-2010 Aaron Bentley and Panometrics, Inc. # Chris Ball # Gianluca Montecchi # Marien Zwart -- cgit From 7e8237f5004a86be0bd90c77e0640cd265a61d72 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 20 Jan 2010 12:28:26 -0500 Subject: Add entry points for functionality needed by CFBE (and probably other UIs) --- libbe/command/target.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 0161772..4bfe82e 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -185,15 +185,24 @@ def add_target(bugdir, bug, summary): return target def targets(bugdir): + """Generate all possible target bug summaries.""" bugdir.load_all_bugs() for bug in bugdir: if bug.severity == 'target': yield bug.summary -def complete_target(command, argument, fragment=None): +def target_dict(bugdir): """ - List possible command completions for fragment. - - argument argument is not used. + Return a dict with bug UUID keys and bug summary values for all + target bugs. """ + ret = {} + bugdir.load_all_bugs() + for bug in bugdir: + if bug.severity == 'target': + ret[bug.uuid] = bug.summary + return ret + +def complete_target(command, argument, fragment=None): + """List possible command completions for fragment.""" return targets(command._get_bugdir()) -- cgit From e531ce31bd50db83919864fe3738914126337e91 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 21 Jan 2010 12:52:24 -0500 Subject: Ajdust Target tests for cached BugDir.uuids() implementation --- libbe/command/target.py | 1 + 1 file changed, 1 insertion(+) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 4bfe82e..6bb348f 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -46,6 +46,7 @@ class Target (libbe.command.Command): >>> ui.io.stdout = StringIO.StringIO() >>> ret = ui.run(cmd, {'resolve':True}, ['tomorrow']) >>> output = ui.io.get_stdout().strip() + >>> bd.flush_reload() >>> target = bd.bug_from_uuid(output) >>> print target.summary tomorrow -- cgit From 35e12f3d56dfc21c49f7e49a59ecf875a7770715 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 23 Jan 2010 18:51:57 -0500 Subject: Fix vars call for `be target --help` --- libbe/command/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/command/target.py') diff --git a/libbe/command/target.py b/libbe/command/target.py index 6bb348f..f8a956b 100644 --- a/libbe/command/target.py +++ b/libbe/command/target.py @@ -112,7 +112,7 @@ class Target (libbe.command.Command): def usage(self): return 'usage: be %(name)s BUG-ID [TARGET]\nor: be %(name)s --resolve [TARGET]' \ - % vars(self) + % vars(self.__class__) def _long_help(self): return """ -- cgit