I am trying to write a parser class derived from the Python argparse ArgumentParser class. The outlines of the following code work fine on the command line but generate an error I am struggling to understand in the context of my module.
The code (stripped down a little to remove the unimportant stuff) is as follows:
class SansParser(argparse.ArgumentParser):
"""Argument parser for preparing a SansModel fit or calculation
"""
def __init__(self):
"""Initialisation method for the parser class"""
argparse.ArgumentParser.__init__(self)
# Subparsers for the two commands 'calc' and 'fit'
self.subparsers = self.add_subparsers()
self.fit_parser = self.subparsers.add_parser('fit', help="Fit a dataset")
self.fit_parser.add_argument('-d', '-data', '-dataset', type = str,
dest = 'dataset',
help = "The dataset to fit in SasXML format")
self.fit_parser.set_defaults(func=fit)
self.calc_parser = self.subparsers.add_parser('calc', prog='test')
self.calc_parser.set_defaults(func=calculate)
I can run the equivalent of this as a script and its fine. If I run it from either shell or import into python command line and try to instantiate the class I get:
$ python sansmodel.py
Traceback (most recent call last):
File "sansmodel.py", line 57, in <module>
parser = SansParser()
File "sansmodel.py", line 41, in __init__
self.fit_parser = self.subparsers.add_parser('fit', help="Fit a dataset")
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py",
line 1064, in add_parser
parser = self._parser_class(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'prog'
As far as I can tell the code in argparse itself at line 1064 explicitly creates the 'prog' keyword and this is the expected behaviour so I'm confused as to where it is unexpected. I'm guessing I've got something backwards with the scope somehow?
Unless you're overwritting some argparse.ArgumentParser
behaviour, I recommend to create a parser object and add the arguments and the subparsers to that object.
That said, the problem is that when adding a new parser the __init__
method, that has been overwritten by the SansParser
implementation, doesn't accept the same arguments as the original ArgumentParser
.
A workaround to the problem should be this one:
self.subparsers._parser_class = argparse.ArgumentParser
This way, when add_parser
is called, instead of creating a new SansParser
(that would fail because of infinite recursion), a new ArgumentParser
will be created.