# googleapiutils2
Utilities for
[Google's v2 Python API](https://github.com/googleapis/google-api-python-client).
Currently supports sections of the following resources:
- [Drive](https://developers.google.com/drive/api/reference/rest/v3): `DriveResource`,
`FilesResource`, `PermissionsResource`, `RepliesResource`, `...`
- [Sheets](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets):
`SpreadsheetsResource`, `ValuesResource`, `...`
- [Geocoding](https://developers.google.com/maps/documentation/geocoding/overview)
## Quickstart 🚀
This project requires Python `^3.10` to run.
Several dependencies are needed, namely the aforesaid Google Python API, but also
Google's oauth library, and `requests`. Pre-bundled for ease of use are the fairly
monolithic `google-api-stubs`, which greatly improves the usage experience.
### via [`poetry`](https://python-poetry.org/docs/)
Install poetry, then run
> poetry install
And you're done.
## Overview 📖
The library was written to be consistent with Google's own Python API - just a little
easier to use. Most `Drive` and `Sheets` operations are supported using explicit
parameters. But most functions thereof take a `**kwargs` parameter (used for parameter
forwarding) to allow for the more granular usage of the underlying API.
A note on IDs: anytime a resource ID is needed, one can be provide the actual resource
ID, or the URL to the resource. If a URL is provided, this mapping is cached for future
use.
## Authentication 🔑
Before using a `Drive` or `Sheets` object, one must first authenticate. This is done via
the `google.oauth2` library, creating a `Credentials` object.
### Custom Credentials
The library supports two methods of authentication:
- via a Google service account (recommended, see more
[here](https://cloud.google.com/iam/docs/creating-managing-service-accounts))
- via OAuth2 (see more
[here](https://developers.google.com/identity/protocols/oauth2/native-app))
With a service account, one can programmatically access resources without user input.
This is by far the easiest route, but requires a bit of setup.
If one's not using a service account, the library will attempt to open a browser window
to authenticate using the provided credentials. This authentication is cached for future
usage (though it does expire on some interval) - so an valid token path is required.
See the [`get_oauth2_creds`](googleapiutils2/utils.py) function for more information.
### Default Credentials
To expedite development, all credentials-based objects will default to using a service
account by way of the following discovery scheme:
- If `./auth/credentials.json` exists, use that credentials file.
- If the `GOOGLE_API_CREDENTIALS` environment variable is set, use the credentials
file pointed to by the variable.
## Drive 📁
### MIME Types
When you upload a file to Google Drive, you must specify the original file's MIME type and the desired uploaded MIME type: the `from_mime_type` and `to_mime_type` parameters, respectively. The `GoogleMimeTypes` class provides a list of common MIME types.
We attempt to infer both MIME types from the file extension, but this is not always possible. The inference scheme is as thus:
- If either parameter is explicitly set, e.g. is not None, the value is used.
- If the file's already been uploaded, the MIME type is inferred from the file's metadata.
- If the file's not been uploaded, the MIME type is inferred from the file's extension.
- If the file's extension is not recognized, the MIME type is set to `GoogleMimeTypes.file`.
### Example: upload a file to a folder.
```python
from googleapiutils2 import Drive, get_oauth2_creds
creds = get_oauth2_creds() # explicitly get the credentials; you can share these with Sheets, etc.
drive = Drive(creds=creds)
# This will upload to your root Google Drive folder
drive.upload(
filepath="examples/hey.txt",
name="Asset 1",
to_mime_type=GoogleMimeTypes.docs,
)
```
### Example: copy a file to a folder.
```python
from googleapiutils2 import Drive
FILE_ID = ...
FOLDER_URL = ...
drive = Drive() # implicitly get the credentials
filename = "Heyy"
file = drive.get(filename, parents=[FOLDER_URL])
if file is not None:
drive.delete(file["id"])
file = drive.copy(file_id=FILE_ID, to_filename=filename, to_folder_id=FOLDER_URL)
```
What the above does is:
- Get the OAuth2 credentials using the default discvoery scheme (JSON object
representing the requisite credentials, see
[here](https://developers.google.com/identity/protocols/oauth2/native-app#step-2:-send-a-request-to-googles-oauth-2.0-server)
for more information).
- create a `Drive` object thereupon.
- Get the file with the given name, and delete it if it exists.
- Copy the file with the given ID to the given folder, and return the new file.
## Sheets 📊
### Example: update a range of cells in a sheet.
```python
SHEET_ID = ...
sheets = Sheets() # implicitly get the credentials
Sheet1 = SheetsValueRange(sheets, SHEET_ID, sheet_name="Sheet1")
rows = [
{
"Heyy": "99",
}
]
Sheet1[2:3, ...].update(rows)
```
What the above does is:
- Get the OAuth2 credentials using the default discovery scheme (JSON object
representing the requisite credentials, see
[here](https://developers.google.com/identity/protocols/oauth2/native-app#step-2:-send-a-request-to-googles-oauth-2.0-server)
for more information).
- create a `Sheets` object thereupon.
- Create a `SheetsValueRange` object, which is a wrapper around the
`spreadsheets.values` API.
- Update the range `Sheet1!A2:B3` with the given rows.
Note the slicing syntax, which will feel quite familiar for any user of Numpy or Pandas.
### SheetSlice
A `SheetsValueRange` object can be sliced in a similar manner to that of a Numpy array.
The syntax is as follows:
slc = Sheet[rows, cols]
Wherein `rows` and `cols` are either integers, slices of integers (stride is not
supported), strings (in A1 notation), or ellipses (`...`).
Note that Google's implementation of A1 notation is 1-indexed; 0 is invalid (e.g., 1
maps to `A`, 2 to `B`, etc.)
```py
ix = SheetSlice["Sheet1", 1:3, 2:4] # "Sheet1!B2:D4"
ix = SheetSlice["Sheet1", "A1:B2"] # "Sheet1!A1:B2"
ix = SheetSlice[1:3, 2:4] # "Sheet1!B2:D4"
ix = SheetSlice["A1:B2"] # "Sheet1!A1:B2"
ix = SheetSlice[..., 1:3] # "Sheet1!A1:Z3"
values = {
SheetSlice["A1:B2"]: [
["Heyy", "99"],
["Heyy", "99"],
],
} # "Sheet1!A1:B2" = [["Heyy", "99"], ["Heyy", "99"]]
```
A `SheetSlice` can also be used as a key into a `SheetsValueRange`, or a dictionary (to
use in updating a sheet's range via `.update()`, for example). Further, a
`SheetsValueRange` can be sliced in a similar manner to that of a `SheetSlice`.
```py
Sheet1[2:3, ...].update(rows)
...
```
### Why "2" 🤔
Don't ask :3
Raw data
{
"_id": null,
"home_page": "https://github.com/mkbabb/googleapiutils2",
"name": "googleapiutils2",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.12",
"maintainer_email": null,
"keywords": "google, googleapi, google-api, google api, googleapiutils2, google-sheets-api, google-drive-api",
"author": "Mike Babb",
"author_email": "mike7400@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/7b/3d/0fab57405a040ff1a7d16382fc9ea665c74b079872fd8ff58787c683651f/googleapiutils2-0.14.7.tar.gz",
"platform": null,
"description": "# googleapiutils2\n\nUtilities for\n[Google's v2 Python API](https://github.com/googleapis/google-api-python-client).\nCurrently supports sections of the following resources:\n\n- [Drive](https://developers.google.com/drive/api/reference/rest/v3): `DriveResource`,\n `FilesResource`, `PermissionsResource`, `RepliesResource`, `...`\n- [Sheets](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets):\n `SpreadsheetsResource`, `ValuesResource`, `...`\n- [Geocoding](https://developers.google.com/maps/documentation/geocoding/overview)\n\n## Quickstart \ud83d\ude80\n\nThis project requires Python `^3.10` to run.\n\nSeveral dependencies are needed, namely the aforesaid Google Python API, but also\nGoogle's oauth library, and `requests`. Pre-bundled for ease of use are the fairly\nmonolithic `google-api-stubs`, which greatly improves the usage experience.\n\n### via [`poetry`](https://python-poetry.org/docs/)\n\nInstall poetry, then run\n\n> poetry install\n\nAnd you're done.\n\n## Overview \ud83d\udcd6\n\nThe library was written to be consistent with Google's own Python API - just a little\neasier to use. Most `Drive` and `Sheets` operations are supported using explicit\nparameters. But most functions thereof take a `**kwargs` parameter (used for parameter\nforwarding) to allow for the more granular usage of the underlying API.\n\nA note on IDs: anytime a resource ID is needed, one can be provide the actual resource\nID, or the URL to the resource. If a URL is provided, this mapping is cached for future\nuse.\n\n## Authentication \ud83d\udd11\n\nBefore using a `Drive` or `Sheets` object, one must first authenticate. This is done via\nthe `google.oauth2` library, creating a `Credentials` object.\n\n### Custom Credentials\n\nThe library supports two methods of authentication:\n\n- via a Google service account (recommended, see more\n [here](https://cloud.google.com/iam/docs/creating-managing-service-accounts))\n- via OAuth2 (see more\n [here](https://developers.google.com/identity/protocols/oauth2/native-app))\n\nWith a service account, one can programmatically access resources without user input.\nThis is by far the easiest route, but requires a bit of setup.\n\nIf one's not using a service account, the library will attempt to open a browser window\nto authenticate using the provided credentials. This authentication is cached for future\nusage (though it does expire on some interval) - so an valid token path is required.\n\nSee the [`get_oauth2_creds`](googleapiutils2/utils.py) function for more information.\n\n### Default Credentials\n\nTo expedite development, all credentials-based objects will default to using a service\naccount by way of the following discovery scheme:\n\n- If `./auth/credentials.json` exists, use that credentials file.\n- If the `GOOGLE_API_CREDENTIALS` environment variable is set, use the credentials\n file pointed to by the variable.\n\n## Drive \ud83d\udcc1\n\n### MIME Types\n\nWhen you upload a file to Google Drive, you must specify the original file's MIME type and the desired uploaded MIME type: the `from_mime_type` and `to_mime_type` parameters, respectively. The `GoogleMimeTypes` class provides a list of common MIME types.\n\nWe attempt to infer both MIME types from the file extension, but this is not always possible. The inference scheme is as thus:\n\n- If either parameter is explicitly set, e.g. is not None, the value is used.\n- If the file's already been uploaded, the MIME type is inferred from the file's metadata.\n- If the file's not been uploaded, the MIME type is inferred from the file's extension.\n- If the file's extension is not recognized, the MIME type is set to `GoogleMimeTypes.file`.\n\n### Example: upload a file to a folder.\n\n```python\nfrom googleapiutils2 import Drive, get_oauth2_creds\n\ncreds = get_oauth2_creds() # explicitly get the credentials; you can share these with Sheets, etc.\ndrive = Drive(creds=creds)\n\n# This will upload to your root Google Drive folder\ndrive.upload(\n filepath=\"examples/hey.txt\",\n name=\"Asset 1\",\n to_mime_type=GoogleMimeTypes.docs,\n)\n```\n\n### Example: copy a file to a folder.\n\n```python\nfrom googleapiutils2 import Drive\nFILE_ID = ...\nFOLDER_URL = ...\n\ndrive = Drive() # implicitly get the credentials\n\nfilename = \"Heyy\"\n\nfile = drive.get(filename, parents=[FOLDER_URL])\nif file is not None:\n drive.delete(file[\"id\"])\n\nfile = drive.copy(file_id=FILE_ID, to_filename=filename, to_folder_id=FOLDER_URL)\n```\n\nWhat the above does is:\n\n- Get the OAuth2 credentials using the default discvoery scheme (JSON object\n representing the requisite credentials, see\n [here](https://developers.google.com/identity/protocols/oauth2/native-app#step-2:-send-a-request-to-googles-oauth-2.0-server)\n for more information).\n- create a `Drive` object thereupon.\n- Get the file with the given name, and delete it if it exists.\n- Copy the file with the given ID to the given folder, and return the new file.\n\n## Sheets \ud83d\udcca\n\n### Example: update a range of cells in a sheet.\n\n```python\nSHEET_ID = ...\n\nsheets = Sheets() # implicitly get the credentials\n\nSheet1 = SheetsValueRange(sheets, SHEET_ID, sheet_name=\"Sheet1\")\n\nrows = [\n {\n \"Heyy\": \"99\",\n }\n]\nSheet1[2:3, ...].update(rows)\n```\n\nWhat the above does is:\n\n- Get the OAuth2 credentials using the default discovery scheme (JSON object\n representing the requisite credentials, see\n [here](https://developers.google.com/identity/protocols/oauth2/native-app#step-2:-send-a-request-to-googles-oauth-2.0-server)\n for more information).\n- create a `Sheets` object thereupon.\n- Create a `SheetsValueRange` object, which is a wrapper around the\n `spreadsheets.values` API.\n- Update the range `Sheet1!A2:B3` with the given rows.\n\nNote the slicing syntax, which will feel quite familiar for any user of Numpy or Pandas.\n\n### SheetSlice\n\nA `SheetsValueRange` object can be sliced in a similar manner to that of a Numpy array.\nThe syntax is as follows:\n\n slc = Sheet[rows, cols]\n\nWherein `rows` and `cols` are either integers, slices of integers (stride is not\nsupported), strings (in A1 notation), or ellipses (`...`).\n\nNote that Google's implementation of A1 notation is 1-indexed; 0 is invalid (e.g., 1\nmaps to `A`, 2 to `B`, etc.)\n\n```py\nix = SheetSlice[\"Sheet1\", 1:3, 2:4] # \"Sheet1!B2:D4\"\nix = SheetSlice[\"Sheet1\", \"A1:B2\"] # \"Sheet1!A1:B2\"\nix = SheetSlice[1:3, 2:4] # \"Sheet1!B2:D4\"\nix = SheetSlice[\"A1:B2\"] # \"Sheet1!A1:B2\"\nix = SheetSlice[..., 1:3] # \"Sheet1!A1:Z3\"\n\nvalues = {\n SheetSlice[\"A1:B2\"]: [\n [\"Heyy\", \"99\"],\n [\"Heyy\", \"99\"],\n ],\n} # \"Sheet1!A1:B2\" = [[\"Heyy\", \"99\"], [\"Heyy\", \"99\"]]\n```\n\nA `SheetSlice` can also be used as a key into a `SheetsValueRange`, or a dictionary (to\nuse in updating a sheet's range via `.update()`, for example). Further, a\n`SheetsValueRange` can be sliced in a similar manner to that of a `SheetSlice`.\n\n```py\nSheet1[2:3, ...].update(rows)\n...\n```\n\n### Why \"2\" \ud83e\udd14\n\nDon't ask :3\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Wrapper for Google's Python API.",
"version": "0.14.7",
"project_urls": {
"Homepage": "https://github.com/mkbabb/googleapiutils2",
"Repository": "https://github.com/mkbabb/googleapiutils2"
},
"split_keywords": [
"google",
" googleapi",
" google-api",
" google api",
" googleapiutils2",
" google-sheets-api",
" google-drive-api"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "063a5193e66a474f5d0bdccf2f972bfe7ac5dfd7aa8dd42eb348f9d061f3d709",
"md5": "6ecbd5929c2b31a2ff5444025837f311",
"sha256": "1248f744e3d62e90bdf19c0c921ec4aa2ab251febcbd1ae373cebd743ca4c47e"
},
"downloads": -1,
"filename": "googleapiutils2-0.14.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6ecbd5929c2b31a2ff5444025837f311",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.12",
"size": 44706,
"upload_time": "2024-10-24T19:37:36",
"upload_time_iso_8601": "2024-10-24T19:37:36.045380Z",
"url": "https://files.pythonhosted.org/packages/06/3a/5193e66a474f5d0bdccf2f972bfe7ac5dfd7aa8dd42eb348f9d061f3d709/googleapiutils2-0.14.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7b3d0fab57405a040ff1a7d16382fc9ea665c74b079872fd8ff58787c683651f",
"md5": "5772da6bbd7a909398c3fe04f0557636",
"sha256": "b5a667ecceb5c848c85b9a9f5dcacdadf831216b17be939eb2c04a86dd4f1f15"
},
"downloads": -1,
"filename": "googleapiutils2-0.14.7.tar.gz",
"has_sig": false,
"md5_digest": "5772da6bbd7a909398c3fe04f0557636",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.12",
"size": 41575,
"upload_time": "2024-10-24T19:37:37",
"upload_time_iso_8601": "2024-10-24T19:37:37.477968Z",
"url": "https://files.pythonhosted.org/packages/7b/3d/0fab57405a040ff1a7d16382fc9ea665c74b079872fd8ff58787c683651f/googleapiutils2-0.14.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-24 19:37:37",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mkbabb",
"github_project": "googleapiutils2",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "googleapiutils2"
}