"""Shared collection and field-query contracts.""" from datetime import datetime from typing import Literal from pydantic import Field, model_validator from ..catalog.contracts import Scope from ..schemas import Contract class FieldFilters(Scope): q: str = Field(default="", max_length=300) dataset_id: str | None = None category: str | None = None subcategory: str | None = None field_type: str | None = None coverage_min: float | None = Field(default=None, ge=0, le=1) coverage_max: float | None = Field(default=None, ge=0, le=1) user_count_min: int | None = Field(default=None, ge=0) user_count_max: int | None = Field(default=None, ge=0) alpha_count_min: int | None = Field(default=None, ge=0) alpha_count_max: int | None = Field(default=None, ge=0) synced_from: datetime | None = None synced_to: datetime | None = None sort: Literal["id", "name", "dataset_id", "coverage", "user_count", "alpha_count", "synced_at"] = "id" direction: Literal["asc", "desc"] = "asc" limit: int = Field(default=25, ge=1, le=100) offset: int = Field(default=0, ge=0) @model_validator(mode="after") def ranges(self): for key in ("coverage", "user_count", "alpha_count"): low, high = getattr(self, key + "_min"), getattr(self, key + "_max") if low is not None and high is not None and low > high: raise ValueError("筛选下限不能超过上限") return self class FieldReference(Contract): scope: Scope dataset_id: str = Field(min_length=1, max_length=200) field_id: str = Field(min_length=1, max_length=200) source: Literal["local", "worldquant"] = "local" collection_version: str | None = None class PreparationCreate(Contract): name: str = Field(min_length=1, max_length=200) note: str = Field(default="", max_length=20000) scope: Scope fields: list[FieldReference] = Field(default_factory=list, max_length=10000) class PreparationVersion(Contract): version: int = Field(ge=1) class PreparationEdit(PreparationVersion): name: str = Field(min_length=1, max_length=200) note: str = Field(default="", max_length=20000) class MemberChange(PreparationVersion): fields: list[FieldReference] = Field(default_factory=list, max_length=10000) remove_ids: list[str] = Field(default_factory=list, max_length=10000) class PreparationReference(PreparationVersion): id: str = Field(min_length=1, max_length=36) class PreparationReferences(Contract): items: list[PreparationReference] = Field(min_length=1, max_length=100) class DatasetCopy(Contract): scope: Scope dataset_id: str = Field(min_length=1, max_length=200) collection_version: str