{ "info": { "author": "David Gilman", "author_email": "dgilman@gilslotd.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: AsyncIO", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only" ], "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.5 because of its use of async/await syntax.\n\n[![Documentation Status](https://readthedocs.org/projects/gspread-asyncio/badge/?version=latest)](https://gspread-asyncio.readthedocs.io/en/latest/?badge=latest) [![Build Status](https://travis-ci.org/dgilman/gspread_asyncio.svg?branch=master)](https://travis-ci.org/dgilman/gspread_asyncio)\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```\nimport asyncio\n\nimport gspread_asyncio\nfrom oauth2client.service_account import ServiceAccountCredentials\n\n\nasync def run(agcm):\n agc = await agcm.authorize()\n ss = await agc.create('Test Spreadsheet')\n print('Spreadsheet URL: https://docs.google.com/spreadsheets/d/{0}'.format(ss.id))\n await agc.insert_permission(ss.id, None, perm_type='anyone', role='writer')\n\n ws = await ss.add_worksheet('My Test Worksheet', 10, 5)\n zero_ws = await ss.get_worksheet(0)\n\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\n await asyncio.sleep(30)\n agcm.loop.stop()\n\ndef get_creds():\n return ServiceAccountCredentials.from_json_keyfile_name('serviceacct_spreadsheet.json',\n ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive',\n 'https://www.googleapis.com/auth/spreadsheets'])\n\nagcm = gspread_asyncio.AsyncioGspreadClientManager(get_creds)\nloop = asyncio.get_event_loop()\nloop.set_debug(True)\nloop.create_task(run(agcm))\nloop.run_forever()\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* There is a [bug in the underlying gspread library](https://github.com/burnash/gspread/issues/600) where the `Spreadsheet.title` property does I/O. I think this should be fixed at the gspread layer, but until then you may have issues from failed API calls when accessing the `.title` property.\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\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/dgilman/gspread_asyncio", "keywords": "spreadsheets,google-spreadsheets,asyncio", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "gspread-asyncio", "package_url": "https://pypi.org/project/gspread-asyncio/", "platform": "", "project_url": "https://pypi.org/project/gspread-asyncio/", "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" }, "release_url": "https://pypi.org/project/gspread-asyncio/1.0.0/", "requires_dist": [ "requests (==2.*)", "gspread (==3.*)" ], "requires_python": ">=3.5", "summary": "asyncio wrapper for burnash's Google Spreadsheet API library, gspread", "version": "1.0.0" }, "last_serial": 4603223, "releases": { "0.1.8": [ { "comment_text": "", "digests": { "md5": "148ba93116bd6068f89e8faef521b4a6", "sha256": "bb93e5dae1ac91998a5a13576625d4398dd37a0814825259f9bc7526a05d0047" }, "downloads": -1, "filename": "gspread_asyncio-0.1.8-py3-none-any.whl", "has_sig": false, "md5_digest": "148ba93116bd6068f89e8faef521b4a6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5", "size": 11964, "upload_time": "2018-10-16T01:41:14", "url": "https://files.pythonhosted.org/packages/5a/0f/af3c77964adc5f6505a1fe47d24f82580d211035bb60c15d9f11e2ac5634/gspread_asyncio-0.1.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "edbe131c74efc6a22e98575de3626302", "sha256": "1c7c434269abbc2c7496f4d481f5026a36f52f6b7937b9e508f7d46d09113b1f" }, "downloads": -1, "filename": "gspread_asyncio-0.1.8.tar.gz", "has_sig": false, "md5_digest": "edbe131c74efc6a22e98575de3626302", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 10860, "upload_time": "2018-10-16T01:41:16", "url": "https://files.pythonhosted.org/packages/fb/cd/0c26e39e760203ead182db068aeb3df6ea112256b7773a9bbe64b57e5486/gspread_asyncio-0.1.8.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "4fd06d2a5e0522ad5718eed59eda8cc0", "sha256": "d7d58bbab3163acff26c41e4359b67f70aeef748ab1b83d1a7f15713e9b8f46d" }, "downloads": -1, "filename": "gspread_asyncio-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4fd06d2a5e0522ad5718eed59eda8cc0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5", "size": 12010, "upload_time": "2018-12-15T18:04:28", "url": "https://files.pythonhosted.org/packages/b6/e8/cea0203eaeeed6b7557b63d1ef10f4d2c346cc0b4bc70343f0aff1781a08/gspread_asyncio-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8512abf6b5dfb40d5dbdda9ee5414fb7", "sha256": "f927bcf808128439e70f06d6b422f861516125fa57c25c7181c725ff5fbf74aa" }, "downloads": -1, "filename": "gspread_asyncio-1.0.0.tar.gz", "has_sig": false, "md5_digest": "8512abf6b5dfb40d5dbdda9ee5414fb7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 13059, "upload_time": "2018-12-15T18:04:30", "url": "https://files.pythonhosted.org/packages/48/d3/72758293c45efdc0d96d363d4b3b3fce4466f8fd1fe8cd867e7fa29161b7/gspread_asyncio-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4fd06d2a5e0522ad5718eed59eda8cc0", "sha256": "d7d58bbab3163acff26c41e4359b67f70aeef748ab1b83d1a7f15713e9b8f46d" }, "downloads": -1, "filename": "gspread_asyncio-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4fd06d2a5e0522ad5718eed59eda8cc0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5", "size": 12010, "upload_time": "2018-12-15T18:04:28", "url": "https://files.pythonhosted.org/packages/b6/e8/cea0203eaeeed6b7557b63d1ef10f4d2c346cc0b4bc70343f0aff1781a08/gspread_asyncio-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8512abf6b5dfb40d5dbdda9ee5414fb7", "sha256": "f927bcf808128439e70f06d6b422f861516125fa57c25c7181c725ff5fbf74aa" }, "downloads": -1, "filename": "gspread_asyncio-1.0.0.tar.gz", "has_sig": false, "md5_digest": "8512abf6b5dfb40d5dbdda9ee5414fb7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5", "size": 13059, "upload_time": "2018-12-15T18:04:30", "url": "https://files.pythonhosted.org/packages/48/d3/72758293c45efdc0d96d363d4b3b3fce4466f8fd1fe8cd867e7fa29161b7/gspread_asyncio-1.0.0.tar.gz" } ] }