Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/rework test cassettes recording #1004

Merged
merged 4 commits into from Mar 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/api.rst
Expand Up @@ -16,6 +16,9 @@ Client
.. autoclass:: gspread.Client
:members:

.. autoclass:: gspread.client.BackoffClient
:members:

Models
------

Expand Down
65 changes: 65 additions & 0 deletions gspread/client.py
Expand Up @@ -7,6 +7,8 @@

"""

from http import HTTPStatus

from google.auth.transport.requests import AuthorizedSession

from .exceptions import APIError, SpreadsheetNotFound
Expand Down Expand Up @@ -442,3 +444,66 @@ def remove_permission(self, file_id, permission_id):

params = {"supportsAllDrives": True}
self.request("delete", url, params=params)


class BackoffClient(Client):
"""BackoffClient is a gspread client with exponential
backoff retries.

In case a request fails due to some API rate limits,
it will wait for some time, then retry the request.

This can help by trying the request after some time and
prevent the application from failing (by raising an APIError exception).

.. Warning::
This Client is not production ready yet.
Use it at your own risk !

.. note::
Currently known issues are:

* will retry exponentially even when the error should
raise instantly. Due to the Drive API that raises
403 (Forbidden) errors for forbidden access and
for api rate limit exceeded."""

_HTTP_ERROR_CODES = [
HTTPStatus.FORBIDDEN, # Drive API return a 403 Forbidden on usage rate limit exceeded
HTTPStatus.REQUEST_TIMEOUT, # in case of a timeout
HTTPStatus.TOO_MANY_REQUESTS, # sheet API usage rate limit exceeded
]
_NR_BACKOFF = 0
_MAX_BACKOFF = 128 # arbitrary maximum backoff
_MAX_BACKOFF_REACHED = False # Stop after reaching _MAX_BACKOFF

def request(self, *args, **kwargs):
try:
return super().request(*args, **kwargs)
except APIError as err:
data = err.response.json()
code = data["error"]["code"]

# check if error should retyr
if code in self._HTTP_ERROR_CODES and self._MAX_BACKOFF_REACHED is False:
self._NR_BACKOFF += 1
wait = min(2 ** self._NR_BACKOFF, self._MAX_BACKOFF)

if wait >= self._MAX_BACKOFF:
self._MAX_BACKOFF_REACHED = True

import time

time.sleep(wait)

# make the request again
response = self.request(*args, **kwargs)

# reset counters for next time
self._NR_BACKOFF = 0
self._MAX_BACKOFF_REACHED = False

return response

# failed too many times, raise APIEerror
raise err
289 changes: 0 additions & 289 deletions tests/cassettes/CellTest.json

This file was deleted.

360 changes: 322 additions & 38 deletions tests/cassettes/CellTest.test_a1_value.json

Large diffs are not rendered by default.

362 changes: 323 additions & 39 deletions tests/cassettes/CellTest.test_define_named_range.json

Large diffs are not rendered by default.

360 changes: 322 additions & 38 deletions tests/cassettes/CellTest.test_delete_named_range.json

Large diffs are not rendered by default.

434 changes: 359 additions & 75 deletions tests/cassettes/CellTest.test_merge_cells.json

Large diffs are not rendered by default.

452 changes: 368 additions & 84 deletions tests/cassettes/CellTest.test_numeric_value.json

Large diffs are not rendered by default.

328 changes: 306 additions & 22 deletions tests/cassettes/CellTest.test_properties.json

Large diffs are not rendered by default.

Expand Up @@ -30,11 +30,17 @@
"message": "Not Found"
},
"headers": {
"Server": [
"ESF"
"X-Frame-Options": [
"SAMEORIGIN"
],
"Content-Type": [
"application/json; charset=UTF-8"
"Date": [
"Sun, 27 Feb 2022 16:50:08 GMT"
],
"Cache-Control": [
"private"
],
"X-Content-Type-Options": [
"nosniff"
],
"Transfer-Encoding": [
"chunked"
Expand All @@ -44,20 +50,14 @@
"X-Origin",
"Referer"
],
"X-Content-Type-Options": [
"nosniff"
],
"X-Frame-Options": [
"SAMEORIGIN"
],
"Cache-Control": [
"private"
"Content-Type": [
"application/json; charset=UTF-8"
],
"Alt-Svc": [
"h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""
],
"Date": [
"Sat, 15 Jan 2022 17:12:18 GMT"
"Server": [
"ESF"
],
"X-XSS-Protection": [
"0"
Expand Down
266 changes: 131 additions & 135 deletions tests/cassettes/ClientTest.test_copy.json

Large diffs are not rendered by default.

74 changes: 37 additions & 37 deletions tests/cassettes/ClientTest.test_create.json
Expand Up @@ -36,59 +36,59 @@
"message": "OK"
},
"headers": {
"Server": [
"GSE"
"X-Frame-Options": [
"SAMEORIGIN"
],
"Expires": [
"Mon, 01 Jan 1990 00:00:00 GMT"
"Date": [
"Sun, 27 Feb 2022 16:50:15 GMT"
],
"Content-Type": [
"application/json; charset=UTF-8"
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
],
"X-Content-Type-Options": [
"nosniff"
],
"Transfer-Encoding": [
"chunked"
],
"Expires": [
"Mon, 01 Jan 1990 00:00:00 GMT"
],
"Vary": [
"Origin",
"X-Origin"
],
"X-Content-Type-Options": [
"nosniff"
],
"X-Frame-Options": [
"SAMEORIGIN"
],
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
"Content-Type": [
"application/json; charset=UTF-8"
],
"Alt-Svc": [
"h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""
],
"Date": [
"Sat, 15 Jan 2022 17:12:25 GMT"
],
"Pragma": [
"no-cache"
],
"Content-Security-Policy": [
"frame-ancestors 'self'"
],
"X-XSS-Protection": [
"1; mode=block"
],
"Pragma": [
"no-cache"
],
"Server": [
"GSE"
],
"content-length": [
"166"
]
},
"body": {
"string": "{\n \"kind\": \"drive#file\",\n \"id\": \"1U1V2YYNL6AnEHJEM4c6h_ApS74D0PjOJIxAWBsoZnXM\",\n \"name\": \"Test Spreadsheet\",\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\"\n}\n"
"string": "{\n \"kind\": \"drive#file\",\n \"id\": \"1j0S2IlBAqXskWC10Gcoaar810NVMB3iQRZuZYsp8ze4\",\n \"name\": \"Test Spreadsheet\",\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\"\n}\n"
}
}
},
{
"request": {
"method": "GET",
"uri": "https://sheets.googleapis.com/v4/spreadsheets/1U1V2YYNL6AnEHJEM4c6h_ApS74D0PjOJIxAWBsoZnXM?includeGridData=false",
"uri": "https://sheets.googleapis.com/v4/spreadsheets/1j0S2IlBAqXskWC10Gcoaar810NVMB3iQRZuZYsp8ze4?includeGridData=false",
"body": null,
"headers": {
"User-Agent": [
Expand All @@ -114,11 +114,17 @@
"message": "OK"
},
"headers": {
"Server": [
"ESF"
"X-Frame-Options": [
"SAMEORIGIN"
],
"Content-Type": [
"application/json; charset=UTF-8"
"Date": [
"Sun, 27 Feb 2022 16:50:16 GMT"
],
"Cache-Control": [
"private"
],
"X-Content-Type-Options": [
"nosniff"
],
"Transfer-Encoding": [
"chunked"
Expand All @@ -128,20 +134,14 @@
"X-Origin",
"Referer"
],
"X-Content-Type-Options": [
"nosniff"
],
"X-Frame-Options": [
"SAMEORIGIN"
],
"Cache-Control": [
"private"
"Content-Type": [
"application/json; charset=UTF-8"
],
"Alt-Svc": [
"h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""
],
"Date": [
"Sat, 15 Jan 2022 17:12:25 GMT"
"Server": [
"ESF"
],
"X-XSS-Protection": [
"0"
Expand All @@ -151,7 +151,7 @@
]
},
"body": {
"string": "{\n \"spreadsheetId\": \"1U1V2YYNL6AnEHJEM4c6h_ApS74D0PjOJIxAWBsoZnXM\",\n \"properties\": {\n \"title\": \"Test Spreadsheet\",\n \"locale\": \"en_US\",\n \"autoRecalc\": \"ON_CHANGE\",\n \"timeZone\": \"Etc/GMT\",\n \"defaultFormat\": {\n \"backgroundColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n },\n \"padding\": {\n \"top\": 2,\n \"right\": 3,\n \"bottom\": 2,\n \"left\": 3\n },\n \"verticalAlignment\": \"BOTTOM\",\n \"wrapStrategy\": \"OVERFLOW_CELL\",\n \"textFormat\": {\n \"foregroundColor\": {},\n \"fontFamily\": \"arial,sans,sans-serif\",\n \"fontSize\": 10,\n \"bold\": false,\n \"italic\": false,\n \"strikethrough\": false,\n \"underline\": false,\n \"foregroundColorStyle\": {\n \"rgbColor\": {}\n }\n },\n \"backgroundColorStyle\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n \"spreadsheetTheme\": {\n \"primaryFontFamily\": \"Arial\",\n \"themeColors\": [\n {\n \"colorType\": \"TEXT\",\n \"color\": {\n \"rgbColor\": {}\n }\n },\n {\n \"colorType\": \"BACKGROUND\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n {\n \"colorType\": \"ACCENT1\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.25882354,\n \"green\": 0.52156866,\n \"blue\": 0.95686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT2\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.91764706,\n \"green\": 0.2627451,\n \"blue\": 0.20784314\n }\n }\n },\n {\n \"colorType\": \"ACCENT3\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.9843137,\n \"green\": 0.7372549,\n \"blue\": 0.015686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT4\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.20392157,\n \"green\": 0.65882355,\n \"blue\": 0.3254902\n }\n }\n },\n {\n \"colorType\": \"ACCENT5\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 0.42745098,\n \"blue\": 0.003921569\n }\n }\n },\n {\n \"colorType\": \"ACCENT6\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.27450982,\n \"green\": 0.7411765,\n \"blue\": 0.7764706\n }\n }\n },\n {\n \"colorType\": \"LINK\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.06666667,\n \"green\": 0.33333334,\n \"blue\": 0.8\n }\n }\n }\n ]\n }\n },\n \"sheets\": [\n {\n \"properties\": {\n \"sheetId\": 0,\n \"title\": \"Sheet1\",\n \"index\": 0,\n \"sheetType\": \"GRID\",\n \"gridProperties\": {\n \"rowCount\": 1000,\n \"columnCount\": 26\n }\n }\n }\n ],\n \"spreadsheetUrl\": \"https://docs.google.com/spreadsheets/d/1U1V2YYNL6AnEHJEM4c6h_ApS74D0PjOJIxAWBsoZnXM/edit\"\n}\n"
"string": "{\n \"spreadsheetId\": \"1j0S2IlBAqXskWC10Gcoaar810NVMB3iQRZuZYsp8ze4\",\n \"properties\": {\n \"title\": \"Test Spreadsheet\",\n \"locale\": \"en_US\",\n \"autoRecalc\": \"ON_CHANGE\",\n \"timeZone\": \"Etc/GMT\",\n \"defaultFormat\": {\n \"backgroundColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n },\n \"padding\": {\n \"top\": 2,\n \"right\": 3,\n \"bottom\": 2,\n \"left\": 3\n },\n \"verticalAlignment\": \"BOTTOM\",\n \"wrapStrategy\": \"OVERFLOW_CELL\",\n \"textFormat\": {\n \"foregroundColor\": {},\n \"fontFamily\": \"arial,sans,sans-serif\",\n \"fontSize\": 10,\n \"bold\": false,\n \"italic\": false,\n \"strikethrough\": false,\n \"underline\": false,\n \"foregroundColorStyle\": {\n \"rgbColor\": {}\n }\n },\n \"backgroundColorStyle\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n \"spreadsheetTheme\": {\n \"primaryFontFamily\": \"Arial\",\n \"themeColors\": [\n {\n \"colorType\": \"TEXT\",\n \"color\": {\n \"rgbColor\": {}\n }\n },\n {\n \"colorType\": \"BACKGROUND\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n {\n \"colorType\": \"ACCENT1\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.25882354,\n \"green\": 0.52156866,\n \"blue\": 0.95686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT2\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.91764706,\n \"green\": 0.2627451,\n \"blue\": 0.20784314\n }\n }\n },\n {\n \"colorType\": \"ACCENT3\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.9843137,\n \"green\": 0.7372549,\n \"blue\": 0.015686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT4\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.20392157,\n \"green\": 0.65882355,\n \"blue\": 0.3254902\n }\n }\n },\n {\n \"colorType\": \"ACCENT5\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 0.42745098,\n \"blue\": 0.003921569\n }\n }\n },\n {\n \"colorType\": \"ACCENT6\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.27450982,\n \"green\": 0.7411765,\n \"blue\": 0.7764706\n }\n }\n },\n {\n \"colorType\": \"LINK\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.06666667,\n \"green\": 0.33333334,\n \"blue\": 0.8\n }\n }\n }\n ]\n }\n },\n \"sheets\": [\n {\n \"properties\": {\n \"sheetId\": 0,\n \"title\": \"Sheet1\",\n \"index\": 0,\n \"sheetType\": \"GRID\",\n \"gridProperties\": {\n \"rowCount\": 1000,\n \"columnCount\": 26\n }\n }\n }\n ],\n \"spreadsheetUrl\": \"https://docs.google.com/spreadsheets/d/1j0S2IlBAqXskWC10Gcoaar810NVMB3iQRZuZYsp8ze4/edit\"\n}\n"
}
}
}
Expand Down