Search code examples
pythongoogle-drive-apigoogle-api-python-client

Google REST HTTP request delivers more properties than google-api-python-client Python request


If I issue a request directly using the HTTP REST interface like this:

GET https://www.googleapis.com/drive/v2/files/1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA?key={YOUR_API_KEY}

I get a set of metadata for the file that contains, among other things, the file properties elements. If instead, I call using the Python library to the drive API, like this:

md = service.files().get(fileId='1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA').execute()

I get a dict in md that contains a much more limited set of data, properties is missing among others. I have not expressed fields filtering.

Is this a limitation of the Google Python lib or do I need to set some option?

Update: Based on comments I went back and checked authentication. I am using Oauth2 straight from the Google cookbook and the full auth scope ('https://www.googleapis.com/auth/drive'). The code below is (I think) the minimum necessary to demonstrate the result.

import httplib2
import os
import json

from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Other Client 1'


def get_credentials():
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir, 'drive-tagger.json')
    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatability with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials


def main():
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v2', http=http)

    md = service.properties().list(fileId='1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA').execute()
    print "properties().list() returns:"
    print json.dumps(md, indent=4)
    print "***Done***"

if __name__ == '__main__':
    main()

If I run this I get an authentication browser pop-up and authenticate to the same domain as I use in API explorer. The result is this:

Authentication successful.
Storing credentials to C:\Users\scott_jackson\.credentials\drive-tagger.json
properties().list() returns:
{
    "items": [], 
    "kind": "drive#propertyList", 
    "etag": "\"amKkzAMv_fUBF0Cxt1a1WaLm5Nk/vyGp6PvFo4RvsFtPoIWeCReyIC8\"", 
    "selfLink": "https://www.googleapis.com/drive/v2/files/1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA/properties?alt=json"
}
***Done***

Note that "items" is empty. If, however, I use the API explorer, and authenticate into the same domain and request the same fileId I get:

{
 "kind": "drive#propertyList",
 "etag": "\"amKkzAMv_fUBF0Cxt1a1WaLm5Nk/BEYHBcaVZiElhupVVaqT2nEhnc0\"",
 "selfLink": "https://www.googleapis.com/drive/v2/files/1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA/properties",
 "items": [
  {

   "kind": "drive#property",
   "etag": "\"amKkzAMv_fUBF0Cxt1a1WaLm5Nk/Mg7GWY95vfY7E-2gvlxRbl7MLDk\"",
   "selfLink": "https://www.googleapis.com/drive/v2/files/1el16TSNYvaGQndXXDZjheN_CANnWbA9wSA/properties/md5sum?visibility=PRIVATE",
   "key": "md5sum",
   "visibility": "PRIVATE",
   "value": "a61b0d91a294364b0c4eebb3ee83c09a"
  }
 ]
}

which has the 'items' I'm looking for.

Any insights would be appreciated.


Solution

  • Note that the property is marked as PRIVATE. That means only the application that created it can see it. Since you say it shows up in the APIs Explorer, I'm guessing you probably also created the property via the APIs Explorer and did so as a private property.

    If you're using the explorer, try creating the property as public. That would allow your python script to see it. Or create the property using your app's identity instead if you'd prefer to keep it private to your app.