Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/codealmanac/core/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
from pydantic import BaseModel, ConfigDict
from typing import Annotated

from pydantic import AfterValidator, BaseModel, ConfigDict


class CodeAlmanacModel(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")


def _require_non_negative_limit(value: int | None) -> int | None:
if value is not None and value < 0:
raise ValueError("limit must be non-negative")
return value


NonNegativeLimit = Annotated[int | None, AfterValidator(_require_non_negative_limit)]
RequiredNonNegativeLimit = Annotated[int, AfterValidator(_require_non_negative_limit)]
6 changes: 6 additions & 0 deletions src/codealmanac/core/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ def required_text(value: str, field_name: str) -> str:
if not text:
raise ValueError(f"{field_name} must not be empty")
return text


def optional_text(value: str | None, field_name: str) -> str | None:
if value is None:
return None
return required_text(value, field_name)
13 changes: 2 additions & 11 deletions src/codealmanac/services/index/requests.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
from pathlib import Path

from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.models import CodeAlmanacModel, NonNegativeLimit
from codealmanac.services.repositories.models import RepositoryName


class SearchIndexRequest(CodeAlmanacModel):
query: str | None = None
topics: tuple[str, ...] = ()
mentions: str | None = None
limit: int | None = None

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int | None) -> int | None:
if value is not None and value < 0:
raise ValueError("limit must be non-negative")
return value
limit: NonNegativeLimit = None


class ReindexRequest(CodeAlmanacModel):
Expand Down
6 changes: 2 additions & 4 deletions src/codealmanac/services/runs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pydantic import StringConstraints, field_validator, model_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.text import required_text
from codealmanac.core.text import optional_text, required_text
from codealmanac.services.harnesses.models import (
HarnessEvent,
HarnessKind,
Expand Down Expand Up @@ -187,9 +187,7 @@ def require_ingest_input_text(cls, value: tuple[str, ...]) -> tuple[str, ...]:
@field_validator("model", "title", "guidance")
@classmethod
def require_optional_text(cls, value: str | None) -> str | None:
if value is None:
return None
return required_text(value, "run spec text")
return optional_text(value, "run spec text")

@model_validator(mode="after")
def validate_kind_payload(self) -> "RunSpec":
Expand Down
11 changes: 2 additions & 9 deletions src/codealmanac/services/runs/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pydantic import field_validator, model_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.models import CodeAlmanacModel, NonNegativeLimit
from codealmanac.core.text import required_text
from codealmanac.services.harnesses.models import HarnessEvent, HarnessTranscriptRef
from codealmanac.services.repositories.models import RepositoryName
Expand All @@ -21,14 +21,7 @@

class ListRunsRequest(CodeAlmanacModel):
repository_name: RepositoryName | None = None
limit: int | None = None

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int | None) -> int | None:
if value is not None and value < 0:
raise ValueError("limit must be non-negative")
return value
limit: NonNegativeLimit = None


class ShowRunRequest(CodeAlmanacModel):
Expand Down
13 changes: 2 additions & 11 deletions src/codealmanac/services/search/requests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from pathlib import Path

from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.models import CodeAlmanacModel, NonNegativeLimit
from codealmanac.services.repositories.models import RepositoryName


Expand All @@ -12,11 +10,4 @@ class SearchPagesRequest(CodeAlmanacModel):
query: str | None = None
topics: tuple[str, ...] = ()
mentions: str | None = None
limit: int | None = None

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int | None) -> int | None:
if value is not None and value < 0:
raise ValueError("limit must be non-negative")
return value
limit: NonNegativeLimit = None
33 changes: 8 additions & 25 deletions src/codealmanac/services/viewer/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.models import (
CodeAlmanacModel,
NonNegativeLimit,
RequiredNonNegativeLimit,
)
from codealmanac.core.text import required_text
from codealmanac.services.repositories.models import RepositoryName
from codealmanac.services.runs.models import RunId
Expand Down Expand Up @@ -41,21 +45,14 @@ class ViewerSearchRequest(CodeAlmanacModel):
cwd: Path
repository_name: RepositoryName | None = None
query: str | None = None
limit: int = 50

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int) -> int:
if value < 0:
raise ValueError("limit must be non-negative")
return value
limit: RequiredNonNegativeLimit = 50


class ViewerFileRequest(CodeAlmanacModel):
cwd: Path
path: str
repository_name: RepositoryName | None = None
limit: int = 50
limit: RequiredNonNegativeLimit = 50

@field_validator("path")
@classmethod
Expand All @@ -69,13 +66,6 @@ def normalize_file_path(cls, value: str) -> str:
raise ValueError("file path must be repo-relative")
return normalized

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int) -> int:
if value < 0:
raise ValueError("limit must be non-negative")
return value


class ViewerTopicRequest(CodeAlmanacModel):
cwd: Path
Expand All @@ -92,14 +82,7 @@ def require_slug(cls, value: str) -> str:
class ViewerJobsRequest(CodeAlmanacModel):
cwd: Path
repository_name: RepositoryName | None = None
limit: int | None = None

@field_validator("limit")
@classmethod
def non_negative_limit(cls, value: int | None) -> int | None:
if value is not None and value < 0:
raise ValueError("limit must be non-negative")
return value
limit: NonNegativeLimit = None


class ViewerJobRequest(CodeAlmanacModel):
Expand Down
10 changes: 3 additions & 7 deletions src/codealmanac/workflows/build/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.text import required_text
from codealmanac.core.text import optional_text
from codealmanac.services.harnesses.models import HarnessKind
from codealmanac.services.repositories.models import RepositoryName
from codealmanac.services.runs.models import RunId
Expand All @@ -22,9 +22,7 @@ class BuildRequest(CodeAlmanacModel):
@field_validator("model", "title", "guidance")
@classmethod
def require_optional_text(cls, value: str | None) -> str | None:
if value is None:
return None
return required_text(value, "build request text")
return optional_text(value, "build request text")


class StartedBuildRequest(CodeAlmanacModel):
Expand All @@ -40,6 +38,4 @@ class StartedBuildRequest(CodeAlmanacModel):
@field_validator("model", "title", "guidance")
@classmethod
def require_optional_text(cls, value: str | None) -> str | None:
if value is None:
return None
return required_text(value, "build request text")
return optional_text(value, "build request text")
6 changes: 2 additions & 4 deletions src/codealmanac/workflows/garden/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.text import required_text
from codealmanac.core.text import optional_text
from codealmanac.services.harnesses.models import HarnessKind
from codealmanac.services.repositories.models import RepositoryName
from codealmanac.services.runs.models import RunId
Expand All @@ -21,9 +21,7 @@ class GardenRequest(CodeAlmanacModel):
@field_validator("model", "title", "guidance")
@classmethod
def require_optional_text(cls, value: str | None) -> str | None:
if value is None:
return None
return required_text(value, "garden request text")
return optional_text(value, "garden request text")


class StartedGardenRequest(GardenRequest):
Expand Down
6 changes: 2 additions & 4 deletions src/codealmanac/workflows/ingest/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pydantic import field_validator

from codealmanac.core.models import CodeAlmanacModel
from codealmanac.core.text import required_text
from codealmanac.core.text import optional_text
from codealmanac.services.harnesses.models import HarnessKind
from codealmanac.services.repositories.models import RepositoryName
from codealmanac.services.runs.models import RunId
Expand All @@ -29,9 +29,7 @@ def require_inputs(cls, value: tuple[str, ...]) -> tuple[str, ...]:
@field_validator("model", "title", "guidance")
@classmethod
def require_optional_text(cls, value: str | None) -> str | None:
if value is None:
return None
return required_text(value, "ingest request text")
return optional_text(value, "ingest request text")


class StartedIngestRequest(IngestRequest):
Expand Down
Loading