From 7a6fde2a3fce2afbfbddd73be04a989e609ea6f5 Mon Sep 17 00:00:00 2001 From: pederhan Date: Fri, 1 Mar 2024 14:52:10 +0100 Subject: [PATCH 1/3] Don't reinstantiate client unless needed --- CHANGELOG.md | 7 +++++++ harborapi/client.py | 33 +++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 609a3af6..3a3dc8ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,13 @@ While the project is still on major version 0, breaking changes may be introduce +## [0.23.4](https://github.com/unioslo/harborapi/tree/harborapi-v0.23.4) - 2024-03-01 + +### Changed + +- `HarborAsyncClient.authenticate(verify=...)` will no longer instantiate a new client object if the `verify` value is identical to current one. + + ## [0.23.3](https://github.com/unioslo/harborapi/tree/harborapi-v0.23.3) - 2024-03-01 ### Fixed diff --git a/harborapi/client.py b/harborapi/client.py index b7a416c0..ae06bb70 100644 --- a/harborapi/client.py +++ b/harborapi/client.py @@ -224,23 +224,28 @@ def __init__( raise ValueError("A Harbor API URL is required.") self.authenticate(username, secret, basicauth, credentials_file, url, **kwargs) - # Instantiate persistent HTTP client using the redirect policy - # NOTE: any reason we don't specify headers here too? - self.client = httpx.AsyncClient( - follow_redirects=follow_redirects, - timeout=timeout, - cookies=CookieDiscarder(), - verify=verify, - ) - self.validate = validate self.raw = raw self.retry = retry + self.verify = verify + self.timeout = timeout + self.follow_redirects = follow_redirects if logging or os.environ.get("HARBORAPI_LOGGING", "") == "1": enable_logging() self.response_log = ResponseLog(max_logs=max_logs) + self.client = self._get_client() + + def _get_client(self) -> httpx.AsyncClient: + """Returns a new HTTPX client instance.""" + # NOTE: any reason we don't specify headers here too? + return httpx.AsyncClient( + follow_redirects=self.follow_redirects, + timeout=self.timeout, + cookies=CookieDiscarder(), + verify=self.verify, + ) def authenticate( self, @@ -321,15 +326,11 @@ def authenticate( # If user want to change SSL verification, we have to reinstantiate the client # https://www.python-httpx.org/advanced/ssl/#ssl-configuration-on-client-instances - if verify is not None: + if verify is not None and verify != self.verify: # TODO: add abstraction for client instantiation # that can be used in __init__ and here - self.client = httpx.AsyncClient( - follow_redirects=self.client.follow_redirects, - timeout=self.client.timeout, - cookies=CookieDiscarder(), - verify=verify, - ) + self.verify = verify + self.client = self._get_client() @contextlib.contextmanager def no_retry(self) -> Generator[None, None, None]: From dda1c005af3ba385bcdb12020be5cb6254254305 Mon Sep 17 00:00:00 2001 From: pederhan Date: Fri, 1 Mar 2024 14:53:25 +0100 Subject: [PATCH 2/3] Remove outdated comment --- harborapi/client.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/harborapi/client.py b/harborapi/client.py index ae06bb70..dad66676 100644 --- a/harborapi/client.py +++ b/harborapi/client.py @@ -327,8 +327,6 @@ def authenticate( # If user want to change SSL verification, we have to reinstantiate the client # https://www.python-httpx.org/advanced/ssl/#ssl-configuration-on-client-instances if verify is not None and verify != self.verify: - # TODO: add abstraction for client instantiation - # that can be used in __init__ and here self.verify = verify self.client = self._get_client() From 168a3f2c90e3345f59a9ff97a8cad0c320aadd38 Mon Sep 17 00:00:00 2001 From: pederhan Date: Fri, 1 Mar 2024 14:57:21 +0100 Subject: [PATCH 3/3] Add authenticate(verify=...) tests --- tests/test_client.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_client.py b/tests/test_client.py index a3dc6001..ca3e2fff 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -707,6 +707,27 @@ def test_authenticate( ) +@pytest.mark.parametrize("verify", [True, False]) +def test_authenticate_verify(verify: bool) -> None: + client = HarborAsyncClient( + url="https://example.com/api/v2.0", + username="username", + secret="secret", + verify=verify, # instantiate with our verify value + ) + + # Calling authenticate should NOT change the client instance + client_id_pre = id(client.client) + client.authenticate(verify=verify) + assert client.verify == verify + assert id(client.client) == client_id_pre + + # Calling with a different value should instantiate a new client + client.authenticate(verify=not verify) + assert client.verify == (not verify) + assert id(client.client) != client_id_pre + + @pytest.mark.asyncio @pytest.mark.parametrize( "status_code",