Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
Expand All @@ -33,3 +33,24 @@ jobs:

- name: Run tests
run: uv run pytest -v

windows-smoke:
runs-on: windows-latest

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0

- name: Set up Python 3.13
run: uv python install 3.13

- name: Install dependencies
env:
UV_DEFAULT_INDEX: https://pypi.org/simple
UV_INDEX_URL: https://pypi.org/simple
run: uv sync --all-extras

- name: Run Windows compatibility smoke test
run: uv run pytest tests/test_windows_compat.py -v
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ authors = [
]
license = "Apache-2.0"
dependencies = [
"fastmcp>=2.14.4",
"fastmcp>=2.14.4,<3",
"psutil>=6.1",
]

[project.scripts]
Expand Down
8 changes: 2 additions & 6 deletions task_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import codecs
import json
import os
import resource
import signal
import sqlite3
import sys
Expand All @@ -22,6 +21,7 @@
from datetime import datetime, timezone
from pathlib import Path

import psutil
from fastmcp import FastMCP
from fastmcp.server.dependencies import get_context
from fastmcp.tools.tool import ToolResult
Expand Down Expand Up @@ -318,11 +318,7 @@ def clear_output_files() -> int:

def get_memory_mb() -> float:
"""Get current process memory usage in MB (RSS - resident set size)."""
usage = resource.getrusage(resource.RUSAGE_SELF)
# ru_maxrss is in bytes on Linux, kilobytes on macOS
if os.uname().sysname == "Darwin":
return usage.ru_maxrss / (1024 * 1024) # KB to MB
return usage.ru_maxrss / 1024 # bytes to MB on Linux
return psutil.Process(os.getpid()).memory_info().rss / (1024 * 1024)


# --- Core Queue Logic ---
Expand Down
50 changes: 50 additions & 0 deletions tests/test_windows_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Cross-platform compatibility tests for the Python package."""

import os
import subprocess
import sys
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parents[1]


def test_memory_reporting_does_not_require_posix_resource(tmp_path):
script = """
import builtins

real_import = builtins.__import__

def import_without_resource(name, globals=None, locals=None, fromlist=(), level=0):
if name == "resource" and globals and globals.get("__name__") == "task_queue":
raise ModuleNotFoundError("No module named 'resource'")
return real_import(name, globals, locals, fromlist, level)

builtins.__import__ = import_without_resource

import task_queue

assert task_queue.get_memory_mb() > 0

# Verify byte conversion and current RSS rather than a lifetime peak value.
from types import SimpleNamespace
from unittest.mock import patch

with patch.object(task_queue.psutil, "Process") as process:
process.return_value.memory_info.return_value = SimpleNamespace(rss=3 * 1024 * 1024)
assert task_queue.get_memory_mb() == 3.0
process.assert_called_once_with(task_queue.os.getpid())
"""
env = os.environ.copy()
env["TASK_QUEUE_DATA_DIR"] = str(tmp_path)

result = subprocess.run(
[sys.executable, "-c", script],
cwd=REPO_ROOT,
env=env,
capture_output=True,
text=True,
timeout=30,
)

assert result.returncode == 0, result.stderr