From cfae8a8302f06a84196700138d7ddbb25e91ea31 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 31 Dec 2009 14:32:39 -0500 Subject: [PATCH] Added UserInterface and other improved abstractions for command handling --- libbe/command/__init__.py | 14 ++- libbe/command/assign.py | 17 +-- libbe/command/base.py | 221 ++++++++++++++++++++++++++++-------- libbe/command/comment.py | 19 ++-- libbe/command/commit.py | 12 +- libbe/command/depend.py | 26 +++-- libbe/command/diff.py | 14 ++- libbe/command/due.py | 20 ++-- libbe/command/help.py | 10 +- libbe/command/html.py | 12 +- libbe/command/import_xml.py | 27 +++-- libbe/command/init.py | 17 +-- libbe/command/list.py | 14 ++- libbe/command/merge.py | 12 +- libbe/command/new.py | 10 +- libbe/command/remove.py | 12 +- libbe/command/set.py | 20 ++-- libbe/command/severity.py | 14 ++- libbe/command/show.py | 18 +-- libbe/command/status.py | 13 ++- libbe/command/subscribe.py | 28 ++--- libbe/command/tag.py | 26 +++-- libbe/command/target.py | 28 ++--- libbe/ui/command_line.py | 78 +++++++------ 24 files changed, 433 insertions(+), 249 deletions(-) diff --git a/libbe/command/__init__.py b/libbe/command/__init__.py index 916b5ce..8c92e6f 100644 --- a/libbe/command/__init__.py +++ b/libbe/command/__init__.py @@ -25,6 +25,16 @@ commands = base.commands Option = base.Option Argument = base.Argument Command = base.Command +InputOutput = base.InputOutput +StdInputOutput = base.StdInputOutput +StringInputOutput = base.StringInputOutput +UnconnectedStorageGetter = base.UnconnectedStorageGetter +StorageCallbacks = base.StorageCallbacks +UserInterface = base.UserInterface -__all__ = [UserError, UnknownCommand, get_command, get_command_class, - commands, Option, Argument, Command] +__all__ = [UserError, UnknownCommand, + get_command, get_command_class, commands, + Option, Argument, Command, + InputOutput, StdInputOutput, StringInputOutput, + StorageCallbacks, UnconnectedStorageGetter, + UserInterface] diff --git a/libbe/command/assign.py b/libbe/command/assign.py index 6cf74bc..b37b9fd 100644 --- a/libbe/command/assign.py +++ b/libbe/command/assign.py @@ -29,29 +29,32 @@ class Assign (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Assign(ui=ui) >>> bd.bug_from_uuid('a').assigned is None True - >>> ret = cmd.run({'user-id':u'Fran\xe7ois'}, ['-', '/a']) + >>> ui._user_id = u'Fran\xe7ois' + >>> ret = ui.run(cmd, args=['-', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned u'Fran\\xe7ois' - >>> ret = cmd.run(args=['someone', '/a', '/b']) + >>> ret = ui.run(cmd, args=['someone', '/a', '/b']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned 'someone' >>> bd.bug_from_uuid('b').assigned 'someone' - >>> ret = cmd.run(args=['none', '/a']) + >>> ret = ui.run(cmd, args=['none', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').assigned is None True + >>> ui.cleanup() >>> bd.cleanup() """ name = 'assign' diff --git a/libbe/command/base.py b/libbe/command/base.py index 2318aa7..357940f 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -3,6 +3,7 @@ import codecs import optparse import os.path +import StringIO import sys import libbe @@ -37,14 +38,19 @@ def get_command(command_name): raise UnknownCommand(command_name) return cmd -def get_command_class(module, command_name): +def get_command_class(module=None, command_name=None): """Retrieves a command class from a module. >>> import_xml_mod = get_command('import-xml') >>> import_xml = get_command_class(import_xml_mod, 'import-xml') >>> repr(import_xml) "" + >>> import_xml = get_command_class(command_name='import-xml') + >>> repr(import_xml) + "" """ + if module == None: + module = get_command(command_name) try: cname = command_name.capitalize().replace('-', '_') cmd = getattr(module, cname) @@ -167,7 +173,7 @@ class OptionFormatter (optparse.IndentedHelpFormatter): return ''.join(ret[:-1]) class Command (object): - """One-line command description. + """One-line command description here. >>> c = Command() >>> print c.help() @@ -183,12 +189,8 @@ class Command (object): name = 'command' - 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() + def __init__(self, ui=None): + self.ui = ui # calling user-interface self.status = None self.result = None self.restrict_file_access = True @@ -203,6 +205,21 @@ class Command (object): self.args = [] def run(self, options=None, args=None): + self.status = 1 # in case we raise an exception + params = self._parse_options_args(options, args) + if params['help'] == True: + pass + else: + params.pop('help') + if params['complete'] != None: + pass + else: + params.pop('complete') + + self.status = self._run(**params) + return self.status + + def _parse_options_args(self, options=None, args=None): if options == None: options = {} if args == None: @@ -242,33 +259,11 @@ class Command (object): if len(args) > len(self.args): # add some additional repeats assert self.args[-1].repeatable == True, self.args[-1].name params[self.args[-1].name].extend(args[len(self.args):]) - - if params['help'] == True: - pass - else: - params.pop('help') - if params['complete'] != None: - pass - else: - params.pop('complete') - - self._setup_io(self.input_encoding, self.output_encoding) - self.status = self._run(**params) - return self.status + return params def _run(self, **kwargs): raise NotImplementedError - def _setup_io(self, input_encoding=None, output_encoding=None): - if input_encoding == None: - input_encoding = libbe.util.encoding.get_input_encoding() - if output_encoding == None: - output_encoding = libbe.util.encoding.get_output_encoding() - self.stdin = codecs.getwriter(input_encoding)(sys.stdin) - self.stdin.encoding = input_encoding - self.stdout = codecs.getwriter(output_encoding)(sys.stdout) - self.stdout.encoding = output_encoding - def help(self, *args): return '\n\n'.join([self.usage(), self._option_help(), @@ -340,43 +335,171 @@ class Command (object): 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.""" + def cleanup(self): + pass + +class InputOutput (object): + def __init__(self, stdin=None, stdout=None): + self.stdin = stdin + self.stdout = stdout + + def setup_command(self, command): + if not hasattr(self.stdin, 'encoding'): + self.stdin.encoding = libbe.util.encoding.get_input_encoding() + if not hasattr(self.stdout, 'encoding'): + self.stdout.encoding = libbe.util.encoding.get_output_encoding() + command.stdin = self.stdin + command.stdin.encoding = self.stdin.encoding + command.stdout = self.stdout + command.stdout.encoding = self.stdout.encoding + + def cleanup(self): + pass + +class StdInputOutput (InputOutput): + def __init__(self, input_encoding=None, output_encoding=None): + stdin,stdout = self._get_io(input_encoding, output_encoding) + InputOutput.__init__(self, stdin, stdout) + + def _get_io(self, input_encoding=None, output_encoding=None): + if input_encoding == None: + input_encoding = libbe.util.encoding.get_input_encoding() + if output_encoding == None: + output_encoding = libbe.util.encoding.get_output_encoding() + stdin = codecs.getwriter(input_encoding)(sys.stdin) + stdin.encoding = input_encoding + stdout = codecs.getwriter(output_encoding)(sys.stdout) + stdout.encoding = output_encoding + return (stdin, stdout) + +class StringInputOutput (InputOutput): + """ + >>> s = StringInputOutput() + >>> s.set_stdin('hello') + >>> s.stdin.read() + 'hello' + >>> s.stdin.read() + >>> print >> s.stdout, 'goodbye' + >>> s.get_stdout() + 'goodbye\n' + >>> s.get_stdout() + '' + + Also works with unicode strings + + >>> s.set_stdin(u'hello') + >>> s.stdin.read() + u'hello' + >>> print >> s.stdout, u'goodbye' + >>> s.get_stdout() + u'goodbye\n' + """ + def __init__(self): + stdin = StringIO.StringIO() + stdin.encoding = 'utf-8' + stdout = StringIO.StringIO() + stdout.encoding = 'utf-8' + InputOutput.__init__(self, stdin, stdout) + + def set_stdin(self, stdin_string): + self.stdin = StringIO.StringIO(stdin_string) + + def get_stdout(self): + ret = self.stdout.getvalue() + self.stdout = StringIO.StringIO() # clear stdout for next read + self.stdin.encoding = 'utf-8' + return ret + +class UnconnectedStorageGetter (object): + def __init__(self, location): + self.location = location + + def __call__(self): + return libbe.storage.get_storage(self.location) + +class StorageCallbacks (object): + def __init__(self, location=None): + if location == None: + location = '.' + self.location = location + self._get_unconnected_storage = UnconnectedStorageGetter(location) + + def setup_command(self, command): + command._get_unconnected_storage = self.get_unconnected_storage + command._get_storage = self.get_storage + command._get_bugdir = self.get_bugdir + + def get_unconnected_storage(self): + """ + Callback for use by commands that need it. + + The returned Storage instance is may actually be connected, + but commands that make use of the returned value should only + make use of non-connected Storage methods. This is mainly + intended for the init command, which calls Storage.init(). + """ if not hasattr(self, '_unconnected_storage'): - if self.get_unconnected_storage == None: + if self._get_unconnected_storage == None: raise NotImplementedError - self._unconnected_storage = self.get_unconnected_storage() + self._unconnected_storage = self._get_unconnected_storage() return self._unconnected_storage - def _get_storage(self): - """ - Callback for use by commands that need it. + def set_unconnected_storage(self, unconnected_storage): + self._unconnected_storage = unconnected_storage - 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... - """ + def get_storage(self): + """Callback for use by commands that need it.""" if not hasattr(self, '_storage'): - self._storage = self._get_unconnected_storage() + self._storage = self.get_unconnected_storage() self._storage.connect() version = self._storage.storage_version() if version != libbe.storage.STORAGE_VERSION: raise libbe.storage.InvalidStorageVersion(version) return self._storage - def _get_bugdir(self): + def set_storage(self, storage): + self._storage = 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) + self._bugdir = libbe.bugdir.BugDir(self.get_storage(), + from_storage=True) return self._bugdir + def set_bugdir(self, bugdir): + self._bugdir = bugdir + + def cleanup(self): + if hasattr(self, '_storage'): + self._storage.disconnect() + +class UserInterface (object): + def __init__(self, io=None, location=None): + if io == None: + io = StringInputOutput() + self.io = io + self.storage_callbacks = StorageCallbacks(location) + self.restrict_file_access = True + + def help(self): + raise NotImplementedError + + def run(self, command, options=None, args=None): + command.ui = self + self.io.setup_command(command) + self.storage_callbacks.setup_command(command) + command.restrict_file_access = self.restrict_file_access + command._get_user_id = self._get_user_id + return command.run(options, args) + 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()) + self._user_id = libbe.ui.util.user.get_user_id( + self.storage_callbacks.get_storage()) return self._user_id def cleanup(self): - if hasattr(self, '_storage'): - self._storage.disconnect() + self.storage_callbacks.cleanup() + self.io.cleanup() diff --git a/libbe/command/comment.py b/libbe/command/comment.py index cb0dcbb..7b859a8 100644 --- a/libbe/command/comment.py +++ b/libbe/command/comment.py @@ -33,13 +33,14 @@ class Comment (libbe.command.Command): >>> import time >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Comment(ui=ui) - >>> ret = cmd.run({'user-id':u'Fran\\xe7ois'}, - ... ['/a', 'This is a comment about a']) + >>> ui._user_id = u'Fran\\xe7ois' + >>> ret = ui.run(cmd, args=['/a', 'This is a comment about a']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('a') >>> bug.load_comments(load_full=False) @@ -58,12 +59,13 @@ class Comment (libbe.command.Command): >>> if 'EDITOR' in os.environ: ... del os.environ['EDITOR'] - >>> ret = cmd.run({'user-id':u'Frank'}, ['/b']) + >>> ui._user_id = u'Frank' + >>> ret = ui.run(cmd, args=['/b']) Traceback (most recent call last): UserError: No comment supplied, and EDITOR not specified. >>> os.environ['EDITOR'] = "echo 'I like cheese' > " - >>> ret = cmd.run({'user-id':u'Frank'}, ['/b']) + >>> ret = ui.run(cmd, args=['/b']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('b') >>> bug.load_comments(load_full=False) @@ -71,6 +73,7 @@ class Comment (libbe.command.Command): >>> print comment.body I like cheese + >>> ui.cleanup() >>> bd.cleanup() """ name = 'comment' diff --git a/libbe/command/commit.py b/libbe/command/commit.py index 7d82e7d..4938c44 100644 --- a/libbe/command/commit.py +++ b/libbe/command/commit.py @@ -30,15 +30,17 @@ class Commit (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False, versioned=True) - >>> cmd = Commit() - >>> 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 = Commit(ui=ui) >>> bd.extra_strings = ['hi there'] >>> bd.flush_reload() - >>> cmd.run({'user-id':'Joe'}, ['Making a commit']) # doctest: +ELLIPSIS + >>> ui.run(cmd, {'user-id':'Joe'}, ['Making a commit']) # doctest: +ELLIPSIS Committed ... + >>> ui.cleanup() >>> bd.cleanup() """ name = 'commit' diff --git a/libbe/command/depend.py b/libbe/command/depend.py index 5e476fc..9068f3a 100644 --- a/libbe/command/depend.py +++ b/libbe/command/depend.py @@ -45,35 +45,37 @@ class Depend (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Depend(ui=ui) - >>> ret = cmd.run(args=['/a', '/b']) + >>> ret = ui.run(cmd, args=['/a', '/b']) a blocked by: b - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a']) a blocked by: b - >>> ret = cmd.run({'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE a blocked by: b closed - >>> ret = cmd.run(args=['/b', '/a']) + >>> ret = ui.run(cmd, args=['/b', '/a']) b blocked by: a b blocks: a - >>> ret = cmd.run({'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'show-status':True}, ['/a']) # doctest: +NORMALIZE_WHITESPACE a blocked by: b closed a blocks: b closed - >>> ret = cmd.run({'repair':True}) - >>> ret = cmd.run({'remove':True}, ['/b', '/a']) + >>> ret = ui.run(cmd, {'repair':True}) + >>> ret = ui.run(cmd, {'remove':True}, ['/b', '/a']) b blocks: a - >>> ret = cmd.run({'remove':True}, ['/a', '/b']) + >>> ret = ui.run(cmd, {'remove':True}, ['/a', '/b']) + >>> ui.cleanup() >>> bd.cleanup() """ name = 'depend' diff --git a/libbe/command/diff.py b/libbe/command/diff.py index d945f96..ebfe8fe 100644 --- a/libbe/command/diff.py +++ b/libbe/command/diff.py @@ -30,27 +30,29 @@ class Diff (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False, versioned=True) + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) >>> cmd = Diff() - >>> cmd._storage = bd.storage - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout >>> original = bd.storage.commit('Original status') >>> bug = bd.bug_from_uuid('a') >>> bug.status = 'closed' >>> changed = bd.storage.commit('Closed bug a') - >>> ret = cmd.run(args=[original]) + >>> ret = ui.run(cmd, args=[original]) Modified bugs: abc/a:cm: Bug A Changed bug settings: status: open -> closed - >>> ret = cmd.run({'subscribe':'%(bugdir_id)s:mod', 'uuids':True}, [original]) + >>> ret = ui.run(cmd, {'subscribe':'%(bugdir_id)s:mod', 'uuids':True}, [original]) a >>> bd.storage.versioned = False - >>> ret = cmd.run(args=[original]) + >>> ret = ui.run(cmd, args=[original]) Traceback (most recent call last): ... UserError: This repository is not revision-controlled. + >>> ui.cleanup() >>> bd.cleanup() """ % {'bugdir_id':libbe.diff.BUGDIR_ID} name = 'diff' diff --git a/libbe/command/due.py b/libbe/command/due.py index f3ad2f1..2eb3194 100644 --- a/libbe/command/due.py +++ b/libbe/command/due.py @@ -29,19 +29,21 @@ class Due (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Due(ui=ui) - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a']) No due date assigned. - >>> ret = cmd.run(args=['/a', 'Thu, 01 Jan 1970 00:00:00 +0000']) - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a', 'Thu, 01 Jan 1970 00:00:00 +0000']) + >>> ret = ui.run(cmd, args=['/a']) Thu, 01 Jan 1970 00:00:00 +0000 - >>> ret = cmd.run(args=['/a', 'none']) - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a', 'none']) + >>> ret = ui.run(cmd, args=['/a']) No due date assigned. + >>> ui.cleanup() >>> bd.cleanup() """ name = 'due' diff --git a/libbe/command/help.py b/libbe/command/help.py index 6e55598..d509d31 100644 --- a/libbe/command/help.py +++ b/libbe/command/help.py @@ -28,11 +28,12 @@ class Help (libbe.command.Command): >>> import sys >>> import libbe.bugdir + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) >>> cmd = Help() - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout - >>> ret = cmd.run(args=['help']) + >>> ret = ui.run(cmd, args=['help']) usage: be help [options] [TOPIC] Options: @@ -61,8 +62,7 @@ class Help (libbe.command.Command): 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(get_unconnected_storage=self.get_unconnected_storage, - ui=self.ui) + c = Class(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 99cd61f..7fd753a 100644 --- a/libbe/command/html.py +++ b/libbe/command/html.py @@ -36,12 +36,13 @@ class HTML (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = HTML(ui=ui) - >>> ret = cmd.run({'output':os.path.join(bd.storage.repo, 'html_export')}) + >>> ret = ui.run(cmd, {'output':os.path.join(bd.storage.repo, 'html_export')}) >>> os.path.exists(os.path.join(bd.storage.repo, 'html_export')) True >>> os.path.exists(os.path.join(bd.storage.repo, 'html_export', 'index.html')) @@ -54,6 +55,7 @@ class HTML (libbe.command.Command): True >>> os.path.exists(os.path.join(bd.storage.repo, 'html_export', 'bugs', 'b.html')) True + >>> ui.cleanup() >>> bd.cleanup() """ name = 'html' diff --git a/libbe/command/import_xml.py b/libbe/command/import_xml.py index 2e96848..be22c82 100644 --- a/libbe/command/import_xml.py +++ b/libbe/command/import_xml.py @@ -44,14 +44,14 @@ class Import_XML (libbe.command.Command): >>> import StringIO >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Import_XML(ui=ui) - >>> cmd.stdin = StringIO.StringIO('cThis is a comment about a') - >>> cmd.stdin.encoding = 'ascii' - >>> ret = cmd.run({'comment-root':'/a'}, ['-']) + >>> ui.io.set_stdin('cThis is a comment about a') + >>> ret = ui.run(cmd, {'comment-root':'/a'}, ['-']) >>> bd.flush_reload() >>> bug = bd.bug_from_uuid('a') >>> bug.load_comments(load_full=False) @@ -63,6 +63,7 @@ class Import_XML (libbe.command.Command): True >>> comment.in_reply_to is None True + >>> ui.cleanup() >>> bd.cleanup() """ name = 'import-xml' @@ -321,7 +322,10 @@ if libbe.TESTING == True: """ def setUp(self): self.bugdir = libbe.bugdir.SimpleBugDir(memory=False) - self.cmd = Import_XML() + io = libbe.command.StringInputOutput() + self.ui = libbe.command.UserInterface(io=io) + self.ui.storage_callbacks.set_storage(self.bugdir.storage) + self.cmd = Import_XML(ui=self.ui) self.cmd._storage = self.bugdir.storage self.cmd._setup_io = lambda i_enc,o_enc : None bugA = self.bugdir.bug_from_uuid('a') @@ -360,13 +364,12 @@ if libbe.TESTING == True: """ - self.cmd.stdin = StringIO.StringIO(self.xml) - self.cmd.stdin.encoding = 'ascii' - self.cmd.stdout = StringIO.StringIO() def tearDown(self): self.bugdir.cleanup() + self.ui.cleanup() def _execute(self, params={}, args=[]): - self.cmd.run(params, args) + self.ui.io.set_stdin(self.xml) + self.ui.run(self.cmd, 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 b52d8e8..2a78147 100644 --- a/libbe/command/init.py +++ b/libbe/command/init.py @@ -30,9 +30,10 @@ class Init (libbe.command.Command): >>> import libbe.storage.vcs >>> import libbe.storage.vcs.base >>> import libbe.util.utility + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) >>> cmd = Init() - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout >>> dir = libbe.util.utility.Dir() >>> vcs = libbe.storage.vcs.vcs_by_name('None') @@ -40,10 +41,10 @@ class Init (libbe.command.Command): >>> try: ... vcs.connect() ... except libbe.storage.ConnectionError: - ... True - True - >>> cmd._unconnected_storage = vcs - >>> cmd.run() + ... 'got error' + 'got error' + >>> ui.storage_callbacks.set_unconnected_storage(vcs) + >>> ui.run(cmd) No revision control detected. BE repository initialized. >>> bd = libbe.bugdir.BugDir(vcs) @@ -55,9 +56,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 + >>> ui.storage_callbacks.set_unconnected_storage(vcs) >>> if vcs.name in libbe.storage.vcs.base.VCS_ORDER: - ... cmd.run() # doctest: +ELLIPSIS + ... ui.run(cmd) # doctest: +ELLIPSIS ... else: ... vcs.init() ... vcs.connect() diff --git a/libbe/command/list.py b/libbe/command/list.py index d48c7ee..3442f42 100644 --- a/libbe/command/list.py +++ b/libbe/command/list.py @@ -59,17 +59,19 @@ class List (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = List(ui=ui) - >>> ret = cmd.run() + >>> ret = ui.run(cmd) abc/a:om: Bug A - >>> ret = cmd.run({'status':'closed'}) + >>> ret = ui.run(cmd, {'status':'closed'}) abc/b:cm: Bug B >>> bd.storage.writeable True + >>> ui.cleanup() >>> bd.cleanup() """ diff --git a/libbe/command/merge.py b/libbe/command/merge.py index 328351e..0c34f69 100644 --- a/libbe/command/merge.py +++ b/libbe/command/merge.py @@ -30,10 +30,11 @@ class Merge (libbe.command.Command): >>> import libbe.bugdir >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_bugdir(bd) + >>> cmd = Merge(ui=ui) >>> a = bd.bug_from_uuid('a') >>> a.comment_root.time = 0 @@ -49,7 +50,7 @@ class Merge (libbe.command.Command): >>> dummy = dummy.new_reply('1 2 3 4') >>> dummy.time = 2 - >>> ret = cmd.run(args=['/a', '/b']) + >>> ret = ui.run(cmd, args=['/a', '/b']) Merged bugs #abc/a# and #abc/b# >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') @@ -134,6 +135,7 @@ class Merge (libbe.command.Command): Merged into bug #abc/a# >>> print b.status closed + >>> ui.cleanup() >>> bd.cleanup() """ name = 'merge' diff --git a/libbe/command/new.py b/libbe/command/new.py index 57ff5dc..a470052 100644 --- a/libbe/command/new.py +++ b/libbe/command/new.py @@ -30,14 +30,15 @@ class New (libbe.command.Command): >>> import libbe.bugdir >>> import libbe.util.id >>> bd = libbe.bugdir.SimpleBugDir(memory=False) + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) >>> cmd = New() - >>> cmd._storage = bd.storage - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout >>> uuid_gen = libbe.util.id.uuid_gen >>> libbe.util.id.uuid_gen = lambda: 'X' - >>> ret = cmd.run(args=['this is a test',]) + >>> ret = ui.run(cmd, args=['this is a test',]) Created bug with ID abc/X >>> libbe.util.id.uuid_gen = uuid_gen >>> bd.flush_reload() @@ -50,6 +51,7 @@ class New (libbe.command.Command): minor >>> print bug.status open + >>> ui.cleanup() >>> bd.cleanup() """ name = 'new' diff --git a/libbe/command/remove.py b/libbe/command/remove.py index 3b9d3f3..c6d481f 100644 --- a/libbe/command/remove.py +++ b/libbe/command/remove.py @@ -26,14 +26,15 @@ class Remove (libbe.command.Command): >>> import sys >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_storage(bd.storage) + >>> cmd = Remove(ui=ui) >>> print bd.bug_from_uuid('b').status closed - >>> ret = cmd.run(args=['/b']) + >>> ret = ui.run(cmd, args=['/b']) Removed bug abc/b >>> bd.flush_reload() >>> try: @@ -41,6 +42,7 @@ class Remove (libbe.command.Command): ... except libbe.bugdir.NoBugMatches: ... print 'Bug not found' Bug not found + >>> ui.cleanup() >>> bd.cleanup() """ name = 'remove' diff --git a/libbe/command/set.py b/libbe/command/set.py index 4fe0117..46a63b4 100644 --- a/libbe/command/set.py +++ b/libbe/command/set.py @@ -34,19 +34,21 @@ class Set (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Set() - >>> 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 = Set(ui=ui) - >>> ret = cmd.run(args=['target']) + >>> ret = ui.run(cmd, args=['target']) None - >>> ret = cmd.run(args=['target', 'abcdefg']) - >>> ret = cmd.run(args=['target']) + >>> ret = ui.run(cmd, args=['target', 'abcdefg']) + >>> ret = ui.run(cmd, args=['target']) abcdefg - >>> ret = cmd.run(args=['target', 'none']) - >>> ret = cmd.run(args=['target']) + >>> ret = ui.run(cmd, args=['target', 'none']) + >>> ret = ui.run(cmd, args=['target']) None + >>> ui.cleanup() >>> bd.cleanup() """ name = 'set' diff --git a/libbe/command/severity.py b/libbe/command/severity.py index 7c1d305..3587325 100644 --- a/libbe/command/severity.py +++ b/libbe/command/severity.py @@ -30,20 +30,22 @@ class Severity (libbe.command.Command): >>> 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 + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_bugdir(bd) + >>> cmd = Severity(ui=ui) >>> bd.bug_from_uuid('a').severity 'minor' - >>> ret = cmd.run(args=['wishlist', '/a']) + >>> ret = ui.run(cmd, args=['wishlist', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').severity 'wishlist' - >>> ret = cmd.run(args=['none', '/a']) + >>> ret = ui.run(cmd, args=['none', '/a']) Traceback (most recent call last): UserError: Invalid severity level: none + >>> ui.cleanup() >>> bd.cleanup() """ name = 'severity' diff --git a/libbe/command/show.py b/libbe/command/show.py index 1a569a6..5ab6dc7 100644 --- a/libbe/command/show.py +++ b/libbe/command/show.py @@ -34,13 +34,14 @@ class Show (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Show() - >>> cmd._storage = bd.storage - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout - >>> cmd.stdout.encoding = 'ascii' - - >>> ret = cmd.run(args=['/a',]) # doctest: +ELLIPSIS + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> io.stdout.encoding = 'ascii' + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_bugdir(bd) + >>> cmd = Show(ui=ui) + + >>> ret = ui.run(cmd, args=['/a',]) # doctest: +ELLIPSIS ID : a Short name : abc/a Severity : minor @@ -52,7 +53,7 @@ class Show (libbe.command.Command): Bug A - >>> ret = cmd.run({'xml':True}, ['/a']) # doctest: +ELLIPSIS + >>> ret = ui.run(cmd, {'xml':True}, ['/a']) # doctest: +ELLIPSIS @@ -71,6 +72,7 @@ class Show (libbe.command.Command): Bug A + >>> ui.cleanup() >>> bd.cleanup() """ name = 'show' diff --git a/libbe/command/status.py b/libbe/command/status.py index 323963a..57a44aa 100644 --- a/libbe/command/status.py +++ b/libbe/command/status.py @@ -27,20 +27,23 @@ class Status (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Status() + >>> io = libbe.command.StringInputOutput() + >>> io.stdout = sys.stdout + >>> ui = libbe.command.UserInterface(io=io) + >>> ui.storage_callbacks.set_bugdir(bd) + >>> cmd = Status(ui=ui) >>> cmd._storage = bd.storage - >>> cmd._setup_io = lambda i_enc,o_enc : None - >>> cmd.stdout = sys.stdout >>> bd.bug_from_uuid('a').status 'open' - >>> ret = cmd.run(args=['closed', '/a']) + >>> ret = ui.run(cmd, args=['closed', '/a']) >>> bd.flush_reload() >>> bd.bug_from_uuid('a').status 'closed' - >>> ret = cmd.run(args=['none', '/a']) + >>> ret = ui.run(cmd, args=['none', '/a']) Traceback (most recent call last): UserError: Invalid status level: none + >>> ui.cleanup() >>> bd.cleanup() """ name = 'status' diff --git a/libbe/command/subscribe.py b/libbe/command/subscribe.py index a837f99..78d6fe0 100644 --- a/libbe/command/subscribe.py +++ b/libbe/command/subscribe.py @@ -35,47 +35,49 @@ class Subscribe (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Subscribe() - >>> cmd._bugdir = bd - >>> 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_bugdir(bd) + >>> cmd = Subscribe(ui=ui) >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> ret = cmd.run({'subscriber':'John Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'John Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: John Doe all * >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings ['SUBSCRIBE:John Doe \\tall\\t*'] - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.com,b.net'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'a.com,b.net'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.com,b.net John Doe all * - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'a.edu'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.com,a.edu,b.net John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'Jane Doe ', 'servers':'a.com'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all a.edu,b.net John Doe all * - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'servers':'*'}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: Jane Doe all * John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'Jane Doe '}, ['/a']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for abc/a: John Doe all * - >>> ret = cmd.run({'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) - >>> ret = cmd.run({'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'unsubscribe':True, 'subscriber':'John Doe '}, ['/a']) + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe ', 'types':'new'}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe new * - >>> ret = cmd.run({'subscriber':'Jane Doe '}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE + >>> ret = ui.run(cmd, {'subscriber':'Jane Doe '}, ['DIR']) # doctest: +NORMALIZE_WHITESPACE Subscriptions for bug directory: Jane Doe all * + >>> ui.cleanup() >>> bd.cleanup() """ name = 'subscribe' diff --git a/libbe/command/tag.py b/libbe/command/tag.py index bdb3f31..87589c0 100644 --- a/libbe/command/tag.py +++ b/libbe/command/tag.py @@ -29,33 +29,34 @@ class Tag (libbe.command.Command): >>> import sys >>> import libbe.bugdir >>> bd = libbe.bugdir.SimpleBugDir(memory=False) - >>> cmd = Tag() - >>> cmd._bugdir = bd - >>> 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_bugdir(bd) + >>> cmd = Tag(ui=ui) >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> ret = cmd.run(args=['/a', 'GUI']) + >>> ret = ui.run(cmd, args=['/a', 'GUI']) Tags for abc/a: GUI >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings ['%(tag_tag)sGUI'] - >>> ret = cmd.run(args=['/a', 'later']) + >>> ret = ui.run(cmd, args=['/a', 'later']) Tags for abc/a: GUI later - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a']) Tags for abc/a: GUI later - >>> ret = cmd.run({'list':True}) + >>> ret = ui.run(cmd, {'list':True}) GUI later - >>> ret = cmd.run(args=['/a', 'Alphabetically first']) + >>> ret = ui.run(cmd, args=['/a', 'Alphabetically first']) Tags for abc/a: Alphabetically first GUI @@ -67,15 +68,16 @@ class Tag (libbe.command.Command): >>> a.extra_strings = [] >>> print a.extra_strings [] - >>> ret = cmd.run(args=['/a']) + >>> ret = ui.run(cmd, args=['/a']) >>> bd.flush_reload() >>> a = bd.bug_from_uuid('a') >>> print a.extra_strings [] - >>> ret = cmd.run(args=['/a', 'Alphabetically first']) + >>> ret = ui.run(cmd, args=['/a', 'Alphabetically first']) Tags for abc/a: Alphabetically first - >>> ret = cmd.run({'remove':True}, ['/a', 'Alphabetically first']) + >>> ret = ui.run(cmd, {'remove':True}, ['/a', 'Alphabetically first']) + >>> ui.cleanup() >>> bd.cleanup() """ % {'tag_tag':TAG_TAG} name = 'tag' 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' diff --git a/libbe/ui/command_line.py b/libbe/ui/command_line.py index 9df474e..b36d251 100755 --- a/libbe/ui/command_line.py +++ b/libbe/ui/command_line.py @@ -145,7 +145,7 @@ class CmdOptionParser(optparse.OptionParser): fragment = parser.rargs[0] self.complete(argument, fragment) else: - print command_option.callback( + print >> self.command.stdout, command_option.callback( self.command, command_option, value) raise CallbackExit @@ -154,16 +154,18 @@ class CmdOptionParser(optparse.OptionParser): if fragment != None: comps = [c for c in comps if c.startswith(fragment)] if len(comps) > 0: - print '\n'.join(comps) + print >> self.command.stdout, '\n'.join(comps) raise CallbackExit - class BE (libbe.command.Command): """Class for parsing the command line arguments for `be`. This class does not contain a useful _run() method. Call this module's main() function instead. - >>> be = BE() + >>> ui = libbe.command.UserInterface() + >>> ui.io.stdout = sys.stdout + >>> be = BE(ui=ui) + >>> ui.io.setup_command(be) >>> p = CmdOptionParser(be) >>> p.exit_after_callback = False >>> try: @@ -228,8 +230,7 @@ class BE (libbe.command.Command): def _long_help(self): cmdlist = [] for name in libbe.command.commands(): - module = libbe.command.get_command(name) - Class = libbe.command.get_command_class(module, name) + Class = libbe.command.get_command_class(command_name=name) assert hasattr(Class, '__doc__') and Class.__doc__ != None, \ 'Command class %s missing docstring' % Class cmdlist.append((name, Class.__doc__.splitlines()[0])) @@ -249,31 +250,51 @@ class BE (libbe.command.Command): def full_version(self, *args): return libbe.version.version(verbose=True) +def dispatch(ui, command, args): + parser = CmdOptionParser(command) + try: + options,args = parser.parse_args(args) + ret = ui.run(command, options, args) + except CallbackExit: + return 0 + except libbe.command.UserError, e: + print >> ui.io.stdout, 'ERROR:\n', e + return 1 + except libbe.storage.ConnectionError, e: + print >> ui.io.stdout, 'Connection Error:\n', e + return 1 + except (libbe.util.id.MultipleIDMatches, libbe.util.id.NoIDMatches, + libbe.util.id.InvalidIDStructure), e: + print >> ui.io.stdout, 'Invalid id:\n', e + return 1 + finally: + command.cleanup() + return ret + def main(): - be = BE() + io = libbe.command.StdInputOutput() + ui = libbe.command.UserInterface(io) + ui.restrict_file_access = False + ui.storage_callbacks = None + be = BE(ui=ui) parser = CmdOptionParser(be) try: options,args = parser.parse_args() except CallbackExit: return 0 except libbe.command.UserError, e: - print 'ERROR:\n', e + print >> be.stdout, 'ERROR:\n', e return 1 - command_name = args[0] + command_name = args.pop(0) try: - module = libbe.command.get_command(command_name) + Class = libbe.command.get_command_class(command_name=command_name) except libbe.command.UnknownCommand, e: - print e + print >> be.stdout, e return 1 - Class = getattr(module, command_name.capitalize()) - class GUCS (object): - def __init__(self, repo): - self.repo = repo - def __call__(self): - return libbe.storage.get_storage(self.repo) - command = Class(get_unconnected_storage=GUCS(options['repo']), ui=be) - parser = CmdOptionParser(command) + + ui.storage_callbacks = libbe.command.StorageCallbacks(options['repo']) + command = Class(ui=ui) if command.name in ['comment']: paginate = 'never' @@ -285,22 +306,9 @@ def main(): paginate = 'never' libbe.ui.util.pager.run_pager(paginate) - try: - options,args = parser.parse_args(args[1:]) - command.run(options, args) - except CallbackExit: - command.cleanup() - return 0 - except libbe.command.UserError, e: - command.cleanup() - print 'ERROR:\n', e - return 1 - except libbe.storage.ConnectionError, e: - command.cleanup() - print 'Connection Error:\n', e - return 1 - command.cleanup() - return 0 + ret = dispatch(ui, command, args) + ui.cleanup() + return ret if __name__ == '__main__': sys.exit(main()) -- 2.26.2