Beispiel #1
0
 def testStrictOptionaParamsThroughArgDef(self):
     flags, args = options._processArgs(
                          {'coverage' : options.STRICT_OPT_PARAM}, {},
                          conarycfg.ConaryConfiguration(False),
                          '', argv=['foo', '--coverage', 'bar'])[0:2]
     assert(flags['coverage'] == True)
     assert(args == ['foo', 'bar'])
     flags, args = options._processArgs(
                          {'coverage' : options.STRICT_OPT_PARAM}, {},
                          conarycfg.ConaryConfiguration(False),
                          '', argv=['foo', '--coverage=bar'])[0:2]
     assert(flags['coverage'] == 'bar')
     assert(args == ['foo'])
Beispiel #2
0
    def testDefaultValues(self):
        flags, args, parser = options._processArgs(
                {'option' : (options.ONE_PARAM,
                    dict(help="Help text", metavar="aaa", default='abc'),
                    )}, {}, conarycfg.ConaryConfiguration(False),
                '', argv=['foo'])[0:3]
        assert(flags['option'] == 'abc')
        sio = StringIO.StringIO()
        parser.print_help(sio)
        self.assertEquals(sio.getvalue(), '''\
Options:
  Command Options:
    --option=aaa       Help text
''')
Beispiel #3
0
 def _getPreCommandOptions(self, argv, cfg):
     """Allow the user to specify generic flags before they specify the
        command to run.
     """
     thisCommand = self.abstractCommand()
     params, cfgMap = thisCommand.prepare()
     defaultGroup = thisCommand.defaultGroup
     kwargs = self._getParserFlags(thisCommand)
     argSet, otherArgs, parser, optionSet = options._processArgs(
                                                 params, {}, cfg,
                                                 usage=self.usage,
                                                 argv=argv[1:],
                                                 interspersedArgs=False,
                                                 **kwargs)
     return argSet, [argv[0]] + otherArgs
Beispiel #4
0
 def _getPreCommandOptions(self, argv, cfg):
     """Allow the user to specify generic flags before they specify the
        command to run.
     """
     thisCommand = self.abstractCommand()
     params, cfgMap = thisCommand.prepare()
     defaultGroup = thisCommand.defaultGroup
     kwargs = self._getParserFlags(thisCommand)
     argSet, otherArgs, parser, optionSet = options._processArgs(
         params, {},
         cfg,
         usage=self.usage,
         argv=argv[1:],
         interspersedArgs=False,
         **kwargs)
     return argSet, [argv[0]] + otherArgs
Beispiel #5
0
class MainHandler(object):
    """
        Class to handle parsing and executing commands set up to use
        AbstractCommands
    """

    abstractCommand = None  # class to grab generic options from.  These
    # can be used in front of
    commandList = []  # list of commands to support.
    name = None  # name to use when showing usage messages.
    version = '<no version>'  # version to return to --version

    hobbleShortOpts = False  # whether or not to allow -mn to be used, or to
    # require -m -n.
    configClass = None
    useConaryOptions = True  # whether to add --config, --debug, --debugger
    # and use cfgMap.
    setSysExcepthook = True

    def __init__(self):
        self._ignoreConfigErrors = False
        self._supportedCommands = {}
        for class_ in reversed(inspect.getmro(self.__class__)):
            if not hasattr(class_, 'commandList'):
                continue
            for command in class_.commandList:
                self._registerCommand(command)

    def registerCommand(self, commandClass):
        supportedCommands = self._supportedCommands
        inst = commandClass()
        inst.setMainHandler(self)
        if isinstance(commandClass.commands, str):
            supportedCommands[commandClass.commands] = inst
        else:
            for cmdName in commandClass.commands:
                supportedCommands[cmdName] = inst

    # this method is public; add private version for bw compat.
    _registerCommand = registerCommand

    def unregisterCommand(self, commandClass):
        if isinstance(commandClass.commands, str):
            del self._supportedCommands[commandClass.commands]
        else:
            for cmdName in commandClass.commands:
                del self._supportedCommands[cmdName]

    # this method is public; add private version for bw compat.
    _unregisterCommand = unregisterCommand

    def _getPreCommandOptions(self, argv, cfg):
        """Allow the user to specify generic flags before they specify the
           command to run.
        """
        thisCommand = self.abstractCommand()
        params, cfgMap = thisCommand.prepare()
        defaultGroup = thisCommand.defaultGroup
        kwargs = self._getParserFlags(thisCommand)
        argSet, otherArgs, parser, optionSet = options._processArgs(
            params, {},
            cfg,
            usage=self.usage,
            argv=argv[1:],
            interspersedArgs=False,
            **kwargs)
        return argSet, [argv[0]] + otherArgs

    def usage(self, rc=1, showAll=False):
        # get the longest command to set the width of the command
        # column
        width = 0
        commandList = set(self._supportedCommands.itervalues())
        for command in commandList:
            if command.hidden:
                continue
            width = max(width, len('/'.join(command.commands)))
        # group the commands together
        groups = dict.fromkeys(x.commandGroup for x in commandList)
        for group in groups.iterkeys():
            groups[group] = [x for x in commandList if x.commandGroup == group]
        # Sort the groups
        groupNames = groups.keys()
        groupNames.sort()
        for group in groupNames:
            if group == 'Hidden Commands':
                continue
            commands = groups[group]
            # filter out hidden commands
            if showAll:
                filtered = commands
            else:
                filtered = [x for x in commands if not x.hidden]
            if not filtered:
                continue
            # print the header for the command group
            print
            print group
            # sort the commands by the first command name
            for command in sorted(filtered, key=lambda x: x.commands[0]):
                print '  %-*s  %s' % (width, '/'.join(
                    command.commands), command.help)
        return rc

    def getConfigFile(self, argv):
        """
            Find the appropriate config file
        """
        if not self.configClass:
            raise RuntimeError, ('Must define a configClass to use with this'
                                 ' main handler')
        if '--skip-default-config' in argv:
            argv.remove('--skip-default-config')
            ccfg = self.configClass(readConfigFiles=False,
                                    ignoreErrors=self._ignoreConfigErrors)
        else:
            ccfg = self.configClass(readConfigFiles=True,
                                    ignoreErrors=self._ignoreConfigErrors)
        return ccfg

    def getParser(self, command):
        thisCommand = self._supportedCommands[command]
        return self.getParserByClass(commandClass)

    def getParserByClass(self, commandClass, commandName=None):
        params, cfgMap = commandClass.prepare()
        usage = self._getUsageByClass(commandClass, commandName=commandName)
        kwargs = self._getParserFlags(commandClass)
        return options._getParser(params, {}, usage=usage, **kwargs)

    def _getUsage(self, commandName):
        commandClass = self._supportedCommands[commandName]
        return self._getUsageByClass(commandClass, commandName)

    def _getUsageByClass(self, commandClass, commandName=None):
        assert self.name, 'You must define the "name" attribute for class "%s"' % self.__class__.__name__
        if not commandName:
            if hasattr(commandClass, 'name'):
                commandName = commandClass.name
            else:
                commandName = commandClass.commands[0]

        commandUsage = '%s %s %s' % (self.name, commandName,
                                     commandClass.paramHelp)
        return commandUsage

    def _getParserFlags(self, thisCommand):
        if thisCommand.hobbleShortOpts is not None:
            hobbleShortOpts = thisCommand.hobbleShortOpts
        else:
            hobbleShortOpts = self.hobbleShortOpts
        defaultGroup = thisCommand.defaultGroup
        description = thisCommand.description
        if not description:
            description = thisCommand.__doc__
        if description is None:
            description = thisCommand.help
        return dict(version=None,
                    useHelp=False,
                    defaultGroup=defaultGroup,
                    hobbleShortOpts=hobbleShortOpts,
                    addDebugOptions=self.useConaryOptions,
                    addConfigOptions=self.useConaryOptions,
                    addVerboseOptions=self.useConaryOptions,
                    description=description)

    def getCommand(self, argv, cfg):
        # note, cfg is not used by this implementation, but it
        # may be used by classes that derive from this one.
        if len(argv) == 1:
            # no command specified
            return None

        commandName = argv[1]
        if commandName not in self._supportedCommands:
            rc = self.usage()
            raise errors.ParseError("%s: unknown command: '%s'" %
                                    (self.name, commandName))
        return self._supportedCommands[commandName]

    def main(self,
             argv=None,
             debuggerException=Exception,
             cfg=None,
             debugAll=False,
             **kw):
        """
            Process argv and execute commands as specified.
        """
        if argv is None:
            argv = sys.argv
        from conary import versions
        supportedCommands = self._supportedCommands

        if '--version' in argv:
            print self.version
            return

        if cfg is None:
            cfg = self.getConfigFile(argv)

        # get the default setting for exception debugging from the
        # config object (if it has a setting).
        debug = getattr(cfg, 'debugExceptions', False)
        if debugAll:
            if hasattr(cfg, 'debugExceptions'):
                cfg.debugExceptions = True
            debug = True
        if self.setSysExcepthook:
            sys.excepthook = util.genExcepthook(debug=debug,
                                                debugCtrlC=debugAll)

        try:
            argSet, argv = self._getPreCommandOptions(argv, cfg)
        except debuggerException:
            raise
        except options.OptionError, e:
            self.usage()
            print >> sys.stderr, e
            sys.exit(e.val)

        thisCommand = self.getCommand(argv, cfg)
        if thisCommand is None:
            return self.usage()
        commandName = argv[1]

        params, cfgMap = thisCommand.prepare()
        kwargs = self._getParserFlags(thisCommand)

        try:
            newArgSet, otherArgs, parser, optionSet = options._processArgs(
                params, {},
                cfg,
                usage=self._getUsage(commandName),
                argv=argv,
                **kwargs)
        except debuggerException, e:
            raise