Skip to content

Commit 1d0a038

Browse files
jopemachineclaude
andcommitted
fix(BA-6003): address CI failures from BackendAISchema migration
* Remove unused BaseModel imports in toml.py, extractor.py, sokovan/deployment/strategy/types.py. * Reflow long line in manager/api/utils.py to satisfy ruff format. * Migrate test classes in tests/unit/common/configs/{test_meta, test_generator,test_inspector}.py from BaseModel to BackendAISchema so they match the narrowed type[BackendAISchema] signatures. * Update test sites expecting raw pydantic.ValidationError to also accept BackendAISchemaValidationFailed via tuple-catch: bulk s/pytest.raises(ValidationError)/pytest.raises((BackendAISchemaValidationFailed, ValidationError))/ plus the corresponding import. Tests against DTO.model_validate now see the wrapped exception; the ValidationError arm still covers constructor paths and any plain BaseModel fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0fdce92 commit 1d0a038

7 files changed

Lines changed: 58 additions & 59 deletions

File tree

src/ai/backend/common/configs/generator/toml.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
from pathlib import Path
77
from typing import TYPE_CHECKING, Any
88

9-
from pydantic import BaseModel
10-
119
from ai.backend.common.configs.inspector import ConfigInspector, FieldSchema
1210
from ai.backend.common.meta import CompositeType, ConfigEnvironment, ConfigExample
1311
from ai.backend.common.types import BackendAISchema

src/ai/backend/common/configs/inspector/extractor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import types
44
from typing import TYPE_CHECKING, Any, cast
55

6-
from pydantic import BaseModel
76
from pydantic.fields import FieldInfo
87
from pydantic_core import PydanticUndefined
98

src/ai/backend/manager/api/utils.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,7 @@ async def wrapped(
238238
*(f"{k}={v!r}" for k, v in metadata.items()),
239239
]
240240
msg = f"{first_error['msg']} [{', '.join(metadata_formatted_items)}]"
241-
raise InvalidAPIParameters(
242-
msg, extra_data={"errors": ex.errors()}
243-
) from ex
241+
raise InvalidAPIParameters(msg, extra_data={"errors": ex.errors()}) from ex
244242
result = await handler(request, checked_params, *args, **kwargs)
245243
return ensure_stream_response_type(result)
246244

src/ai/backend/manager/sokovan/deployment/strategy/types.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from dataclasses import dataclass, field
88
from uuid import UUID
99

10-
from pydantic import BaseModel
11-
1210
from ai.backend.common.data.model_deployment.types import DeploymentStrategy
1311
from ai.backend.common.identifier.deployment import DeploymentID
1412
from ai.backend.common.types import BackendAISchema

tests/unit/common/configs/test_generator.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
from typing import Annotated
55

66
import pytest
7-
from pydantic import BaseModel, Field
7+
from pydantic import Field
8+
9+
from ai.backend.common.types import BackendAISchema
810

911
from ai.backend.common.configs.generator import (
1012
BinarySizeFormatter,
@@ -243,7 +245,7 @@ def test_env_property(self) -> None:
243245
assert generator.env == ConfigEnvironment.PROD
244246

245247
def test_generate_simple_config(self) -> None:
246-
class SimpleConfig(BaseModel):
248+
class SimpleConfig(BackendAISchema):
247249
name: Annotated[
248250
str,
249251
Field(default="default-name"),
@@ -265,7 +267,7 @@ class SimpleConfig(BaseModel):
265267
def test_generate_uses_prod_example(self) -> None:
266268
"""PROD environment uses prod example value."""
267269

268-
class EnvConfig(BaseModel):
270+
class EnvConfig(BackendAISchema):
269271
endpoint: Annotated[
270272
str,
271273
Field(default="default-endpoint"),
@@ -285,7 +287,7 @@ class EnvConfig(BaseModel):
285287
def test_generate_uses_local_example(self) -> None:
286288
"""LOCAL environment uses local example value."""
287289

288-
class EnvConfig(BaseModel):
290+
class EnvConfig(BackendAISchema):
289291
endpoint: Annotated[
290292
str,
291293
Field(default="default-endpoint"),
@@ -303,7 +305,7 @@ class EnvConfig(BaseModel):
303305
assert "localhost:8080" in result
304306

305307
def test_optional_field_commented(self) -> None:
306-
class OptionalConfig(BaseModel):
308+
class OptionalConfig(BackendAISchema):
307309
optional_field: Annotated[
308310
str | None,
309311
Field(default=None),
@@ -322,7 +324,7 @@ class OptionalConfig(BaseModel):
322324
assert "optional_field" in result
323325

324326
def test_secret_field_masked(self) -> None:
325-
class SecretConfig(BaseModel):
327+
class SecretConfig(BackendAISchema):
326328
password: Annotated[
327329
str,
328330
Field(default="secret123"),
@@ -342,7 +344,7 @@ class SecretConfig(BaseModel):
342344
assert "dev-pass" not in result
343345

344346
def test_secret_field_unmasked(self) -> None:
345-
class SecretConfig(BaseModel):
347+
class SecretConfig(BackendAISchema):
346348
password: Annotated[
347349
str,
348350
Field(default="secret123"),
@@ -363,7 +365,7 @@ class SecretConfig(BaseModel):
363365
assert "***SECRET***" not in result
364366

365367
def test_nested_config_section(self) -> None:
366-
class InnerConfig(BaseModel):
368+
class InnerConfig(BackendAISchema):
367369
value: Annotated[
368370
int,
369371
Field(default=10),
@@ -374,7 +376,7 @@ class InnerConfig(BaseModel):
374376
),
375377
]
376378

377-
class OuterConfig(BaseModel):
379+
class OuterConfig(BackendAISchema):
378380
inner: Annotated[
379381
InnerConfig,
380382
Field(default_factory=InnerConfig),
@@ -392,7 +394,7 @@ class OuterConfig(BaseModel):
392394
assert "value" in result
393395

394396
def test_runtime_field_hidden(self) -> None:
395-
class RuntimeConfig(BaseModel):
397+
class RuntimeConfig(BackendAISchema):
396398
runtime_field: Annotated[
397399
str,
398400
Field(default="runtime"),
@@ -421,7 +423,7 @@ class RuntimeConfig(BaseModel):
421423
assert "normal_field" in result
422424

423425
def test_skips_fields_without_meta(self) -> None:
424-
class MixedConfig(BaseModel):
426+
class MixedConfig(BackendAISchema):
425427
with_meta: Annotated[
426428
str,
427429
Field(default="has-meta"),
@@ -442,7 +444,7 @@ class MixedConfig(BaseModel):
442444

443445
class TestConvenienceFunctions:
444446
def test_generate_sample_toml(self) -> None:
445-
class SampleConfig(BaseModel):
447+
class SampleConfig(BackendAISchema):
446448
field: Annotated[
447449
str,
448450
Field(default="default"),
@@ -458,7 +460,7 @@ class SampleConfig(BaseModel):
458460
assert "local" in result
459461

460462
def test_generate_halfstack_toml(self) -> None:
461-
class HalfstackConfig(BaseModel):
463+
class HalfstackConfig(BackendAISchema):
462464
field: Annotated[
463465
str,
464466
Field(default="default"),

tests/unit/common/configs/test_inspector.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
from typing import Annotated
44

55
import pytest
6-
from pydantic import BaseModel, Field
6+
from pydantic import Field
7+
8+
from ai.backend.common.types import BackendAISchema
79

810
from ai.backend.common.configs.inspector import (
911
ConfigInspector,
@@ -155,7 +157,7 @@ def test_frozen(self) -> None:
155157

156158
class TestConfigInspector:
157159
def test_extract_simple_field(self) -> None:
158-
class SimpleConfig(BaseModel):
160+
class SimpleConfig(BackendAISchema):
159161
name: Annotated[
160162
str,
161163
Field(default="default-name"),
@@ -181,7 +183,7 @@ class SimpleConfig(BaseModel):
181183
assert field.doc.added_version == "25.1.0"
182184

183185
def test_extract_uses_serialization_alias(self) -> None:
184-
class AliasedConfig(BaseModel):
186+
class AliasedConfig(BackendAISchema):
185187
my_field: Annotated[
186188
str,
187189
Field(default="value", serialization_alias="my-field"),
@@ -200,7 +202,7 @@ class AliasedConfig(BaseModel):
200202
assert "my_field" not in schema
201203

202204
def test_extract_required_field(self) -> None:
203-
class RequiredConfig(BaseModel):
205+
class RequiredConfig(BackendAISchema):
204206
required_field: Annotated[
205207
str,
206208
Field(),
@@ -217,7 +219,7 @@ class RequiredConfig(BaseModel):
217219
assert schema["required_field"].type_info.required is True
218220

219221
def test_extract_secret_field(self) -> None:
220-
class SecretConfig(BaseModel):
222+
class SecretConfig(BackendAISchema):
221223
password: Annotated[
222224
str,
223225
Field(default="secret123"),
@@ -235,7 +237,7 @@ class SecretConfig(BaseModel):
235237
assert schema["password"].type_info.secret is True
236238

237239
def test_extract_composite_field(self) -> None:
238-
class InnerConfig(BaseModel):
240+
class InnerConfig(BackendAISchema):
239241
value: Annotated[
240242
int,
241243
Field(default=10),
@@ -246,7 +248,7 @@ class InnerConfig(BaseModel):
246248
),
247249
]
248250

249-
class OuterConfig(BaseModel):
251+
class OuterConfig(BackendAISchema):
250252
inner: Annotated[
251253
InnerConfig,
252254
Field(default_factory=InnerConfig),
@@ -266,7 +268,7 @@ class OuterConfig(BaseModel):
266268
assert schema["inner"].children["value"].type_info.type_name == "int"
267269

268270
def test_skips_fields_without_meta(self) -> None:
269-
class MixedConfig(BaseModel):
271+
class MixedConfig(BackendAISchema):
270272
with_meta: Annotated[
271273
str,
272274
Field(default="has-meta"),
@@ -285,7 +287,7 @@ class MixedConfig(BaseModel):
285287
assert "without_meta" not in schema
286288

287289
def test_get_example_value_local(self) -> None:
288-
class ExampleConfig(BaseModel):
290+
class ExampleConfig(BackendAISchema):
289291
endpoint: Annotated[
290292
str,
291293
Field(default="localhost"),
@@ -303,7 +305,7 @@ class ExampleConfig(BaseModel):
303305
assert example == "localhost:8080"
304306

305307
def test_get_example_value_prod(self) -> None:
306-
class ExampleConfig(BaseModel):
308+
class ExampleConfig(BackendAISchema):
307309
endpoint: Annotated[
308310
str,
309311
Field(default="localhost"),
@@ -321,7 +323,7 @@ class ExampleConfig(BaseModel):
321323
assert example == "api.example.com"
322324

323325
def test_get_fields_by_version(self) -> None:
324-
class VersionedConfig(BaseModel):
326+
class VersionedConfig(BackendAISchema):
325327
old_field: Annotated[
326328
str,
327329
Field(default="old"),
@@ -364,7 +366,7 @@ class VersionedConfig(BaseModel):
364366
assert versions == ["24.0.0", "24.6.0", "25.1.0"]
365367

366368
def test_get_deprecated_fields(self) -> None:
367-
class DeprecatedConfig(BaseModel):
369+
class DeprecatedConfig(BackendAISchema):
368370
current_field: Annotated[
369371
str,
370372
Field(default="current"),
@@ -395,7 +397,7 @@ class DeprecatedConfig(BaseModel):
395397
assert deprecated[0][1].doc.deprecation_hint == "Use current_field instead"
396398

397399
def test_get_secret_fields(self) -> None:
398-
class SecretsConfig(BaseModel):
400+
class SecretsConfig(BackendAISchema):
399401
public_field: Annotated[
400402
str,
401403
Field(default="public"),
@@ -424,7 +426,7 @@ class SecretsConfig(BaseModel):
424426
assert secrets[0][0] == "secret_field"
425427

426428
def test_type_name_simple_types(self) -> None:
427-
class TypesConfig(BaseModel):
429+
class TypesConfig(BackendAISchema):
428430
str_field: Annotated[
429431
str,
430432
Field(default=""),
@@ -461,7 +463,7 @@ class TypesConfig(BaseModel):
461463
assert schema["bool_field"].type_info.type_name == "bool"
462464

463465
def test_type_name_optional(self) -> None:
464-
class OptionalConfig(BaseModel):
466+
class OptionalConfig(BackendAISchema):
465467
optional_field: Annotated[
466468
str | None,
467469
Field(default=None),

0 commit comments

Comments
 (0)