fix: clean mypy errors in schemas, models, auth, exceptions layers
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Has been cancelled
CLI Tests / test-cli (push) Has been cancelled
Coverage Phase 1 (70% Target) / test-coverage-70 (push) Has been cancelled
Coverage Phase 2 (85% Target) / test-coverage-85 (push) Has been cancelled
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Package Tests / Python package - aitbc-agent-sdk (push) Has been cancelled
Package Tests / Python package - aitbc-core (push) Has been cancelled
Package Tests / Python package - aitbc-crypto (push) Has been cancelled
Package Tests / Python package - aitbc-sdk (push) Has been cancelled
Package Tests / JavaScript package - aitbc-sdk-js (push) Has been cancelled
Package Tests / JavaScript package - aitbc-token (push) Has been cancelled
Production Tests / Production Integration Tests (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled

schemas/ — 0 errors (11 files):
- federated_learning, decentralized_memory, dao_governance, atomic_swap:
  fix self-imports to import enums from domain layer
- pricing.py: add timezone import, fix default_factory lambda, annotate validator
- __init__.py: remove invalid ser_json_tuples from ConfigDict

models/ — 0 errors (10 files):
- registry.py: add timezone import, fix default_factory lambda, annotate validator,
  add items field to ParameterDefinition (used at callsites)
- services.py: annotate validators with proper types, use ValidationInfo,
  fix no-any-return with explicit typed local
- confidential.py: rename metadata->extra_metadata (conflicts with SQLModel),
  add mypy disable for pydantic-field (raw SQLAlchemy Column pattern)

auth.py: add -> str return type
exceptions.py: fix Optional param defaults to use X | None annotations

pyproject.toml:
- Add pydantic.mypy plugin (fixes false Pydantic v2 positive errors)
- Remove models.* from ignore_errors override (layer now clean)
- Update clean-layer comment

51 source files now pass mypy with no errors.
Remaining ignore_errors: routers, services, storage, utils, contexts (coordinator-api)
and all blanket-suppressed apps.
This commit is contained in:
aitbc
2026-05-25 10:32:34 +02:00
parent 814c2ce891
commit 3d66d34173
12 changed files with 25 additions and 24 deletions

View File

@@ -1,2 +1,2 @@
def get_api_key(): def get_api_key() -> str:
return "test-key" return "test-key"

View File

@@ -102,7 +102,7 @@ class APIError(AITBCError):
error_code: str = "API_ERROR" error_code: str = "API_ERROR"
status_code: int = 500 status_code: int = 500
def __init__(self, message: str, status_code: int = None, response: dict = None): def __init__(self, message: str, status_code: int | None = None, response: dict[str, object] | None = None):
super().__init__(message) super().__init__(message)
self.status_code = status_code or self.status_code self.status_code = status_code or self.status_code
self.response = response self.response = response
@@ -144,7 +144,7 @@ class ValidationError(AITBCError):
error_code: str = "VALIDATION_ERROR" error_code: str = "VALIDATION_ERROR"
status_code: int = 422 status_code: int = 422
def __init__(self, message: str = "Validation failed", details: list[ErrorDetail] = None): def __init__(self, message: str = "Validation failed", details: list[ErrorDetail] | None = None):
super().__init__(message) super().__init__(message)
self.details = details or [] self.details = details or []
@@ -216,7 +216,7 @@ class QuotaExceededError(ConnectorError):
error_code: str = "QUOTA_EXCEEDED" error_code: str = "QUOTA_EXCEEDED"
status_code: int = 429 status_code: int = 429
def __init__(self, message: str = "Quota exceeded", limit: int = None): def __init__(self, message: str = "Quota exceeded", limit: int | None = None):
super().__init__(message) super().__init__(message)
self.limit = limit self.limit = limit

View File

@@ -1,6 +1,7 @@
""" """
Database models for confidential transactions Database models for confidential transactions
""" """
# mypy: disable-error-code="pydantic-field"
import uuid import uuid
@@ -152,7 +153,7 @@ class AuditAuthorizationDB(Base):
# Authorization data # Authorization data
signature = Column(String(512), nullable=False) signature = Column(String(512), nullable=False)
metadata = Column(JSON, nullable=True) extra_metadata = Column(JSON, nullable=True)
# Status # Status
active = Column(Boolean, nullable=False, default=True) active = Column(Boolean, nullable=False, default=True)

View File

@@ -2,7 +2,7 @@
Dynamic service registry models for AITBC Dynamic service registry models for AITBC
""" """
from datetime import datetime from datetime import datetime, timezone
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
@@ -56,6 +56,7 @@ class ParameterDefinition(BaseModel):
max_value: int | float | None = Field(None, description="Maximum value") max_value: int | float | None = Field(None, description="Maximum value")
options: list[str | int] | None = Field(None, description="Available options for enum type") options: list[str | int] | None = Field(None, description="Available options for enum type")
validation: dict[str, Any] | None = Field(None, description="Custom validation rules") validation: dict[str, Any] | None = Field(None, description="Custom validation rules")
items: dict[str, Any] | None = Field(None, description="Schema for array item type")
class HardwareRequirement(BaseModel): class HardwareRequirement(BaseModel):
@@ -112,7 +113,7 @@ class ServiceDefinition(BaseModel):
example_usage: dict[str, Any] | None = Field(None, description="Example usage") example_usage: dict[str, Any] | None = Field(None, description="Example usage")
@validator("id") @validator("id")
def validate_id(cls, v): def validate_id(cls, v: str) -> str:
if not v or not v.replace("_", "").replace("-", "").isalnum(): if not v or not v.replace("_", "").replace("-", "").isalnum():
raise ValueError("Service ID must contain only alphanumeric characters, hyphens, and underscores") raise ValueError("Service ID must contain only alphanumeric characters, hyphens, and underscores")
return v.lower() return v.lower()
@@ -122,7 +123,7 @@ class ServiceRegistry(BaseModel):
"""Service registry containing all available services""" """Service registry containing all available services"""
version: str = Field("1.0.0", description="Registry version") version: str = Field("1.0.0", description="Registry version")
last_updated: datetime = Field(default_factory=datetime.now(timezone.utc), description="Last update time") last_updated: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), description="Last update time")
services: dict[str, ServiceDefinition] = Field(..., description="Service definitions by ID") services: dict[str, ServiceDefinition] = Field(..., description="Service definitions by ID")
def get_service(self, service_id: str) -> ServiceDefinition | None: def get_service(self, service_id: str) -> ServiceDefinition | None:

View File

@@ -5,7 +5,7 @@ Service schemas for common GPU workloads
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, ValidationInfo, field_validator
class ServiceType(StrEnum): class ServiceType(StrEnum):
@@ -133,7 +133,7 @@ class StableDiffusionRequest(BaseModel):
@field_validator("seed") @field_validator("seed")
@classmethod @classmethod
def validate_seed(cls, v): def validate_seed(cls, v: int | list[int] | None) -> int | list[int] | None:
if v is not None and isinstance(v, list): if v is not None and isinstance(v, list):
if len(v) > 4: if len(v) > 4:
raise ValueError("Maximum 4 seeds allowed") raise ValueError("Maximum 4 seeds allowed")
@@ -308,7 +308,7 @@ class BlenderRequest(BaseModel):
@field_validator("frame_end") @field_validator("frame_end")
@classmethod @classmethod
def validate_frame_range(cls, v, info): def validate_frame_range(cls, v: int, info: ValidationInfo) -> int:
if info and info.data and "frame_start" in info.data and v < info.data["frame_start"]: if info and info.data and "frame_start" in info.data and v < info.data["frame_start"]:
raise ValueError("frame_end must be >= frame_start") raise ValueError("frame_end must be >= frame_start")
return v return v
@@ -346,7 +346,8 @@ class ServiceRequest(BaseModel):
} }
service_class = service_classes[self.service_type] service_class = service_classes[self.service_type]
return service_class(**self.request_data) result: WhisperRequest | StableDiffusionRequest | LLMRequest | FFmpegRequest | BlenderRequest = service_class(**self.request_data)
return result
# Service Response Schemas # Service Response Schemas

View File

@@ -395,7 +395,7 @@ class BlockListResponse(BaseModel):
class TransactionSummary(BaseModel): class TransactionSummary(BaseModel):
model_config = ConfigDict(populate_by_name=True, ser_json_tuples=True) model_config = ConfigDict(populate_by_name=True)
hash: str hash: str
block: str | int block: str | int

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from .atomic_swap import SwapStatus from ..domain.atomic_swap import SwapStatus
class SwapCreateRequest(BaseModel): class SwapCreateRequest(BaseModel):

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from .dao_governance import ProposalType from ..domain.dao_governance import ProposalType
class MemberCreate(BaseModel): class MemberCreate(BaseModel):

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from .decentralized_memory import MemoryType, StorageStatus from ..domain.decentralized_memory import MemoryType, StorageStatus
class MemoryNodeCreate(BaseModel): class MemoryNodeCreate(BaseModel):

View File

@@ -1,7 +1,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from .federated_learning import TrainingStatus from ..domain.federated_learning import TrainingStatus
class FederatedSessionCreate(BaseModel): class FederatedSessionCreate(BaseModel):

View File

@@ -3,7 +3,7 @@ Pricing API Schemas
Pydantic models for dynamic pricing API requests and responses Pydantic models for dynamic pricing API requests and responses
""" """
from datetime import datetime from datetime import datetime, timezone
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
@@ -64,7 +64,7 @@ class PricingStrategyRequest(BaseModel):
regions: list[str] | None = Field(None, description="Applicable regions") regions: list[str] | None = Field(None, description="Applicable regions")
@validator("constraints") @validator("constraints")
def validate_constraints(cls, v): def validate_constraints(cls, v: dict[str, Any] | None) -> dict[str, Any] | None:
if v is not None: if v is not None:
# Validate constraint fields # Validate constraint fields
if "min_price" in v and v["min_price"] is not None and v["min_price"] <= 0: if "min_price" in v and v["min_price"] is not None and v["min_price"] <= 0:
@@ -358,7 +358,7 @@ class PricingError(BaseModel):
error_code: str = Field(..., description="Error code") error_code: str = Field(..., description="Error code")
message: str = Field(..., description="Error message") message: str = Field(..., description="Error message")
details: dict[str, Any] | None = Field(None, description="Additional error details") details: dict[str, Any] | None = Field(None, description="Additional error details")
timestamp: datetime = Field(default_factory=datetime.now(timezone.utc), description="Error timestamp") timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc), description="Error timestamp")
class Config: class Config:
json_encoders = {datetime: lambda v: v.isoformat()} json_encoders = {datetime: lambda v: v.isoformat()}

View File

@@ -127,6 +127,7 @@ ensure_newline_before_comments = true
[tool.mypy] [tool.mypy]
python_version = "3.13" python_version = "3.13"
plugins = ["pydantic.mypy"]
exclude = "^apps/(agent-management|agent-coordinator|agent-services|blockchain-node|computing-node|identity-node|marketplace|mining-pool)/.*" exclude = "^apps/(agent-management|agent-coordinator|agent-services|blockchain-node|computing-node|identity-node|marketplace|mining-pool)/.*"
warn_return_any = true warn_return_any = true
warn_unused_configs = true warn_unused_configs = true
@@ -157,16 +158,13 @@ ignore_missing_imports = true
# Tech debt: these modules still have type errors that require per-file annotation work. # Tech debt: these modules still have type errors that require per-file annotation work.
# Tracked in gap analysis. Remove entries as each module is fixed. # Tracked in gap analysis. Remove entries as each module is fixed.
# Clean (no override needed): domain.*, schemas.*, auth, exceptions, models.*
[[tool.mypy.overrides]] [[tool.mypy.overrides]]
module = [ module = [
"apps.coordinator-api.src.app.routers.*", "apps.coordinator-api.src.app.routers.*",
"apps.coordinator-api.src.app.services.*", "apps.coordinator-api.src.app.services.*",
"apps.coordinator-api.src.app.storage.*", "apps.coordinator-api.src.app.storage.*",
"apps.coordinator-api.src.app.utils.*", "apps.coordinator-api.src.app.utils.*",
"apps.coordinator-api.src.app.schemas.*",
"apps.coordinator-api.src.app.models.*",
"apps.coordinator-api.src.app.auth",
"apps.coordinator-api.src.app.exceptions",
"apps.coordinator-api.src.app.contexts.*", "apps.coordinator-api.src.app.contexts.*",
] ]
ignore_errors = true ignore_errors = true