From 9830bec65fba1d974772370c05126fce0d17f768 Mon Sep 17 00:00:00 2001 From: stepskop Date: Wed, 7 May 2025 15:41:03 +0200 Subject: [PATCH] chore: init will fetch api only if needed --- src/apify/_proxy_configuration.py | 33 ++++++++++++-------------- tests/unit/test_proxy_configuration.py | 30 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/apify/_proxy_configuration.py b/src/apify/_proxy_configuration.py index 6fa64f56..1d5b9f72 100644 --- a/src/apify/_proxy_configuration.py +++ b/src/apify/_proxy_configuration.py @@ -178,7 +178,9 @@ def __init__( self._country_code = country_code async def initialize(self) -> None: - """Load the Apify Proxy password if the API token is provided and check access to Apify Proxy and proxy groups. + """Check if using proxy, if so, check the access. + + Load the Apify Proxy password from API (only if not passed to constructor or through env var). Only called if Apify Proxy configuration is used. Also checks if country has access to Apify Proxy groups if the country code is provided. @@ -187,7 +189,17 @@ async def initialize(self) -> None: `ProxyConfiguration` instance instead of calling this manually. """ if self._uses_apify_proxy: - await self._maybe_fetch_password() + if not self._password: + await self._maybe_fetch_password() + if not self._password: + raise ValueError( + 'Apify Proxy password must be provided using the "password" constructor argument ' + f'or the "{ApifyEnvVars.PROXY_PASSWORD}" environment variable. ' + f'You can also provide your Apify token via the "${ApifyEnvVars.TOKEN}" environment variable, ' + f'so that the SDK can fetch the proxy password from Apify API, ' + f'when not provided through constructor or ${ApifyEnvVars.PROXY_PASSWORD}.' + ) + await self._check_access() async def new_proxy_info( @@ -255,22 +267,7 @@ async def _maybe_fetch_password(self) -> None: user_info = await self._apify_client.user().get() if user_info: password = user_info['proxy']['password'] - - if self._password: - if self._password != password: - logger.warning( - 'The Apify Proxy password you provided belongs to a different user than the Apify ' - 'token you are using. Are you sure this is correct?' - ) - else: - self._password = password - - if not self._password: - raise ValueError( - 'Apify Proxy password must be provided using the "password" constructor argument ' - f'or the "{ApifyEnvVars.PROXY_PASSWORD}" environment variable. If you add ' - f'the "{ApifyEnvVars.TOKEN}" environment variable, the password will be automatically inferred.' - ) + self._password = password async def _check_access(self) -> None: proxy_status_url = f'{self._configuration.proxy_status_url}/?format=json' diff --git a/tests/unit/test_proxy_configuration.py b/tests/unit/test_proxy_configuration.py index fe10aefb..96eb0544 100644 --- a/tests/unit/test_proxy_configuration.py +++ b/tests/unit/test_proxy_configuration.py @@ -432,6 +432,36 @@ async def test_initialize_with_manual_password(monkeypatch: pytest.MonkeyPatch, assert proxy_configuration.is_man_in_the_middle is False +async def test_initialize_prefering_password_from_env_over_calling_api( + monkeypatch: pytest.MonkeyPatch, + respx_mock: MockRouter, + patched_apify_client: ApifyClientAsync, +) -> None: + dummy_proxy_status_url = 'http://dummy-proxy-status-url.com' + monkeypatch.setenv(ApifyEnvVars.PROXY_STATUS_URL.value, dummy_proxy_status_url) + monkeypatch.setenv(ApifyEnvVars.PROXY_PASSWORD.value, DUMMY_PASSWORD) + + respx_mock.get(dummy_proxy_status_url).mock( + httpx.Response( + 200, + json={ + 'connected': True, + 'connectionError': None, + 'isManInTheMiddle': False, + }, + ) + ) + + proxy_configuration = ProxyConfiguration() + + await proxy_configuration.initialize() + + assert proxy_configuration._password == DUMMY_PASSWORD + assert proxy_configuration.is_man_in_the_middle is False + + assert len(patched_apify_client.calls['user']['get']) == 0 # type: ignore[attr-defined] + + @pytest.mark.skip(reason='There are issues with log propagation to caplog, see issue #462.') async def test_initialize_with_manual_password_different_than_user_one( monkeypatch: pytest.MonkeyPatch,