refactor: group rpc transport client and methods
This commit is contained in:
+17
-2
@@ -113,7 +113,7 @@ def load_cli_context(
|
||||
|
||||
if rpc_url is not None:
|
||||
_validate_rpc_url(rpc_url)
|
||||
client = RpcWorkflowApiClient(
|
||||
client = rpc_client_from_target(
|
||||
url=rpc_url,
|
||||
timeout_seconds=_rpc_timeout_from_optional_config(
|
||||
resolved_config_path,
|
||||
@@ -161,7 +161,7 @@ def load_cli_context(
|
||||
verbose=verbose,
|
||||
)
|
||||
if isinstance(target, RpcHttpTargetConfig):
|
||||
client = RpcWorkflowApiClient(
|
||||
client = rpc_client_from_target(
|
||||
url=str(target.url),
|
||||
timeout_seconds=(
|
||||
rpc_timeout_seconds
|
||||
@@ -181,6 +181,21 @@ def load_cli_context(
|
||||
raise ValueError(f"unsupported workflow target {target!r}")
|
||||
|
||||
|
||||
def rpc_client_from_target(
|
||||
*,
|
||||
url: str,
|
||||
timeout_seconds: float,
|
||||
) -> RpcWorkflowApiClient:
|
||||
"""Build the remote workflow surface for a resolved RPC target.
|
||||
|
||||
CLI tests patch this project-owned seam instead of monkeypatching `httpx`
|
||||
internals. The production path still keeps HTTP construction inside the
|
||||
transport package.
|
||||
"""
|
||||
|
||||
return RpcWorkflowApiClient(url=url, timeout_seconds=timeout_seconds)
|
||||
|
||||
|
||||
def load_local_cli_context(
|
||||
config_path: str | Path,
|
||||
*,
|
||||
|
||||
@@ -5,9 +5,6 @@ Canonical implementation lives in `wf_sources_mcp.tool_wrappers`.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from wf_sources_mcp.schema_models import model_from_schema
|
||||
from wf_sources_mcp.tool_wrappers import wrap_discovered_tool
|
||||
|
||||
_model_from_schema = model_from_schema # TODO: remove when callers migrate
|
||||
|
||||
__all__ = ["_model_from_schema", "wrap_discovered_tool"]
|
||||
__all__ = ["wrap_discovered_tool"]
|
||||
|
||||
@@ -7,16 +7,18 @@ import fastapi_jsonrpc as jsonrpc
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError
|
||||
from .methods_admin import register_methods as register_admin_methods
|
||||
from .methods_artifacts import register_methods as register_artifact_methods
|
||||
from .methods_capabilities import register_methods as register_capability_methods
|
||||
from .methods_deployments import register_methods as register_deployment_methods
|
||||
from .methods_drafts import register_methods as register_draft_methods
|
||||
from .methods_runs import register_methods as register_run_methods
|
||||
from .methods_source_registry import (
|
||||
from .methods.admin import register_methods as register_admin_methods
|
||||
from .methods.artifacts import register_methods as register_artifact_methods
|
||||
from .methods.capabilities import (
|
||||
register_methods as register_capability_methods,
|
||||
)
|
||||
from .methods.deployments import register_methods as register_deployment_methods
|
||||
from .methods.drafts import register_methods as register_draft_methods
|
||||
from .methods.runs import register_methods as register_run_methods
|
||||
from .methods.source_registry import (
|
||||
register_methods as register_source_registry_methods,
|
||||
)
|
||||
from .methods_sources import register_methods as register_source_methods
|
||||
from .methods.sources import register_methods as register_source_methods
|
||||
|
||||
|
||||
def create_rpc_app(server: WorkflowServer, *, rpc_path: str = "/rpc") -> jsonrpc.API:
|
||||
|
||||
@@ -2,17 +2,15 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
import httpx # noqa: F401 # Backcompat for tests patching client.httpx.AsyncClient.
|
||||
|
||||
from .client_admin import RpcAdminClientMixin
|
||||
from .client_artifacts import RpcArtifactClientMixin
|
||||
from .client_base import RpcClientTransport
|
||||
from .client_capabilities import RpcCapabilityClientMixin
|
||||
from .client_deployments import RpcDeploymentClientMixin
|
||||
from .client_drafts import RpcDraftClientMixin
|
||||
from .client_runs import RpcRunClientMixin
|
||||
from .client_source_registry import RpcSourceRegistryClientMixin
|
||||
from .client_sources import RpcSourceAdminClientMixin
|
||||
from .admin import RpcAdminClientMixin
|
||||
from .artifacts import RpcArtifactClientMixin
|
||||
from .base import RpcClientTransport
|
||||
from .capabilities import RpcCapabilityClientMixin
|
||||
from .deployments import RpcDeploymentClientMixin
|
||||
from .drafts import RpcDraftClientMixin
|
||||
from .runs import RpcRunClientMixin
|
||||
from .source_registry import RpcSourceRegistryClientMixin
|
||||
from .sources import RpcSourceAdminClientMixin
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
+3
-3
@@ -6,14 +6,14 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import (
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import (
|
||||
AdminEmptyParams,
|
||||
DeleteAuthParams,
|
||||
InspectAuthParams,
|
||||
SaveAuthParams,
|
||||
)
|
||||
from .params import RpcParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -6,9 +6,9 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import InspectArtifactParams, ListArtifactsParams, SaveArtifactParams
|
||||
from .params import RpcParams
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import InspectArtifactParams, ListArtifactsParams, SaveArtifactParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -6,9 +6,9 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import InspectCapabilityParams, ListCapabilitiesParams
|
||||
from .params import RpcParams
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import InspectCapabilityParams, ListCapabilitiesParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -6,15 +6,15 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import (
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import (
|
||||
DeleteDeploymentParams,
|
||||
InspectDeploymentParams,
|
||||
ListDeploymentsParams,
|
||||
SaveDeploymentParams,
|
||||
ValidateDeploymentParams,
|
||||
)
|
||||
from .params import RpcParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -6,8 +6,8 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import (
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import (
|
||||
CreateArtifactFromWorkspaceParams,
|
||||
CreateDraftFromCapabilityParams,
|
||||
CreateWrapperFromWorkspaceParams,
|
||||
@@ -18,7 +18,7 @@ from .models import (
|
||||
ValidateDraftParams,
|
||||
ValidateDraftWorkspaceParams,
|
||||
)
|
||||
from .params import RpcParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -6,14 +6,14 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import (
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import (
|
||||
InspectRunParams,
|
||||
ReadRunTraceParams,
|
||||
ResumeRunParams,
|
||||
StartRunParams,
|
||||
)
|
||||
from .params import RpcParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
+3
-3
@@ -7,8 +7,8 @@ import fastapi_jsonrpc as jsonrpc
|
||||
from wf_api import WorkflowSourceRegistrySurface
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import (
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import (
|
||||
AddRegistryEntryParams,
|
||||
ApplyRegistryChangesParams,
|
||||
InspectRegistryEntryParams,
|
||||
@@ -16,7 +16,7 @@ from .models import (
|
||||
RegistryEntryIdParams,
|
||||
UpdateRegistryEntryParams,
|
||||
)
|
||||
from .params import RpcParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def _require_source_registry_admin(
|
||||
+3
-3
@@ -6,9 +6,9 @@ import fastapi_jsonrpc as jsonrpc
|
||||
|
||||
from wf_server import WorkflowServer
|
||||
|
||||
from .errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from .models import InspectSourceParams, ListSourcesParams
|
||||
from .params import RpcParams
|
||||
from ..errors import WorkflowRpcError, raise_workflow_rpc_error
|
||||
from ..models import InspectSourceParams, ListSourcesParams
|
||||
from ..params import RpcParams
|
||||
|
||||
|
||||
def register_methods(
|
||||
@@ -8,12 +8,14 @@ from typing import Any, cast
|
||||
import httpx
|
||||
from typer.testing import CliRunner
|
||||
|
||||
import wf_cli.context as cli_context
|
||||
from wf_api.models import RawWorkflowPlan
|
||||
from wf_cli.app import app
|
||||
from wf_cli.context import CliContext, load_cli_context, load_local_cli_context
|
||||
from wf_core import END
|
||||
from wf_server import build_local_static_workflow_server
|
||||
from wf_transport_rpc_http import RpcWorkflowApiClient, create_rpc_app
|
||||
from wf_transport_rpc_http.client.sources import RpcSourceAdminClientMixin
|
||||
|
||||
|
||||
class BrokenSourceAdmin:
|
||||
@@ -271,16 +273,29 @@ def _interrupt_plan() -> RawWorkflowPlan:
|
||||
)
|
||||
|
||||
|
||||
def _patch_rpc_client_to_server(monkeypatch, server) -> None:
|
||||
"""Route CLI-created RPC clients to an in-process ASGI test server."""
|
||||
|
||||
def fake_rpc_client_from_target(
|
||||
*,
|
||||
url: str,
|
||||
timeout_seconds: float,
|
||||
) -> RpcWorkflowApiClient:
|
||||
return RpcWorkflowApiClient(
|
||||
url=url,
|
||||
timeout_seconds=timeout_seconds,
|
||||
http_client=httpx.AsyncClient(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
|
||||
monkeypatch.setattr(cli_context, "rpc_client_from_target", fake_rpc_client_from_target)
|
||||
|
||||
|
||||
def test_wf_cap_commands_use_rpc_url_override(monkeypatch, tmp_path) -> None:
|
||||
server = build_local_static_workflow_server(tmp_path / "store")
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
|
||||
@@ -325,14 +340,7 @@ def test_wf_cap_commands_use_rpc_url_override(monkeypatch, tmp_path) -> None:
|
||||
|
||||
def test_wf_source_commands_use_rpc_url_override(monkeypatch, tmp_path) -> None:
|
||||
server = build_local_static_workflow_server(tmp_path / "store")
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
@@ -352,14 +360,7 @@ def test_wf_remote_source_inspect_formats_expected_rpc_error(
|
||||
tmp_path,
|
||||
) -> None:
|
||||
server = build_local_static_workflow_server(tmp_path / "store")
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
@@ -382,10 +383,7 @@ def test_wf_remote_source_list_formats_transport_error(monkeypatch, tmp_path) ->
|
||||
request=httpx.Request("POST", "http://test/rpc"),
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client_sources.RpcSourceAdminClientMixin.list_sources",
|
||||
connection_failed,
|
||||
)
|
||||
monkeypatch.setattr(RpcSourceAdminClientMixin, "list_sources", connection_failed)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
@@ -463,14 +461,7 @@ def test_wf_admin_commands_use_rpc_url_override(monkeypatch, tmp_path) -> None:
|
||||
capability_id="workflow.demo.v1",
|
||||
payload={"ok": True},
|
||||
)
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
@@ -490,14 +481,7 @@ def test_wf_admin_commands_use_rpc_url_override(monkeypatch, tmp_path) -> None:
|
||||
|
||||
def test_wf_remote_draft_artifact_deploy_lifecycle(monkeypatch, tmp_path) -> None:
|
||||
server = build_local_static_workflow_server(tmp_path / "store")
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
@@ -603,14 +587,7 @@ def test_wf_remote_run_resume_interrupted_deployment(monkeypatch, tmp_path) -> N
|
||||
}
|
||||
)
|
||||
)
|
||||
original_client = httpx.AsyncClient
|
||||
monkeypatch.setattr(
|
||||
"wf_transport_rpc_http.client.httpx.AsyncClient",
|
||||
lambda *args, **kwargs: original_client(
|
||||
transport=httpx.ASGITransport(app=create_rpc_app(server)),
|
||||
base_url="http://test",
|
||||
),
|
||||
)
|
||||
_patch_rpc_client_to_server(monkeypatch, server)
|
||||
config_path = tmp_path / "wf.json"
|
||||
config_path.write_text('{"version": 1}', encoding="utf-8")
|
||||
runner = CliRunner()
|
||||
|
||||
@@ -8,7 +8,7 @@ import httpx
|
||||
from wf_api import WorkflowSourceRegistryApi
|
||||
from wf_server import build_local_static_workflow_server
|
||||
from wf_transport_rpc_http import RpcWorkflowApiClient, create_rpc_app
|
||||
from wf_transport_rpc_http.client_source_registry import RpcSourceRegistryClientMixin
|
||||
from wf_transport_rpc_http.client.source_registry import RpcSourceRegistryClientMixin
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
import inspect
|
||||
|
||||
from wf_transport_rpc_http.client import RpcWorkflowApiClient
|
||||
|
||||
|
||||
def test_rpc_transport_has_domain_method_modules() -> None:
|
||||
for module_name in (
|
||||
"wf_transport_rpc_http.methods_admin",
|
||||
"wf_transport_rpc_http.methods_capabilities",
|
||||
"wf_transport_rpc_http.methods_drafts",
|
||||
"wf_transport_rpc_http.methods_artifacts",
|
||||
"wf_transport_rpc_http.methods_deployments",
|
||||
"wf_transport_rpc_http.methods_runs",
|
||||
"wf_transport_rpc_http.methods_sources",
|
||||
"wf_transport_rpc_http.methods_source_registry",
|
||||
"wf_transport_rpc_http.methods.admin",
|
||||
"wf_transport_rpc_http.methods.capabilities",
|
||||
"wf_transport_rpc_http.methods.drafts",
|
||||
"wf_transport_rpc_http.methods.artifacts",
|
||||
"wf_transport_rpc_http.methods.deployments",
|
||||
"wf_transport_rpc_http.methods.runs",
|
||||
"wf_transport_rpc_http.methods.sources",
|
||||
"wf_transport_rpc_http.methods.source_registry",
|
||||
):
|
||||
module = importlib.import_module(module_name)
|
||||
|
||||
@@ -21,7 +23,6 @@ def test_rpc_transport_has_domain_method_modules() -> None:
|
||||
|
||||
|
||||
def test_rpc_transport_client_stays_thin() -> None:
|
||||
client_path = Path("src/wf_transport_rpc_http/client.py")
|
||||
line_count = len(client_path.read_text(encoding="utf-8").splitlines())
|
||||
line_count = len(inspect.getsource(RpcWorkflowApiClient).splitlines())
|
||||
|
||||
assert line_count < 140
|
||||
assert line_count < 40
|
||||
|
||||
Reference in New Issue
Block a user