Add pyright strict mode on the whole project (#1254)
This commit is contained in:
parent
ef4e167c1a
commit
c7671e470c
1 changed files with 652 additions and 674 deletions
|
|
@ -11,12 +11,7 @@ from inline_snapshot import Is, snapshot
|
|||
from pydantic import AnyHttpUrl, AnyUrl
|
||||
|
||||
from mcp.client.auth import OAuthClientProvider, PKCEParameters
|
||||
from mcp.shared.auth import (
|
||||
OAuthClientInformationFull,
|
||||
OAuthClientMetadata,
|
||||
OAuthToken,
|
||||
ProtectedResourceMetadata,
|
||||
)
|
||||
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken, ProtectedResourceMetadata
|
||||
|
||||
|
||||
class MockTokenStorage:
|
||||
|
|
@ -66,7 +61,7 @@ def valid_tokens():
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def oauth_provider(client_metadata, mock_storage):
|
||||
def oauth_provider(client_metadata: OAuthClientMetadata, mock_storage: MockTokenStorage):
|
||||
async def redirect_handler(url: str) -> None:
|
||||
"""Mock redirect handler."""
|
||||
pass
|
||||
|
|
@ -115,7 +110,9 @@ class TestOAuthContext:
|
|||
"""Test OAuth context functionality."""
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_oauth_provider_initialization(self, oauth_provider, client_metadata, mock_storage):
|
||||
async def test_oauth_provider_initialization(
|
||||
self, oauth_provider: OAuthClientProvider, client_metadata: OAuthClientMetadata, mock_storage: MockTokenStorage
|
||||
):
|
||||
"""Test OAuthClientProvider basic setup."""
|
||||
assert oauth_provider.context.server_url == "https://api.example.com/v1/mcp"
|
||||
assert oauth_provider.context.client_metadata == client_metadata
|
||||
|
|
@ -123,7 +120,7 @@ class TestOAuthContext:
|
|||
assert oauth_provider.context.timeout == 300.0
|
||||
assert oauth_provider.context is not None
|
||||
|
||||
def test_context_url_parsing(self, oauth_provider):
|
||||
def test_context_url_parsing(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test get_authorization_base_url() extracts base URLs correctly."""
|
||||
context = oauth_provider.context
|
||||
|
||||
|
|
@ -145,7 +142,7 @@ class TestOAuthContext:
|
|||
)
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_token_validity_checking(self, oauth_provider, mock_storage, valid_tokens):
|
||||
async def test_token_validity_checking(self, oauth_provider: OAuthClientProvider, valid_tokens: OAuthToken):
|
||||
"""Test is_token_valid() and can_refresh_token() logic."""
|
||||
context = oauth_provider.context
|
||||
|
||||
|
|
@ -180,7 +177,7 @@ class TestOAuthContext:
|
|||
context.client_info = None
|
||||
assert not context.can_refresh_token()
|
||||
|
||||
def test_clear_tokens(self, oauth_provider, valid_tokens):
|
||||
def test_clear_tokens(self, oauth_provider: OAuthClientProvider, valid_tokens: OAuthToken):
|
||||
"""Test clear_tokens() removes token data."""
|
||||
context = oauth_provider.context
|
||||
context.current_tokens = valid_tokens
|
||||
|
|
@ -198,7 +195,9 @@ class TestOAuthFlow:
|
|||
"""Test OAuth flow methods."""
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_discover_protected_resource_request(self, client_metadata, mock_storage):
|
||||
async def test_discover_protected_resource_request(
|
||||
self, client_metadata: OAuthClientMetadata, mock_storage: MockTokenStorage
|
||||
):
|
||||
"""Test protected resource discovery request building maintains backward compatibility."""
|
||||
|
||||
async def redirect_handler(url: str) -> None:
|
||||
|
|
@ -236,7 +235,7 @@ class TestOAuthFlow:
|
|||
assert "mcp-protocol-version" in request.headers
|
||||
|
||||
@pytest.mark.anyio
|
||||
def test_create_oauth_metadata_request(self, oauth_provider):
|
||||
def test_create_oauth_metadata_request(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test OAuth metadata discovery request building."""
|
||||
request = oauth_provider._create_oauth_metadata_request("https://example.com")
|
||||
|
||||
|
|
@ -250,7 +249,7 @@ class TestOAuthFallback:
|
|||
"""Test OAuth discovery fallback behavior for legacy (act as AS not RS) servers."""
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_oauth_discovery_fallback_order(self, oauth_provider):
|
||||
async def test_oauth_discovery_fallback_order(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test fallback URL construction order."""
|
||||
discovery_urls = oauth_provider._get_discovery_urls()
|
||||
|
||||
|
|
@ -262,7 +261,7 @@ class TestOAuthFallback:
|
|||
]
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_oauth_discovery_fallback_conditions(self, oauth_provider):
|
||||
async def test_oauth_discovery_fallback_conditions(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test the conditions during which an AS metadata discovery fallback will be attempted."""
|
||||
# Ensure no tokens are stored
|
||||
oauth_provider.context.current_tokens = None
|
||||
|
|
@ -365,7 +364,7 @@ class TestOAuthFallback:
|
|||
token_request = await auth_flow.asend(token_response)
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_handle_metadata_response_success(self, oauth_provider):
|
||||
async def test_handle_metadata_response_success(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test successful metadata response handling."""
|
||||
# Create minimal valid OAuth metadata
|
||||
content = b"""{
|
||||
|
|
@ -381,7 +380,7 @@ class TestOAuthFallback:
|
|||
assert str(oauth_provider.context.oauth_metadata.issuer) == "https://auth.example.com/"
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_register_client_request(self, oauth_provider):
|
||||
async def test_register_client_request(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test client registration request building."""
|
||||
request = await oauth_provider._register_client()
|
||||
|
||||
|
|
@ -391,7 +390,7 @@ class TestOAuthFallback:
|
|||
assert request.headers["Content-Type"] == "application/json"
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_register_client_skip_if_registered(self, oauth_provider, mock_storage):
|
||||
async def test_register_client_skip_if_registered(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test client registration is skipped if already registered."""
|
||||
# Set existing client info
|
||||
client_info = OAuthClientInformationFull(
|
||||
|
|
@ -405,7 +404,7 @@ class TestOAuthFallback:
|
|||
assert request is None
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_token_exchange_request(self, oauth_provider):
|
||||
async def test_token_exchange_request(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test token exchange request building."""
|
||||
# Set up required context
|
||||
oauth_provider.context.client_info = OAuthClientInformationFull(
|
||||
|
|
@ -429,7 +428,7 @@ class TestOAuthFallback:
|
|||
assert "client_secret=test_secret" in content
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_refresh_token_request(self, oauth_provider, valid_tokens):
|
||||
async def test_refresh_token_request(self, oauth_provider: OAuthClientProvider, valid_tokens: OAuthToken):
|
||||
"""Test refresh token request building."""
|
||||
# Set up required context
|
||||
oauth_provider.context.current_tokens = valid_tokens
|
||||
|
|
@ -538,11 +537,11 @@ class TestRegistrationResponse:
|
|||
"""Test client registration response handling."""
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_handle_registration_response_reads_before_accessing_text(self, oauth_provider):
|
||||
async def test_handle_registration_response_reads_before_accessing_text(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test that response.aread() is called before accessing response.text."""
|
||||
|
||||
# Track if aread() was called
|
||||
class MockResponse:
|
||||
class MockResponse(httpx.Response):
|
||||
def __init__(self):
|
||||
self.status_code = 400
|
||||
self._aread_called = False
|
||||
|
|
@ -574,7 +573,9 @@ class TestAuthFlow:
|
|||
"""Test the auth flow in httpx."""
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_auth_flow_with_valid_tokens(self, oauth_provider, mock_storage, valid_tokens):
|
||||
async def test_auth_flow_with_valid_tokens(
|
||||
self, oauth_provider: OAuthClientProvider, mock_storage: MockTokenStorage, valid_tokens: OAuthToken
|
||||
):
|
||||
"""Test auth flow when tokens are already valid."""
|
||||
# Pre-store valid tokens
|
||||
await mock_storage.set_tokens(valid_tokens)
|
||||
|
|
@ -600,7 +601,7 @@ class TestAuthFlow:
|
|||
pass # Expected
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_auth_flow_with_no_tokens(self, oauth_provider, mock_storage):
|
||||
async def test_auth_flow_with_no_tokens(self, oauth_provider: OAuthClientProvider):
|
||||
"""Test auth flow when no tokens are available, triggering the full OAuth flow."""
|
||||
# Ensure no tokens are stored
|
||||
oauth_provider.context.current_tokens = None
|
||||
|
|
@ -810,7 +811,11 @@ class TestProtectedResourceWWWAuthenticate:
|
|||
],
|
||||
)
|
||||
def test_extract_resource_metadata_from_www_auth_valid_cases(
|
||||
self, client_metadata, mock_storage, www_auth_header, expected_url
|
||||
self,
|
||||
client_metadata: OAuthClientMetadata,
|
||||
mock_storage: MockTokenStorage,
|
||||
www_auth_header: str,
|
||||
expected_url: str,
|
||||
):
|
||||
"""Test extraction of resource_metadata URL from various valid WWW-Authenticate headers."""
|
||||
|
||||
|
|
@ -862,7 +867,12 @@ class TestProtectedResourceWWWAuthenticate:
|
|||
],
|
||||
)
|
||||
def test_extract_resource_metadata_from_www_auth_invalid_cases(
|
||||
self, client_metadata, mock_storage, status_code, www_auth_header, description
|
||||
self,
|
||||
client_metadata: OAuthClientMetadata,
|
||||
mock_storage: MockTokenStorage,
|
||||
status_code: int,
|
||||
www_auth_header: str | None,
|
||||
description: str,
|
||||
):
|
||||
"""Test extraction returns None for invalid cases."""
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue