# Copyright (C) 2009-2010 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. import codecs import optparse import os.path import StringIO import sys import libbe import libbe.storage import libbe.ui.util.user import libbe.util.encoding import libbe.util.plugin 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(">> 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) except ImportError, e: raise UnknownCommand(command_name) return cmd def modname_to_command_name(modname): """Little hack to replicate >>> import sys >>> def real_modname_to_command_name(modname): ... mod = libbe.util.plugin.import_by_name( ... 'libbe.command.%s' % modname) ... attrs = [getattr(mod, name) for name in dir(mod)] ... commands = [] ... for attr_name in dir(mod): ... attr = getattr(mod, attr_name) ... try: ... if issubclass(attr, Command): ... commands.append(attr) ... except TypeError, e: ... pass ... if len(commands) == 0: ... raise Exception('No Command classes in %s' % dir(mod)) ... return commands[0].name >>> real_modname_to_command_name('new') 'new' >>> real_modname_to_command_name('import_xml') 'import-xml' """ return modname.replace('_', '-') def commands(command_names=False): for modname in libbe.util.plugin.modnames('libbe.command'): if modname not in ['base', 'util']: if command_names == False: yield modname else: yield modname_to_command_name(modname) class CommandInput (object): def __init__(self, name, help=''): self.name = name self.help = help def __str__(self): return '<%s %s>' % (self.__class__.__name__, self.name) def __repr__(self): return self.__str__() class Argument (CommandInput): 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, self.name return assert self.callback == None, '%s: %s' (self.name, self.callback) assert self.arg.name == self.name, \ 'Name missmatch: %s != %s' % (self.arg.name, self.name) assert self.arg.optional == False, self.name assert self.arg.repeatable == False, self.name def __str__(self): return '--%s' % self.name def __repr__(self): return '