From c4aea1eff5b074d11b44cb2c3cda2b0475bfac24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 31 Mar 2025 18:23:16 +0100 Subject: [PATCH] Configure baseline timeouts for requests These represent a good baseline for 99.99% of cases. The remainder can customize the `Session` argument. --- CHANGELOG.md | 1 + todoist_api_python/http_requests.py | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7f185a..191deb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixes - Missing optional `next_cursor` attribute in `CompletedItems` object +- API requests configure appropriate timeouts to avoid connections hanging ## [2.1.7] - 2024-08-13 diff --git a/todoist_api_python/http_requests.py b/todoist_api_python/http_requests.py index a1b0673..94ee3ca 100644 --- a/todoist_api_python/http_requests.py +++ b/todoist_api_python/http_requests.py @@ -12,6 +12,15 @@ Json = dict[str, "Json"] | list["Json"] | str | int | float | bool | None +# Timeouts for requests. +# +# 10 seconds for connecting is a recurring default and adheres to python-requests's +# recommendation of picking a value slightly larger than a multiple of 3. +# +# 60 seconds for reading aligns with Todoist's own internal timeout. All requests are +# forcefully terminated after this time, so there is no point waiting any longer. +TIMEOUT = (10, 60) + def get( session: Session, @@ -19,7 +28,9 @@ def get( token: str | None = None, params: dict[str, Any] | None = None, ) -> Json | bool: - response = session.get(url, params=params, headers=create_headers(token=token)) + response = session.get( + url, params=params, headers=create_headers(token=token), timeout=TIMEOUT + ) if response.status_code == codes.OK: return response.json() @@ -41,9 +52,7 @@ def post( ) response = session.post( - url, - headers=headers, - data=json.dumps(data) if data else None, + url, headers=headers, data=json.dumps(data) if data else None, timeout=TIMEOUT ) if response.status_code == codes.OK: @@ -63,10 +72,7 @@ def delete( headers = create_headers(token=token, request_id=request_id) - response = session.delete( - url, - headers=headers, - ) + response = session.delete(url, headers=headers, timeout=TIMEOUT) response.raise_for_status() return response.ok