From bf3d434b244c57556bec979acbc658c30eb58221 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 12 Dec 2009 00:31:55 -0500 Subject: Added libbe.command.base (with Command class) and moved list command to new format. --- libbe/command/base.py | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 libbe/command/base.py (limited to 'libbe/command/base.py') diff --git a/libbe/command/base.py b/libbe/command/base.py new file mode 100644 index 0000000..973b840 --- /dev/null +++ b/libbe/command/base.py @@ -0,0 +1,224 @@ +# Copyright + +import optparse +import sys + +import libbe +import libbe.util.plugin +import libbe.ui.util.repo + +class UserError(Exception): + pass + +class UnknownCommand(UserError): + def __init__(self, cmd): + Exception.__init__(self, "Unknown command '%s'" % cmd) + self.cmd = cmd + + +def get_command(command_name): + """Retrieves the module for a user command + + >>> try: + ... get_command('asdf') + ... except UnknownCommand, e: + ... print e + Unknown command 'asdf' + >>> repr(get_command('list')).startswith(">> c = Command() + >>> print c.help() + usage: be command [options] + + Options: + -h HELP, --help=HELP Print a help message + + --complete=STRING Print a list of possible completions + + -r REPO, --repo=REPO Select BE repository (see `be help repo`) rather + thanthe current directory. + + A detailed help message. + """ + + name = 'command' + + def __init__(self, input_encoding=None, output_encoding=None): + self.status = None + self.result = None + self.input_encoding = None + self.output_encoding = None + self.options = [ + Option(name='help', short_name='h', + help='Print a help message', + option_callback=self.help), + Option(name='complete', type='string', + help='Print a list of possible completions', + arg=Argument(name='complete', metavar='STRING', optional=True)), + ] + self.args = [] + + def run(self, bugdir, options=None, args=None): + if options == None: + options = {} + if args == None: + args = [] + params = {} + for option in self.options: + if option.name in options: + params[option.name] = options.pop(option.name) + elif option.arg != None: + params[option.name] = option.arg.default + else: # non-arg options are flags, set to default flag value + params[option.name] = False + if len(options) > 0: + raise UserError, 'Invalid options passed to command %s:\n %s' \ + % (self.name, '\n '.join(['%s: %s' % (k,v) + for k,v in options.items()])) + for arg in self.args: + pass + 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(bugdir, **params) + return self.status + + def _run(self, bugdir, **kwargs): + pass + + def _setup_io(self, input_encoding=None, output_encoding=None): + if input_encoding == None: + input_encoding = get_terminal_encoding() + if output_encoding == None: + output_encoding = get_terminal_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(), + self._long_help()]) +# if cmd != None: +# return get_command(cmd).help() +# cmdlist = [] +# for name in commands(): +# module = get_command(name) +# cmdlist.append((name, module.__desc__)) +# cmdlist.sort() +# longest_cmd_len = max([len(name) for name,desc in cmdlist]) +# ret = ["Bugs Everywhere - Distributed bug tracking", +# "", "Supported commands"] +# for name, desc in cmdlist: +# numExtraSpaces = longest_cmd_len-len(name) +# ret.append("be %s%*s %s" % (name, numExtraSpaces, "", desc)) +# ret.extend(["", "Run", " be help [command]", "for more information."]) +# longhelp = "\n".join(ret) +# if parser == None: +# return longhelp +# return parser.help_str() + "\n" + longhelp + + def _usage(self): + usage = 'usage: be %s [options]' % self.name + num_optional = 0 + for arg in self.args: + usage += ' ' + if arg.optional == True: + usage += '[' + num_optional += 1 + usage += arg.metavar + if arg.repeatable == True: + usage += ' ...' + usage += ']'*num_optional + return usage + + def _option_help(self): + o = OptionFormatter(self.options) + return o.option_help().strip('\n') + + def _long_help(self): + return "A detailed help message." -- cgit From 8b4ad37815cbef1e06532179f9ca098588d9cb44 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 12 Dec 2009 01:12:17 -0500 Subject: Moved command completion from libbe.ui.util to libbe.command.util --- libbe/command/base.py | 1 - 1 file changed, 1 deletion(-) (limited to 'libbe/command/base.py') diff --git a/libbe/command/base.py b/libbe/command/base.py index 973b840..d18e070 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -5,7 +5,6 @@ import sys import libbe import libbe.util.plugin -import libbe.ui.util.repo class UserError(Exception): pass -- cgit From 86f886399813d37f3cfcf74a824d352e01eb0d8c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 12 Dec 2009 01:46:22 -0500 Subject: Use get_input/output_encoding() in libbe.command.base.Command --- libbe/command/base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'libbe/command/base.py') diff --git a/libbe/command/base.py b/libbe/command/base.py index d18e070..0db156b 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -4,6 +4,7 @@ import optparse import sys import libbe +import libbe.util.encoding import libbe.util.plugin class UserError(Exception): @@ -170,9 +171,9 @@ class Command (object): def _setup_io(self, input_encoding=None, output_encoding=None): if input_encoding == None: - input_encoding = get_terminal_encoding() + input_encoding = libbe.util.get_input_encoding() if output_encoding == None: - output_encoding = get_terminal_encoding() + output_encoding = libbe.util.get_output_encoding() self.stdin = codecs.getwriter(input_encoding)(sys.stdin) self.stdin.encoding = input_encoding self.stdout = codecs.getwriter(output_encoding)(sys.stdout) -- cgit From dff6bd9bf89ca80e2265696a478e540476718c9c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 12 Dec 2009 20:57:59 -0500 Subject: Moved be to libbe.ui.command_line and transitioned to Command format. --- libbe/command/base.py | 102 ++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 45 deletions(-) (limited to 'libbe/command/base.py') diff --git a/libbe/command/base.py b/libbe/command/base.py index 0db156b..252dd24 100644 --- a/libbe/command/base.py +++ b/libbe/command/base.py @@ -36,7 +36,7 @@ def get_command(command_name): def commands(): for modname in libbe.util.plugin.modnames('libbe.command'): - if modname != 'base': + if modname not in ['base', 'util']: yield modname class CommandInput (object): @@ -44,28 +44,48 @@ class CommandInput (object): self.name = name self.help = help -class Option (CommandInput): - def __init__(self, option_callback=None, short_name=None, arg=None, - type=None, *args, **kwargs): - CommandInput.__init__(self, *args, **kwargs) - self.option_callback = option_callback - self.short_name = short_name - self.arg = arg - self.type = type - if self.arg != None: - assert self.arg.name == self.name, \ - 'Name missmatch: %s != %s' % (self.arg.name, self.name) - class Argument (CommandInput): - def __init__(self, metavar=None, default=None, + def __init__(self, metavar=None, default=None, type='string', optional=False, repeatable=False, completion_callback=None, *args, **kwargs): CommandInput.__init__(self, *args, **kwargs) self.metavar = metavar self.default = default + self.type = type self.optional = optional self.repeatable = repeatable self.completion_callback = completion_callback + if self.metavar == None: + self.metavar = self.name.upper() + +class Option (CommandInput): + def __init__(self, callback=None, short_name=None, arg=None, + *args, **kwargs): + CommandInput.__init__(self, *args, **kwargs) + self.callback = callback + self.short_name = short_name + self.arg = arg + if self.arg == None and self.callback == None: + # use an implicit boolean argument + self.arg = Argument(name=self.name, help=self.help, + default=False, type='bool') + self.validate() + + def validate(self): + if self.arg == None: + assert self.callback != None + return + assert self.callback == None, self.callback + assert self.arg.name == self.name, \ + 'Name missmatch: %s != %s' % (self.arg.name, self.name) + assert self.arg.optional == False + assert self.arg.repeatable == False + + def __str__(self): + return '--%s' % self.name + + def __repr__(self): + return '