Merge branch 'master' into issue-640
This commit is contained in:
@@ -9,6 +9,8 @@ cryptography==49.0.0
|
|||||||
h11==0.16.0
|
h11==0.16.0
|
||||||
httpcore==1.0.9
|
httpcore==1.0.9
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
|
# Starlette 1.3.x TestClient prefers httpx2; plain httpx remains for MCP/runtime (#682).
|
||||||
|
httpx2==2.9.1
|
||||||
httpx-sse==0.4.3
|
httpx-sse==0.4.3
|
||||||
idna==3.18
|
idna==3.18
|
||||||
iniconfig==2.3.0
|
iniconfig==2.3.0
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
"""Starlette TestClient uses httpx2 without deprecation warning (#682)."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import warnings
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
|
|
||||||
|
class TestHttpx2Installed(unittest.TestCase):
|
||||||
|
def test_httpx2_importable(self) -> None:
|
||||||
|
httpx2 = importlib.import_module("httpx2")
|
||||||
|
self.assertTrue(hasattr(httpx2, "Client") or hasattr(httpx2, "AsyncClient"))
|
||||||
|
|
||||||
|
|
||||||
|
class TestNoStarletteTestClientDeprecation(unittest.TestCase):
|
||||||
|
def test_starlette_testclient_import_does_not_warn(self) -> None:
|
||||||
|
# Force a fresh import path so a previous httpx-fallback warning cannot
|
||||||
|
# hide a regression after httpx2 is present. Restore sys.modules afterwards.
|
||||||
|
saved = {
|
||||||
|
name: sys.modules[name]
|
||||||
|
for name in list(sys.modules)
|
||||||
|
if name == "starlette.testclient" or name.startswith("starlette.testclient.")
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
for name in list(saved):
|
||||||
|
del sys.modules[name]
|
||||||
|
|
||||||
|
with warnings.catch_warnings(record=True) as caught:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
import starlette.testclient as testclient # noqa: F401
|
||||||
|
|
||||||
|
dep = [
|
||||||
|
w
|
||||||
|
for w in caught
|
||||||
|
if "httpx" in str(w.message).lower()
|
||||||
|
and "deprecated" in str(w.message).lower()
|
||||||
|
]
|
||||||
|
self.assertEqual(
|
||||||
|
dep,
|
||||||
|
[],
|
||||||
|
f"expected no Starlette httpx deprecation warning; got: "
|
||||||
|
f"{[str(w.message) for w in dep]}",
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
sys.modules.update(saved)
|
||||||
|
|
||||||
|
def test_canonical_webui_testclient_import(self) -> None:
|
||||||
|
with warnings.catch_warnings(record=True) as caught:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
from tests.webui_testclient import TestClient
|
||||||
|
from webui.app import create_app
|
||||||
|
|
||||||
|
client = TestClient(create_app())
|
||||||
|
response = client.get("/")
|
||||||
|
self.assertIn(response.status_code, {200, 302, 404})
|
||||||
|
|
||||||
|
dep = [
|
||||||
|
w
|
||||||
|
for w in caught
|
||||||
|
if "httpx" in str(w.message).lower()
|
||||||
|
and "deprecated" in str(w.message).lower()
|
||||||
|
]
|
||||||
|
self.assertEqual(dep, [], [str(w.message) for w in dep])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
import control_plane_db
|
import control_plane_db
|
||||||
from webui.analytics_loader import (
|
from webui.analytics_loader import (
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.audit_validator import audit_report, infer_task_kind
|
from webui.audit_validator import audit_report, infer_task_kind
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.deployment_boundary import (
|
from webui.deployment_boundary import (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from task_capability_map import TASK_CAPABILITY_MAP
|
from task_capability_map import TASK_CAPABILITY_MAP
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
import control_plane_db
|
import control_plane_db
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.lease_loader import (
|
from webui.lease_loader import (
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
from starlette.routing import Route
|
from starlette.routing import Route
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.project_registry import (
|
from webui.project_registry import (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.prompt_library import find_prompt, library_to_dict, load_prompt_library, prompt_to_dict
|
from webui.prompt_library import find_prompt, library_to_dict, load_prompt_library, prompt_to_dict
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from unittest import mock
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.queue_loader import (
|
from webui.queue_loader import (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from unittest import mock
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.runtime_health import _role_kind, load_runtime_snapshot, snapshot_to_dict
|
from webui.runtime_health import _role_kind, load_runtime_snapshot, snapshot_to_dict
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from pathlib import Path
|
|||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.routing import Route
|
from starlette.routing import Route
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui import layout
|
from webui import layout
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from unittest import mock
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
import control_plane_db
|
import control_plane_db
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.deployment_boundary import scan_text_for_client_secrets
|
from webui.deployment_boundary import scan_text_for_client_secrets
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
import control_plane_db
|
import control_plane_db
|
||||||
from canonical_thread_handoff import (
|
from canonical_thread_handoff import (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||||
|
|
||||||
from starlette.testclient import TestClient
|
from tests.webui_testclient import TestClient
|
||||||
|
|
||||||
from webui.app import create_app
|
from webui.app import create_app
|
||||||
from webui.worktree_scanner import (
|
from webui.worktree_scanner import (
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
"""Canonical Web UI ``TestClient`` import for the Gitea-Tools suite (#682).
|
||||||
|
|
||||||
|
Starlette 1.3+ builds ``starlette.testclient.TestClient`` on ``httpx2``.
|
||||||
|
Plain ``httpx`` still works but emits ``StarletteDeprecationWarning``.
|
||||||
|
|
||||||
|
All Web UI tests import ``TestClient`` from this module so:
|
||||||
|
|
||||||
|
* dependency intent is single-sourced (``httpx2`` in ``requirements.txt``);
|
||||||
|
* a future client-construction helper has one place to land;
|
||||||
|
* import-site audits do not need to re-scan every ``test_webui_*.py``.
|
||||||
|
|
||||||
|
Runtime MCP / FastMCP code continues to use ``httpx``; this module is
|
||||||
|
test-only and does not change production clients.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from starlette.testclient import TestClient
|
||||||
|
|
||||||
|
__all__ = ["TestClient"]
|
||||||
Reference in New Issue
Block a user