From 1b9c628529848af370adbc67b5ba298236a1b86d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 14 Dec 2009 23:15:58 -0500 Subject: [PATCH] Transitioned severity to Command-format, also added Command._get_*() The old .requires_* thing was rediculous. The new ._get_*() callbacks allow the caller to provide a means for getting the expensive structures, which the command can use, or not, as required. This will also make it easier to implement the completion callbacks. The callbacks should probably have matching .set_*() methods, to avoid the current cache tweaking cmd._storage = ... etc. But that can wait for now... --- libbe/command/assign.py | 31 +++++---- libbe/command/base.py | 73 ++++++++++++++----- libbe/command/comment.py | 13 ++-- libbe/command/commit.py | 10 +-- libbe/command/depend.py | 21 +++--- libbe/command/due.py | 15 ++-- libbe/command/help.py | 5 +- libbe/command/html.py | 7 +- libbe/command/import_xml.py | 12 ++-- libbe/command/init.py | 10 +-- libbe/command/list.py | 10 +-- libbe/command/merge.py | 9 +-- libbe/command/new.py | 7 +- libbe/command/remove.py | 7 +- libbe/command/severity.py | 135 +++++++++++++++++------------------- libbe/ui/command_line.py | 23 ++---- libbe/ui/util/cmdutil.py | 14 ---- 17 files changed, 208 insertions(+), 194 deletions(-) diff --git a/libbe/command/assign.py b/libbe/command/assign.py index 241c815..6cf74bc 100644 --- a/libbe/command/assign.py +++ b/libbe/command/assign.py @@ -30,24 +30,25 @@ class Assign (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Assign() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> bd.bug_from_uuid('a').assigned is None True - >>> ret = cmd.run(bd.storage, bd, {'user-id':u'Fran\xe7ois'}, ['-', '/a']) + >>> ret = cmd.run({'user-id':u'Fran\xe7ois'}, ['-', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned u'Fran\\xe7ois' - >>> ret = cmd.run(bd.storage, bd, args=['someone', '/a', '/b']) + >>> ret = cmd.run(args=['someone', '/a', '/b']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned 'someone' >>> bd.bug_from_uuid('b').assigned 'someone' - >>> ret = cmd.run(bd.storage, bd, args=['none', '/a']) + >>> ret = cmd.run(args=['none', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned is None True @@ -57,10 +58,9 @@ class Assign (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.args.extend([ libbe.command.Argument( - name='assignee', metavar='ASSIGNEE', default=None, + name='assigned', metavar='ASSIGNED', default=None, completion_callback=libbe.command.util.complete_assigned), libbe.command.Argument( name='bug-id', metavar='BUG-ID', default=None, @@ -68,27 +68,28 @@ class Assign (libbe.command.Command): completion_callback=libbe.command.util.complete_bug_id), ]) - def _run(self, storage, bugdir, **params): - assignee = params['assignee'] - if assignee == 'none': - assignee = None - elif assignee == '-': - assignee = params['user-id'] + def _run(self, **params): + assigned = params['assigned'] + if assigned == 'none': + assigned = None + elif assigned == '-': + assigned = self._get_user_id() + bugdir = self._get_bugdir() for bug_id in params['bug-id']: bug,dummy_comment = \ libbe.command.util.bug_comment_from_user_id(bugdir, bug_id) - if bug.assigned != assignee: - bug.assigned = assignee + if bug.assigned != assigned: + bug.assigned = assigned return 0 def _long_help(self): return """ Assign a person to fix a bug. -Assignees should be the person's Bugs Everywhere identity, the same +Assigneds should be the person's Bugs Everywhere identity, the same string that appears in Creator fields. -Special assignee strings: +Special assigned strings: "-" assign the bug to yourself "none" un-assigns the bug """ diff --git a/libbe/command/base.py b/libbe/command/base.py index 54463c8..2aaf51e 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -177,16 +177,15 @@ class Command (object): name = 'command' - def __init__(self, input_encoding=None, output_encoding=None): + def __init__(self, input_encoding=None, output_encoding=None, + get_unconnected_storage=None, ui=None): + self.input_encoding = input_encoding + self.output_encoding = output_encoding + self.get_unconnected_storage = get_unconnected_storage + self.ui = ui # calling user-interface, e.g. for Help() self.status = None self.result = None - self.ui = None # calling user-interface, e.g. for Help() - self.requires_bugdir = False - self.requires_storage = False - self.requires_unconnected_storage = False self.restrict_file_access = True - self.input_encoding = None - self.output_encoding = None self.options = [ Option(name='help', short_name='h', help='Print a help message.', @@ -197,7 +196,7 @@ class Command (object): ] self.args = [] - def run(self, storage=None, bugdir=None, options=None, args=None): + def run(self, options=None, args=None): if options == None: options = {} if args == None: @@ -213,9 +212,7 @@ class Command (object): params[option.name] = False assert 'user-id' not in params, params['user-id'] if 'user-id' in options: - params['user-id'] = options.pop('user-id') - else: - params['user-id'] = libbe.ui.util.user.get_user_id(storage) + self._user_id = options.pop('user-id') if len(options) > 0: raise UserError, 'Invalid option passed to command %s:\n %s' \ % (self.name, '\n '.join(['%s: %s' % (k,v) @@ -253,11 +250,11 @@ class Command (object): params.pop('complete') self._setup_io(self.input_encoding, self.output_encoding) - self.status = self._run(storage, bugdir, **params) + self.status = self._run(**params) return self.status - def _run(self, storage, bugdir, **kwargs): - pass + def _run(self, **kwargs): + raise NotImplementedError def _setup_io(self, input_encoding=None, output_encoding=None): if input_encoding == None: @@ -306,7 +303,7 @@ class Command (object): return argument.completion_callback(self, argument, fragment) return [] # the particular argument doesn't supply completion info - def check_restricted_access(self, storage, path): + def _check_restricted_access(self, storage, path): """ Check that the file at path is inside bugdir.root. This is important if you allow other users to execute becommands with @@ -322,15 +319,15 @@ class Command (object): >>> s.repo = os.path.expanduser('~/x/') >>> c = Command() >>> try: - ... c.check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) + ... c._check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) ... except UserError, e: ... assert str(e).startswith('file access restricted!'), str(e) ... print 'we got the expected error' we got the expected error - >>> c.check_restricted_access(s, os.path.expanduser('~/x')) - >>> c.check_restricted_access(s, os.path.expanduser('~/x/y')) + >>> c._check_restricted_access(s, os.path.expanduser('~/x')) + >>> c._check_restricted_access(s, os.path.expanduser('~/x/y')) >>> c.restrict_file_access = False - >>> c.check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) + >>> c._check_restricted_access(s, os.path.expanduser('~/.ssh/id_rsa')) """ if self.restrict_file_access == True: path = os.path.abspath(path) @@ -339,3 +336,41 @@ class Command (object): return raise UserError('file access restricted!\n %s not in %s' % (path, repo)) + + def _get_unconnected_storage(self): + """Callback for use by commands that need it.""" + if not hasattr(self, '_unconnected_storage'): + if self.get_unconnected_storage == None: + raise NotImplementedError + self._unconnected_storage = self.get_unconnected_storage() + return self._unconnected_storage + + def _get_storage(self): + """ + Callback for use by commands that need it. + + Note that with the current implementation, + _get_unconnected_storage() will not work after this method + runs, but that shouldn't be an issue for any command I can + think of... + """ + if not hasattr(self, '_storage'): + self._storage = self._get_unconnected_storage() + self._storage.connect() + return self._storage + + def _get_bugdir(self): + """Callback for use by commands that need it.""" + if not hasattr(self, '_bugdir'): + self._bugdir = libbe.bugdir.BugDir(self._get_storage(), from_storage=True) + return self._bugdir + + def _get_user_id(self): + """Callback for use by commands that need it.""" + if not hasattr(self, '_user_id'): + self._user_id = libbe.ui.util.user.get_user_id(self._get_storage()) + return self._user_id + + def cleanup(self): + if hasattr(self, '_storage'): + self._storage.disconnect() diff --git a/libbe/command/comment.py b/libbe/command/comment.py index 23def57..cb0dcbb 100644 --- a/libbe/command/comment.py +++ b/libbe/command/comment.py @@ -34,10 +34,11 @@ class Comment (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Comment() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(bd.storage, bd, {'user-id':u'Fran\\xe7ois'}, + >>> ret = cmd.run({'user-id':u'Fran\\xe7ois'}, ... ['/a', 'This is a comment about a']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('a') @@ -57,12 +58,12 @@ class Comment (libbe.command.Command): >>> if 'EDITOR' in os.environ: ... del os.environ['EDITOR'] - >>> ret = cmd.run(bd.storage, bd, {'user-id':u'Frank'}, ['/b']) + >>> ret = cmd.run({'user-id':u'Frank'}, ['/b']) Traceback (most recent call last): UserError: No comment supplied, and EDITOR not specified. >>> os.environ['EDITOR'] = "echo 'I like cheese' > " - >>> ret = cmd.run(bd.storage, bd, {'user-id':u'Frank'}, ['/b']) + >>> ret = cmd.run({'user-id':u'Frank'}, ['/b']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('b') >>> bug.load_comments(load_full=False) @@ -76,7 +77,6 @@ class Comment (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='author', short_name='a', help='Set the comment author', @@ -101,7 +101,8 @@ class Comment (libbe.command.Command): completion_callback=libbe.command.util.complete_assigned), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() bug,parent = \ libbe.command.util.bug_comment_from_user_id(bugdir, params['id']) if params['comment'] == None: @@ -133,7 +134,7 @@ class Comment (libbe.command.Command): if not body.endswith('\n'): body+='\n' if params['author'] == None: - params['author'] = params['user-id'] + params['author'] = self._get_user_id() new = parent.new_reply(body=body) for key in ['alt-id', 'author', 'content-type']: diff --git a/libbe/command/commit.py b/libbe/command/commit.py index f795e80..4ef619c 100644 --- a/libbe/command/commit.py +++ b/libbe/command/commit.py @@ -40,11 +40,11 @@ class Commit (libbe.command.Command): >>> vcs.repo = dir.path >>> vcs.init() >>> vcs.connect() + >>> cmd._storage = vcs >>> if vcs.name in libbe.storage.vcs.base.VCS_ORDER: ... bd = libbe.bugdir.BugDir(vcs, from_storage=False) ... bd.extra_strings = ['hi there'] - ... cmd.run(vcs, None, {'user-id':'Joe'}, - ... ['Making a commit']) # doctest: +ELLIPSIS + ... cmd.run({'user-id':'Joe'}, ['Making a commit']) # doctest: +ELLIPSIS ... else: ... print 'Committed ...' Committed ... @@ -56,7 +56,6 @@ class Commit (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_storage = True self.options.extend([ libbe.command.Option(name='body', short_name='b', help='Provide the detailed body for the commit message. In the special case that FILE == "EDITOR", spawn an editor to enter the body text (in which case you cannot use stdin for the summary)', @@ -70,20 +69,21 @@ class Commit (libbe.command.Command): name='comment', metavar='COMMENT', default=None), ]) - def _run(self, storage, bugdir=None, **params): + def _run(self, **params): if params['comment'] == '-': # read summary from stdin assert params['body'] != 'EDITOR', \ 'Cannot spawn and editor when the summary is using stdin.' summary = sys.stdin.readline() else: summary = params['comment'] + storage = self._get_storage() if params['body'] == None: body = None elif params['body'] == 'EDITOR': body = libbe.ui.util.editor.editor_string( 'Please enter your commit message above') else: - self.check_restricted_access(storage, params['body']) + self._check_restricted_access(storage, params['body']) body = libbe.util.encoding.get_file_contents( params['body'], decode=True) try: diff --git a/libbe/command/depend.py b/libbe/command/depend.py index 471fd28..5e476fc 100644 --- a/libbe/command/depend.py +++ b/libbe/command/depend.py @@ -46,40 +46,40 @@ class Depend (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Depend() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(bd.storage, bd, {}, ['/a', '/b']) + >>> ret = cmd.run(args=['/a', '/b']) a blocked by: b - >>> ret = cmd.run(bd.storage, bd, {}, ['/a']) + >>> ret = cmd.run(args=['/a']) a blocked by: b - >>> ret = cmd.run(bd.storage, bd, {'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE a blocked by: b closed - >>> ret = cmd.run(bd.storage, bd, {}, ['/b', '/a']) + >>> ret = cmd.run(args=['/b', '/a']) b blocked by: a b blocks: a - >>> ret = cmd.run(bd.storage, bd, {'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = cmd.run({'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE a blocked by: b closed a blocks: b closed - >>> ret = cmd.run(bd.storage, bd, {'repair':True}) - >>> ret = cmd.run(bd.storage, bd, {'remove':True}, ['/b', '/a']) + >>> ret = cmd.run({'repair':True}) + >>> ret = cmd.run({'remove':True}, ['/b', '/a']) b blocks: a - >>> ret = cmd.run(bd.storage, bd, {'remove':True}, ['/a', '/b']) + >>> ret = cmd.run({'remove':True}, ['/a', '/b']) >>> bd.cleanup() """ name = 'depend' def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='remove', short_name='r', help='Remove dependency (instead of adding it)'), @@ -114,7 +114,7 @@ class Depend (libbe.command.Command): completion_callback=libbe.command.util.complete_bug_id), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): if params['repair'] == True and params['bug-id'] != None: raise libbe.command.UsageError( 'No arguments with --repair calls.') @@ -125,6 +125,7 @@ class Depend (libbe.command.Command): and params['blocking-bug-id'] != None: raise libbe.command.UsageError( 'Only one bug id used in tree mode.') + bugdir = self._get_bugdir() if params['repair'] == True: good,fixed,broken = check_dependencies(bugdir, repair_broken_links=True) assert len(broken) == 0, broken diff --git a/libbe/command/due.py b/libbe/command/due.py index 372f10a..119115c 100644 --- a/libbe/command/due.py +++ b/libbe/command/due.py @@ -28,16 +28,17 @@ class Due (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Due() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(bd.storage, bd, {}, ['/a']) + >>> ret = cmd.run(args=['/a']) No due date assigned. - >>> ret = cmd.run(bd.storage, bd, {}, ['/a', 'Thu, 01 Jan 1970 00:00:00 +0000']) - >>> ret = cmd.run(bd.storage, bd, {}, ['/a']) + >>> ret = cmd.run(args=['/a', 'Thu, 01 Jan 1970 00:00:00 +0000']) + >>> ret = cmd.run(args=['/a']) Thu, 01 Jan 1970 00:00:00 +0000 - >>> ret = cmd.run(bd.storage, bd, {}, ['/a', 'none']) - >>> ret = cmd.run(bd.storage, bd, {}, ['/a']) + >>> ret = cmd.run(args=['/a', 'none']) + >>> ret = cmd.run(args=['/a']) No due date assigned. >>> bd.cleanup() """ @@ -45,7 +46,6 @@ class Due (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.args.extend([ libbe.command.Argument( name='bug-id', metavar='BUG-ID', @@ -54,7 +54,8 @@ class Due (libbe.command.Command): name='due', metavar='DUE', optional=True), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() bug,dummy_comment = libbe.command.util.bug_comment_from_user_id( bugdir, params['bug-id']) if params['due'] == None: diff --git a/libbe/command/help.py b/libbe/command/help.py index c8d700d..6e55598 100644 --- a/libbe/command/help.py +++ b/libbe/command/help.py @@ -54,14 +54,15 @@ class Help (libbe.command.Command): completion_callback=self.complete_topic) ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): if params['topic'] == None: if hasattr(self.ui, 'help'): self.ui.help() elif params['topic'] in libbe.command.commands(): module = libbe.command.get_command(params['topic']) Class = libbe.command.get_command_class(module,params['topic']) - c = Class() + c = Class(get_unconnected_storage=self.get_unconnected_storage, + ui=self.ui) print >> self.stdout, c.help().rstrip('\n') elif params['topic'] in TOPICS: print >> self.stdout, TOPICS[params['topic']].rstrip('\n') diff --git a/libbe/command/html.py b/libbe/command/html.py index 485753f..0f993ae 100644 --- a/libbe/command/html.py +++ b/libbe/command/html.py @@ -37,12 +37,13 @@ class HTML (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = HTML() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> cwd = os.getcwd() >>> os.chdir(bd.storage.repo) - >>> ret = cmd.run(bd.storage, bd) + >>> ret = cmd.run() >>> os.path.exists('./html_export') True >>> os.path.exists('./html_export/index.html') @@ -62,7 +63,6 @@ class HTML (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='output', short_name='o', help='Set the output path (%default)', @@ -96,10 +96,11 @@ class HTML (libbe.command.Command): help='Verbose output, default is %default'), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): if params['export-template'] == True: html_gen.write_default_template(params['export-template-dir']) return 0 + bugdir = self._get_bugdir() bugdir.load_all_bugs() html_gen = HTMLGen(bugdir, template=params['template-dir'], diff --git a/libbe/command/import_xml.py b/libbe/command/import_xml.py index f06c741..e73d90f 100644 --- a/libbe/command/import_xml.py +++ b/libbe/command/import_xml.py @@ -45,12 +45,13 @@ class Import_XML (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Import_XML() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> cmd.stdin = StringIO.StringIO('cThis is a comment about a') >>> cmd.stdin.encoding = 'ascii' - >>> ret = cmd.run(bd.storage, bd, {'comment-root':'/a'}, ['-']) + >>> ret = cmd.run({'comment-root':'/a'}, ['-']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('a') >>> bug.load_comments(load_full=False) @@ -68,7 +69,6 @@ class Import_XML (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='ignore-missing-references', short_name='i', help="If any comment's refers to a non-existent comment, ignore it (instead of raising an exception)."), @@ -85,7 +85,8 @@ class Import_XML (libbe.command.Command): name='xml-file', metavar='XML-FILE'), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() writeable = bugdir.storage.writeable bugdir.storage.writeable = False if params['comment-root'] != None: @@ -113,7 +114,7 @@ class Import_XML (libbe.command.Command): if params['xml-file'] == '-': xml = self.stdin.read().encode(self.stdin.encoding) else: - self.check_restricted_access(storage, params['xml-file']) + self._check_restricted_access(storage, params['xml-file']) xml = libbe.util.encoding.get_file_contents( params['xml-file']) @@ -321,6 +322,7 @@ if libbe.TESTING == True: def setUp(self): self.bugdir = libbe.bugdir.SimpleBugDir(memory=False) self.cmd = Import_XML() + self.cmd._storage = self.bugdir.storage self.cmd._setup_io = lambda i_enc,o_enc : None bugA = self.bugdir.bug_from_uuid('a') self.bugdir.remove_bug(bugA) @@ -364,7 +366,7 @@ if libbe.TESTING == True: def tearDown(self): self.bugdir.cleanup() def _execute(self, params={}, args=[]): - self.cmd.run(self.bugdir.storage, self.bugdir, params, args) + self.cmd.run(params, args) self.bugdir.flush_reload() def testCleanBugdir(self): uuids = list(self.bugdir.uuids()) diff --git a/libbe/command/init.py b/libbe/command/init.py index 017cdc3..b52d8e8 100644 --- a/libbe/command/init.py +++ b/libbe/command/init.py @@ -42,7 +42,8 @@ class Init (libbe.command.Command): ... except libbe.storage.ConnectionError: ... True True - >>> cmd.run(vcs) + >>> cmd._unconnected_storage = vcs + >>> cmd.run() No revision control detected. BE repository initialized. >>> bd = libbe.bugdir.BugDir(vcs) @@ -54,8 +55,9 @@ class Init (libbe.command.Command): >>> vcs = libbe.storage.vcs.installed_vcs() >>> vcs.repo = dir.path >>> vcs._vcs_init(vcs.repo) + >>> cmd._unconnected_storage = vcs >>> if vcs.name in libbe.storage.vcs.base.VCS_ORDER: - ... cmd.run(vcs) # doctest: +ELLIPSIS + ... cmd.run() # doctest: +ELLIPSIS ... else: ... vcs.init() ... vcs.connect() @@ -70,9 +72,9 @@ class Init (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_unconnected_storage = True - def _run(self, storage, bugdir=None, **params): + def _run(self, **params): + storage = self._get_unconnected_storage() if not os.path.isdir(storage.repo): raise libbe.command.UserError( 'No such directory: %s' % storage.repo) diff --git a/libbe/command/list.py b/libbe/command/list.py index 7c3f5af..8bdeaae 100644 --- a/libbe/command/list.py +++ b/libbe/command/list.py @@ -60,11 +60,13 @@ class List (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = List() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(bd.storage, bd) + + >>> ret = cmd.run() abc/a:om: Bug A - >>> ret = cmd.run(bd.storage, bd, {'status':'closed'}) + >>> ret = cmd.run({'status':'closed'}) abc/b:cm: Bug B >>> bd.storage.writeable True @@ -75,7 +77,6 @@ class List (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='status', help='Only show bugs matching the STATUS specifier', @@ -131,7 +132,8 @@ class List (libbe.command.Command): # # ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() writeable = bugdir.storage.writeable bugdir.storage.writeable = False cmp_list, status, severity, assigned, extra_strings_regexps = \ diff --git a/libbe/command/merge.py b/libbe/command/merge.py index 4624ab7..e3bf943 100644 --- a/libbe/command/merge.py +++ b/libbe/command/merge.py @@ -31,6 +31,7 @@ class Merge (libbe.command.Command): >>> import libbe.comment >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Merge() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout @@ -48,7 +49,7 @@ class Merge (libbe.command.Command): >>> dummy = dummy.new_reply('1 2 3 4') >>> dummy.time = 2 - >>> ret = cmd.run(bd.storage, bd, {}, ['/a', '/b']) + >>> ret = cmd.run(args=['/a', '/b']) Merged bugs #abc/a# and #abc/b# >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') @@ -139,7 +140,6 @@ class Merge (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.args.extend([ libbe.command.Argument( name='bug-id', metavar='BUG-ID', default=None, @@ -149,7 +149,8 @@ class Merge (libbe.command.Command): completion_callback=libbe.command.util.complete_bug_id), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() bugA,dummy_comment = \ libbe.command.util.bug_comment_from_user_id( bugdir, params['bug-id']) @@ -166,7 +167,7 @@ class Merge (libbe.command.Command): if comment.alt_id == None: comment.storage = None comment.alt_id = comment.uuid - comment.storage = storage + comment.storage = bugdir.storage comment.uuid = libbe.util.id.uuid_gen() comment.save() # force onto disk under bugA diff --git a/libbe/command/new.py b/libbe/command/new.py index d840503..de215fa 100644 --- a/libbe/command/new.py +++ b/libbe/command/new.py @@ -31,11 +31,12 @@ class New (libbe.command.Command): >>> import libbe.util.id >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = New() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> libbe.util.id.uuid_gen = lambda: 'X' - >>> ret = cmd.run(bd.storage, bd, args=['this is a test',]) + >>> ret = cmd.run(args=['this is a test',]) Created bug with ID abc/X >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('X') @@ -53,7 +54,6 @@ class New (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.options.extend([ libbe.command.Option(name='reporter', short_name='r', help='The user who reported the bug', @@ -69,11 +69,12 @@ class New (libbe.command.Command): libbe.command.Argument(name='summary', metavar='SUMMARY') ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): if params['summary'] == '-': # read summary from stdin summary = self.stdin.readline() else: summary = params['summary'] + bugdir = self._get_bugdir() bug = bugdir.new_bug(summary=summary.strip()) if params['reporter'] != None: bug.reporter = params['reporter'] diff --git a/libbe/command/remove.py b/libbe/command/remove.py index e516443..3b9d3f3 100644 --- a/libbe/command/remove.py +++ b/libbe/command/remove.py @@ -27,12 +27,13 @@ class Remove (libbe.command.Command): >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) >>> cmd = Remove() + >>> cmd._storage = bd.storage >>> cmd._setup_io = lambda i_enc,o_enc : None >>> cmd.stdout = sys.stdout >>> print bd.bug_from_uuid('b').status closed - >>> ret = cmd.run(bd.storage, bd, args=['/b']) + >>> ret = cmd.run(args=['/b']) Removed bug abc/b >>> bd.flush_reload() >>> try: @@ -46,7 +47,6 @@ class Remove (libbe.command.Command): def __init__(self, *args, **kwargs): libbe.command.Command.__init__(self, *args, **kwargs) - self.requires_bugdir = True self.args.extend([ libbe.command.Argument( name='bug-id', metavar='BUG-ID', default=None, @@ -54,7 +54,8 @@ class Remove (libbe.command.Command): completion_callback=libbe.command.util.complete_bug_id), ]) - def _run(self, storage, bugdir, **params): + def _run(self, **params): + bugdir = self._get_bugdir() user_ids = [] for bug_id in params['bug-id']: bug,dummy_comment = libbe.command.util.bug_comment_from_user_id( diff --git a/libbe/command/severity.py b/libbe/command/severity.py index 804dc4e..f6b586f 100644 --- a/libbe/command/severity.py +++ b/libbe/command/severity.py @@ -17,51 +17,65 @@ # 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. -"""Show or change a bug's severity level""" -from libbe import cmdutil, bugdir, bug -__desc__ = __doc__ -def execute(args, manipulate_encodings=True, restrict_file_access=False, - dir="."): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a"], manipulate_encodings=False) - minor - >>> execute(["a", "wishlist"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) - wishlist - >>> execute(["a", "none"], manipulate_encodings=False) +import libbe +import libbe.bug +import libbe.command +import libbe.command.util + +class Severity (libbe.command.Command): + """Change a bug's severity level + + >>> import sys + >>> import libbe.bugdir + >>> bd = libbe.bugdir.SimpleBugDir(memory=False) + >>> cmd = Severity() + >>> cmd._storage = bd.storage + >>> cmd._setup_io = lambda i_enc,o_enc : None + >>> cmd.stdout = sys.stdout + + >>> bd.bug_from_uuid('a').severity + 'minor' + >>> ret = cmd.run(args=['wishlist', '/a']) + >>> bd.flush_reload() + >>> bd.bug_from_uuid('a').severity + 'wishlist' + >>> ret = cmd.run(args=['none', '/a']) Traceback (most recent call last): UserError: Invalid severity level: none >>> bd.cleanup() """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) not in (1,2): - raise cmdutil.UsageError - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings, - root=dir) - bug = cmdutil.bug_from_id(bd, args[0]) - if len(args) == 1: - print bug.severity - elif len(args) == 2: - try: - bug.severity = args[1] - except ValueError, e: - if e.name != "severity": - raise e - raise cmdutil.UserError ("Invalid severity level: %s" % e.value) + name = 'severity' -def get_parser(): - parser = cmdutil.CmdOptionParser("be severity BUG-ID [SEVERITY]") - return parser + def __init__(self, *args, **kwargs): + libbe.command.Command.__init__(self, *args, **kwargs) + self.args.extend([ + libbe.command.Argument( + name='severity', metavar='SEVERITY', default=None, + completion_callback=libbe.command.util.complete_severity), + libbe.command.Argument( + name='bug-id', metavar='BUG-ID', default=None, + repeatable=True, + completion_callback=libbe.command.util.complete_bug_id), + ]) + + def _run(self, **params): + bugdir = self._get_bugdir() + for bug_id in params['bug-id']: + bug,dummy_comment = \ + libbe.command.util.bug_comment_from_user_id(bugdir, bug_id) + if bug.severity != params['severity']: + try: + bug.severity = params['severity'] + except ValueError, e: + if e.name != 'severity': + raise e + raise libbe.command.UserError( + 'Invalid severity level: %s' % e.value) + return 0 -def help(): - longhelp=[""" + def _long_help(self): + ret = [""" Show or change a bug's severity level. If no severity is specified, the current value is printed. If a severity level @@ -69,38 +83,13 @@ is specified, it will be assigned to the bug. Severity levels are: """] - try: # See if there are any per-tree severity configurations - bd = bugdir.BugDir(from_disk=True, manipulate_encodings=False) - except bugdir.NoBugDir, e: - pass # No tree, just show the defaults - longest_severity_len = max([len(s) for s in bug.severity_values]) - for severity in bug.severity_values : - description = bug.severity_description[severity] - s = "%*s : %s\n" % (longest_severity_len, severity, description) - longhelp.append(s) - longhelp = ''.join(longhelp) - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option,value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - for pos,value in enumerate(args): - if value == "--complete": - try: # See if there are any per-tree severity configurations - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=False) - except bugdir.NoBugDir: - bd = None - if pos == 0: # fist positional argument is a bug id - ids = [] - if bd != None: - bd.load_all_bugs() - filter = lambda bg : bg.active==True - bugs = [bg for bg in bd if filter(bg)==True] - ids = [bd.bug_shortname(bg) for bg in bugs] - raise cmdutil.GetCompletions(ids) - elif pos == 1: # second positional argument is a severity - raise cmdutil.GetCompletions(bug.severity_values) - raise cmdutil.GetCompletions() + try: # See if there are any per-tree severity configurations + bd = self._get_bugdir() + except NotImplementedError: + pass # No tree, just show the defaults + longest_severity_len = max([len(s) for s in libbe.bug.severity_values]) + for severity in bug.severity_values : + description = bug.severity_description[severity] + ret.append('%*s : %s\n' \ + % (longest_severity_len, severity, description)) + return ''.join(ret) diff --git a/libbe/ui/command_line.py b/libbe/ui/command_line.py index 84f9450..0aa34f7 100755 --- a/libbe/ui/command_line.py +++ b/libbe/ui/command_line.py @@ -264,29 +264,18 @@ def main(): print e return 1 Class = getattr(module, command_name.capitalize()) - command = Class() - command.ui = self + def gucs(): + return libbe.storage.get_storage(options['repo']) + command = Class(get_unconnected_storage=gucs, ui=ui) parser = CmdOptionParser(command) - storage = None - bugdir = None - if command.requires_bugdir == True: - assert command.requires_unconnected_storage == False - storage = libbe.storage.get_storage(options['repo']) - storage.connect() - bugdir = libbe.bugdir.BugDir(storage, from_storage=True) - elif command.requires_storage == True \ - or command.requires_unconnected_storage == True: - storage = libbe.storage.get_storage(options['repo']) - if command.requires_unconnected_storage == False: - storage.connect() try: options,args = parser.parse_args(args[1:]) - command.run(storage, bugdir, options, args) + command.run(options, args) except CallbackExit: - if storage != None: storage.disconnect() + command.cleanup() return 0 except libbe.command.UserError, e: - if storage != None: storage.disconnect() + command.cleanup() print 'ERROR:\n', e return 1 if storage != None: storage.disconnect() diff --git a/libbe/ui/util/cmdutil.py b/libbe/ui/util/cmdutil.py index 86ff9fc..f2eb5b9 100644 --- a/libbe/ui/util/cmdutil.py +++ b/libbe/ui/util/cmdutil.py @@ -59,20 +59,6 @@ def execute(cmd, args, def restrict_file_access(bugdir, path): - """ - Check that the file at path is inside bugdir.root. This is - important if you allow other users to execute becommands with your - username (e.g. if you're running be-handle-mail through your - ~/.procmailrc). If this check wasn't made, a user could e.g. - run - be commit -b ~/.ssh/id_rsa "Hack to expose ssh key" - which would expose your ssh key to anyone who could read the VCS - log. - """ - in_root = bugdir.vcs.path_in_root(path, bugdir.root) - if in_root == False: - raise UserError('file access restricted!\n %s not in %s' - % (path, bugdir.root)) def parse_id(id): """ -- 2.26.2