From e6275de4ed1e81331c457ceff08f79461e9552bd Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Sat, 21 Feb 2026 12:40:11 +0200 Subject: [PATCH] fix: handle class overrides for retry polices correctly Previous implementation didn't work as intended because there was still override in init. Current implementation instead of playing with guessing separates default and instance setttings. Also update test cases to handle this scenario correctly --- src/ahriman/core/http/sync_http_client.py | 18 +++++++++++------- src/ahriman/core/repository/repository.py | 8 +++----- .../ahriman/core/http/test_sync_http_client.py | 16 ++++++++++------ .../ahriman/core/repository/test_repository.py | 5 +++-- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/ahriman/core/http/sync_http_client.py b/src/ahriman/core/http/sync_http_client.py index db987bc6..2bb30d92 100644 --- a/src/ahriman/core/http/sync_http_client.py +++ b/src/ahriman/core/http/sync_http_client.py @@ -22,7 +22,7 @@ import sys from functools import cached_property from requests.adapters import BaseAdapter, HTTPAdapter -from typing import Any, IO, Literal +from typing import Any, ClassVar, IO, Literal from urllib3.util.retry import Retry from ahriman import __version__ @@ -39,14 +39,18 @@ class SyncHttpClient(LazyLogging): wrapper around requests library to reduce boilerplate Attributes: + DEFAULT_MAX_RETRIES(int): (class attribute) default maximum amount of retries + DEFAULT_RETRY_BACKOFF(float): (class attribute) default retry exponential backoff + DEFAULT_TIMEOUT(int | None): (class attribute) default HTTP request timeout in seconds auth(tuple[str, str] | None): HTTP basic auth object if set - retry(Retry): retry policy of the HTTP client. Disabled by default + retry(Retry): retry policy of the HTTP client suppress_errors(bool): suppress logging of request errors timeout(int | None): HTTP request timeout in seconds """ - retry: Retry = Retry() - timeout: int | None = None + DEFAULT_MAX_RETRIES: ClassVar[int] = 0 + DEFAULT_RETRY_BACKOFF: ClassVar[float] = 0.0 + DEFAULT_TIMEOUT: ClassVar[int | None] = 30 def __init__(self, configuration: Configuration | None = None, section: str | None = None, *, suppress_errors: bool = False) -> None: @@ -65,10 +69,10 @@ class SyncHttpClient(LazyLogging): self.suppress_errors = suppress_errors - self.timeout = configuration.getint(section, "timeout", fallback=30) + self.timeout = configuration.getint(section, "timeout", fallback=self.DEFAULT_TIMEOUT) self.retry = SyncHttpClient.retry_policy( - max_retries=configuration.getint(section, "max_retries", fallback=0), - retry_backoff=configuration.getfloat(section, "retry_backoff", fallback=0.0), + max_retries=configuration.getint(section, "max_retries", fallback=self.DEFAULT_MAX_RETRIES), + retry_backoff=configuration.getfloat(section, "retry_backoff", fallback=self.DEFAULT_RETRY_BACKOFF), ) @cached_property diff --git a/src/ahriman/core/repository/repository.py b/src/ahriman/core/repository/repository.py index 19c736dc..7d223278 100644 --- a/src/ahriman/core/repository/repository.py +++ b/src/ahriman/core/repository/repository.py @@ -88,11 +88,9 @@ class Repository(Executor, UpdateHandler): Args: configuration(Configuration): configuration instance """ - AUR.timeout = configuration.getint("aur", "timeout", fallback=30) - AUR.retry = AUR.retry_policy( - max_retries=configuration.getint("aur", "max_retries", fallback=0), - retry_backoff=configuration.getfloat("aur", "retry_backoff", fallback=0.0), - ) + AUR.DEFAULT_MAX_RETRIES = configuration.getint("aur", "max_retries", fallback=0) + AUR.DEFAULT_RETRY_BACKOFF = configuration.getfloat("aur", "retry_backoff", fallback=0.0) + AUR.DEFAULT_TIMEOUT = configuration.getint("aur", "timeout", fallback=30) def _set_context(self) -> None: """ diff --git a/tests/ahriman/core/http/test_sync_http_client.py b/tests/ahriman/core/http/test_sync_http_client.py index 4324c1e8..7fac1e3d 100644 --- a/tests/ahriman/core/http/test_sync_http_client.py +++ b/tests/ahriman/core/http/test_sync_http_client.py @@ -49,14 +49,18 @@ def test_retry_policy() -> None: """ must set retry policy """ - SyncHttpClient.retry = SyncHttpClient.retry_policy(1, 2.0) - AUR.retry = AUR.retry_policy(3, 4.0) + SyncHttpClient.DEFAULT_MAX_RETRIES = 1 + SyncHttpClient.DEFAULT_RETRY_BACKOFF = 2.0 + AUR.DEFAULT_MAX_RETRIES = 3 + AUR.DEFAULT_RETRY_BACKOFF = 4.0 - assert SyncHttpClient.retry.connect == 1 - assert SyncHttpClient.retry.backoff_factor == 2.0 + client = SyncHttpClient() + assert client.retry.connect == 1 + assert client.retry.backoff_factor == 2.0 - assert AUR.retry.connect == 3 - assert AUR.retry.backoff_factor == 4.0 + aur = AUR() + assert aur.retry.connect == 3 + assert aur.retry.backoff_factor == 4.0 def test_exception_response_text() -> None: diff --git a/tests/ahriman/core/repository/test_repository.py b/tests/ahriman/core/repository/test_repository.py index cb4e885f..e2e39b38 100644 --- a/tests/ahriman/core/repository/test_repository.py +++ b/tests/ahriman/core/repository/test_repository.py @@ -31,8 +31,9 @@ def test_set_globals(configuration: Configuration) -> None: configuration.set_option("aur", "max_retries", "10") Repository._set_globals(configuration) - assert AUR.timeout == 42 - assert AUR.retry.connect == 10 + aur = AUR() + assert aur.timeout == 42 + assert aur.retry.connect == 10 def test_set_context(configuration: Configuration, database: SQLite, mocker: MockerFixture) -> None: