Skip to main content
Glama
hileamlakB

PRIMS – Python Runtime Interpreter MCP Server

test_sandbox_env.py7.68 kB
"""Unit tests for server.sandbox.env module.""" import sys from pathlib import Path from unittest.mock import AsyncMock, Mock, patch import pytest from server.sandbox.env import _DEFAULT_PACKAGES, create_virtualenv class TestCreateVirtualenv: """Test virtual environment creation.""" @pytest.mark.asyncio async def test_create_virtualenv_success(self, temp_dir: Path) -> None: """Test successful virtual environment creation.""" requirements = ["numpy", "pandas"] with ( patch("server.sandbox.env.venv") as mock_venv, patch( "server.sandbox.env.asyncio.create_subprocess_exec" ) as mock_subprocess, ): # Mock venv creation mock_builder = Mock() mock_venv.EnvBuilder.return_value = mock_builder # Mock subprocess for pip install mock_process = AsyncMock() mock_process.communicate = AsyncMock(return_value=(b"", b"")) mock_process.returncode = 0 mock_subprocess.return_value = mock_process # Call function python_path = await create_virtualenv(requirements, temp_dir) # Verify venv creation mock_venv.EnvBuilder.assert_called_once_with(with_pip=True, clear=True) mock_builder.create.assert_called_once() # Verify pip install call mock_subprocess.assert_called_once() args = mock_subprocess.call_args[0] # Check that python executable path is correct expected_python = ( temp_dir / "venv" / ("Scripts" if sys.platform.startswith("win") else "bin") / "python" ) assert Path(args[0]) == expected_python assert args[1:4] == ("-m", "pip", "install") assert "--no-cache-dir" in args # Check that requirements include both custom and default packages install_args = args[4:] # Skip python, -m, pip, install install_args = [arg for arg in install_args if arg != "--no-cache-dir"] expected_packages = list(dict.fromkeys(requirements + _DEFAULT_PACKAGES)) for package in expected_packages: assert package in install_args # Check return value assert python_path == expected_python @pytest.mark.asyncio async def test_create_virtualenv_pip_failure(self, temp_dir: Path) -> None: """Test virtual environment creation with pip install failure.""" requirements = ["invalid-package"] with ( patch("server.sandbox.env.venv") as mock_venv, patch( "server.sandbox.env.asyncio.create_subprocess_exec" ) as mock_subprocess, ): # Mock venv creation mock_builder = Mock() mock_venv.EnvBuilder.return_value = mock_builder # Mock subprocess for pip install failure mock_process = AsyncMock() mock_process.communicate = AsyncMock( return_value=(b"", b"ERROR: Could not find package") ) mock_process.returncode = 1 mock_subprocess.return_value = mock_process # Should raise RuntimeError with pytest.raises(RuntimeError, match="pip install failed"): _ = await create_virtualenv(requirements, temp_dir) @pytest.mark.asyncio async def test_create_virtualenv_no_requirements(self, temp_dir: Path) -> None: """Test virtual environment creation with no additional requirements.""" requirements: list[str] = [] with ( patch("server.sandbox.env.venv") as mock_venv, patch( "server.sandbox.env.asyncio.create_subprocess_exec" ) as mock_subprocess, ): # Mock venv creation mock_builder = Mock() mock_venv.EnvBuilder.return_value = mock_builder # Mock subprocess for pip install mock_process = AsyncMock() mock_process.communicate = AsyncMock(return_value=(b"", b"")) mock_process.returncode = 0 mock_subprocess.return_value = mock_process # Call function _ = await create_virtualenv(requirements, temp_dir) # Should still install default packages mock_subprocess.assert_called_once() args = mock_subprocess.call_args[0] install_args = args[4:] # Skip python, -m, pip, install install_args = [arg for arg in install_args if arg != "--no-cache-dir"] for package in _DEFAULT_PACKAGES: assert package in install_args @pytest.mark.asyncio async def test_create_virtualenv_duplicate_requirements( self, temp_dir: Path ) -> None: """Test that duplicate requirements are deduplicated.""" requirements = [ "pandas", "numpy", "pandas", ] # pandas is duplicated and also in defaults with ( patch("server.sandbox.env.venv") as mock_venv, patch( "server.sandbox.env.asyncio.create_subprocess_exec" ) as mock_subprocess, ): # Mock venv creation mock_builder = Mock() mock_venv.EnvBuilder.return_value = mock_builder # Mock subprocess for pip install mock_process = AsyncMock() mock_process.communicate = AsyncMock(return_value=(b"", b"")) mock_process.returncode = 0 mock_subprocess.return_value = mock_process # Call function _ = await create_virtualenv(requirements, temp_dir) # Check that duplicates are removed args = mock_subprocess.call_args[0] install_args = args[4:] # Skip python, -m, pip, install install_args = [arg for arg in install_args if arg != "--no-cache-dir"] # pandas should appear only once pandas_count = install_args.count("pandas") assert pandas_count == 1 def test_default_packages_constant(self) -> None: """Test that default packages are properly defined.""" assert isinstance(_DEFAULT_PACKAGES, list) assert len(_DEFAULT_PACKAGES) > 0 assert "pandas" in _DEFAULT_PACKAGES assert "openpyxl" in _DEFAULT_PACKAGES assert "requests" in _DEFAULT_PACKAGES @pytest.mark.asyncio async def test_create_virtualenv_windows_path(self, temp_dir: Path) -> None: """Test that Windows-style paths are handled correctly.""" requirements = ["numpy"] with ( patch("server.sandbox.env.venv") as mock_venv, patch( "server.sandbox.env.asyncio.create_subprocess_exec" ) as mock_subprocess, patch("server.sandbox.env.sys.platform", "win32"), ): # Mock venv creation mock_builder = Mock() mock_venv.EnvBuilder.return_value = mock_builder # Mock subprocess for pip install mock_process = AsyncMock() mock_process.communicate = AsyncMock(return_value=(b"", b"")) mock_process.returncode = 0 mock_subprocess.return_value = mock_process # Call function python_path = await create_virtualenv(requirements, temp_dir) # Check that Windows path is used expected_python = temp_dir / "venv" / "Scripts" / "python" assert python_path == expected_python

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hileamlakB/Python-Runtime-Interpreter-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server