From 04e48d72ea5514ba642a1bedafc472473c511461 Mon Sep 17 00:00:00 2001 From: Sachin Shaji Date: Tue, 2 Apr 2024 14:50:44 +0530 Subject: [PATCH] feat: introduce retry mechanism for session --- sw360/sw360_api.py | 15 ++++++++++++++- tests/test_sw360_base.py | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/sw360/sw360_api.py b/sw360/sw360_api.py index 38489e8..a5aeab5 100644 --- a/sw360/sw360_api.py +++ b/sw360/sw360_api.py @@ -12,6 +12,8 @@ from typing import Any, Dict, Optional import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry from .attachments import AttachmentsMixin from .clearing import ClearingMixin @@ -23,6 +25,17 @@ from .vendor import VendorMixin from .vulnerabilities import VulnerabilitiesMixin +# Retry mechanism for rate limiting +adapter = HTTPAdapter(max_retries=Retry( + total=5, + status_forcelist=[429, 500, 502, 503, 504], + respect_retry_after_header=True, + backoff_factor=30, + allowed_methods=["HEAD", "GET", "OPTIONS", "POST", "PUT", "PATCH"] +)) +session = requests.Session() +session.mount("http://", adapter) +session.mount("https://", adapter) class SW360( AttachmentsMixin, @@ -75,7 +88,7 @@ def login_api(self, token: str = "") -> bool: :raises SW360Error: if the login fails """ if not self.force_no_session: - self.session = requests.Session() + self.session = session self.session.headers = self.api_headers.copy() # type: ignore url = self.url + "resource/api/" diff --git a/tests/test_sw360_base.py b/tests/test_sw360_base.py index 7514b4e..4b00790 100644 --- a/tests/test_sw360_base.py +++ b/tests/test_sw360_base.py @@ -298,7 +298,24 @@ def test_api_get_raw_error_string(self) -> None: else: self.assertEqual(404, context.exception.response.status_code) self.assertEqual("Error-String", context.exception.response.text) + + @responses.activate + def test_login_server_not_responding(self) -> None: + lib = SW360(self.MYURL, self.MYTOKEN, False) + responses.add( + responses.GET, + url=self.MYURL + "resource/api/", + body = '{"error": "Internal Server Error", "message": "An unexpected error occurred on the server."}', + status=500, + content_type="application/json", + adding_headers={"Authorization": "Token " + self.MYTOKEN}, + ) + + with self.assertRaises(SW360Error) as context: + lib.login_api() + + self.assertEqual(self.ERROR_MSG_NO_LOGIN, context.exception.message) if __name__ == "__main__": unittest.main()