refactor: move inline imports to module level (#1893)
This commit is contained in:
parent
c06362126b
commit
5d80f4efc8
7 changed files with 58 additions and 122 deletions
|
|
@ -2,6 +2,9 @@
|
|||
Tests for OAuth error handling in the auth handlers.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import secrets
|
||||
import unittest.mock
|
||||
from typing import Any
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
|
@ -14,6 +17,7 @@ from starlette.applications import Starlette
|
|||
|
||||
from mcp.server.auth.provider import AuthorizeError, RegistrationError, TokenError
|
||||
from mcp.server.auth.routes import create_auth_routes
|
||||
from mcp.server.auth.settings import ClientRegistrationOptions, RevocationOptions
|
||||
from tests.server.fastmcp.auth.test_auth_integration import MockOAuthProvider
|
||||
|
||||
|
||||
|
|
@ -25,8 +29,6 @@ def oauth_provider():
|
|||
|
||||
@pytest.fixture
|
||||
def app(oauth_provider: MockOAuthProvider):
|
||||
from mcp.server.auth.settings import ClientRegistrationOptions, RevocationOptions
|
||||
|
||||
# Enable client registration
|
||||
client_registration_options = ClientRegistrationOptions(enabled=True)
|
||||
revocation_options = RevocationOptions(enabled=True)
|
||||
|
|
@ -53,10 +55,6 @@ def client(app: Starlette):
|
|||
@pytest.fixture
|
||||
def pkce_challenge():
|
||||
"""Create a PKCE challenge with code_verifier and code_challenge."""
|
||||
import base64
|
||||
import hashlib
|
||||
import secrets
|
||||
|
||||
# Generate a code verifier
|
||||
code_verifier = secrets.token_urlsafe(64)[:128]
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
Integration tests for MCP Oauth Protected Resource.
|
||||
"""
|
||||
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from inline_snapshot import snapshot
|
||||
|
|
@ -159,8 +161,6 @@ class TestRouteConsistency:
|
|||
)
|
||||
|
||||
# Extract path from metadata URL
|
||||
from urllib.parse import urlparse
|
||||
|
||||
metadata_path = urlparse(str(metadata_url)).path
|
||||
|
||||
# Verify consistency
|
||||
|
|
@ -181,8 +181,6 @@ class TestRouteConsistency:
|
|||
|
||||
# Test URL generation
|
||||
metadata_url = build_resource_metadata_url(resource_url_obj)
|
||||
from urllib.parse import urlparse
|
||||
|
||||
url_path = urlparse(str(metadata_url)).path
|
||||
|
||||
# Test route creation
|
||||
|
|
|
|||
|
|
@ -1258,8 +1258,6 @@ class TestAuthEndpoints:
|
|||
)
|
||||
|
||||
# Send base64 without colon (invalid format)
|
||||
import base64
|
||||
|
||||
invalid_creds = base64.b64encode(b"no-colon-here").decode()
|
||||
response = await test_client.post(
|
||||
"/token",
|
||||
|
|
@ -1306,8 +1304,6 @@ class TestAuthEndpoints:
|
|||
)
|
||||
|
||||
# Send different client_id in Basic auth header
|
||||
import base64
|
||||
|
||||
wrong_creds = base64.b64encode(f"wrong-client-id:{client_info['client_secret']}".encode()).decode()
|
||||
response = await test_client.post(
|
||||
"/token",
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
# pyright: reportUnknownLambdaType=false
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Annotated, Any, Final, TypedDict
|
||||
from typing import Annotated, Any, Final, NamedTuple, TypedDict
|
||||
|
||||
import annotated_types
|
||||
import pytest
|
||||
from dirty_equals import IsPartialDict
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
from mcp.server.fastmcp.utilities.func_metadata import func_metadata
|
||||
from mcp.types import CallToolResult
|
||||
|
||||
|
|
@ -558,7 +559,6 @@ async def test_str_annotation_runtime_validation():
|
|||
|
||||
def test_structured_output_requires_return_annotation():
|
||||
"""Test that structured_output=True requires a return annotation"""
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
def func_no_annotation(): # pragma: no cover
|
||||
return "hello"
|
||||
|
|
@ -881,8 +881,6 @@ def test_tool_call_result_annotated_is_structured_and_invalid():
|
|||
def test_tool_call_result_in_optional_is_rejected():
|
||||
"""Test that Optional[CallToolResult] raises InvalidSignature"""
|
||||
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
def func_optional_call_tool_result() -> CallToolResult | None: # pragma: no cover
|
||||
return CallToolResult(content=[])
|
||||
|
||||
|
|
@ -896,8 +894,6 @@ def test_tool_call_result_in_optional_is_rejected():
|
|||
def test_tool_call_result_in_union_is_rejected():
|
||||
"""Test that Union[str, CallToolResult] raises InvalidSignature"""
|
||||
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
def func_union_call_tool_result() -> str | CallToolResult: # pragma: no cover
|
||||
return CallToolResult(content=[])
|
||||
|
||||
|
|
@ -910,7 +906,6 @@ def test_tool_call_result_in_union_is_rejected():
|
|||
|
||||
def test_tool_call_result_in_pipe_union_is_rejected():
|
||||
"""Test that str | CallToolResult raises InvalidSignature"""
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
def func_pipe_union_call_tool_result() -> str | CallToolResult: # pragma: no cover
|
||||
return CallToolResult(content=[])
|
||||
|
|
@ -985,9 +980,6 @@ def test_structured_output_nested_models():
|
|||
|
||||
def test_structured_output_unserializable_type_error():
|
||||
"""Test error when structured_output=True is used with unserializable types"""
|
||||
from typing import NamedTuple
|
||||
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
# Test with a class that has non-serializable default values
|
||||
class ConfigWithCallable:
|
||||
|
|
@ -1185,8 +1177,6 @@ def test_basemodel_reserved_names_with_json_preparsing():
|
|||
|
||||
|
||||
def test_disallowed_type_qualifier():
|
||||
from mcp.server.fastmcp.exceptions import InvalidSignature
|
||||
|
||||
def func_disallowed_qualifier() -> Final[int]: # type: ignore
|
||||
pass # pragma: no cover
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ from mcp.types import (
|
|||
NotificationParams,
|
||||
ProgressNotification,
|
||||
ProgressNotificationParams,
|
||||
PromptReference,
|
||||
ReadResourceResult,
|
||||
ResourceListChangedNotification,
|
||||
ResourceTemplateReference,
|
||||
ServerNotification,
|
||||
ServerRequest,
|
||||
TextContent,
|
||||
|
|
@ -583,8 +585,6 @@ async def test_completion(server_transport: str, server_url: str) -> None:
|
|||
assert result.capabilities.prompts is not None
|
||||
|
||||
# Test resource completion
|
||||
from mcp.types import ResourceTemplateReference
|
||||
|
||||
completion_result = await session.complete(
|
||||
ref=ResourceTemplateReference(type="ref/resource", uri="github://repos/{owner}/{repo}"),
|
||||
argument={"name": "repo", "value": ""},
|
||||
|
|
@ -600,8 +600,6 @@ async def test_completion(server_transport: str, server_url: str) -> None:
|
|||
assert "specification" in completion_result.completion.values
|
||||
|
||||
# Test prompt completion
|
||||
from mcp.types import PromptReference
|
||||
|
||||
completion_result = await session.complete(
|
||||
ref=PromptReference(type="ref/prompt", name="review_code"),
|
||||
argument={"name": "language", "value": "py"},
|
||||
|
|
@ -644,8 +642,6 @@ async def test_fastmcp_quickstart(server_transport: str, server_url: str) -> Non
|
|||
assert tool_result.content[0].text == "30"
|
||||
|
||||
# Test greeting resource directly
|
||||
from pydantic import AnyUrl
|
||||
|
||||
resource_result = await session.read_resource(AnyUrl("greeting://Alice"))
|
||||
assert len(resource_result.contents) == 1
|
||||
assert isinstance(resource_result.contents[0], TextResourceContents)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ from unittest.mock import patch
|
|||
|
||||
import pytest
|
||||
from pydantic import BaseModel
|
||||
from starlette.applications import Starlette
|
||||
from starlette.routing import Mount, Route
|
||||
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
from mcp.server.fastmcp.exceptions import ToolError
|
||||
from mcp.server.fastmcp.prompts.base import Message, UserMessage
|
||||
from mcp.server.fastmcp.resources import FileResource, FunctionResource
|
||||
from mcp.server.fastmcp.utilities.types import Audio, Image
|
||||
|
|
@ -51,8 +53,6 @@ class TestServer:
|
|||
@pytest.mark.anyio
|
||||
async def test_sse_app_returns_starlette_app(self):
|
||||
"""Test that sse_app returns a Starlette application with correct routes."""
|
||||
from starlette.applications import Starlette
|
||||
|
||||
mcp = FastMCP("test", host="0.0.0.0") # Use 0.0.0.0 to avoid auto DNS protection
|
||||
app = mcp.sse_app()
|
||||
|
||||
|
|
@ -617,8 +617,6 @@ class TestServerTools:
|
|||
@pytest.mark.anyio
|
||||
async def test_remove_nonexistent_tool(self):
|
||||
"""Test that removing a non-existent tool raises ToolError."""
|
||||
from mcp.server.fastmcp.exceptions import ToolError
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
with pytest.raises(ToolError, match="Unknown tool: nonexistent"):
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
import anyio
|
||||
import pytest
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from mcp import types
|
||||
from mcp.client.session import ClientSession
|
||||
from mcp.server.elicitation import CancelledElicitation, DeclinedElicitation
|
||||
from mcp.server.elicitation import CancelledElicitation, DeclinedElicitation, elicit_url
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
from mcp.server.session import ServerSession
|
||||
from mcp.shared.context import RequestContext
|
||||
|
|
@ -110,8 +111,6 @@ async def test_url_elicitation_cancel():
|
|||
@pytest.mark.anyio
|
||||
async def test_url_elicitation_helper_function():
|
||||
"""Test the elicit_url helper function."""
|
||||
from mcp.server.elicitation import elicit_url
|
||||
|
||||
mcp = FastMCP(name="URLElicitationHelperServer")
|
||||
|
||||
@mcp.tool(description="Tool using elicit_url helper")
|
||||
|
|
@ -180,8 +179,6 @@ async def test_url_no_content_in_response():
|
|||
@pytest.mark.anyio
|
||||
async def test_form_mode_still_works():
|
||||
"""Ensure form mode elicitation still works after SEP 1036."""
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
mcp = FastMCP(name="FormModeBackwardCompatServer")
|
||||
|
||||
class NameSchema(BaseModel):
|
||||
|
|
@ -267,8 +264,6 @@ async def test_url_elicitation_required_error_code():
|
|||
@pytest.mark.anyio
|
||||
async def test_elicit_url_typed_results():
|
||||
"""Test that elicit_url returns properly typed result objects."""
|
||||
from mcp.server.elicitation import elicit_url
|
||||
|
||||
mcp = FastMCP(name="TypedResultsServer")
|
||||
|
||||
@mcp.tool(description="Test declined result")
|
||||
|
|
@ -329,8 +324,6 @@ async def test_elicit_url_typed_results():
|
|||
@pytest.mark.anyio
|
||||
async def test_deprecated_elicit_method():
|
||||
"""Test the deprecated elicit() method for backward compatibility."""
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
mcp = FastMCP(name="DeprecatedElicitServer")
|
||||
|
||||
class EmailSchema(BaseModel):
|
||||
|
|
|
|||
Loading…
Reference in a new issue