gspread-asyncio


Namegspread-asyncio JSON
Version 2.0.0 PyPI version JSON
download
home_pagehttps://github.com/dgilman/gspread_asyncio
Summaryasyncio wrapper for burnash's Google Spreadsheet API library, gspread
upload_time2024-02-10 20:51:01
maintainer
docs_urlNone
authorDavid Gilman
requires_python>=3.8
licenseMIT
keywords spreadsheets google-spreadsheets asyncio
VCS
bugtrack_url
requirements cachetools certifi charset-normalizer google-auth google-auth-oauthlib gspread idna oauthlib pyasn1 pyasn1-modules requests requests-oauthlib rsa strenum urllib3
Travis-CI
coveralls test coverage No coveralls.
            # gspread_asyncio

An [asyncio wrapper](https://docs.python.org/3/library/asyncio.html) for [burnash's excellent Google Spreadsheet API library](https://github.com/burnash/gspread). `gspread_asyncio` isn't just a plain asyncio wrapper around the `gspread` API, it implements several useful and helpful features on top of those APIs. It's useful for long-running processes and one-off scripts.

Requires Python >= 3.8.

[![Documentation Status](https://readthedocs.org/projects/gspread-asyncio/badge/?version=latest)](https://gspread-asyncio.readthedocs.io/en/latest/?badge=latest) ![CI status](https://github.com/dgilman/gspread_asyncio/actions/workflows/ci.yml/badge.svg)


## Features

* Complete async wrapping of the `gspread` API. All `gspread` API calls are run off the main thread in a threadpool executor.
* Internal caching and reuse of `gspread` `Client`/`Spreadsheet`/`Worksheet` objects.
* Automatic renewal of expired credentials.
* Automatic retries of spurious failures from Google's servers (HTTP 5xx).
* Automatic rate limiting with defaults set to Google's default API limits.
* Many methods that don't need to return a value can optionally return an already-scheduled `Future` (the `nowait` kwarg). You can ignore that future, allowing forward progress on your calling coroutine while the asyncio event loop schedules and runs the Google Spreadsheet API call at a later time for you.

## Example usage

```python
import asyncio

import gspread_asyncio

# from google-auth package
from google.oauth2.service_account import Credentials 

# First, set up a callback function that fetches our credentials off the disk.
# gspread_asyncio needs this to re-authenticate when credentials expire.

def get_creds():
    # To obtain a service account JSON file, follow these steps:
    # https://gspread.readthedocs.io/en/latest/oauth2.html#for-bots-using-service-account
    creds = Credentials.from_service_account_file("serviceacct_spreadsheet.json")
    scoped = creds.with_scopes([
        "https://spreadsheets.google.com/feeds",
        "https://www.googleapis.com/auth/spreadsheets",
        "https://www.googleapis.com/auth/drive",
    ])
    return scoped

# Create an AsyncioGspreadClientManager object which
# will give us access to the Spreadsheet API.

agcm = gspread_asyncio.AsyncioGspreadClientManager(get_creds)

# Here's an example of how you use the API:

async def example(agcm):
    # Always authorize first.
    # If you have a long-running program call authorize() repeatedly.
    agc = await agcm.authorize()

    ss = await agc.create("Test Spreadsheet")
    print("Spreadsheet URL: https://docs.google.com/spreadsheets/d/{0}".format(ss.id))
    print("Open the URL in your browser to see gspread_asyncio in action!")

    # Allow anyone with the URL to write to this spreadsheet.
    await agc.insert_permission(ss.id, None, perm_type="anyone", role="writer")

    # Create a new spreadsheet but also grab a reference to the default one.
    ws = await ss.add_worksheet("My Test Worksheet", 10, 5)
    zero_ws = await ss.get_worksheet(0)

    # Write some stuff to both spreadsheets.
    for row in range(1, 11):
        for col in range(1, 6):
            val = "{0}/{1}".format(row, col)
            await ws.update_cell(row, col, val + " ws")
            await zero_ws.update_cell(row, col, val + " zero ws")
    print("All done!")

# Turn on debugging if you're new to asyncio!
asyncio.run(example(agcm), debug=True)
```

## Observational notes and gotchas

* This module does not define its own exceptions, it propagates instances of `gspread.exceptions.GSpreadException`.
* Always call `AsyncioGspreadClientManager.authorize()`, `AsyncioGspreadClient.open_*()` and `AsyncioGspreadSpreadsheet.get_worksheet()` before doing any work on a spreadsheet. These methods keep an internal cache so it is painless to call them many times, even inside of a loop. This makes sure you always have a valid set of authentication credentials from Google.
* The only object you should store in your application is the `AsyncioGspreadClientManager` (`agcm`).
* Right now the `gspread` library does not support bulk appends of rows or bulk changes of cells. When this is done `gspread_asyncio` will support batching of these Google API calls without any changes to the Python `gspread_asyncio` API.
* I came up with the default 1.1 second delay between API calls (the `gspread_delay` kwarg) after extensive experimentation. The official API rate limit is one call every second but however Google measures these things introduces a tiny bit of jitter that will get you rate blocked if you ride that limit exactly.
* Google's service reliability on these endpoints is surprisingly bad. There are frequent HTTP 500s and the retry logic will save your butt in long-running scripts or short, one-shot, one-off ones.
* Experimentation also found that Google's credentials expire after an hour and the default `reauth_interval` of 45 minutes takes care of that just fine.

## License

MIT

## Sponsorship

Development of gspread_asyncio is sponsored by [Pro Football History.com, your source for NFL coaching biographies.](https://pro-football-history.com)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/dgilman/gspread_asyncio",
    "name": "gspread-asyncio",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "spreadsheets,google-spreadsheets,asyncio",
    "author": "David Gilman",
    "author_email": "dgilman@gilslotd.com",
    "download_url": "https://files.pythonhosted.org/packages/bf/7e/480054799ce34cec733d9d33951a801ffd2aea16dcdeea6801807aa44d83/gspread_asyncio-2.0.0.tar.gz",
    "platform": null,
    "description": "# gspread_asyncio\n\nAn [asyncio wrapper](https://docs.python.org/3/library/asyncio.html) for [burnash's excellent Google Spreadsheet API library](https://github.com/burnash/gspread). `gspread_asyncio` isn't just a plain asyncio wrapper around the `gspread` API, it implements several useful and helpful features on top of those APIs. It's useful for long-running processes and one-off scripts.\n\nRequires Python >= 3.8.\n\n[![Documentation Status](https://readthedocs.org/projects/gspread-asyncio/badge/?version=latest)](https://gspread-asyncio.readthedocs.io/en/latest/?badge=latest) ![CI status](https://github.com/dgilman/gspread_asyncio/actions/workflows/ci.yml/badge.svg)\n\n\n## Features\n\n* Complete async wrapping of the `gspread` API. All `gspread` API calls are run off the main thread in a threadpool executor.\n* Internal caching and reuse of `gspread` `Client`/`Spreadsheet`/`Worksheet` objects.\n* Automatic renewal of expired credentials.\n* Automatic retries of spurious failures from Google's servers (HTTP 5xx).\n* Automatic rate limiting with defaults set to Google's default API limits.\n* Many methods that don't need to return a value can optionally return an already-scheduled `Future` (the `nowait` kwarg). You can ignore that future, allowing forward progress on your calling coroutine while the asyncio event loop schedules and runs the Google Spreadsheet API call at a later time for you.\n\n## Example usage\n\n```python\nimport asyncio\n\nimport gspread_asyncio\n\n# from google-auth package\nfrom google.oauth2.service_account import Credentials \n\n# First, set up a callback function that fetches our credentials off the disk.\n# gspread_asyncio needs this to re-authenticate when credentials expire.\n\ndef get_creds():\n    # To obtain a service account JSON file, follow these steps:\n    # https://gspread.readthedocs.io/en/latest/oauth2.html#for-bots-using-service-account\n    creds = Credentials.from_service_account_file(\"serviceacct_spreadsheet.json\")\n    scoped = creds.with_scopes([\n        \"https://spreadsheets.google.com/feeds\",\n        \"https://www.googleapis.com/auth/spreadsheets\",\n        \"https://www.googleapis.com/auth/drive\",\n    ])\n    return scoped\n\n# Create an AsyncioGspreadClientManager object which\n# will give us access to the Spreadsheet API.\n\nagcm = gspread_asyncio.AsyncioGspreadClientManager(get_creds)\n\n# Here's an example of how you use the API:\n\nasync def example(agcm):\n    # Always authorize first.\n    # If you have a long-running program call authorize() repeatedly.\n    agc = await agcm.authorize()\n\n    ss = await agc.create(\"Test Spreadsheet\")\n    print(\"Spreadsheet URL: https://docs.google.com/spreadsheets/d/{0}\".format(ss.id))\n    print(\"Open the URL in your browser to see gspread_asyncio in action!\")\n\n    # Allow anyone with the URL to write to this spreadsheet.\n    await agc.insert_permission(ss.id, None, perm_type=\"anyone\", role=\"writer\")\n\n    # Create a new spreadsheet but also grab a reference to the default one.\n    ws = await ss.add_worksheet(\"My Test Worksheet\", 10, 5)\n    zero_ws = await ss.get_worksheet(0)\n\n    # Write some stuff to both spreadsheets.\n    for row in range(1, 11):\n        for col in range(1, 6):\n            val = \"{0}/{1}\".format(row, col)\n            await ws.update_cell(row, col, val + \" ws\")\n            await zero_ws.update_cell(row, col, val + \" zero ws\")\n    print(\"All done!\")\n\n# Turn on debugging if you're new to asyncio!\nasyncio.run(example(agcm), debug=True)\n```\n\n## Observational notes and gotchas\n\n* This module does not define its own exceptions, it propagates instances of `gspread.exceptions.GSpreadException`.\n* Always call `AsyncioGspreadClientManager.authorize()`, `AsyncioGspreadClient.open_*()` and `AsyncioGspreadSpreadsheet.get_worksheet()` before doing any work on a spreadsheet. These methods keep an internal cache so it is painless to call them many times, even inside of a loop. This makes sure you always have a valid set of authentication credentials from Google.\n* The only object you should store in your application is the `AsyncioGspreadClientManager` (`agcm`).\n* Right now the `gspread` library does not support bulk appends of rows or bulk changes of cells. When this is done `gspread_asyncio` will support batching of these Google API calls without any changes to the Python `gspread_asyncio` API.\n* I came up with the default 1.1 second delay between API calls (the `gspread_delay` kwarg) after extensive experimentation. The official API rate limit is one call every second but however Google measures these things introduces a tiny bit of jitter that will get you rate blocked if you ride that limit exactly.\n* Google's service reliability on these endpoints is surprisingly bad. There are frequent HTTP 500s and the retry logic will save your butt in long-running scripts or short, one-shot, one-off ones.\n* Experimentation also found that Google's credentials expire after an hour and the default `reauth_interval` of 45 minutes takes care of that just fine.\n\n## License\n\nMIT\n\n## Sponsorship\n\nDevelopment of gspread_asyncio is sponsored by [Pro Football History.com, your source for NFL coaching biographies.](https://pro-football-history.com)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "asyncio wrapper for burnash's Google Spreadsheet API library, gspread",
    "version": "2.0.0",
    "project_urls": {
        "Documentation": "https://gspread-asyncio.readthedocs.io/en/latest/",
        "Homepage": "https://github.com/dgilman/gspread_asyncio",
        "Source": "https://github.com/dgilman/gspread_asyncio",
        "Tracker": "https://github.com/dgilman/gspread_asyncio/issues"
    },
    "split_keywords": [
        "spreadsheets",
        "google-spreadsheets",
        "asyncio"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a28279c5d77c2f7175e14f9af971c692492c1eaf8a8bd4ccd5ec8d4c22e962a6",
                "md5": "7b87c88ad21cef706be801aa8d6db560",
                "sha256": "63713a5337d52d538bb26815d96f98950cbdfae67600e1c137cea8608f41e5c4"
            },
            "downloads": -1,
            "filename": "gspread_asyncio-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7b87c88ad21cef706be801aa8d6db560",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 23045,
            "upload_time": "2024-02-10T20:51:00",
            "upload_time_iso_8601": "2024-02-10T20:51:00.151462Z",
            "url": "https://files.pythonhosted.org/packages/a2/82/79c5d77c2f7175e14f9af971c692492c1eaf8a8bd4ccd5ec8d4c22e962a6/gspread_asyncio-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bf7e480054799ce34cec733d9d33951a801ffd2aea16dcdeea6801807aa44d83",
                "md5": "7b8a7d588e9949040d6af01cef29c2e4",
                "sha256": "693d81a80b17f65cdbb16a292b8cb8a17ffe886dd5aeadbc4a06188ebbc4b2b6"
            },
            "downloads": -1,
            "filename": "gspread_asyncio-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "7b8a7d588e9949040d6af01cef29c2e4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 25402,
            "upload_time": "2024-02-10T20:51:01",
            "upload_time_iso_8601": "2024-02-10T20:51:01.918958Z",
            "url": "https://files.pythonhosted.org/packages/bf/7e/480054799ce34cec733d9d33951a801ffd2aea16dcdeea6801807aa44d83/gspread_asyncio-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-10 20:51:01",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "dgilman",
    "github_project": "gspread_asyncio",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "cachetools",
            "specs": [
                [
                    "==",
                    "5.3.2"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2024.2.2"
                ]
            ]
        },
        {
            "name": "charset-normalizer",
            "specs": [
                [
                    "==",
                    "3.3.2"
                ]
            ]
        },
        {
            "name": "google-auth",
            "specs": [
                [
                    "==",
                    "2.27.0"
                ]
            ]
        },
        {
            "name": "google-auth-oauthlib",
            "specs": [
                [
                    "==",
                    "1.2.0"
                ]
            ]
        },
        {
            "name": "gspread",
            "specs": [
                [
                    "==",
                    "6.0.1"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "3.6"
                ]
            ]
        },
        {
            "name": "oauthlib",
            "specs": [
                [
                    "==",
                    "3.2.2"
                ]
            ]
        },
        {
            "name": "pyasn1",
            "specs": [
                [
                    "==",
                    "0.5.1"
                ]
            ]
        },
        {
            "name": "pyasn1-modules",
            "specs": [
                [
                    "==",
                    "0.3.0"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.31.0"
                ]
            ]
        },
        {
            "name": "requests-oauthlib",
            "specs": [
                [
                    "==",
                    "1.3.1"
                ]
            ]
        },
        {
            "name": "rsa",
            "specs": [
                [
                    "==",
                    "4.9"
                ]
            ]
        },
        {
            "name": "strenum",
            "specs": [
                [
                    "==",
                    "0.4.15"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "2.2.0"
                ]
            ]
        }
    ],
    "lcname": "gspread-asyncio"
}
        
Elapsed time: 2.38666s