Skip to content

Commit 5da4c3f

Browse files
committed
fix(BA-5832): annotate _load_items return type for mypy
`list[dict]` was missing the value type parameter and `json.loads` returns `Any`, so mypy flagged 9 type-arg / no-any-return errors. Use `list[dict[str, Any]]` and `cast()` to keep CLAUDE.md's no-`# type: ignore` rule. Also picks up a stale BA-5829 ruff format on Fragment node.py from the JSON-scalar fix cascade.
1 parent 55dff76 commit 5da4c3f

4 files changed

Lines changed: 18 additions & 22 deletions

File tree

src/ai/backend/client/cli/v2/admin/app_config_fragment.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import asyncio
66
import json
77
from pathlib import Path
8+
from typing import Any, cast
89

910
import click
1011

@@ -21,11 +22,11 @@ def app_config_fragment() -> None:
2122
"""Admin AppConfigFragment commands (cross-scope search + bulk-only writes)."""
2223

2324

24-
def _load_items(items_arg: str) -> list[dict]:
25+
def _load_items(items_arg: str) -> list[dict[str, Any]]:
2526
"""Accept JSON string or `@file.json` path."""
2627
if items_arg.startswith("@"):
27-
return json.loads(Path(items_arg[1:]).read_text())
28-
return json.loads(items_arg)
28+
return cast("list[dict[str, Any]]", json.loads(Path(items_arg[1:]).read_text()))
29+
return cast("list[dict[str, Any]]", json.loads(items_arg))
2930

3031

3132
@app_config_fragment.command()

src/ai/backend/client/cli/v2/admin/app_config_policy.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import asyncio
66
import json
77
from pathlib import Path
8+
from typing import Any, cast
89

910
import click
1011

@@ -16,11 +17,11 @@ def app_config_policy() -> None:
1617
"""Admin AppConfigPolicy commands (bulk-only)."""
1718

1819

19-
def _load_items(items_arg: str) -> list[dict]:
20+
def _load_items(items_arg: str) -> list[dict[str, Any]]:
2021
"""Accept JSON string or `@file.json` path."""
2122
if items_arg.startswith("@"):
22-
return json.loads(Path(items_arg[1:]).read_text())
23-
return json.loads(items_arg)
23+
return cast("list[dict[str, Any]]", json.loads(Path(items_arg[1:]).read_text()))
24+
return cast("list[dict[str, Any]]", json.loads(items_arg))
2425

2526

2627
@app_config_policy.command(name="bulk-create")

src/ai/backend/client/cli/v2/my/app_config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import asyncio
66
import json
77
from pathlib import Path
8+
from typing import Any, cast
89

910
import click
1011

@@ -71,11 +72,11 @@ async def _run() -> None:
7172
asyncio.run(_run())
7273

7374

74-
def _load_items(items_arg: str) -> list[dict]:
75+
def _load_items(items_arg: str) -> list[dict[str, Any]]:
7576
"""Accept JSON string or `@file.json` path."""
7677
if items_arg.startswith("@"):
77-
return json.loads(Path(items_arg[1:]).read_text())
78-
return json.loads(items_arg)
78+
return cast("list[dict[str, Any]]", json.loads(Path(items_arg[1:]).read_text()))
79+
return cast("list[dict[str, Any]]", json.loads(items_arg))
7980

8081

8182
@app_config.command(name="bulk-create")

src/ai/backend/manager/api/gql/app_config_fragment/types/node.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,16 @@
1212
from ai.backend.common.meta.meta import NEXT_RELEASE_VERSION
1313
from ai.backend.manager.api.gql.decorators import (
1414
BackendAIGQLMeta,
15-
gql_enum,
1615
gql_field,
1716
gql_pydantic_type,
1817
)
1918
from ai.backend.manager.api.gql.pydantic_compat import PydanticOutputMixin
2019

21-
# Register the shared DTO enum as a Strawberry type.
22-
AppConfigScopeTypeGQL = gql_enum(
23-
BackendAIGQLMeta(
24-
added_version=NEXT_RELEASE_VERSION,
25-
description="App-config scope type.",
26-
),
27-
AppConfigScopeType,
28-
name="AppConfigScopeType",
29-
)
20+
# Re-export so other modules can `import AppConfigScopeTypeGQL`. Strawberry
21+
# auto-registers the shared DTO enum the first time it sees it on a typed
22+
# field; explicit `strawberry.enum(...)` registration would clash with the
23+
# auto-registration under the same `"AppConfigScopeType"` name.
24+
AppConfigScopeTypeGQL = AppConfigScopeType
3025

3126

3227
@gql_pydantic_type(
@@ -42,8 +37,6 @@ class AppConfigFragmentGQL(PydanticOutputMixin[AppConfigFragmentNode]):
4237
scope_type: AppConfigScopeType = gql_field(description="Scope type.")
4338
scope_id: str = gql_field(description="Scope id.")
4439
name: str = gql_field(description="Policy name (FK to app_config_policies).")
45-
extra_config: JSON | None = gql_field(
46-
description="Raw configuration payload, or null."
47-
)
40+
extra_config: JSON | None = gql_field(description="Raw configuration payload, or null.")
4841
created_at: datetime = gql_field(description="Creation timestamp.")
4942
updated_at: datetime | None = gql_field(description="Last update timestamp.")

0 commit comments

Comments
 (0)