From 7c3582fd3c35e270a98e4193462b0f3c22684229 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Sun, 26 Jan 2025 14:32:25 +0100 Subject: [PATCH 1/4] Fix base_url usage in HttpxRequestAdapter Fixes #374 Modify `HttpxRequestAdapter` to use `http_client.base_url` if `base_url` is not explicitly set. * Update the constructor in `packages/http/httpx/kiota_http/httpx_request_adapter.py` to check and use `http_client.base_url` if `base_url` is not provided. * Update the `base_url` property to return `http_client.base_url` if `_base_url` is not set. * Add a test in `packages/http/httpx/tests/test_httpx_request_adapter.py` to verify that `HttpxRequestAdapter` uses `http_client.base_url` if `base_url` is not explicitly set. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/microsoft/kiota-python/issues/374?shareId=XXXX-XXXX-XXXX-XXXX). --- packages/http/httpx/kiota_http/httpx_request_adapter.py | 4 ++-- packages/http/httpx/tests/test_httpx_request_adapter.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/http/httpx/kiota_http/httpx_request_adapter.py b/packages/http/httpx/kiota_http/httpx_request_adapter.py index 11276110..9140000e 100644 --- a/packages/http/httpx/kiota_http/httpx_request_adapter.py +++ b/packages/http/httpx/kiota_http/httpx_request_adapter.py @@ -88,7 +88,7 @@ def __init__( http_client = KiotaClientFactory.create_with_default_middleware() self._http_client = http_client if not base_url: - base_url = "" + base_url = str(http_client.base_url) self._base_url: str = base_url if not observability_options: observability_options = ObservabilityOptions() @@ -101,7 +101,7 @@ def base_url(self) -> str: Returns: str: The base url """ - return self._base_url + return self._base_url or str(self._http_client.base_url) @base_url.setter def base_url(self, value: str) -> None: diff --git a/packages/http/httpx/tests/test_httpx_request_adapter.py b/packages/http/httpx/tests/test_httpx_request_adapter.py index 0df147ec..20757cec 100644 --- a/packages/http/httpx/tests/test_httpx_request_adapter.py +++ b/packages/http/httpx/tests/test_httpx_request_adapter.py @@ -400,3 +400,9 @@ async def test_retries_on_cae_failure( ), ] request_adapter._authentication_provider.authenticate_request.assert_has_awaits(calls) + + +def test_httpx_request_adapter_uses_http_client_base_url(auth_provider): + http_client = httpx.AsyncClient(base_url=BASE_URL) + request_adapter = HttpxRequestAdapter(auth_provider, http_client=http_client) + assert request_adapter.base_url == BASE_URL From 0a27991bd4165c94bc39fbbf37bc210252c64916 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Tue, 28 Jan 2025 13:03:55 +0000 Subject: [PATCH 2/4] fix: Check for not when using the http_client._base_url --- packages/http/httpx/kiota_http/httpx_request_adapter.py | 6 +++--- packages/http/httpx/kiota_http/kiota_client_factory.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/http/httpx/kiota_http/httpx_request_adapter.py b/packages/http/httpx/kiota_http/httpx_request_adapter.py index 9140000e..de2ba703 100644 --- a/packages/http/httpx/kiota_http/httpx_request_adapter.py +++ b/packages/http/httpx/kiota_http/httpx_request_adapter.py @@ -86,9 +86,9 @@ def __init__( self._serialization_writer_factory = serialization_writer_factory if not http_client: http_client = KiotaClientFactory.create_with_default_middleware() - self._http_client = http_client + self._http_client: httpx.AsyncClient = http_client if not base_url: - base_url = str(http_client.base_url) + base_url = str(http_client.base_url) if http_client.base_url != None else "" self._base_url: str = base_url if not observability_options: observability_options = ObservabilityOptions() @@ -101,7 +101,7 @@ def base_url(self) -> str: Returns: str: The base url """ - return self._base_url or str(self._http_client.base_url) + return self._base_url or str(self._http_client.base_url) if self._http_client.base_url != None else "" @base_url.setter def base_url(self, value: str) -> None: diff --git a/packages/http/httpx/kiota_http/kiota_client_factory.py b/packages/http/httpx/kiota_http/kiota_client_factory.py index 93481ecc..9d70d3ff 100644 --- a/packages/http/httpx/kiota_http/kiota_client_factory.py +++ b/packages/http/httpx/kiota_http/kiota_client_factory.py @@ -55,7 +55,7 @@ def create_with_default_middleware( instantiating default middleware. Defaults to dict[str, RequestOption]=None. Returns: - httpx.AsycClient: An instance of the AsyncClient object + httpx.AsyncClient: An instance of the AsyncClient object """ kiota_async_client = KiotaClientFactory.get_default_client() if client is None else client From 7f9819aaf2861e63b5d2e095ff04d6919d872c5f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 09:38:37 -0500 Subject: [PATCH 3/4] chore: formatting --- .../http/httpx/kiota_http/httpx_request_adapter.py | 4 +++- .../httpx/tests/middleware_tests/test_retry_handler.py | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/http/httpx/kiota_http/httpx_request_adapter.py b/packages/http/httpx/kiota_http/httpx_request_adapter.py index de2ba703..2f566061 100644 --- a/packages/http/httpx/kiota_http/httpx_request_adapter.py +++ b/packages/http/httpx/kiota_http/httpx_request_adapter.py @@ -101,7 +101,9 @@ def base_url(self) -> str: Returns: str: The base url """ - return self._base_url or str(self._http_client.base_url) if self._http_client.base_url != None else "" + return self._base_url or str( + self._http_client.base_url + ) if self._http_client.base_url != None else "" @base_url.setter def base_url(self, value: str) -> None: diff --git a/packages/http/httpx/tests/middleware_tests/test_retry_handler.py b/packages/http/httpx/tests/middleware_tests/test_retry_handler.py index de7dd4f9..e576ac0c 100644 --- a/packages/http/httpx/tests/middleware_tests/test_retry_handler.py +++ b/packages/http/httpx/tests/middleware_tests/test_retry_handler.py @@ -224,7 +224,7 @@ def request_handler(request: httpx.Request): return httpx.Response(200, ) return httpx.Response( TOO_MANY_REQUESTS, - headers={RETRY_AFTER: "200"}, # value exceeds max delay of 180 secs + headers={RETRY_AFTER: "200"}, # value exceeds max delay of 180 secs ) # Retry-after value takes precedence over the RetryHandlerOption value specified here @@ -238,6 +238,7 @@ def request_handler(request: httpx.Request): assert resp.status_code == 429 assert RETRY_ATTEMPT not in resp.request.headers + @pytest.mark.asyncio async def test_max_retries_respected(): """Test that a request is not retried more than max_retries configured""" @@ -245,16 +246,14 @@ async def test_max_retries_respected(): def request_handler(request: httpx.Request): if RETRY_ATTEMPT in request.headers: return httpx.Response(200, ) - return httpx.Response( - TOO_MANY_REQUESTS, - ) + return httpx.Response(TOO_MANY_REQUESTS, ) # Retry-after value takes precedence over the RetryHandlerOption value specified here handler = RetryHandler(RetryHandlerOption(10, 3, True)) request = httpx.Request( 'GET', BASE_URL, - headers={RETRY_ATTEMPT: '5'} # value exceeds max retries configured + headers={RETRY_ATTEMPT: '5'} # value exceeds max retries configured ) mock_transport = httpx.MockTransport(request_handler) resp = await handler.send(request, mock_transport) @@ -262,6 +261,7 @@ def request_handler(request: httpx.Request): assert RETRY_ATTEMPT in resp.request.headers assert resp.request.headers[RETRY_ATTEMPT] == '5' + @pytest.mark.asyncio async def test_retry_options_apply_per_request(): """Test that a request options are applied per request""" From 67b6a88244a22c9de9c1e9ae2021d87de299579b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 28 Jan 2025 09:41:18 -0500 Subject: [PATCH 4/4] chore: formatting --- packages/http/httpx/kiota_http/httpx_request_adapter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/http/httpx/kiota_http/httpx_request_adapter.py b/packages/http/httpx/kiota_http/httpx_request_adapter.py index 2f566061..9f379fe5 100644 --- a/packages/http/httpx/kiota_http/httpx_request_adapter.py +++ b/packages/http/httpx/kiota_http/httpx_request_adapter.py @@ -88,7 +88,7 @@ def __init__( http_client = KiotaClientFactory.create_with_default_middleware() self._http_client: httpx.AsyncClient = http_client if not base_url: - base_url = str(http_client.base_url) if http_client.base_url != None else "" + base_url = str(http_client.base_url) if http_client.base_url is not None else "" self._base_url: str = base_url if not observability_options: observability_options = ObservabilityOptions() @@ -103,7 +103,7 @@ def base_url(self) -> str: """ return self._base_url or str( self._http_client.base_url - ) if self._http_client.base_url != None else "" + ) if self._http_client.base_url is not None else "" @base_url.setter def base_url(self, value: str) -> None: