mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Address maintainer review: reload support, type annotation, test imports
This commit is contained in:
parent
52144ce20b
commit
9d635bc026
3 changed files with 40 additions and 40 deletions
|
|
@ -481,8 +481,6 @@ async def run(
|
|||
ignored_options.append("--port")
|
||||
if path:
|
||||
ignored_options.append("--path")
|
||||
if reload:
|
||||
ignored_options.append("--reload")
|
||||
if ignored_options:
|
||||
logger.warning(
|
||||
f"Options {', '.join(ignored_options)} are ignored in module mode "
|
||||
|
|
@ -506,6 +504,25 @@ async def run(
|
|||
if env.build_command(test_cmd) != test_cmd:
|
||||
env_builder = env.build_command
|
||||
|
||||
if reload:
|
||||
# Build a fastmcp run command for the reload watcher to restart
|
||||
reload_cmd = ["fastmcp", "run", server_spec, "--module", "--no-reload"]
|
||||
if log_level:
|
||||
reload_cmd.extend(["--log-level", log_level])
|
||||
if no_banner:
|
||||
reload_cmd.append("--no-banner")
|
||||
if env_builder is not None:
|
||||
reload_cmd.append("--skip-env")
|
||||
if server_args:
|
||||
reload_cmd.append("--")
|
||||
reload_cmd.extend(server_args)
|
||||
if env_builder is not None:
|
||||
reload_cmd = env_builder(reload_cmd)
|
||||
await run_module.run_with_reload(
|
||||
reload_cmd, reload_dirs=reload_dir, is_stdio=True
|
||||
)
|
||||
return
|
||||
|
||||
run_module.run_module_command(
|
||||
server_spec,
|
||||
env_command_builder=env_builder,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import re
|
|||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
|
|
@ -259,7 +260,7 @@ async def run_command(
|
|||
def run_module_command(
|
||||
module_name: str,
|
||||
*,
|
||||
env_command_builder: Any | None = None,
|
||||
env_command_builder: Callable[[list[str]], list[str]] | None = None,
|
||||
extra_args: list[str] | None = None,
|
||||
) -> None:
|
||||
"""Run a Python module directly using ``python -m <module>``.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
import inspect
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from fastmcp.cli.cli import inspector, run
|
||||
from fastmcp.cli.run import (
|
||||
create_mcp_config_server,
|
||||
is_url,
|
||||
run_module_command,
|
||||
)
|
||||
from fastmcp.client.client import Client
|
||||
from fastmcp.client.transports import FastMCPTransport
|
||||
|
|
@ -702,10 +707,6 @@ class TestRunModuleCommand:
|
|||
|
||||
def test_runs_python_m_module(self):
|
||||
"""Test that run_module_command invokes python -m <module>."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.run import run_module_command
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -725,10 +726,6 @@ class TestRunModuleCommand:
|
|||
|
||||
def test_forwards_extra_args(self):
|
||||
"""Test that extra arguments are forwarded after the module name."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.run import run_module_command
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -746,10 +743,6 @@ class TestRunModuleCommand:
|
|||
|
||||
def test_uses_env_command_builder(self):
|
||||
"""Test that env_command_builder wraps the command."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.run import run_module_command
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -774,11 +767,6 @@ class TestRunModuleCommand:
|
|||
|
||||
def test_exits_with_subprocess_error_code(self):
|
||||
"""Test that non-zero exit codes from the module are propagated."""
|
||||
import subprocess
|
||||
from unittest.mock import patch
|
||||
|
||||
from fastmcp.cli.run import run_module_command
|
||||
|
||||
with (
|
||||
patch(
|
||||
"fastmcp.cli.run.subprocess.run",
|
||||
|
|
@ -792,11 +780,6 @@ class TestRunModuleCommand:
|
|||
|
||||
def test_no_env_builder_runs_plain_python(self):
|
||||
"""Test that without env_command_builder, plain python is used."""
|
||||
import sys
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.run import run_module_command
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -819,8 +802,6 @@ class TestRunModuleMode:
|
|||
|
||||
async def test_run_module_mode_requires_server_spec(self):
|
||||
"""Test that module mode exits with error when server_spec is None."""
|
||||
from fastmcp.cli.cli import run
|
||||
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
await run(None, module=True)
|
||||
|
||||
|
|
@ -828,10 +809,6 @@ class TestRunModuleMode:
|
|||
|
||||
async def test_run_module_mode_warns_ignored_options(self, caplog):
|
||||
"""Test that ignored options produce a warning in module mode."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.cli import run
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -846,17 +823,12 @@ class TestRunModuleMode:
|
|||
transport="sse",
|
||||
host="0.0.0.0",
|
||||
port=8080,
|
||||
reload=True,
|
||||
)
|
||||
|
||||
assert any("ignored in module mode" in r.message for r in caplog.records)
|
||||
|
||||
async def test_run_module_mode_delegates_to_run_module_command(self):
|
||||
"""Test that module mode calls run_module_command with correct args."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastmcp.cli.cli import run
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.returncode = 0
|
||||
|
||||
|
|
@ -872,16 +844,26 @@ class TestRunModuleMode:
|
|||
assert "-m" in cmd
|
||||
assert "my_module" in cmd
|
||||
|
||||
async def test_run_module_mode_with_reload(self):
|
||||
"""Test that --reload in module mode delegates to run_with_reload."""
|
||||
with patch(
|
||||
"fastmcp.cli.run.run_with_reload", new_callable=AsyncMock
|
||||
) as mock_reload:
|
||||
await run("my_module", module=True, reload=True, skip_env=True)
|
||||
|
||||
mock_reload.assert_called_once()
|
||||
cmd = mock_reload.call_args[0][0]
|
||||
assert "fastmcp" in cmd
|
||||
assert "--module" in cmd
|
||||
assert "--no-reload" in cmd
|
||||
assert "my_module" in cmd
|
||||
|
||||
|
||||
class TestInspectorModuleMode:
|
||||
"""Test the inspector command's module-mode handling."""
|
||||
|
||||
async def test_inspector_module_mode_skips_load_server(self):
|
||||
"""Test that inspector with module=True skips load_server() and forwards --module."""
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from fastmcp.cli.cli import inspector
|
||||
|
||||
mock_config = MagicMock()
|
||||
mock_config.deployment.port = 8080
|
||||
mock_config.environment.build_command = lambda cmd: cmd
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue