From 593ffa48e863b7e521d30d3cdb79ae3a797b5076 Mon Sep 17 00:00:00 2001 From: Daniel Perrefort Date: Wed, 17 Dec 2025 16:06:51 -0500 Subject: [PATCH 1/5] Disable redirect by default --- keystone_client/http.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/keystone_client/http.py b/keystone_client/http.py index eebc1ff..f3e07d2 100644 --- a/keystone_client/http.py +++ b/keystone_client/http.py @@ -19,10 +19,11 @@ from .log import DefaultContextAdapter +# Default client settings DEFAULT_TIMEOUT = 15 DEFAULT_REDIRECTS = 10 DEFAULT_VERIFY = True -DEFAULT_FOLLOW = True +DEFAULT_FOLLOW = False DEFAULT_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) HttpMethod = Literal["get", "post", "put", "patch", "delete"] From 2b3d44fb7bdc12ef9af0c6994e3d7e6a0782d7e2 Mon Sep 17 00:00:00 2001 From: Daniel Perrefort Date: Wed, 17 Dec 2025 16:10:25 -0500 Subject: [PATCH 2/5] Drops use of globals for defaults --- keystone_client/client.py | 18 +++++++++--------- keystone_client/http.py | 17 +++++------------ keystone_client/log.py | 3 ++- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/keystone_client/client.py b/keystone_client/client.py index 6c66bac..d06c36b 100644 --- a/keystone_client/client.py +++ b/keystone_client/client.py @@ -6,7 +6,7 @@ """ import abc -from typing import Any, Dict, Optional, Union +from typing import Any, Callable, Dict, Optional, Union import httpx from httpx import HTTPStatusError @@ -215,7 +215,7 @@ def is_authenticated(self, timeout: int = httpx.USE_CLIENT_DEFAULT) -> dict: response = self.http_get(self.IDENTITY_ENDPOINT, timeout=timeout) return self._handle_identity_response(response) - def _create_factory(self, endpoint: Endpoint) -> callable: + def _create_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data creation methods.""" def create_record(data: Optional[RequestData] = None, files: Optional[RequestFiles] = None) -> dict: @@ -235,7 +235,7 @@ def create_record(data: Optional[RequestData] = None, files: Optional[RequestFil return create_record - def _retrieve_factory(self, endpoint: Endpoint) -> callable: + def _retrieve_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data retrieval methods.""" def retrieve_record( @@ -269,7 +269,7 @@ def retrieve_record( return retrieve_record - def _update_factory(self, endpoint: Endpoint) -> callable: + def _update_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data update methods.""" def update_record( @@ -294,7 +294,7 @@ def update_record( return update_record - def _delete_factory(self, endpoint: Endpoint) -> callable: + def _delete_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data deletion methods.""" def delete_record(pk: int, raise_not_exists: bool = False) -> None: @@ -366,7 +366,7 @@ async def is_authenticated(self, timeout: int = httpx.USE_CLIENT_DEFAULT) -> dic response = await self.http_get(self.IDENTITY_ENDPOINT, timeout=timeout) return self._handle_identity_response(response) - def _create_factory(self, endpoint: Endpoint) -> callable: + def _create_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data creation methods.""" async def create_record(data: Optional[RequestData] = None, files: Optional[RequestFiles] = None) -> dict: @@ -386,7 +386,7 @@ async def create_record(data: Optional[RequestData] = None, files: Optional[Requ return create_record - def _retrieve_factory(self, endpoint: Endpoint) -> callable: + def _retrieve_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data retrieval methods.""" async def retrieve_record( @@ -420,7 +420,7 @@ async def retrieve_record( return retrieve_record - def _update_factory(self, endpoint: Endpoint) -> callable: + def _update_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data update methods.""" async def update_record( @@ -445,7 +445,7 @@ async def update_record( return update_record - def _delete_factory(self, endpoint: Endpoint) -> callable: + def _delete_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data deletion methods.""" async def delete_record(pk: int, raise_not_exists: bool = False) -> None: diff --git a/keystone_client/http.py b/keystone_client/http.py index f3e07d2..e02e6ec 100644 --- a/keystone_client/http.py +++ b/keystone_client/http.py @@ -19,13 +19,6 @@ from .log import DefaultContextAdapter -# Default client settings -DEFAULT_TIMEOUT = 15 -DEFAULT_REDIRECTS = 10 -DEFAULT_VERIFY = True -DEFAULT_FOLLOW = False -DEFAULT_LIMITS = httpx.Limits(max_connections=100, max_keepalive_connections=20) - HttpMethod = Literal["get", "post", "put", "patch", "delete"] logger = logging.getLogger('kclient') @@ -42,11 +35,11 @@ def __init__( self, base_url: str, *, - verify_ssl: bool = DEFAULT_VERIFY, - follow_redirects: bool = DEFAULT_FOLLOW, - max_redirects: int = DEFAULT_REDIRECTS, - timeout: Optional[int] = DEFAULT_TIMEOUT, - limits: httpx.Limits = DEFAULT_LIMITS, + verify_ssl: bool = 15, + follow_redirects: bool = True, + max_redirects: int = 10, + timeout: Optional[int] = False, + limits: httpx.Limits = httpx.Limits(max_connections=100, max_keepalive_connections=20), transport: Optional[httpx.BaseTransport] = None, ) -> None: """Initialize a new HTTP session. diff --git a/keystone_client/log.py b/keystone_client/log.py index 5a91486..5a6938d 100644 --- a/keystone_client/log.py +++ b/keystone_client/log.py @@ -7,6 +7,7 @@ """ import logging +from typing import Literal class DefaultContextAdapter(logging.LoggerAdapter): @@ -32,7 +33,7 @@ class ContextFilter(logging.Filter): required_attr = ("cid", "baseurl", "method", "endpoint", "url") - def filter(self, record: logging.LogRecord) -> True: + def filter(self, record: logging.LogRecord) -> Literal[True]: """Ensure a log record has all required contextual attributes. Any missing contextual attributes are set to an empty string. From 6d098c1716a6577a60cd37164ff57ba55b69b5f4 Mon Sep 17 00:00:00 2001 From: Daniel Perrefort Date: Wed, 17 Dec 2025 16:11:54 -0500 Subject: [PATCH 3/5] Minor typing fixes --- keystone_client/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/keystone_client/client.py b/keystone_client/client.py index d06c36b..115d73a 100644 --- a/keystone_client/client.py +++ b/keystone_client/client.py @@ -57,19 +57,19 @@ def is_authenticated(self) -> dict: """Return metadata for the currently authenticated user.""" @abc.abstractmethod - def _create_factory(self, endpoint: Endpoint) -> callable: + def _create_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data creation methods.""" @abc.abstractmethod - def _retrieve_factory(self, endpoint: Endpoint) -> callable: + def _retrieve_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data retrieval methods.""" @abc.abstractmethod - def _update_factory(self, endpoint: Endpoint) -> callable: + def _update_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data update methods.""" @abc.abstractmethod - def _delete_factory(self, endpoint: Endpoint) -> callable: + def _delete_factory(self, endpoint: Endpoint) -> Callable: """Factory function for data deletion methods.""" @staticmethod From 09f33c72b266a6ef043615aee12571cbce529f37 Mon Sep 17 00:00:00 2001 From: Daniel Perrefort Date: Wed, 17 Dec 2025 16:49:31 -0500 Subject: [PATCH 4/5] follow_redirects = False --- keystone_client/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keystone_client/http.py b/keystone_client/http.py index e02e6ec..8845903 100644 --- a/keystone_client/http.py +++ b/keystone_client/http.py @@ -36,7 +36,7 @@ def __init__( base_url: str, *, verify_ssl: bool = 15, - follow_redirects: bool = True, + follow_redirects: bool = False, max_redirects: int = 10, timeout: Optional[int] = False, limits: httpx.Limits = httpx.Limits(max_connections=100, max_keepalive_connections=20), From 628f80bdd24e115fd00ca63007d9e4c9a6fd4d27 Mon Sep 17 00:00:00 2001 From: Daniel Perrefort Date: Wed, 17 Dec 2025 16:53:46 -0500 Subject: [PATCH 5/5] Fixes argument mixup --- keystone_client/http.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keystone_client/http.py b/keystone_client/http.py index 8845903..d1c9deb 100644 --- a/keystone_client/http.py +++ b/keystone_client/http.py @@ -35,10 +35,10 @@ def __init__( self, base_url: str, *, - verify_ssl: bool = 15, + verify_ssl: bool = True, follow_redirects: bool = False, max_redirects: int = 10, - timeout: Optional[int] = False, + timeout: Optional[int] = 15, limits: httpx.Limits = httpx.Limits(max_connections=100, max_keepalive_connections=20), transport: Optional[httpx.BaseTransport] = None, ) -> None: