mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-15 18:19:10 +02:00
When GitHub's API rate limits cause asyncio shutdown issues, the test times out rather than failing with the underlying 429 error. Updated the detection logic to check for 429 indicators in the captured output when a timeout occurs. Also increased the per-test timeout from 15s to 30s to give remote API calls more breathing room. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
import os
|
|
|
|
import pytest
|
|
|
|
|
|
def _is_rate_limit_error(excinfo, report=None) -> bool:
|
|
"""Check if an exception indicates a rate limit error from GitHub API.
|
|
|
|
Args:
|
|
excinfo: The exception info from pytest
|
|
report: Optional test report for additional context (captured output, longrepr)
|
|
"""
|
|
if excinfo is None:
|
|
return False
|
|
|
|
exc = excinfo.value
|
|
exc_type = excinfo.typename
|
|
exc_str = str(exc).lower()
|
|
|
|
# BrokenResourceError typically indicates connection closed due to rate limit
|
|
if exc_type == "BrokenResourceError":
|
|
return True
|
|
|
|
# httpx.HTTPStatusError with 429 status
|
|
if exc_type == "HTTPStatusError":
|
|
try:
|
|
if hasattr(exc, "response") and exc.response.status_code == 429:
|
|
return True
|
|
except Exception:
|
|
pass
|
|
|
|
# Check for rate limit indicators in exception message
|
|
if "429" in exc_str or "rate limit" in exc_str or "too many requests" in exc_str:
|
|
return True
|
|
|
|
# Timeout exceptions may indicate rate limiting when the 429 causes asyncio
|
|
# shutdown issues. Check if it's a timeout and look for 429 in the captured output.
|
|
if "timeout" in exc_type.lower() or "timeout" in exc_str:
|
|
# Check captured output for 429 indicators
|
|
if report is not None:
|
|
longrepr_str = str(report.longrepr).lower() if report.longrepr else ""
|
|
if "429" in longrepr_str or "too many requests" in longrepr_str:
|
|
return True
|
|
|
|
# Check captured stdout/stderr
|
|
for section_name, content in getattr(report, "sections", []):
|
|
if "429" in content or "too many requests" in content.lower():
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
@pytest.hookimpl(hookwrapper=True)
|
|
def pytest_runtest_makereport(item, call):
|
|
"""Convert rate limit failures to skips for GitHub integration tests."""
|
|
outcome = yield
|
|
report = outcome.get_result()
|
|
|
|
# Only process actual failures during the call phase, not xfails
|
|
if (
|
|
report.when == "call"
|
|
and report.failed
|
|
and not hasattr(report, "wasxfail")
|
|
and item.module.__name__ == "tests.integration_tests.test_github_mcp_remote"
|
|
and _is_rate_limit_error(call.excinfo, report)
|
|
):
|
|
report.outcome = "skipped"
|
|
report.longrepr = (
|
|
os.path.abspath(__file__),
|
|
None,
|
|
"Skipped: Skipping due to GitHub API rate limit (429)",
|
|
)
|