Skip to content

Commit a02be59

Browse files
fix(server): resolve lint, type, and spelling errors in route helpers
1 parent 697db0d commit a02be59

9 files changed

Lines changed: 60 additions & 20 deletions

File tree

.github/actions/spelling/allow.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ amannn
2020
aproject
2121
ARequest
2222
ARun
23+
ARoute
2324
AServer
2425
AServers
2526
AService
@@ -94,6 +95,8 @@ notif
9495
npx
9596
oauthoidc
9697
oidc
98+
oneof
99+
oneofs
97100
Oneof
98101
OpenAPI
99102
openapiv
@@ -112,6 +115,7 @@ proto
112115
protobuf
113116
Protobuf
114117
protoc
118+
protojson
115119
pydantic
116120
pyi
117121
pypistats
@@ -125,6 +129,7 @@ rmi
125129
RS256
126130
RUF
127131
SECP256R1
132+
SFIXED
128133
SLF
129134
socio
130135
sse

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Claude Code Guidelines
2+
3+
## Commits
4+
5+
- Never include `Co-Authored-By: Claude` or any AI attribution in commit messages.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from a2a.server.routes.helpers.fastapi import add_a2a_routes_to_fastapi
22

3+
34
__all__ = [
45
'add_a2a_routes_to_fastapi',
56
]

src/a2a/server/routes/helpers/_proto_schema.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
from typing import Any
44

55
from google.protobuf.descriptor import Descriptor, FieldDescriptor
6+
from google.protobuf.message import Message
67

78
from a2a.types.a2a_pb2 import (
89
SendMessageRequest,
910
TaskPushNotificationConfig,
1011
)
1112

1213

13-
REST_BODY_TYPES: dict[tuple[str, str], type] = {
14+
REST_BODY_TYPES: dict[tuple[str, str], type[Message]] = {
1415
('/message:send', 'POST'): SendMessageRequest,
1516
('/message:stream', 'POST'): SendMessageRequest,
1617
('/tasks/{id}/pushNotificationConfigs', 'POST'): TaskPushNotificationConfig,
@@ -73,7 +74,7 @@ def field_schema(
7374

7475

7576
def message_schema(
76-
descriptor: Descriptor, components: dict[str, Any]
77+
descriptor: Descriptor | Any, components: dict[str, Any]
7778
) -> dict[str, Any]:
7879
"""Returns a $ref to descriptor's schema, registering it in components if needed."""
7980
if descriptor.full_name in _WELL_KNOWN_SCHEMAS:

src/a2a/server/routes/helpers/fastapi.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
from typing import TYPE_CHECKING, Any
22

3-
from a2a.server.routes.helpers._proto_schema import (REST_BODY_TYPES,
4-
message_schema)
5-
from a2a.server.routes.helpers.jsonrpc import \
6-
DESCRIPTION as _JSONRPC_DESCRIPTION
7-
from a2a.server.routes.helpers.jsonrpc import \
8-
envelope_schema as _jsonrpc_envelope_schema
3+
from a2a.server.routes.helpers._proto_schema import (
4+
REST_BODY_TYPES,
5+
message_schema,
6+
)
7+
from a2a.server.routes.helpers.jsonrpc import (
8+
DESCRIPTION as _JSONRPC_DESCRIPTION,
9+
)
10+
from a2a.server.routes.helpers.jsonrpc import (
11+
envelope_schema as _jsonrpc_envelope_schema,
12+
)
913
from a2a.utils.constants import PROTOCOL_VERSION_1_0, VERSION_HEADER
1014

15+
1116
if TYPE_CHECKING:
1217
from fastapi import FastAPI
18+
from fastapi.routing import APIRoute as _A2ARoute
1319
from starlette.routing import BaseRoute, Route
1420

1521
_package_fastapi_installed = True
@@ -169,14 +175,26 @@ def add_a2a_routes_to_fastapi(
169175

170176
for route in jsonrpc_routes or ():
171177
extra = jsonrpc_extra if isinstance(route, Route) else None
172-
_attach_route(app, route, _JSONRPC_TAG, openapi_extra=extra, require_version_header=True)
178+
_attach_route(
179+
app,
180+
route,
181+
_JSONRPC_TAG,
182+
openapi_extra=extra,
183+
require_version_header=True,
184+
)
173185

174186
for route in rest_routes or ():
175187
extra = (
176188
_rest_body_extra(route, rest_extras)
177189
if isinstance(route, Route)
178190
else None
179191
)
180-
_attach_route(app, route, _REST_TAG, openapi_extra=extra, require_version_header=True)
192+
_attach_route(
193+
app,
194+
route,
195+
_REST_TAG,
196+
openapi_extra=extra,
197+
require_version_header=True,
198+
)
181199

182200
_install_components(app, components)

src/a2a/server/routes/helpers/jsonrpc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from typing import Any
44

5+
from google.protobuf.message import Message
6+
57
from a2a.server.routes.helpers._proto_schema import message_schema
68
from a2a.types.a2a_pb2 import (
79
CancelTaskRequest,
@@ -17,7 +19,7 @@
1719
)
1820

1921

20-
METHOD_TYPES: dict[str, type] = {
22+
METHOD_TYPES: dict[str, type[Message]] = {
2123
'SendMessage': SendMessageRequest,
2224
'SendStreamingMessage': SendMessageRequest,
2325
'GetTask': GetTaskRequest,

tests/server/routes/helpers/test_fastapi.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ def test_routes_dispatch_under_fastapi(
7070
app = _build_app(agent_card, mock_handler)
7171
client = TestClient(app)
7272

73-
assert (
74-
client.get(AGENT_CARD_WELL_KNOWN_PATH).json()['name'] == 'Test Agent'
75-
)
73+
assert client.get(AGENT_CARD_WELL_KNOWN_PATH).json()['name'] == 'Test Agent'
7674
rpc_response = client.post(
7775
'/', json={'jsonrpc': '2.0', 'id': '1', 'method': 'NoSuchMethod'}
7876
).json()
@@ -155,7 +153,10 @@ def test_routes_without_body_have_no_request_body(
155153
assert 'requestBody' not in paths[AGENT_CARD_WELL_KNOWN_PATH]['get']
156154
assert 'requestBody' not in paths['/tasks']['get']
157155
assert 'requestBody' not in paths['/tasks/{id}:cancel']['post']
158-
assert 'requestBody' not in paths['/tasks/{id}/pushNotificationConfigs/{push_id}']['delete']
156+
assert (
157+
'requestBody'
158+
not in paths['/tasks/{id}/pushNotificationConfigs/{push_id}']['delete']
159+
)
159160

160161

161162
def test_a2a_version_header_on_dispatcher_routes(
@@ -167,8 +168,7 @@ def test_a2a_version_header_on_dispatcher_routes(
167168

168169
def _has_version_header(op: dict) -> bool:
169170
return any(
170-
p.get('name') == VERSION_HEADER
171-
for p in op.get('parameters', [])
171+
p.get('name') == VERSION_HEADER for p in op.get('parameters', [])
172172
)
173173

174174
assert _has_version_header(paths['/']['post'])

tests/server/routes/helpers/test_jsonrpc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ def test_envelope_schema_deduplicates_shared_param_types():
3636
# SendMessage and SendStreamingMessage share SendMessageRequest.
3737
components = {}
3838
envelope_schema(components)
39-
refs = [r['$ref'] for r in components['A2ARequest']['properties']['params']['oneOf']]
39+
refs = [
40+
r['$ref']
41+
for r in components['A2ARequest']['properties']['params']['oneOf']
42+
]
4043
assert len(refs) == len(set(refs))
4144

4245

tests/server/routes/helpers/test_proto_schema.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ def test_message_schema_recurses_into_nested_types():
2929

3030
def test_message_schema_well_known_type_inline():
3131
from google.protobuf.descriptor_pool import Default
32-
struct_descriptor = Default().FindMessageTypeByName('google.protobuf.Struct')
32+
33+
struct_descriptor = Default().FindMessageTypeByName(
34+
'google.protobuf.Struct'
35+
)
3336
components = {}
3437
schema = message_schema(struct_descriptor, components)
3538
assert schema == {'type': 'object'}
@@ -54,7 +57,9 @@ def test_message_schema_oneof_variants_have_required():
5457

5558
def test_field_schema_repeated_wraps_in_array():
5659
components = {}
57-
msg_descriptor = SendMessageRequest.DESCRIPTOR.fields_by_name['message'].message_type
60+
msg_descriptor = SendMessageRequest.DESCRIPTOR.fields_by_name[
61+
'message'
62+
].message_type
5863
parts_field = msg_descriptor.fields_by_name['parts']
5964
schema = field_schema(parts_field, components)
6065
assert schema['type'] == 'array'

0 commit comments

Comments
 (0)