Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Google Analytics credentials without gflags - using run_flow() instead?

This may take a second to explain so please bear with me:

I'm working on a project for work that requires me to pull in google analytics data. I originally did this following this link, so after installing the API client pip install --upgrade google-api-python-client and setting things up like the client_secrets.json, it wanted gflags to be installed in order to execute the run() statement. (i.e credentials = run(FLOW, storage))

Now, I was getting the error message to install gflags or better to use run_flow() (exact error message was this):

NotImplementedError: The gflags library must be installed to use tools.run(). Please install gflags or preferably switch to using tools.run_flow().

I originally used gflags (a few months ago), but it wasn't compatible with our framework (pyramid), so we removed it until we could figure out what the issue was. And the reason why it's preferable to switch from gflags to run_flow() is because gflags has been deprecated, so I don't want to use it like I had. What I'm trying to do now is switch over to using run_flow()

The issue with this is run_flow() expects a command line argument to be sent to it and this is not a command line application. I found some documentation that was helpful but I'm stuck on building the flags for the run_flow() function.

Before showing code one more thing to explain.

run_flow() takes three arguments (documentation here). It takes the flow and storage just like run() does, but it also takes a flags object. the gflags library built a flags ArgumentParser object that was used in the oauth2client execution method.

a few other links that were helpful in building the argumentParser object:

  • Link 1: https://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.tools-module.html
  • Link 2: https://developers.google.com/compute/docs/api/python-guide

The second link is very helpful to see how it would be executed, so now when I try to do something similar, sys.argv pulls in the location of my virtual environment that is running aka pserve and also pulls in my .ini file (which stores credentials for my machine to run the virtual environment). But that throws an error because its expecting something else, and this is where I'm stuck.

  • I don't know what flags object I need to build to send through run_flow()
  • I don't know what argv arguments I need passed in order for the statement flags = parser.parse_args(argv[1:]) to retrieve the correct information (I don't know what the correct information is supposed to be)

Code:

CLIENT_SECRETS = client_file.uri
MISSING_CLIENT_SECRETS_MESSAGE = '%s is missing' % CLIENT_SECRETS
FLOW = flow_from_clientsecrets(
    CLIENT_SECRETS,
    scope='https://www.googleapis.com/auth/analytics.readonly',
    message=MISSING_CLIENT_SECRETS_MESSAGE
)
TOKEN_FILE_NAME = 'analytics.dat'

def prepare_credentials(self, argv):
    storage = Storage(self.TOKEN_FILE_NAME)
    credentials = storage.get()

    if credentials is None or credentials.invalid:
        parser = argparse.ArgumentParser(description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            parents=[tools.argparser])
        flags = parser.parse_args(argv[1:]) # i could also do just argv, both error
        credentials = run_flow(self.FLOW, storage, flags) 
    return credentials

def initialize_service(self, argv):
    http = httplib2.Http()
    credentials = self.prepare_credentials(self, argv)
    http = credentials.authorize(http)
    return build('analytics', 'v3', http=http)

I call a main function passing sys.argv that calls the initialize_service

def main(self, argv):
    service = self.initialize_service(self, argv)

    try:
        #do a query and stuff here

I knew this wouldn't work because my application is not a command line application but rather a full integrated service but I figured it was worth a shot. Any thoughts on how to build the flags object correctly?

like image 688
John Ruddell Avatar asked Jul 22 '14 14:07

John Ruddell


1 Answers

from oauth2client import tools

flags = tools.argparser.parse_args(args=[])
credentials = tools.run_flow(flow, storage, flags)

Took a bit of mucking about but climbed my way out the two traps it dropped me into:

  1. have to use the argparser provided in tools
  2. I had to feed args an empty list to prevent it from reading args off the command line, which was a problem because I'm running it from inside a unittest (so different cmdline args).
like image 125
John Mee Avatar answered Oct 19 '22 20:10

John Mee