From e3861fe9bef324512a3529879c4cc19b91bb238b Mon Sep 17 00:00:00 2001 From: kapil971390 Date: Fri, 26 Jun 2026 12:12:38 +0530 Subject: [PATCH] fix(proxy): raise ValueError for unknown IP_PROXY_PROVIDER_NAME When IP_PROXY_PROVIDER_NAME in config.py is set to an unrecognised value (e.g. typo "kuaidalli" instead of "kuaidaili"), IpProxyProvider.get() returns None which is silently stored in ProxyIpPool.ip_provider. The crash surfaces later as: AttributeError: 'NoneType' object has no attribute 'get_proxy' with no hint about what went wrong or how to fix it. Add an explicit None-check in create_ip_pool() that raises ValueError with the bad name and the list of valid options, so the root cause is immediately visible. Also add a regression test covering the four invalid-name edge cases (typo, empty string, wrong case, unknown name) and the three valid names to confirm they are unaffected. --- proxy/proxy_ip_pool.py | 8 +++++++- test/test_proxy_ip_pool.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/proxy/proxy_ip_pool.py b/proxy/proxy_ip_pool.py index 8041d38..a58b14d 100644 --- a/proxy/proxy_ip_pool.py +++ b/proxy/proxy_ip_pool.py @@ -202,11 +202,17 @@ async def create_ip_pool(ip_pool_count: int, enable_validate_ip: bool) -> ProxyI :param enable_validate_ip: Whether to enable IP proxy validation :return: """ + ip_provider = IpProxyProvider.get(config.IP_PROXY_PROVIDER_NAME) + if ip_provider is None: + raise ValueError( + f"Unknown proxy provider: '{config.IP_PROXY_PROVIDER_NAME}'. " + f"Valid options: {list(IpProxyProvider.keys())}" + ) is_static = config.IP_PROXY_PROVIDER_NAME == ProviderNameEnum.STATIC_PROVIDER.value pool = ProxyIpPool( ip_pool_count=ip_pool_count, enable_validate_ip=False if is_static else enable_validate_ip, - ip_provider=IpProxyProvider.get(config.IP_PROXY_PROVIDER_NAME), + ip_provider=ip_provider, ) await pool.load_proxies() return pool diff --git a/test/test_proxy_ip_pool.py b/test/test_proxy_ip_pool.py index 266f988..a4a567e 100644 --- a/test/test_proxy_ip_pool.py +++ b/test/test_proxy_ip_pool.py @@ -268,4 +268,23 @@ class TestIpPool(IsolatedAsyncioTestCase): print(f" Is expired after setting expired proxy: {is_expired}") self.assertTrue(is_expired, msg="Expired proxy should return True") + async def test_create_ip_pool_unknown_provider_raises_value_error(self): + """create_ip_pool() should raise ValueError with a helpful message when + IP_PROXY_PROVIDER_NAME is not in the IpProxyProvider registry, rather than + passing None silently and crashing with AttributeError in load_proxies().""" + from proxy.proxy_ip_pool import IpProxyProvider + from unittest.mock import patch + + invalid_cases = ["kuaidalli", "", "KUAIDAILI", "unknown_provider"] + + for bad_name in invalid_cases: + with self.subTest(provider=bad_name): + with patch("proxy.proxy_ip_pool.config") as mock_config: + mock_config.IP_PROXY_PROVIDER_NAME = bad_name + with self.assertRaises(ValueError) as ctx: + from proxy.proxy_ip_pool import create_ip_pool + await create_ip_pool(ip_pool_count=1, enable_validate_ip=False) + self.assertIn(bad_name, str(ctx.exception)) + self.assertIn(str(list(IpProxyProvider.keys())), str(ctx.exception)) + print("\n=== Standalone IP proxy expiration detection test completed ===\n")