From 8866482af8e69481855c27800d0716889762ee66 Mon Sep 17 00:00:00 2001 From: Deadpool2000 Date: Sun, 5 Apr 2026 15:16:59 +0530 Subject: [PATCH 1/2] feat: allow injecting custom HTTP clients for advanced transport and retry configurations --- openapi_python_sdk/async_client.py | 4 ++-- openapi_python_sdk/async_oauth_client.py | 4 ++-- openapi_python_sdk/client.py | 4 ++-- openapi_python_sdk/oauth_client.py | 4 ++-- tests/test_async_client.py | 10 ++++++++++ tests/test_client.py | 10 ++++++++++ 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/openapi_python_sdk/async_client.py b/openapi_python_sdk/async_client.py index 7ff6e6a..608cbbc 100644 --- a/openapi_python_sdk/async_client.py +++ b/openapi_python_sdk/async_client.py @@ -10,8 +10,8 @@ class AsyncClient: Suitable for use with FastAPI, aiohttp, etc. """ - def __init__(self, token: str): - self.client = httpx.AsyncClient() + def __init__(self, token: str, client: Any = None): + self.client = client if client is not None else httpx.AsyncClient() self.auth_header: str = f"Bearer {token}" self.headers: Dict[str, str] = { "Authorization": self.auth_header, diff --git a/openapi_python_sdk/async_oauth_client.py b/openapi_python_sdk/async_oauth_client.py index 2633c93..c3234cf 100644 --- a/openapi_python_sdk/async_oauth_client.py +++ b/openapi_python_sdk/async_oauth_client.py @@ -12,8 +12,8 @@ class AsyncOauthClient: Suitable for use with FastAPI, aiohttp, etc. """ - def __init__(self, username: str, apikey: str, test: bool = False): - self.client = httpx.AsyncClient() + def __init__(self, username: str, apikey: str, test: bool = False, client: Any = None): + self.client = client if client is not None else httpx.AsyncClient() self.url: str = TEST_OAUTH_BASE_URL if test else OAUTH_BASE_URL self.auth_header: str = ( "Basic " + base64.b64encode(f"{username}:{apikey}".encode("utf-8")).decode() diff --git a/openapi_python_sdk/client.py b/openapi_python_sdk/client.py index 16956cf..aa58ee1 100644 --- a/openapi_python_sdk/client.py +++ b/openapi_python_sdk/client.py @@ -14,8 +14,8 @@ class Client: Synchronous client for making authenticated requests to Openapi endpoints. """ - def __init__(self, token: str): - self.client = httpx.Client() + def __init__(self, token: str, client: Any = None): + self.client = client if client is not None else httpx.Client() self.auth_header: str = f"Bearer {token}" self.headers: Dict[str, str] = { "Authorization": self.auth_header, diff --git a/openapi_python_sdk/oauth_client.py b/openapi_python_sdk/oauth_client.py index 8c8c446..61b583b 100644 --- a/openapi_python_sdk/oauth_client.py +++ b/openapi_python_sdk/oauth_client.py @@ -12,8 +12,8 @@ class OauthClient: Synchronous client for handling Openapi authentication and token management. """ - def __init__(self, username: str, apikey: str, test: bool = False): - self.client = httpx.Client() + def __init__(self, username: str, apikey: str, test: bool = False, client: Any = None): + self.client = client if client is not None else httpx.Client() self.url: str = TEST_OAUTH_BASE_URL if test else OAUTH_BASE_URL self.auth_header: str = ( "Basic " + base64.b64encode(f"{username}:{apikey}".encode("utf-8")).decode() diff --git a/tests/test_async_client.py b/tests/test_async_client.py index d25454b..461305b 100644 --- a/tests/test_async_client.py +++ b/tests/test_async_client.py @@ -42,6 +42,11 @@ async def test_get_scopes(self, mock_httpx): await oauth.aclose() mock_httpx.return_value.aclose.assert_called_once() + def test_custom_client_transport(self): + custom_client = MagicMock() + oauth = AsyncOauthClient(username="user", apikey="key", client=custom_client) + self.assertEqual(oauth.client, custom_client) + class TestAsyncClient(unittest.IsolatedAsyncioTestCase): """ @@ -85,6 +90,11 @@ async def test_request_post(self, mock_httpx): await client.aclose() mock_httpx.return_value.aclose.assert_called_once() + def test_custom_client_transport(self): + custom_client = MagicMock() + client = AsyncClient(token="abc123", client=custom_client) + self.assertEqual(client.client, custom_client) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_client.py b/tests/test_client.py index 75fe1e4..3b8f874 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -56,6 +56,11 @@ def test_auth_header_is_basic(self, mock_httpx): oauth = OauthClient(username="user", apikey="key") self.assertTrue(oauth.auth_header.startswith("Basic ")) + def test_custom_client_transport(self): + custom_client = MagicMock() + oauth = OauthClient(username="user", apikey="key", client=custom_client) + self.assertEqual(oauth.client, custom_client) + class TestClient(unittest.TestCase): @@ -109,6 +114,11 @@ def test_defaults_on_empty_request(self, mock_httpx): method="GET", url="", headers=client.headers, json={}, params={} ) + def test_custom_client_transport(self): + custom_client = MagicMock() + client = Client(token="tok", client=custom_client) + self.assertEqual(client.client, custom_client) + if __name__ == "__main__": unittest.main() From 7499139a216555c0c7ffa8a77c83d851295b2b08 Mon Sep 17 00:00:00 2001 From: Deadpool2000 Date: Sun, 5 Apr 2026 15:17:56 +0530 Subject: [PATCH 2/2] docs: add instructions for customizing transport layer and retry logic --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 39db3d5..b48d866 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,26 @@ resp = client.request( ) ``` +### Customizing the Transport Layer + +If you need to configure custom retry logic, proxies, or use a different HTTP client (such as passing a `requests.Session` with a custom urllib3 `Retry`), you can inject it directly using the `client` parameter on any SDK class: + +```python +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry +from openapi_python_sdk import Client +import requests + +retry = Retry(total=3) +adapter = HTTPAdapter(max_retries=retry) + +session = requests.Session() +session.mount("https://", adapter) + +# Pass the custom session to the Client explicitly +client = Client("token", client=session) +``` + ## Async Usage The SDK provides `AsyncClient` and `AsyncOauthClient` for use with asynchronous frameworks like FastAPI or `aiohttp`.