Source code for ocdskingfishercolab.google

"""Google Sheets and Google Drive integration."""

import warnings

import flattentool
import google.auth
import gspread
import httplib2
from flattentool.exceptions import FlattenToolWarning
from gspread_dataframe import set_with_dataframe
from oauth2client.client import GoogleCredentials
from oauth2client.contrib.gce import AppAssertionCredentials
from pydrive2.auth import GoogleAuth
from pydrive2.drive import GoogleDrive

try:
    from google.colab import auth
except ImportError:
    # Assume we are in a testing environment.
    from unittest.mock import Mock

    auth = Mock()

from ocdskingfishercolab.download import write_data_as_json

# Patch PyDrive2 like at: https://github.com/googlecolab/colabtools/blob/main/google/colab/_import_hooks/_pydrive.py
old_local_webserver_auth = GoogleAuth.LocalWebserverAuth


def _local_web_server_auth(self, *args, **kwargs):
    if isinstance(self.credentials, AppAssertionCredentials):
        self.credentials.refresh(httplib2.Http())
        return None
    return old_local_webserver_auth(self, *args, **kwargs)


GoogleAuth.LocalWebserverAuth = _local_web_server_auth


[docs] def authenticate_gspread(): """ Authenticate the current user and give the notebook permission to connect to Google Spreadsheets. :returns: a `Google Sheets Client <https://gspread.readthedocs.io/en/latest/api.html#client>`__ instance :rtype: gspread.Client """ auth.authenticate_user() credentials, _ = google.auth.default() return gspread.authorize(credentials)
[docs] def authenticate_pydrive(): """ Authenticate the current user and give the notebook permission to connect to Google Drive. :returns: a `GoogleDrive <https://gsuitedevs.github.io/PyDrive/docs/build/html/pydrive.html#module-pydrive.drive>`__ instance :rtype: pydrive2.drive.GoogleDrive """ # noqa: E501 auth.authenticate_user() gauth = GoogleAuth() gauth.credentials = GoogleCredentials.get_application_default() return GoogleDrive(gauth)
def _save_file_to_drive(metadata, filename): drive = authenticate_pydrive() drive_file = drive.CreateFile(metadata) drive_file.SetContentFile(filename) drive_file.Upload() return drive_file
[docs] def save_dataframe_to_sheet(spreadsheet_name, dataframe, sheetname, *, prompt=True): """ Save a data frame to a worksheet in Google Sheets, after asking the user for confirmation. :param str spreadsheet_name: the name of the spreadsheet :param pandas.DataFrame dataframe: a data frame :param str sheetname: the name of the sheet to add :param bool prompt: whether to prompt the user """ if dataframe.empty: print("Data frame is empty.") # noqa: T201 return if not prompt or input("Save to Google Sheets? (y/N)") == "y": gc = authenticate_gspread() try: sheet = gc.open(spreadsheet_name) except gspread.SpreadsheetNotFound: sheet = gc.create(spreadsheet_name) try: worksheet = sheet.add_worksheet(sheetname, dataframe.shape[0], dataframe.shape[1]) except gspread.exceptions.APIError: newsheetname = input(f"{sheetname} already exists, enter a new name:") worksheet = sheet.add_worksheet(newsheetname, dataframe.shape[0], dataframe.shape[1]) set_with_dataframe(worksheet, dataframe)
[docs] def save_dataframe_to_spreadsheet(dataframe, name): """ Dump the ``release_package`` column of a data frame to a JSON file, convert the JSON file to an Excel file, and upload the Excel file to Google Drive. :param pandas.DataFrame dataframe: a data frame :param str name: the basename of the Excel file to write """ if dataframe.empty: print("Data frame is empty.") # noqa: T201 return write_data_as_json(dataframe["release_package"][0], "release_package.json") with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=FlattenToolWarning) flattentool.flatten( "release_package.json", main_sheet_name="releases", root_list_path="releases", root_id="ocid", schema="https://standard.open-contracting.org/1.1/en/release-schema.json", disable_local_refs=True, remove_empty_schema_columns=True, root_is_list=False, output_format="xlsx", ) drive_file = _save_file_to_drive({"title": f"{name}.xlsx"}, "flattened.xlsx") print(f"Uploaded file with ID {drive_file['id']!r}") # noqa: T201