From 5a7f470b3cee7fdeabe086f60dc0cd1777d6528d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=B0=B8=E8=B5=AB?= <1259085392@qq.com> Date: Sat, 28 Mar 2026 20:38:43 +0900 Subject: [PATCH 1/4] fix: bundle httpx SOCKS proxy support --- pyproject.toml | 1 + requirements.txt | 1 + tests/test_httpx_socks_dependency.py | 36 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 tests/test_httpx_socks_dependency.py diff --git a/pyproject.toml b/pyproject.toml index 463da49556..0b2d66d8db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ dependencies = [ "faiss-cpu>=1.12.0", "filelock>=3.18.0", "google-genai>=1.56.0", + "httpx[socks]>=0.28.1", "lark-oapi>=1.4.15", "lxml-html-clean>=0.4.2", "mcp>=1.8.0", diff --git a/requirements.txt b/requirements.txt index 5c45ecd332..b96d72008f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,7 @@ docstring-parser>=0.16 faiss-cpu>=1.12.0 filelock>=3.18.0 google-genai>=1.56.0 +httpx[socks]>=0.28.1 lark-oapi>=1.4.15 lxml-html-clean>=0.4.2 mcp>=1.8.0 diff --git a/tests/test_httpx_socks_dependency.py b/tests/test_httpx_socks_dependency.py new file mode 100644 index 0000000000..27b3e7199a --- /dev/null +++ b/tests/test_httpx_socks_dependency.py @@ -0,0 +1,36 @@ +import re +from pathlib import Path + +import tomllib + +PROJECT_ROOT = Path(__file__).resolve().parents[1] +REQUIREMENTS_PATH = PROJECT_ROOT / "requirements.txt" +PYPROJECT_PATH = PROJECT_ROOT / "pyproject.toml" +HTTPX_SOCKS_PATTERN = re.compile(r"^httpx\[socks\](?:\s*[<>=!~].*)?$") + + +def _contains_httpx_socks_dependency(entries: list[str]) -> bool: + return any(HTTPX_SOCKS_PATTERN.match(entry.strip()) for entry in entries) + + +def _read_requirements() -> list[str]: + entries = [] + for line in REQUIREMENTS_PATH.read_text(encoding="utf-8").splitlines(): + candidate = line.split("#", 1)[0].strip() + if candidate: + entries.append(candidate) + return entries + + +def _read_pyproject_dependencies() -> list[str]: + with PYPROJECT_PATH.open("rb") as file: + pyproject = tomllib.load(file) + return pyproject["project"]["dependencies"] + + +def test_requirements_include_httpx_socks_dependency() -> None: + assert _contains_httpx_socks_dependency(_read_requirements()) + + +def test_pyproject_declares_httpx_socks_dependency() -> None: + assert _contains_httpx_socks_dependency(_read_pyproject_dependencies()) From db5eb664d6b8bae67736d335b4a47bbab56ff730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=B0=B8=E8=B5=AB?= <1259085392@qq.com> Date: Sat, 28 Mar 2026 20:51:25 +0900 Subject: [PATCH 2/4] test: tighten SOCKS dependency regression coverage --- tests/test_httpx_socks_dependency.py | 36 ++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/tests/test_httpx_socks_dependency.py b/tests/test_httpx_socks_dependency.py index 27b3e7199a..b3f1b1350a 100644 --- a/tests/test_httpx_socks_dependency.py +++ b/tests/test_httpx_socks_dependency.py @@ -9,8 +9,12 @@ HTTPX_SOCKS_PATTERN = re.compile(r"^httpx\[socks\](?:\s*[<>=!~].*)?$") -def _contains_httpx_socks_dependency(entries: list[str]) -> bool: - return any(HTTPX_SOCKS_PATTERN.match(entry.strip()) for entry in entries) +def _read_httpx_socks_dependency(entries: list[str]) -> str | None: + for entry in entries: + candidate = entry.strip() + if HTTPX_SOCKS_PATTERN.match(candidate): + return candidate + return None def _read_requirements() -> list[str]: @@ -29,8 +33,32 @@ def _read_pyproject_dependencies() -> list[str]: def test_requirements_include_httpx_socks_dependency() -> None: - assert _contains_httpx_socks_dependency(_read_requirements()) + requirements_dependency = _read_httpx_socks_dependency(_read_requirements()) + + assert requirements_dependency is not None, ( + "Expected httpx[socks] dependency in requirements.txt for SOCKS proxy support" + ) def test_pyproject_declares_httpx_socks_dependency() -> None: - assert _contains_httpx_socks_dependency(_read_pyproject_dependencies()) + pyproject_dependency = _read_httpx_socks_dependency(_read_pyproject_dependencies()) + + assert pyproject_dependency is not None, ( + "Expected httpx[socks] dependency in pyproject.toml for SOCKS proxy support" + ) + + +def test_httpx_socks_dependency_spec_matches_between_dependency_files() -> None: + requirements_dependency = _read_httpx_socks_dependency(_read_requirements()) + pyproject_dependency = _read_httpx_socks_dependency(_read_pyproject_dependencies()) + + assert requirements_dependency is not None, ( + "Expected httpx[socks] dependency in requirements.txt for SOCKS proxy support" + ) + assert pyproject_dependency is not None, ( + "Expected httpx[socks] dependency in pyproject.toml for SOCKS proxy support" + ) + assert requirements_dependency == pyproject_dependency, ( + "Expected httpx[socks] dependency spec to match between requirements.txt " + "and pyproject.toml for SOCKS proxy support" + ) From d0431a1c94c8d6ed39cf84009cddb43204adc551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=B0=B8=E8=B5=AB?= <1259085392@qq.com> Date: Sat, 28 Mar 2026 21:12:42 +0900 Subject: [PATCH 3/4] test: allow SOCKS dependency environment markers --- tests/test_httpx_socks_dependency.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_httpx_socks_dependency.py b/tests/test_httpx_socks_dependency.py index b3f1b1350a..219f7ebdfd 100644 --- a/tests/test_httpx_socks_dependency.py +++ b/tests/test_httpx_socks_dependency.py @@ -6,7 +6,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1] REQUIREMENTS_PATH = PROJECT_ROOT / "requirements.txt" PYPROJECT_PATH = PROJECT_ROOT / "pyproject.toml" -HTTPX_SOCKS_PATTERN = re.compile(r"^httpx\[socks\](?:\s*[<>=!~].*)?$") +HTTPX_SOCKS_PATTERN = re.compile(r"^httpx\[socks\](?:\s*[<>=!~][^;]*)?(?:\s*;.*)?$") def _read_httpx_socks_dependency(entries: list[str]) -> str | None: @@ -62,3 +62,12 @@ def test_httpx_socks_dependency_spec_matches_between_dependency_files() -> None: "Expected httpx[socks] dependency spec to match between requirements.txt " "and pyproject.toml for SOCKS proxy support" ) + + +def test_httpx_socks_pattern_allows_environment_markers() -> None: + entry = 'httpx[socks]; python_version >= "3.11"' + + assert HTTPX_SOCKS_PATTERN.match(entry), ( + "Expected httpx[socks] dependency pattern to allow environment markers " + "for SOCKS proxy support" + ) From 540ff50b6b375bf79a1a22f517540f8f4cd8599a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=B0=B8=E8=B5=AB?= <1259085392@qq.com> Date: Sat, 28 Mar 2026 21:21:37 +0900 Subject: [PATCH 4/4] test: broaden SOCKS dependency regex coverage --- tests/test_httpx_socks_dependency.py | 50 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/tests/test_httpx_socks_dependency.py b/tests/test_httpx_socks_dependency.py index 219f7ebdfd..499921253f 100644 --- a/tests/test_httpx_socks_dependency.py +++ b/tests/test_httpx_socks_dependency.py @@ -1,6 +1,7 @@ import re from pathlib import Path +import pytest import tomllib PROJECT_ROOT = Path(__file__).resolve().parents[1] @@ -64,10 +65,49 @@ def test_httpx_socks_dependency_spec_matches_between_dependency_files() -> None: ) -def test_httpx_socks_pattern_allows_environment_markers() -> None: - entry = 'httpx[socks]; python_version >= "3.11"' +@pytest.mark.parametrize( + "entry", + [ + "httpx[socks]", + "httpx[socks]==0.27.0", + "httpx[socks]==0.28.1", + "httpx[socks]>=0.27.0,<0.28.0", + "httpx[socks]>=0.27,<0.29", + 'httpx[socks]; python_version >= "3.11"', + 'httpx[socks]>=0.27.0 ; python_version < "3.13"', + 'httpx[socks] ; python_version < "3.13"', + 'httpx[socks] >=0.27 ; python_version < "3.13"', + ], +) +def test_httpx_socks_pattern_matches_valid_variants(entry: str) -> None: + match = HTTPX_SOCKS_PATTERN.match(entry) + + assert match is not None, ( + f"Expected httpx[socks] dependency pattern to match valid entry for " + f"SOCKS proxy support: {entry}" + ) + assert match.group(0) == entry, ( + f"Expected httpx[socks] dependency pattern to fully match valid entry " + f"for SOCKS proxy support: {entry}" + ) + - assert HTTPX_SOCKS_PATTERN.match(entry), ( - "Expected httpx[socks] dependency pattern to allow environment markers " - "for SOCKS proxy support" +@pytest.mark.parametrize( + "entry", + [ + "httpx", + "httpx==0.27.0", + "httpx[http2]", + "httpx[socks-extra]", + "httpx [socks]", + "someprefix httpx[socks]", + "httpx[socks] trailing-text", + "httpx[socks] extra ; markers", + "httpx[socks]andmore", + ], +) +def test_httpx_socks_pattern_rejects_invalid_variants(entry: str) -> None: + assert HTTPX_SOCKS_PATTERN.match(entry) is None, ( + f"Expected httpx[socks] dependency pattern to reject invalid entry for " + f"SOCKS proxy support: {entry}" )