Skip to content

Instantly share code, notes, and snippets.

@rmasters
Last active May 19, 2021 14:40
Show Gist options
  • Save rmasters/0f71267dfbb01ded07fe4c873254d2e4 to your computer and use it in GitHub Desktop.
Save rmasters/0f71267dfbb01ded07fe4c873254d2e4 to your computer and use it in GitHub Desktop.
Work around Pydrive's lack of support for service_account.json
# Dynamically generated files
.service_account_pkcs12.asc

Quickstart

  1. Download, extract the Gist ZIP file and open a terminal in the folder
  2. Save your service_account.json from the Google API dashboard to the folder
  3. With Poetry:
    1. poetry install
    2. poetry shell
  4. Without Poetry:
    1. python -m venv .venv
    2. source .venv/bin/activate
    3. pip install -r requirements.txt
  5. python main.py
import json
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
import yaml
def generate_pydrive_settings(source_file: str = "service_account.json"):
"""
It appears Pydrive was made before Google introduced its (v3?) JSON auth files. We need to configure Pydrive to
handle the existing service_account.json we already have.
Pydrive expects to be configured by loading a settings.yaml object, but we can work around _that_ by merging these
updated configs into GoogleAuth.settings before calling GoogleAuth.ServiceAuth(). Unfortunately the private key must
still be loaded from file...
"""
with open(source_file, "r") as infile:
config = json.load(infile)
# Pydrive expects the private key to be in its own file...
pkcs12_path = ".service_account_pkcs12.asc"
with open(pkcs12_path, "w") as f:
f.write(config['private_key'])
settings = {
# Pydrive can extract _some_ fields from the service_account.json...
"client_config_file": source_file,
"save_credentials": False,
"service_config": {
"client_service_email": config['client_email'],
"client_pkcs12_file_path": pkcs12_path,
# This is apparently used for delegated access - we don't need this, you might?
"client_user_email": None,
},
}
return settings
def main():
gauth_settings = generate_pydrive_settings()
gauth = GoogleAuth()
gauth.settings.update(gauth_settings)
gauth.ServiceAuth()
drive = GoogleDrive(gauth)
fileList = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
print(len(fileList))
for file1 in fileList:
print('title: %s, id: %s' % (file1['title'], file1['id']))
main()
[tool.poetry]
name = "pydrive_service_account_test"
version = "0.1.0"
description = ""
authors = ["Ross Masters <ross.masters@lendable.co.uk>"]
[tool.poetry.dependencies]
python = "^3.8"
pydrive = "^1.3.1"
pyyaml = "^5.4.1"
pyopenssl = "^20.0.1"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
cachetools==4.2.2
certifi==2020.12.5
cffi==1.14.5
chardet==4.0.0
cryptography==3.4.7
google-api-core==1.27.0
google-api-python-client==2.4.0
google-auth==1.30.0
google-auth-httplib2==0.1.0
googleapis-common-protos==1.53.0
httplib2==0.19.1
idna==2.10
oauth2client==4.1.3
packaging==20.9
protobuf==3.17.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
pydrive==1.3.1
pyopenssl==20.0.1
pyparsing==2.4.7
pytz==2021.1
pyyaml==5.4.1
requests==2.25.1
rsa==4.7.2
six==1.16.0
uritemplate==3.0.1
urllib3==1.26.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment