Skip to content

Commit 2c4f1a7

Browse files
authored
refactor(lint): Update Linting Checks and fix missed lint errors (#159)
1 parent 011d632 commit 2c4f1a7

35 files changed

+231
-134
lines changed

.github/linters/.jscpd.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"ignore": ["**/.github/**", "**/.git/**", "**/tests/**", "**/examples/**"],
2+
"ignore": ["**/.github/**", "**/.git/**", "**/tests/**"],
33
"threshold": 3,
44
"reporters": ["html", "markdown"]
55
}

.ruff.toml renamed to .github/linters/.ruff.toml

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,22 @@ target-version = "py310" # Minimum Python version
1313

1414
[lint]
1515
ignore = [
16-
"COM812",
17-
"FBT001",
18-
"FBT002",
19-
"D203",
20-
"D213",
21-
"D100", # Ignore Missing docstring in public module (often desired at top level __init__.py)
22-
"D104", # Ignore Missing docstring in public package (often desired at top level __init__.py)
23-
"D107", # Ignore Missing docstring in __init__ (use class docstring)
24-
"TD002", # Ignore Missing author in TODOs (often not required)
25-
"TD003", # Ignore Missing issue link in TODOs (often not required/available)
26-
"T201", # Ignore print presence
16+
"COM812", # Trailing comma missing.
17+
"FBT001", # Boolean positional arg in function definition
18+
"FBT002", # Boolean default value in function definition
19+
"D203", # 1 blank line required before class docstring (Google: 0)
20+
"D213", # Multi-line docstring summary should start at the second line (Google: first line)
21+
"D100", # Ignore Missing docstring in public module (often desired at top level __init__.py)
22+
"D104", # Ignore Missing docstring in public package (often desired at top level __init__.py)
23+
"D107", # Ignore Missing docstring in __init__ (use class docstring)
24+
"TD002", # Ignore Missing author in TODOs (often not required)
25+
"TD003", # Ignore Missing issue link in TODOs (often not required/available)
26+
"T201", # Ignore print presence
2727
"RUF012", # Ignore Mutable class attributes should be annotated with `typing.ClassVar`
28-
"RUF013", # Ignore implicit optional
28+
"E501", # Ignore line length (handled by Ruff's dynamic line length)
29+
"ANN002",
30+
"ANN003",
31+
"ANN401",
2932
]
3033

3134
select = [
@@ -46,12 +49,14 @@ select = [
4649
"PTH",# flake8-use-pathlib (use pathlib instead of os.path where possible)
4750
"PL", # Pylint rules ported to Ruff (PLC, PLE, PLR, PLW)
4851
"PIE",# flake8-pie (misc code improvements, e.g., no-unnecessary-pass)
49-
"RUF",# Ruff-specific rules (e.g., RUF001-003 ambiguous unicode)
52+
"RUF",# Ruff-specific rules (e.g., RUF001-003 ambiguous unicode, RUF013 implicit optional)
5053
"RET",# flake8-return (consistency in return statements)
5154
"SLF",# flake8-self (check for private member access via `self`)
5255
"TID",# flake8-tidy-imports (relative imports, banned imports - configure if needed)
5356
"YTT",# flake8-boolean-trap (checks for boolean positional arguments, truthiness tests - Google Style §3.10)
5457
"TD", # flake8-todos (check TODO format - Google Style §3.7)
58+
"TCH",# flake8-type-checking (helps manage TYPE_CHECKING blocks and imports)
59+
"PYI",# flake8-pyi (best practices for .pyi stub files, some rules are useful for .py too)
5560
]
5661

5762
exclude = [
@@ -76,7 +81,7 @@ exclude = [
7681
"node_modules",
7782
"venv",
7883
"*/migrations/*",
79-
"test_*",
84+
"noxfile.py",
8085
]
8186

8287
[lint.isort]
@@ -94,6 +99,8 @@ lines-between-types = 1
9499

95100
[lint.pydocstyle]
96101
convention = "google"
102+
ignore-decorators = ["typing.overload", "abc.abstractmethod"]
103+
ignore-var-parameters = true
97104

98105
[lint.flake8-annotations]
99106
mypy-init-return = true
@@ -113,11 +120,26 @@ inline-quotes = "single"
113120

114121
[lint.per-file-ignores]
115122
"__init__.py" = ["F401", "D", "ANN"] # Ignore unused imports in __init__.py
116-
"*_test.py" = ["D", "ANN"] # Ignore docstring and annotation issues in test files
117-
"test_*.py" = ["D", "ANN"] # Ignore docstring and annotation issues in test files
123+
"*_test.py" = [
124+
"D", # All pydocstyle rules
125+
"ANN", # Missing type annotation for function argument
126+
"RUF013", # Implicit optional type in test function signatures
127+
"S101", # Use of `assert` detected (expected in tests)
128+
"PLR2004",
129+
"SLF001",
130+
]
131+
"test_*.py" = [
132+
"D",
133+
"ANN",
134+
"RUF013",
135+
"S101",
136+
"PLR2004",
137+
"SLF001",
138+
]
118139
"types.py" = ["D", "E501", "N815"] # Ignore docstring and annotation issues in types.py
119140

120141
[format]
142+
exclude = ["types.py"]
121143
docstring-code-format = true
122144
docstring-code-line-length = "dynamic" # Or set to 80
123145
quote-style = "single"

.github/workflows/linter.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,5 @@ jobs:
6363
VALIDATE_TYPESCRIPT_STANDARD: false
6464
VALIDATE_GIT_COMMITLINT: false
6565
PYTHON_MYPY_CONFIG_FILE: .mypy.ini
66-
FILTER_REGEX_INCLUDE: "^src/**"
66+
FILTER_REGEX_INCLUDE: ".*src/**/*"
6767
PYTHON_RUFF_CONFIG_FILE: .ruff.toml

.vscode/settings.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,17 @@
77
"editor.defaultFormatter": "charliermarsh.ruff",
88
"editor.formatOnSave": true,
99
"editor.codeActionsOnSave": {
10-
"source.organizeImports": "always"
10+
"source.organizeImports": "always",
11+
"source.fixAll.ruff": "explicit"
1112
}
1213
},
13-
"ruff.importStrategy": "fromEnvironment"
14+
"ruff.importStrategy": "fromEnvironment",
15+
"ruff.lint.args": [
16+
"--config",
17+
".github/linters/.ruff.toml"
18+
],
19+
"ruff.format.args": [
20+
"--config",
21+
".github/linters/.ruff.toml"
22+
]
1423
}

noxfile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737

3838
@nox.session(python=DEFAULT_PYTHON_VERSION)
39-
def format(session):
39+
def format(session) -> None:
4040
"""Format Python code using autoflake, pyupgrade, and ruff."""
4141
# Sort Spelling Allowlist
4242
spelling_allow_file = '.github/actions/spelling/allow.txt'
@@ -141,10 +141,14 @@ def format(session):
141141
'ruff',
142142
'check',
143143
'--fix-only',
144+
'--config',
145+
'.github/linters/.ruff.toml',
144146
*lint_paths_py,
145147
)
146148
session.run(
147149
'ruff',
148150
'format',
151+
'--config',
152+
'.github/linters/.ruff.toml',
149153
*lint_paths_py,
150154
)

src/a2a/auth/user.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ class UnauthenticatedUser(User):
2121
"""A representation that no user has been authenticated in the request."""
2222

2323
@property
24-
def is_authenticated(self):
24+
def is_authenticated(self) -> bool:
25+
"""Returns whether the current user is authenticated."""
2526
return False
2627

2728
@property
2829
def user_name(self) -> str:
30+
"""Returns the user name of the current user."""
2931
return ''

src/a2a/server/agent_execution/agent_executor.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ class AgentExecutor(ABC):
1212
"""
1313

1414
@abstractmethod
15-
async def execute(self, context: RequestContext, event_queue: EventQueue):
15+
async def execute(
16+
self, context: RequestContext, event_queue: EventQueue
17+
) -> None:
1618
"""Execute the agent's logic for a given request context.
1719
1820
The agent should read necessary information from the `context` and
@@ -27,7 +29,9 @@ async def execute(self, context: RequestContext, event_queue: EventQueue):
2729
"""
2830

2931
@abstractmethod
30-
async def cancel(self, context: RequestContext, event_queue: EventQueue):
32+
async def cancel(
33+
self, context: RequestContext, event_queue: EventQueue
34+
) -> None:
3135
"""Request the agent to cancel an ongoing task.
3236
3337
The agent should attempt to stop the task identified by the task_id

src/a2a/server/agent_execution/context.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class RequestContext:
2020
tasks.
2121
"""
2222

23-
def __init__(
23+
def __init__( # noqa: PLR0913
2424
self,
2525
request: MessageSendParams | None = None,
2626
task_id: str | None = None,
@@ -37,6 +37,7 @@ def __init__(
3737
context_id: The ID of the context explicitly provided in the request or path.
3838
task: The existing `Task` object retrieved from the store, if any.
3939
related_tasks: A list of other tasks related to the current request (e.g., for tool use).
40+
call_context: The server call context associated with this request.
4041
"""
4142
if related_tasks is None:
4243
related_tasks = []
@@ -64,7 +65,7 @@ def __init__(
6465
else:
6566
self._check_or_generate_context_id()
6667

67-
def get_user_input(self, delimiter='\n') -> str:
68+
def get_user_input(self, delimiter: str = '\n') -> str:
6869
"""Extracts text content from the user's message parts.
6970
7071
Args:
@@ -80,7 +81,7 @@ def get_user_input(self, delimiter='\n') -> str:
8081

8182
return get_message_text(self._params.message, delimiter)
8283

83-
def attach_related_task(self, task: Task):
84+
def attach_related_task(self, task: Task) -> None:
8485
"""Attaches a related task to the context.
8586
8687
This is useful for scenarios like tool execution where a new task

src/a2a/server/agent_execution/request_context_builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
class RequestContextBuilder(ABC):
9-
"""Builds request context to be supplied to agent executor"""
9+
"""Builds request context to be supplied to agent executor."""
1010

1111
@abstractmethod
1212
async def build(

src/a2a/server/agent_execution/simple_request_context_builder.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,22 @@
77

88

99
class SimpleRequestContextBuilder(RequestContextBuilder):
10-
"""Builds request context and populates referred tasks"""
10+
"""Builds request context and populates referred tasks."""
1111

1212
def __init__(
1313
self,
1414
should_populate_referred_tasks: bool = False,
1515
task_store: TaskStore | None = None,
1616
) -> None:
17+
"""Initializes the SimpleRequestContextBuilder.
18+
19+
Args:
20+
should_populate_referred_tasks: If True, the builder will fetch tasks
21+
referenced in `params.message.referenceTaskIds` and populate the
22+
`related_tasks` field in the RequestContext. Defaults to False.
23+
task_store: The TaskStore instance to use for fetching referred tasks.
24+
Required if `should_populate_referred_tasks` is True.
25+
"""
1726
self._task_store = task_store
1827
self._should_populate_referred_tasks = should_populate_referred_tasks
1928

@@ -25,6 +34,23 @@ async def build(
2534
task: Task | None = None,
2635
context: ServerCallContext | None = None,
2736
) -> RequestContext:
37+
"""Builds the request context for an agent execution.
38+
39+
This method assembles the RequestContext object. If the builder was
40+
initialized with `should_populate_referred_tasks=True`, it fetches all tasks
41+
referenced in `params.message.referenceTaskIds` from the `task_store`.
42+
43+
Args:
44+
params: The parameters of the incoming message send request.
45+
task_id: The ID of the task being executed.
46+
context_id: The ID of the current execution context.
47+
task: The primary task object associated with the request.
48+
context: The server call context, containing metadata about the call.
49+
50+
Returns:
51+
An instance of RequestContext populated with the provided information
52+
and potentially a list of related tasks.
53+
"""
2854
related_tasks: list[Task] | None = None
2955

3056
if (

src/a2a/server/apps/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""HTTP application components for the A2A server."""
22

3-
from .jsonrpc import (
3+
from a2a.server.apps.jsonrpc import (
44
A2AFastAPIApplication,
55
A2AStarletteApplication,
66
CallContextBuilder,

src/a2a/server/apps/jsonrpc/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
"""A2A JSON-RPC Applications."""
22

3-
from .fastapi_app import A2AFastAPIApplication
4-
from .jsonrpc_app import CallContextBuilder, JSONRPCApplication
5-
from .starlette_app import A2AStarletteApplication
3+
from a2a.server.apps.jsonrpc.fastapi_app import A2AFastAPIApplication
4+
from a2a.server.apps.jsonrpc.jsonrpc_app import (
5+
CallContextBuilder,
6+
JSONRPCApplication,
7+
)
8+
from a2a.server.apps.jsonrpc.starlette_app import A2AStarletteApplication
69

710

811
__all__ = [

src/a2a/server/apps/jsonrpc/fastapi_app.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
from typing import Any
44

5-
from fastapi import FastAPI, Request
5+
from fastapi import FastAPI, Request, Response
66

7+
from a2a.server.apps.jsonrpc.jsonrpc_app import (
8+
CallContextBuilder,
9+
JSONRPCApplication,
10+
)
711
from a2a.server.request_handlers.jsonrpc_handler import RequestHandler
812
from a2a.types import AgentCard
913

10-
from .jsonrpc_app import CallContextBuilder, JSONRPCApplication
11-
1214

1315
logger = logging.getLogger(__name__)
1416

@@ -50,8 +52,8 @@ def __init__(
5052
def build(
5153
self,
5254
agent_card_url: str = '/.well-known/agent.json',
53-
extended_agent_card_url: str = '/agent/authenticatedExtendedCard',
5455
rpc_url: str = '/',
56+
extended_agent_card_url: str = '/agent/authenticatedExtendedCard',
5557
**kwargs: Any,
5658
) -> FastAPI:
5759
"""Builds and returns the FastAPI application instance.
@@ -68,17 +70,17 @@ def build(
6870
app = FastAPI(**kwargs)
6971

7072
@app.post(rpc_url)
71-
async def handle_a2a_request(request: Request):
73+
async def handle_a2a_request(request: Request) -> Response:
7274
return await self._handle_requests(request)
7375

7476
@app.get(agent_card_url)
75-
async def get_agent_card(request: Request):
77+
async def get_agent_card(request: Request) -> Response:
7678
return await self._handle_get_agent_card(request)
7779

7880
if self.agent_card.supportsAuthenticatedExtendedCard:
7981

8082
@app.get(extended_agent_card_url)
81-
async def get_extended_agent_card(request: Request):
83+
async def get_extended_agent_card(request: Request) -> Response:
8284
return await self._handle_get_authenticated_extended_agent_card(
8385
request
8486
)

0 commit comments

Comments
 (0)