pythonargparsepython-decorators

Subparsers.add_parser TypeError: __init__() got an unexpected keyword argument 'prog'


I need to implement an ArgParse builder to generate parsers and regarding subparsers and arguments. I created a decorator to declare subparsers as action. Here is the class which contains the decorator:

class Controller(object):
    endpoints = None
    parser = None
    subparsers = None

    def __init__(self, endpoint=None):
        from src.app.commons.ArgParser import ArgParser
        if not self.parser:
            self.parser = ArgParser()
        # Get all 
        self.endpoints = utilities.conf_wrapper()
        self.mod = endpoint
        if not self.subparsers:
            self.subparsers = self.parser.add_subparsers(help=gettext('%s_SUBPARSER_HELP' % str(self.mod).upper()))
        self.parser.add_argument_group(self.mod, gettext('%s_GROUP_DESC' % str(self.mod).upper()))


    def endpoint(self, endpoint, **kwargs):
        """ Create an endpoint to define a method on behalf of subparser"""
        ref = self
        def decorator(f):
            """
            Create subparser for controller object
            @param f as a function to call
            @return decorator method
            """
            # TODO Set given function f as a subparser destination
            new_sub_parser = ref.subparsers.add_parser(endpoint, help=gettext('%s_%s_HELP' % (ref.mod, endpoint)))
            [new_sub_parser.add_argument("--%s" % arg, action='store') for arg in ref.endpoints[ref.mod][endpoint]["params"]]
            setattr(ConsoleInterface, 'do_%s' % endpoint, f)

        return decorator

And here is how I call it inside the class:

from src.app.controller import Controller

network = Controller("network")


@network.endpoint('create')
def create(*args):
    try:
        print "I am here"
    except Exception as err:
        print err

What I am expecting here is create some parsers as command like this:

$~ network create [arguments]

According to the ArgParse docs I do everything right, but I got the exception like:

  File "/projectpath/src/app/controller/__init__.py", line 48, in decorator
    new_sub_parser = ref.subparsers.add_parser(endpoint, help=gettext('%s_%s_HELP' % (ref.mod, endpoint)))
  File "/usr/lib/python2.7/argparse.py", line 1066, in add_parser
    parser = self._parser_class(**kwargs)
  TypeError: __init__() got an unexpected keyword argument 'prog'

When I look at the ArgParse._SubParsersAction.__init()__ it covers 'prog' inside kwargs.


Solution

  • The problem may be with ArgParser() class. I don't know what that is, though it may be a customized argparse.ArgumentParser (as subclass).

    add_parser makes sure there is a prog in the kwargs, which it then passes to parser = self._parser_class(**kwargs). _parser_class is the class of the main parser unless an alternative is specified in the add_subparsers line.

    So I'm guessing that ArgParser does not accept a prog keyword, even though ArgumentParser does. But I don't think we can help you without knowing more about its source.