1

Is it possible to load credentials from dict instead of file? This would make it easier to use short scripts in cloud functions, because then there is no need for uploading files. Normally authorization goes like this:

import pygsheets
gc = pygsheets.authorize(service_file='client_secret.json')

If credentials are stored in the a variable like this:

secret = {
  "type": "service_account",
  "project_id": "XXXXXXXXXX",
  "private_key_id": "XXXXXXXXXX",
  "private_key": "XXXXXXXXXX"
  "client_email": "XXXXXXXXXX",
  "client_id": "XXXXXXXXXX",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "XXXXXXXXXX"
}

Would it be possible to load them with custom_credentials instead of service_file? The docs don't give any instructions on how to use it, except "this option will ignore any other parameters". The following code:

import pygsheets
gc = pygsheets.authorize(custom_credentials=secret)

Throws the following error:

AttributeError: 'dict' object has no attribute 'before_request'

Is there another way to do this? In gspread, for example, there is the following option:

ServiceAccountCredentials.from_json_keyfile_dict(keyfile_dict, scope)

Any suggestions? Thanks!!!

PythonSherpa
  • 2,560
  • 3
  • 19
  • 40

3 Answers3

4

Just did this! So what we ended up doing was to write a tempfile and then loading that for authorize. Working example below:

import tempfile

def _google_creds_as_file():
    temp = tempfile.NamedTemporaryFile()
    temp.write(json.dumps({
        "type": "service_account",
        "project_id": "xxxx-yyy",
        "private_key_id": "xxxxxxx",
        "private_key": "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----\n",
        "client_email": "xxx@yyyy.iam.gserviceaccount.com",
        "client_id": "xxxxx",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxxxx%40xxxx.iam.gserviceaccount.com"
    }))
    temp.flush()
    return temp

creds_file = _google_creds_as_file()
gc = pygsheets.authorize(service_account_file=creds_file.name)
Arif Amirani
  • 26,265
  • 3
  • 33
  • 30
  • 2
    Worked for me. One change need to make was to convert the output of `json.dumps()` to bytes with `.encode('utf-8')` in order to write to the tempfile. – Michael Discenza Jul 21 '19 at 21:39
  • worked for me as well. this is a pretty good method to work around and it should work with other type of credential files too. I am unable to get the service_account_env_var way working. whatever string value i put in with all type of formats it does not seem to like it. – Bigs May 13 '22 at 05:22
1

Thanks for the suggestion @kontinuity. After some digging I found out there is actually already a pull request for this: https://github.com/nithinmurali/pygsheets/pull/345

In the authorization.py there is a new option called service_account_env_var. Just tried it and this works perfect.

PythonSherpa
  • 2,560
  • 3
  • 19
  • 40
1

The custom_credentials should be a credentials object as mentioned here. If you don't want to create a tmp file, you can create an object directly from the json.

SCOPES = ('https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive')
service_account_info = json.loads(secret)
my_credentials = service_account.Credentials.from_service_account_info(service_account_info, scopes=SCOPES)
Nithin
  • 5,470
  • 37
  • 44