0

I'm working on a simple Git/Redmine glue script but I'm having some difficulty using optional arguments with the Python argparse module.

With the following code:

import argparse
class MyClass:
 def StartWork(self, issueNumber, **kwargs):
 if issueNumber is None:
 issueNumber = input("please enter an issue number: ")
 else:
 print("issue number detected")
 print(issueNumber)
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='MyClass-command', help='Command to perform')
subparsers.required = True
startWorkParser = subparsers.add_parser('startwork', help='Command to begin work on a new branch')
startWorkParser.add_argument("issuenumber", type=int, help="The issue number used to create a local branch based on the specified issue number", nargs='?', default=None)
startWorkParser.set_defaults(func=MyClass.StartWork)
# Parse the arguments to make sure we have all the information requried to actually do something.
args = parser.parse_args()
mc = MyClass()
try:
 args.func(mc, **vars(args))
except AssertionError as e:
 print("Error: "+str(e))
# Parse the arguments to make sure we have all the information required to actually do something.
args = parser.parse_args()

I'd expect a call like this:

python MyClass.py startwork

...to result in the user being prompted for an issue number. Instead I get:

Traceback (most recent call last):
 File "C:\Projects\RedmnieGlue\MyClass.py", line 23, in <module>
 args.func(mc, **vars(args))
TypeError: StartWork() missing 1 required positional argument: 'issueNumber'

So why is the nargs='?' not prevailing here?

Edit

If I call it like this:

python MyClass.py startwork -h

I get this:

usage: class1.py startwork [-h] [issuenumber]
positional arguments:
 issuenumber The issue number used to create a local branch based on the
 specified issue number
optional arguments:
 -h, --help show this help message and exit

...which (based on the [] around issuenumber) suggests to me it is understanding that is an optional argument but something is preventing it from working as I'd expect it to. Something to do with my use of subparsers and calling methods with the arg parser perhaps?

asked May 5, 2016 at 11:28
5
  • I'm able to run this code without any errors. Commented May 5, 2016 at 11:40
  • 1
    (1) There is a syntax error in def StartWork(...) (missing trailing colon). (2) The error message does not match the shown code (e.g. there’s no Main function), so whatever is wrong with your code is not showing in your simplified version. Commented May 5, 2016 at 11:46
  • It was an attempt to pare down the original code into a workable example. I'll fix it so it's a complete working solution... Commented May 5, 2016 at 12:16
  • @poke - give that a shot now. Commented May 5, 2016 at 12:23
  • Are you not mixing between the arguments given to your script and the ones the function StartWork get? Doesn't def StartWork(self, issueNumber=None, **kwargs): solve your issue? Commented May 5, 2016 at 12:33

1 Answer 1

2

If you print the contents of vars(args) before your function call like this:

print(vars(args))
args.func(mc, **vars(args))

Then you can easily verify whether there is something wrong with the argument parser or not. With a call of the script without arguments (e.g. python myscript.py), you get the following output:

{'MyClass-command': 'startwork', 'issuenumber': None, 'func': <function MyClass.StartWork at 0x000000493898C510>}

As you can see issuenumber actually is in that dictionary, and it did get the default value. So the error you are seeing is not because of the argument parser (it’s also not an argparse error, so the validation on the arguments—with issuenumber being optional—is absolutely correct).

Instead, what’s going wrong is that the argument issuenumber is not passed to the positional argument when using **vars(args). The reason that does not happen is actually quite simply:

The dictionary key is issuenumber; the function expects a issueNumber (note the upper case N). So either change the function to use a lowercase issuenumber, or change the argument parser to store the value in issueNumber instead.

answered May 5, 2016 at 12:33
Sign up to request clarification or add additional context in comments.

2 Comments

Well spotted on the source of the error @poke and setting issueNumber=None in the definition of the StartWork method makes it work as expected once the case of the method matches that of the argument definition.
Just one more thing to note; When setting up the name so it always matches what StartWork requires, this works very well: inspect.getargspec(MyClass.StartWork).args[1]

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.