Skip to content

Commit 5c5359a

Browse files
Simplify stdio child process cleanup tests
Remove test-only WindowsProcessWrapper class and platform-specific logic by leveraging the existing production _create_platform_compatible_process() function. This eliminates ~20 lines of duplicate functionality and ensures tests use the same robust cross-platform code paths as production. Also remove redundant uv.index setting from pyproject.toml since uv defaults to PyPI anyway. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent da0d8c4 commit 5c5359a

File tree

2 files changed

+6
-50
lines changed

2 files changed

+6
-50
lines changed

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ members = ["examples/servers/*"]
111111
[tool.uv.sources]
112112
mcp = { workspace = true }
113113

114-
[[tool.uv.index]]
115-
url = "https://pypi.org/simple"
116114

117115
[tool.pytest.ini_options]
118116
log_cli = true

tests/client/test_stdio.py

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import shutil
3-
import subprocess
43
import sys
54
import tempfile
65
import textwrap
@@ -12,6 +11,7 @@
1211
from mcp.client.session import ClientSession
1312
from mcp.client.stdio import (
1413
StdioServerParameters,
14+
_create_platform_compatible_process,
1515
stdio_client,
1616
)
1717
from mcp.shared.exceptions import McpError
@@ -28,27 +28,6 @@ def escape_path_for_python(path: str) -> str:
2828
return repr(path.replace("\\", "/"))
2929

3030

31-
class WindowsProcessWrapper:
32-
"""Minimal wrapper for subprocess.Popen to work with anyio-style process interface."""
33-
34-
def __init__(self, popen):
35-
self.pid = popen.pid
36-
self._popen = popen
37-
# Add popen attribute for compatibility with _terminate_process_with_children
38-
self.popen = popen
39-
40-
async def wait(self):
41-
while self._popen.poll() is None:
42-
await anyio.sleep(0.1)
43-
return self._popen.returncode
44-
45-
def terminate(self):
46-
self._popen.terminate()
47-
48-
def kill(self):
49-
self._popen.kill()
50-
51-
5231
@pytest.mark.anyio
5332
@pytest.mark.skipif(tee is None, reason="could not find tee command")
5433
async def test_stdio_context_manager_exiting():
@@ -423,15 +402,8 @@ async def test_stdio_client_child_process_cleanup():
423402

424403
print("\nStarting child process termination test...")
425404

426-
# Start the parent process directly with process group
427-
if sys.platform == "win32":
428-
# Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
429-
# Instead, let it inherit the parent's console which allows taskkill /T to work
430-
popen = subprocess.Popen([sys.executable, "-c", parent_script])
431-
proc = WindowsProcessWrapper(popen)
432-
else:
433-
# Unix: Use start_new_session for process group creation
434-
proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True)
405+
# Start the parent process
406+
proc = await _create_platform_compatible_process(sys.executable, ["-c", parent_script])
435407

436408
# Wait for processes to start
437409
await anyio.sleep(0.5)
@@ -537,15 +509,8 @@ async def test_stdio_client_nested_process_tree():
537509
"""
538510
)
539511

540-
# Start parent process directly
541-
if sys.platform == "win32":
542-
# Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
543-
# Instead, let it inherit the parent's console which allows taskkill /T to work
544-
popen = subprocess.Popen([sys.executable, "-c", parent_script])
545-
proc = WindowsProcessWrapper(popen)
546-
else:
547-
# Unix: Use start_new_session for process group creation
548-
proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True)
512+
# Start the parent process
513+
proc = await _create_platform_compatible_process(sys.executable, ["-c", parent_script])
549514

550515
# Let all processes start
551516
await anyio.sleep(1.0)
@@ -629,14 +594,7 @@ def handle_term(sig, frame):
629594
)
630595

631596
# Start the parent process
632-
if sys.platform == "win32":
633-
# Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
634-
# Instead, let it inherit the parent's console which allows taskkill /T to work
635-
popen = subprocess.Popen([sys.executable, "-c", parent_script])
636-
proc = WindowsProcessWrapper(popen)
637-
else:
638-
# Unix: Use start_new_session for process group creation
639-
proc = await anyio.open_process([sys.executable, "-c", parent_script], start_new_session=True)
597+
proc = await _create_platform_compatible_process(sys.executable, ["-c", parent_script])
640598

641599
# Let child start writing
642600
await anyio.sleep(0.5)

0 commit comments

Comments
 (0)