One canonical pydantic model, many scoped projections — with a relationship graph that survives them.
Project description
pydantic-prism
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:
- Documentation home — the full table of contents.
- Tutorial: your first scoped model — one hand-held lesson, one model to two projections.
- How-to guides — short recipes: redact PII, trace data flow, PATCH models, LLM tool schemas, FastAPI, ORM bridge, editor stubs, diagrams.
- Reference — the API,
the
pydantic-prismCLI, and the error table. - Explanation — the scope algebra, why
projections aren't inheritance, what
ref()does and does not model.
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. Prefermode="after"(no race); else callrun_inherited_beforein 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2c81680bf26f4048fc7e88edd7bb2132e30aaee0cfc7865683919500e833cce
|
|
| MD5 |
949226459a0e2f6f0570770b931aef05
|
|
| BLAKE2b-256 |
b193d9f40b86d38fb90e37c239d2063d391b91aed6c6406abcd9acf87915f1f3
|
Provenance
The following attestation bundles were made for pydantic_prism-0.5.0.tar.gz:
Publisher:
release.yml on release-art/pydantic-prism
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pydantic_prism-0.5.0.tar.gz -
Subject digest:
f2c81680bf26f4048fc7e88edd7bb2132e30aaee0cfc7865683919500e833cce - Sigstore transparency entry: 1794464114
- Sigstore integration time:
-
Permalink:
release-art/pydantic-prism@c2d551ca13e23ca5655a573f5764e746d486bc63 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/release-art
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c2d551ca13e23ca5655a573f5764e746d486bc63 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
075cc033489b5f5a3f6cd8d87d6222469fb0e6d27a43cc380233bfeab8bc9d7a
|
|
| MD5 |
1410e16784708b8e43deb771d04cc261
|
|
| BLAKE2b-256 |
960358fdb4f6ae77a380f85f5eb6774abe015ba19af4decc29a2dd761a2e89e3
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pydantic_prism-0.5.0-py3-none-any.whl -
Subject digest:
075cc033489b5f5a3f6cd8d87d6222469fb0e6d27a43cc380233bfeab8bc9d7a - Sigstore transparency entry: 1794464347
- Sigstore integration time:
-
Permalink:
release-art/pydantic-prism@c2d551ca13e23ca5655a573f5764e746d486bc63 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/release-art
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c2d551ca13e23ca5655a573f5764e746d486bc63 -
Trigger Event:
push
-
Statement type: