Repository navigation
Description
Created with Claude Code from the spec in #1341.
Parent
Sub-issue of #1341. Ticket 5 of 14.
What to build
A developer writes
@stackencrypt.model("users") # decorator name is an assumption; see PR #1284
class User:
email: Annotated[str, stackencrypt.TextEq]
age: Annotated[int, stackencrypt.Passthrough]on a dataclass, an attrs class, a Pydantic model, a NamedTuple or a SQLAlchemy declarative class, and the class statement either completes or raises DeclarationError at that line, with no credentials and no network. This ticket covers the reader and rule A only: every annotated field must carry exactly one marker.
Covered here: DECLARATION_NO_MARKER, DECLARATION_TWO_MARKERS, DECLARATION_NOT_OUTERMOST (the marker must be in the outermost Annotated, with the structural wrapper rule for Mapped[Annotated[...]]), Ignore fields leaving the plan. The plan the reader produces is the input to the next ticket.
Amendment: the code for a misplaced marker.
A marker in the wrong place now raises DECLARATION_MARKER_NOT_OUTERMOST, not DECLARATION_NOT_OUTERMOST. An example is Annotated[Mapped[str], TextEq].
The spec already uses DECLARATION_NOT_OUTERMOST for the decorator order. One code for two mistakes would give the developer the wrong remedy. The decorator order is checked in #1387.
PR #1433 also raises two codes from the spec early, because its review asked for them:
DECLARATION_HINTS_UNRESOLVED, for a hint that does not resolve.DECLARATION_ALREADY_DECLARED, for a class decorated twice.
Amendment: error codes are now lower_snake_case. See the amendment on #1341. Read each code in this issue in lower case, such as declaration_no_marker for DECLARATION_NO_MARKER.
Acceptance criteria
- Each of the five class kinds declares successfully with one
TextEqfield, onePassthroughfield and oneIgnorefield. - The three codes above raise
DeclarationErrorwith the field name and the code in the message. -
Mapped[Annotated[str, TextEq]]is accepted;Annotated[Mapped[str], TextEq]is refused withNOT_OUTERMOST. - A relationship marked
Ignoredoes not appear in the plan. - Tests run on 3.9 and 3.14 in CI, with and without
from __future__ import annotations.
Activity
refactor(python): use lower_snake_case error codes and reasons (#1386)
feat(python): read a model's declaration and check rule A (#1386)
refactor(python): use lower_snake_case error codes and reasons (#1386)