mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-24 14:34:17 +02:00
270 lines
9.1 KiB
Python
270 lines
9.1 KiB
Python
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import Environment
|
|
|
|
|
|
class TestEnvironmentBuildUVArgs:
|
|
"""Test the Environment.build_uv_args() method."""
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_basic(self, mock_dev_path):
|
|
"""Test building basic uv args."""
|
|
env = Environment()
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = ["run", "--with", "fastmcp", "fastmcp", "run", "server.py"]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_editable(self, mock_dev_path):
|
|
"""Test building uv args with editable package."""
|
|
editable_path = "/path/to/package"
|
|
env = Environment(editable=editable_path)
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--with",
|
|
"fastmcp",
|
|
"--with-editable",
|
|
editable_path,
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_packages(self, mock_dev_path):
|
|
"""Test building uv args with additional packages."""
|
|
env = Environment(dependencies=["pkg1", "pkg2"])
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--with",
|
|
"fastmcp",
|
|
"--with",
|
|
"pkg1",
|
|
"--with",
|
|
"pkg2",
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_python_version(self, mock_dev_path):
|
|
"""Test building uv args with Python version."""
|
|
env = Environment(python="3.11")
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--python",
|
|
"3.11",
|
|
"--with",
|
|
"fastmcp",
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_project(self, mock_dev_path):
|
|
"""Test building uv args with project directory."""
|
|
project_path = "/path/to/project"
|
|
env = Environment(project=project_path)
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--project",
|
|
project_path,
|
|
"--with",
|
|
"fastmcp",
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_requirements(self, mock_dev_path):
|
|
"""Test building uv args with requirements file."""
|
|
req_path = "requirements.txt"
|
|
env = Environment(requirements=req_path)
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--with",
|
|
"fastmcp",
|
|
"--with-requirements",
|
|
req_path,
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_with_all_options(self, mock_dev_path):
|
|
"""Test building uv args with all options."""
|
|
project_path = "/my/project"
|
|
editable_path = "/local/pkg"
|
|
requirements_path = "reqs.txt"
|
|
env = Environment(
|
|
python="3.10",
|
|
project=project_path,
|
|
dependencies=["pandas", "numpy"],
|
|
requirements=requirements_path,
|
|
editable=editable_path,
|
|
)
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--python",
|
|
"3.10",
|
|
"--project",
|
|
project_path,
|
|
"--with",
|
|
"fastmcp",
|
|
"--with",
|
|
"pandas",
|
|
"--with",
|
|
"numpy",
|
|
"--with-requirements",
|
|
requirements_path,
|
|
"--with-editable",
|
|
editable_path,
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_no_command(self, mock_dev_path):
|
|
"""Test building uv args with no command."""
|
|
env = Environment(python="3.11")
|
|
args = env.build_uv_args()
|
|
expected = ["run", "--python", "3.11", "--with", "fastmcp"]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path", return_value=None)
|
|
def test_build_uv_args_string_command(self, mock_dev_path):
|
|
"""Test building uv args with string command."""
|
|
env = Environment()
|
|
args = env.build_uv_args("python")
|
|
expected = ["run", "--with", "fastmcp", "python"]
|
|
assert args == expected
|
|
|
|
def test_needs_uv_true(self):
|
|
"""Test that needs_uv returns True when environment settings are present."""
|
|
env = Environment(python="3.11")
|
|
assert env.needs_uv() is True
|
|
|
|
env = Environment(dependencies=["pkg"])
|
|
assert env.needs_uv() is True
|
|
|
|
env = Environment(requirements="reqs.txt")
|
|
assert env.needs_uv() is True
|
|
|
|
env = Environment(project="/project")
|
|
assert env.needs_uv() is True
|
|
|
|
env = Environment(editable="/pkg")
|
|
assert env.needs_uv() is True
|
|
|
|
def test_needs_uv_false(self):
|
|
"""Test that needs_uv returns False when no environment settings are present."""
|
|
env = Environment()
|
|
assert env.needs_uv() is False
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path")
|
|
def test_build_uv_args_development_mode(self, mock_dev_path):
|
|
"""Test building uv args in development mode (when fastmcp project is found)."""
|
|
# Mock finding the development path
|
|
dev_path = Path("/path/to/fastmcp/dev")
|
|
mock_dev_path.return_value = dev_path
|
|
|
|
env = Environment()
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = [
|
|
"run",
|
|
"--with-editable",
|
|
str(dev_path),
|
|
"fastmcp",
|
|
"run",
|
|
"server.py",
|
|
]
|
|
assert args == expected
|
|
|
|
@patch.object(Environment, "_find_fastmcp_dev_path")
|
|
def test_build_uv_args_production_mode(self, mock_dev_path):
|
|
"""Test building uv args in production mode (when no fastmcp project is found)."""
|
|
# Mock not finding the development path
|
|
mock_dev_path.return_value = None
|
|
|
|
env = Environment()
|
|
args = env.build_uv_args(["fastmcp", "run", "server.py"])
|
|
expected = ["run", "--with", "fastmcp", "fastmcp", "run", "server.py"]
|
|
assert args == expected
|
|
|
|
@patch("pathlib.Path.cwd")
|
|
@patch("pathlib.Path.exists")
|
|
@patch("pathlib.Path.read_text")
|
|
def test_find_fastmcp_dev_path_found(self, mock_read_text, mock_exists, mock_cwd):
|
|
"""Test finding fastmcp development path when pyproject.toml exists."""
|
|
# Set up mock current directory
|
|
mock_cwd_path = Path("/path/to/fastmcp")
|
|
mock_cwd.return_value = mock_cwd_path
|
|
|
|
# Mock pyproject.toml exists and contains fastmcp name
|
|
mock_exists.return_value = True
|
|
mock_read_text.return_value = """[project]
|
|
name = "fastmcp"
|
|
version = "2.0.0"
|
|
"""
|
|
|
|
env = Environment()
|
|
result = env._find_fastmcp_dev_path()
|
|
|
|
assert result == mock_cwd_path
|
|
|
|
@patch("pathlib.Path.cwd")
|
|
@patch("pathlib.Path.exists")
|
|
def test_find_fastmcp_dev_path_not_found(self, mock_exists, mock_cwd):
|
|
"""Test not finding fastmcp development path when no pyproject.toml exists."""
|
|
# Set up mock current directory
|
|
mock_cwd_path = Path("/some/other/directory")
|
|
mock_cwd.return_value = mock_cwd_path
|
|
|
|
# Mock pyproject.toml doesn't exist
|
|
mock_exists.return_value = False
|
|
|
|
env = Environment()
|
|
result = env._find_fastmcp_dev_path()
|
|
|
|
assert result is None
|
|
|
|
@patch("pathlib.Path.cwd")
|
|
@patch("pathlib.Path.exists")
|
|
@patch("pathlib.Path.read_text")
|
|
def test_find_fastmcp_dev_path_wrong_project(
|
|
self, mock_read_text, mock_exists, mock_cwd
|
|
):
|
|
"""Test not finding fastmcp when pyproject.toml exists but is for different project."""
|
|
# Set up mock current directory
|
|
mock_cwd_path = Path("/path/to/other/project")
|
|
mock_cwd.return_value = mock_cwd_path
|
|
|
|
# Mock pyproject.toml exists but is for different project
|
|
mock_exists.return_value = True
|
|
mock_read_text.return_value = """[project]
|
|
name = "other-project"
|
|
version = "1.0.0"
|
|
"""
|
|
|
|
env = Environment()
|
|
result = env._find_fastmcp_dev_path()
|
|
|
|
assert result is None
|