pythongoogle-oauthargparseoptparse

Imported python module overrides option parser


I have written a python utility script that uses optparse to include options and flags at script launch.

Everything works great, but when I import google API oauth2client and run its execute function, it overrides my add_options into the options it uses.

When I say 'overrides' I mean that even though my script add options to my option parser, when I execute the script like so:

./myscript --help

I get a detailed response of the options I added to my script:

Usage: myscript [options]

Options:
    -h, --help            show this help message and exit
    -u USER, --user=USER  resources owned by this username

But, when I actually execute my script like so:

./myscript --user myuser

I get the following error:

usage: smyscript [-h] [--auth_host_name AUTH_HOST_NAME]
               [--noauth_local_webserver]
               [--auth_host_port [AUTH_HOST_PORT     
               [AUTH_HOST_PORT  ...]]]
               [--logging_level 
               {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
 myscript: error: unrecognized arguments: --user myuser

Another important thing to know is that I'm using my own module that wraps oauth2client like so:

import oauth2client
import argparse

def execute():

    parser = argparse.ArgumentParser(
            description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            parents=[tools.argparser])
            # don't use any flags                                                                           
    flags = parser.parse_args(None)

    flow = client.flow_from_clientsecrets(
             client_secret_path,
             scope=scope_path,
             message=tools.message_if_missing(client_secret))
    # open credential storage path                                                                                                                                                                 
     credential_storage =  file.Storage(self._credential_storage_path)
     credentials = credential_storage.get()
     # get credentails if necessary                                                                                                                                                                 
     if credentials is None or credentials.invalid:
          credentials = tools.run_flow(flow, credential_storage, flags)                                                                                       

Then my script looks something like that:

import myown_oauth2client_wrapper

from optparse import OptionParser

if __name__ == "__main__":
    usage = "something"
    parser_ = OptionParser(usage)

    parser_.add_option("-u","--user")
    (options_, args) = parser_.parse_args()

    myown_oauth2client_wrapper.execute()

How can I avoid this option override?

Shahar


Solution

  • In a previous question, Getting Youtube data using Python

    I found that the google api uses argparse.

    from outh2client.tools import argparser
    

    My deduction is that it is parsing the sys.argv when imported.

    As I asked in the comment, we need to know what errors you are getting. What do mean by 'overrides'? What's the indication of that? Are you getting a parser error message, the kind produced by argparse or optparse? If so, what message.

    Show us the commandline that gives the error, along with the error message.

    You might want to call the script with -h to see who/what prints parsing help message.


    So tools.argparser is an argparse parser with those auth and logging arguments defined. In the question I answered earlier, the user used that parser directly (with an addition of their own). You are using that parser as a parent.

    parser = argparse.ArgumentParser(...
            parents=[tools.argparser])                                                                    
    flags = parser.parse_args(None)
    

    It now parses sys.argv. Since --user was not defined for this parser, it raises the myscript: error: unrecognized arguments: --user myuser.

    One solution is to use:

    flags, extras = parser.parse_known_args(None)
    

    Now I expect it to run, and for extras to equal ['--user', 'myuser'].

    Another option is to define a --user argument for this parser.

    parser.add_argument('-u','--user',help='dummy user argument')