diff --git a/apps/coordinator-api/src/app/auth.py b/apps/coordinator-api/src/app/auth.py index 05a48677..183a5f7d 100755 --- a/apps/coordinator-api/src/app/auth.py +++ b/apps/coordinator-api/src/app/auth.py @@ -1,2 +1,2 @@ -def get_api_key(): +def get_api_key() -> str: return "test-key" diff --git a/apps/coordinator-api/src/app/exceptions.py b/apps/coordinator-api/src/app/exceptions.py index 4d783856..b62d8eef 100755 --- a/apps/coordinator-api/src/app/exceptions.py +++ b/apps/coordinator-api/src/app/exceptions.py @@ -102,7 +102,7 @@ class APIError(AITBCError): error_code: str = "API_ERROR" 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) self.status_code = status_code or self.status_code self.response = response @@ -144,7 +144,7 @@ class ValidationError(AITBCError): error_code: str = "VALIDATION_ERROR" 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) self.details = details or [] @@ -216,7 +216,7 @@ class QuotaExceededError(ConnectorError): error_code: str = "QUOTA_EXCEEDED" 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) self.limit = limit diff --git a/apps/coordinator-api/src/app/models/confidential.py b/apps/coordinator-api/src/app/models/confidential.py index e29f9251..bfedf984 100755 --- a/apps/coordinator-api/src/app/models/confidential.py +++ b/apps/coordinator-api/src/app/models/confidential.py @@ -1,6 +1,7 @@ """ Database models for confidential transactions """ +# mypy: disable-error-code="pydantic-field" import uuid @@ -152,7 +153,7 @@ class AuditAuthorizationDB(Base): # Authorization data signature = Column(String(512), nullable=False) - metadata = Column(JSON, nullable=True) + extra_metadata = Column(JSON, nullable=True) # Status active = Column(Boolean, nullable=False, default=True) diff --git a/apps/coordinator-api/src/app/models/registry.py b/apps/coordinator-api/src/app/models/registry.py index 89213ef2..29a84ccf 100755 --- a/apps/coordinator-api/src/app/models/registry.py +++ b/apps/coordinator-api/src/app/models/registry.py @@ -2,7 +2,7 @@ Dynamic service registry models for AITBC """ -from datetime import datetime +from datetime import datetime, timezone from enum import StrEnum from typing import Any @@ -56,6 +56,7 @@ class ParameterDefinition(BaseModel): max_value: int | float | None = Field(None, description="Maximum value") options: list[str | int] | None = Field(None, description="Available options for enum type") 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): @@ -112,7 +113,7 @@ class ServiceDefinition(BaseModel): example_usage: dict[str, Any] | None = Field(None, description="Example usage") @validator("id") - def validate_id(cls, v): + def validate_id(cls, v: str) -> str: if not v or not v.replace("_", "").replace("-", "").isalnum(): raise ValueError("Service ID must contain only alphanumeric characters, hyphens, and underscores") return v.lower() @@ -122,7 +123,7 @@ class ServiceRegistry(BaseModel): """Service registry containing all available services""" 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") def get_service(self, service_id: str) -> ServiceDefinition | None: diff --git a/apps/coordinator-api/src/app/models/services.py b/apps/coordinator-api/src/app/models/services.py index bb038e69..a4bbe1aa 100755 --- a/apps/coordinator-api/src/app/models/services.py +++ b/apps/coordinator-api/src/app/models/services.py @@ -5,7 +5,7 @@ Service schemas for common GPU workloads from enum import StrEnum from typing import Any -from pydantic import BaseModel, Field, field_validator +from pydantic import BaseModel, Field, ValidationInfo, field_validator class ServiceType(StrEnum): @@ -133,7 +133,7 @@ class StableDiffusionRequest(BaseModel): @field_validator("seed") @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 len(v) > 4: raise ValueError("Maximum 4 seeds allowed") @@ -308,7 +308,7 @@ class BlenderRequest(BaseModel): @field_validator("frame_end") @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"]: raise ValueError("frame_end must be >= frame_start") return v @@ -346,7 +346,8 @@ class ServiceRequest(BaseModel): } 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 diff --git a/apps/coordinator-api/src/app/schemas/__init__.py b/apps/coordinator-api/src/app/schemas/__init__.py index 1f139bf7..ba086647 100755 --- a/apps/coordinator-api/src/app/schemas/__init__.py +++ b/apps/coordinator-api/src/app/schemas/__init__.py @@ -395,7 +395,7 @@ class BlockListResponse(BaseModel): class TransactionSummary(BaseModel): - model_config = ConfigDict(populate_by_name=True, ser_json_tuples=True) + model_config = ConfigDict(populate_by_name=True) hash: str block: str | int diff --git a/apps/coordinator-api/src/app/schemas/atomic_swap.py b/apps/coordinator-api/src/app/schemas/atomic_swap.py index e0318fd1..ab746d67 100755 --- a/apps/coordinator-api/src/app/schemas/atomic_swap.py +++ b/apps/coordinator-api/src/app/schemas/atomic_swap.py @@ -1,7 +1,7 @@ from pydantic import BaseModel -from .atomic_swap import SwapStatus +from ..domain.atomic_swap import SwapStatus class SwapCreateRequest(BaseModel): diff --git a/apps/coordinator-api/src/app/schemas/dao_governance.py b/apps/coordinator-api/src/app/schemas/dao_governance.py index daf6811e..0bbdba0d 100755 --- a/apps/coordinator-api/src/app/schemas/dao_governance.py +++ b/apps/coordinator-api/src/app/schemas/dao_governance.py @@ -1,7 +1,7 @@ from pydantic import BaseModel, Field -from .dao_governance import ProposalType +from ..domain.dao_governance import ProposalType class MemberCreate(BaseModel): diff --git a/apps/coordinator-api/src/app/schemas/decentralized_memory.py b/apps/coordinator-api/src/app/schemas/decentralized_memory.py index 8554eb78..0be09ccc 100755 --- a/apps/coordinator-api/src/app/schemas/decentralized_memory.py +++ b/apps/coordinator-api/src/app/schemas/decentralized_memory.py @@ -1,7 +1,7 @@ from pydantic import BaseModel, Field -from .decentralized_memory import MemoryType, StorageStatus +from ..domain.decentralized_memory import MemoryType, StorageStatus class MemoryNodeCreate(BaseModel): diff --git a/apps/coordinator-api/src/app/schemas/federated_learning.py b/apps/coordinator-api/src/app/schemas/federated_learning.py index 3084338e..2a9db8f6 100755 --- a/apps/coordinator-api/src/app/schemas/federated_learning.py +++ b/apps/coordinator-api/src/app/schemas/federated_learning.py @@ -1,7 +1,7 @@ from pydantic import BaseModel -from .federated_learning import TrainingStatus +from ..domain.federated_learning import TrainingStatus class FederatedSessionCreate(BaseModel): diff --git a/apps/coordinator-api/src/app/schemas/pricing.py b/apps/coordinator-api/src/app/schemas/pricing.py index 98fdd3d3..d7bc303f 100755 --- a/apps/coordinator-api/src/app/schemas/pricing.py +++ b/apps/coordinator-api/src/app/schemas/pricing.py @@ -3,7 +3,7 @@ Pricing API Schemas Pydantic models for dynamic pricing API requests and responses """ -from datetime import datetime +from datetime import datetime, timezone from enum import StrEnum from typing import Any @@ -64,7 +64,7 @@ class PricingStrategyRequest(BaseModel): regions: list[str] | None = Field(None, description="Applicable regions") @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: # Validate constraint fields 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") message: str = Field(..., description="Error message") 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: json_encoders = {datetime: lambda v: v.isoformat()} diff --git a/pyproject.toml b/pyproject.toml index aaf793d2..f3da10a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,6 +127,7 @@ ensure_newline_before_comments = true [tool.mypy] python_version = "3.13" +plugins = ["pydantic.mypy"] exclude = "^apps/(agent-management|agent-coordinator|agent-services|blockchain-node|computing-node|identity-node|marketplace|mining-pool)/.*" warn_return_any = 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. # Tracked in gap analysis. Remove entries as each module is fixed. +# Clean (no override needed): domain.*, schemas.*, auth, exceptions, models.* [[tool.mypy.overrides]] module = [ "apps.coordinator-api.src.app.routers.*", "apps.coordinator-api.src.app.services.*", "apps.coordinator-api.src.app.storage.*", "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.*", ] ignore_errors = true