Skip to main content

One canonical pydantic model, many scoped projections — with a relationship graph that survives them.

Project description

pydantic-prism

Tests Coverage Skipped XFailed Warnings Duration Last run

Project one canonical pydantic model along any axis — and keep the relationship graph that survives the projection.

Tag a single model's fields with named scopes; derive real pydantic.BaseModel subclasses per scope (API response, storage row, LLM tool input, audit log) with working validation, serialization, and JSON schema. Declare FK-style references in the same metadata and introspect them through __refs__ — the graph survives every projection. The projection half has prior art; combining it with an introspectable relationship graph does not.

30 seconds

from typing import Annotated
from uuid import UUID

from pydantic_prism import Scope, ScopedModel, scoped


class Public(Scope): ...
class Internal(Public): ...   # Internal sees everything Public sees
class Storage(Internal): ...  # Storage sees everything Internal sees


class User(ScopedModel):
    id: Annotated[UUID, scoped(Public)]
    email: Annotated[str, scoped(Internal)]
    password_hash: Annotated[str, scoped(Storage)]
    display_name: Annotated[str, scoped(Public)]


UserPublic = User.scope(Public)      # fields: id, display_name
UserInternal = User.scope(Internal)  # fields: id, email, display_name
UserStorage = User.scope(Storage)    # all four fields

UserPublic is a real, cached BaseModel subclass named "UserPublic"User.scope(Public) is User.scope(Public), so FastAPI response models and OpenAPI component schemas stay stable.

Scopes are classes; inheritance forms the scope graph, so the membership rule is one line: a field tagged T is in projection S iff issubclass(S, T). Untagged fields belong to no scope and can never leak into a projection. Scopes compose with set operators (| & - ~), both in field tags and at the call site.

Why not hand-write UserIn / UserOut?

Parallel classes drift from the canonical, lose constraints, and have no idea your models reference each other. Prism derives every face from one source of truth and keeps the references coherent across all of them. See projections, not inheritance.

In fact prism derives those two faces by name: tag read-only fields Out and write-only fields In, then User.input(Public) (a UserIn that drops read-only fields and forbids unknown keys — mass-assignment-safe by shape) and User.output(Public) (a UserOut that never echoes write-only fields). See prevent mass-assignment.

Install

pip install pydantic-prism        # pydantic >= 2.12, Python >= 3.12

Documentation

The docs follow the Diátaxis framework — start where your need fits:

ROADMAP.md lists what is shipped, planned, and deliberately out of scope.

Gotchas

  • Before-validator ordering. A @scoped_validator(mode="before") runs before a plain @model_validator(mode="before") it inherits from a base (pydantic is child-first), so a child depending on the base hook's transformation sees raw data. prism warns at class definition. Prefer mode="after" (no race); else call run_inherited_before in the validator. See carry a custom base.

Develop

pdm install -G dev
bin/test.sh                       # pytest with coverage (100% gate)
bin/autoformat.sh                 # ruff format + ruff check --fix
pdm run pyright                   # strict, src/

MIT licensed. Built on the public pydantic API only — no pydantic._internal.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydantic_prism-0.5.0.tar.gz (111.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydantic_prism-0.5.0-py3-none-any.whl (73.9 kB view details)

Uploaded Python 3

File details

Details for the file pydantic_prism-0.5.0.tar.gz.

File metadata

  • Download URL: pydantic_prism-0.5.0.tar.gz
  • Upload date:
  • Size: 111.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydantic_prism-0.5.0.tar.gz
Algorithm Hash digest
SHA256 f2c81680bf26f4048fc7e88edd7bb2132e30aaee0cfc7865683919500e833cce
MD5 949226459a0e2f6f0570770b931aef05
BLAKE2b-256 b193d9f40b86d38fb90e37c239d2063d391b91aed6c6406abcd9acf87915f1f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydantic_prism-0.5.0.tar.gz:

Publisher: release.yml on release-art/pydantic-prism

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydantic_prism-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: pydantic_prism-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 73.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydantic_prism-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 075cc033489b5f5a3f6cd8d87d6222469fb0e6d27a43cc380233bfeab8bc9d7a
MD5 1410e16784708b8e43deb771d04cc261
BLAKE2b-256 960358fdb4f6ae77a380f85f5eb6774abe015ba19af4decc29a2dd761a2e89e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydantic_prism-0.5.0-py3-none-any.whl:

Publisher: release.yml on release-art/pydantic-prism

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page