Skip to content

Commit 870a97d

Browse files
RahulHeredIvYaNshhh
authored andcommitted
Apply code quality fixes and Python 3.10+ compatibility (#4)
Run black, ruff, and fix linting issues across all example server code and tests. Code formatting: - Apply black formatting to all Python files - Fix import sorting with ruff isort Linting fixes: - Remove unused imports - Fix unused variable assignments - Update imports to use collections.abc.Callable Configuration updates: - Update pyproject.toml ruff config to use lint section - Fix deprecated ruff configuration format Python 3.10+ compatibility: - Add `from __future__ import annotations` for union type hints - Required for `X | Y` syntax on Python versions < 3.10
1 parent c9ea80b commit 870a97d

14 files changed

Lines changed: 98 additions & 75 deletions

File tree

examples/auth/py_auth_mcp_server/app.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
Creates and configures the Flask application for the Auth MCP Server.
44
"""
55

6+
from __future__ import annotations
7+
68
from pathlib import Path
7-
from typing import Any
89

910
from flask import Flask
1011
from flask_cors import CORS
@@ -79,7 +80,9 @@ def create_app(
7980
if config.jwks_auto_refresh:
8081
auth_client.set_option("auto_refresh", "true")
8182
if config.request_timeout > 0:
82-
auth_client.set_option("request_timeout", str(config.request_timeout))
83+
auth_client.set_option(
84+
"request_timeout", str(config.request_timeout)
85+
)
8386

8487
app.config["AUTH_CLIENT"] = auth_client
8588
except Exception as e:

examples/auth/py_auth_mcp_server/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
/gopher-orch/examples/auth/auth_server_config.h
55
"""
66

7-
from dataclasses import dataclass, field
7+
from __future__ import annotations
8+
9+
from dataclasses import dataclass
810
from pathlib import Path
911
from typing import Any
1012

@@ -157,9 +159,7 @@ def build_config(config_map: dict[str, str]) -> AuthServerConfig:
157159
# Derive endpoints from auth_server_url if not explicitly set
158160
if config.auth_server_url:
159161
if not config.jwks_uri:
160-
config.jwks_uri = (
161-
f"{config.auth_server_url}/protocol/openid-connect/certs"
162-
)
162+
config.jwks_uri = f"{config.auth_server_url}/protocol/openid-connect/certs"
163163
if not config.token_endpoint:
164164
config.token_endpoint = (
165165
f"{config.auth_server_url}/protocol/openid-connect/token"

examples/auth/py_auth_mcp_server/middleware/oauth_auth.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
Mirrors OAuthAuthFilter from the C++ example.
55
"""
66

7+
from __future__ import annotations
8+
9+
from collections.abc import Callable
710
from functools import wraps
8-
from typing import Any, Callable
11+
from typing import Any
912

1013
from flask import Response, g, jsonify, request
1114

examples/auth/py_auth_mcp_server/routes/health.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
and load balancer health checks.
55
"""
66

7+
from __future__ import annotations
8+
79
import time
810
from dataclasses import dataclass
911
from datetime import datetime, timezone

examples/auth/py_auth_mcp_server/routes/mcp_handler.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
for tool registration and invocation.
55
"""
66

7+
from __future__ import annotations
8+
9+
from collections.abc import Callable
710
from dataclasses import dataclass, field
8-
from typing import Any, Callable, TypedDict
11+
from typing import Any, TypedDict
912

10-
from flask import Blueprint, Flask, Response, g, jsonify, request
13+
from flask import Blueprint, Flask, Response, jsonify, request
1114

1215

1316
class JsonRpcErrorCode:
@@ -238,16 +241,12 @@ def handle_request(self, body: Any) -> JsonRpcResponse:
238241
request_id = rpc_request.id
239242

240243
try:
241-
result = self._dispatch_method(
242-
rpc_request.method, rpc_request.params or {}
243-
)
244+
result = self._dispatch_method(rpc_request.method, rpc_request.params or {})
244245
return JsonRpcResponse(jsonrpc="2.0", id=request_id, result=result)
245246
except JsonRpcError as e:
246247
return JsonRpcResponse(jsonrpc="2.0", id=request_id, error=e)
247248
except Exception as e:
248-
error = JsonRpcError(
249-
code=JsonRpcErrorCode.INTERNAL_ERROR, message=str(e)
250-
)
249+
error = JsonRpcError(code=JsonRpcErrorCode.INTERNAL_ERROR, message=str(e))
251250
return JsonRpcResponse(jsonrpc="2.0", id=request_id, error=error)
252251

253252
def _parse_request(self, body: Any) -> JsonRpcRequest | JsonRpcError:
@@ -285,9 +284,7 @@ def _parse_request(self, body: Any) -> JsonRpcRequest | JsonRpcError:
285284
params=params,
286285
)
287286

288-
def _dispatch_method(
289-
self, method: str, params: dict[str, Any]
290-
) -> Any:
287+
def _dispatch_method(self, method: str, params: dict[str, Any]) -> Any:
291288
"""Dispatch a method call to the appropriate handler."""
292289
if method == "initialize":
293290
return self._handle_initialize(params)

examples/auth/py_auth_mcp_server/routes/oauth_endpoints.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
- /oauth/register (RFC 7591 dynamic registration)
99
"""
1010

11+
from __future__ import annotations
12+
1113
import math
1214
import time
1315
from typing import Any
@@ -28,9 +30,7 @@ def _set_cors_headers(response: Response) -> Response:
2830
Response with CORS headers set.
2931
"""
3032
response.headers["Access-Control-Allow-Origin"] = "*"
31-
response.headers["Access-Control-Allow-Methods"] = (
32-
"GET, POST, PUT, DELETE, OPTIONS"
33-
)
33+
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
3434
response.headers["Access-Control-Allow-Headers"] = (
3535
"Authorization, Content-Type, Accept, Origin, X-Requested-With"
3636
)

examples/auth/py_auth_mcp_server/tools/weather_tools.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
Mirrors the weather tools from the C++ auth example.
55
"""
66

7+
from __future__ import annotations
8+
79
import json
810
from typing import Any
911

@@ -168,10 +170,12 @@ def access_denied(scope: str) -> ToolResult:
168170
content=[
169171
ToolContentItem(
170172
type="text",
171-
text=json.dumps({
172-
"error": "access_denied",
173-
"message": f"Access denied. Required scope: {scope}",
174-
}),
173+
text=json.dumps(
174+
{
175+
"error": "access_denied",
176+
"message": f"Access denied. Required scope: {scope}",
177+
}
178+
),
175179
),
176180
],
177181
is_error=True,

examples/auth/pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ exclude = '''
6161
[tool.ruff]
6262
line-length = 88
6363
target-version = "py310"
64+
65+
[tool.ruff.lint]
6466
select = [
6567
"E", # pycodestyle errors
6668
"W", # pycodestyle warnings
@@ -74,7 +76,7 @@ ignore = [
7476
"E501", # line too long (handled by black)
7577
]
7678

77-
[tool.ruff.isort]
79+
[tool.ruff.lint.isort]
7880
known-first-party = ["py_auth_mcp_server", "gopher_mcp_python"]
7981

8082
[tool.mypy]

examples/auth/tests/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"""Pytest fixtures for py_auth_mcp_server tests."""
22

3+
from __future__ import annotations
4+
35
import pytest
46
from flask import Flask
57
from flask.testing import FlaskClient
68

79
from gopher_mcp_python.ffi.auth import AuthContext
8-
910
from py_auth_mcp_server import AuthServerConfig, create_app, create_default_config
1011
from py_auth_mcp_server.routes.mcp_handler import McpHandler
1112

examples/auth/tests/test_config.py

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Tests for configuration module."""
22

33
import tempfile
4-
from pathlib import Path
54

65
import pytest
76

@@ -68,7 +67,7 @@ def test_empty_content(self):
6867
def test_only_comments(self):
6968
"""Test parsing content with only comments."""
7069
content = "# comment 1\n# comment 2"
71-
result = parse_config_file("")
70+
result = parse_config_file(content)
7271
assert result == {}
7372

7473

@@ -86,11 +85,13 @@ def test_default_values(self):
8685

8786
def test_custom_values(self):
8887
"""Test custom values override defaults."""
89-
config = build_config({
90-
"host": "127.0.0.1",
91-
"port": "8080",
92-
"auth_disabled": "true",
93-
})
88+
config = build_config(
89+
{
90+
"host": "127.0.0.1",
91+
"port": "8080",
92+
"auth_disabled": "true",
93+
}
94+
)
9495
assert config.host == "127.0.0.1"
9596
assert config.port == 8080
9697

@@ -102,10 +103,12 @@ def test_port_type_conversion(self):
102103

103104
def test_boolean_type_conversion(self):
104105
"""Test boolean values are converted correctly."""
105-
config = build_config({
106-
"auth_disabled": "true",
107-
"jwks_auto_refresh": "false",
108-
})
106+
config = build_config(
107+
{
108+
"auth_disabled": "true",
109+
"jwks_auto_refresh": "false",
110+
}
111+
)
109112
assert config.auth_disabled is True
110113
assert config.jwks_auto_refresh is False
111114

@@ -116,10 +119,12 @@ def test_server_url_default(self):
116119

117120
def test_server_url_custom(self):
118121
"""Test custom server_url."""
119-
config = build_config({
120-
"server_url": "https://api.example.com",
121-
"auth_disabled": "true",
122-
})
122+
config = build_config(
123+
{
124+
"server_url": "https://api.example.com",
125+
"auth_disabled": "true",
126+
}
127+
)
123128
assert config.server_url == "https://api.example.com"
124129

125130

@@ -128,44 +133,52 @@ class TestEndpointDerivation:
128133

129134
def test_derives_jwks_uri(self):
130135
"""Test jwks_uri is derived from auth_server_url."""
131-
config = build_config({
132-
"auth_server_url": "https://auth.example.com/realms/test",
133-
"client_id": "test-client",
134-
"client_secret": "secret",
135-
})
136+
config = build_config(
137+
{
138+
"auth_server_url": "https://auth.example.com/realms/test",
139+
"client_id": "test-client",
140+
"client_secret": "secret",
141+
}
142+
)
136143
assert config.jwks_uri == (
137144
"https://auth.example.com/realms/test/protocol/openid-connect/certs"
138145
)
139146

140147
def test_derives_token_endpoint(self):
141148
"""Test token_endpoint is derived from auth_server_url."""
142-
config = build_config({
143-
"auth_server_url": "https://auth.example.com/realms/test",
144-
"client_id": "test-client",
145-
"client_secret": "secret",
146-
})
149+
config = build_config(
150+
{
151+
"auth_server_url": "https://auth.example.com/realms/test",
152+
"client_id": "test-client",
153+
"client_secret": "secret",
154+
}
155+
)
147156
assert config.token_endpoint == (
148157
"https://auth.example.com/realms/test/protocol/openid-connect/token"
149158
)
150159

151160
def test_derives_issuer(self):
152161
"""Test issuer is derived from auth_server_url."""
153-
config = build_config({
154-
"auth_server_url": "https://auth.example.com/realms/test",
155-
"client_id": "test-client",
156-
"client_secret": "secret",
157-
})
162+
config = build_config(
163+
{
164+
"auth_server_url": "https://auth.example.com/realms/test",
165+
"client_id": "test-client",
166+
"client_secret": "secret",
167+
}
168+
)
158169
assert config.issuer == "https://auth.example.com/realms/test"
159170

160171
def test_explicit_values_not_overwritten(self):
161172
"""Test explicit values are not overwritten by derivation."""
162-
config = build_config({
163-
"auth_server_url": "https://auth.example.com/realms/test",
164-
"jwks_uri": "https://custom.example.com/jwks",
165-
"issuer": "https://custom-issuer.example.com",
166-
"client_id": "test-client",
167-
"client_secret": "secret",
168-
})
173+
config = build_config(
174+
{
175+
"auth_server_url": "https://auth.example.com/realms/test",
176+
"jwks_uri": "https://custom.example.com/jwks",
177+
"issuer": "https://custom-issuer.example.com",
178+
"client_id": "test-client",
179+
"client_secret": "secret",
180+
}
181+
)
169182
assert config.jwks_uri == "https://custom.example.com/jwks"
170183
assert config.issuer == "https://custom-issuer.example.com"
171184

0 commit comments

Comments
 (0)