Skip to main content

Render valbridge IR into Pydantic v2 models

Project description

valbridge-pydantic

valbridge adapter for generating Pydantic v2 models from JSON Schema.

Verified against pydantic 2.12.5.

Local Verification

All commands run from the adapter directory (python/packages/adapters/pydantic/).

Compliance (runtime validation)

# from repo root cli/ directory — builds CLI then runs full compliance
cd ../../cli && go build -o valbridge . && ./valbridge compliance --lang python --adapter-path ../python/packages/adapters/pydantic

Unit tests

uv run pytest

Type checking (static)

uv run pyright src/

Fallback Typing Guardrails

Allowed Any fallbacks

These constructs produce Annotated[Any, BeforeValidator(...)] by design. The static type is Any because the semantic domain is unbounded — no Python type expression can represent the true set of valid values.

Construct Reason Example
not Negation is "everything except X" — no union can express this not: { type: "string" } accepts any non-string
conditional (if/then only, if/else only) When only one branch exists, values not matching if pass through unconstrained if: {...}, then: {...} with no else
typeGuarded (heterogeneous dispatch) Unmatched types pass through the guard — domain is unbounded Type guard with object/array branches, but string input passes
Open tuple (no items: false) Extra elements beyond prefix items are untyped prefixItems: [string, int] without items: false
Recursive refs Self-referencing $ref (cycle detected, path starts with #) $ref: "#" or $ref: "#/$defs/TreeNode"

Narrowed constructs (must NOT use Any)

These constructs must produce a narrower type than Any.

Construct Expected type How it narrows
oneOf T1 | T2 | ... _union_base_type() computes union from sub-schema types
conditional (if/then/else) ThenType | ElseType _union_base_type([then_type, else_type])
Closed tuple (items: false) tuple[T1 | T2, ...] _union_base_type(item_types) on prefix items
Tuple with rest schema tuple[T1 | ... | TRest, ...] _union_base_type(item_types + [rest_type])
const (object) dict _json_value_type(value)
const (array) list _json_value_type(value)
const (primitive) bool, int, float, str, None _json_value_type(value)
enum (complex values) dict | str, list | int, etc. _json_values_union_type(values)
allOf (object merges) BaseModel subclass Intersection merges fields into a single model
Type-guarded object BaseModel subclass Guard dispatches to object renderer

Disallowed patterns

These patterns are errors. The renderer must raise ConversionError instead:

  • Unknown IR node kind: the catch-all case _: in render() raises ConversionError
  • Unresolved external refs: render_ref raises ConversionError when resolved is None and path doesn't start with #
  • Silent Any fallback: new renderer branches must NOT return Any without an explicit, documented reason. If a construct can be narrowed, it must be.

Required test coverage for new renderer branches

When adding or modifying a renderer function:

  1. If the branch produces Any: add a unit test proving it (e.g. test_render_not_stays_any) and document the reason in the "Allowed Any fallbacks" table above
  2. If the branch produces a narrower type: add a unit test proving the narrow type (e.g. test_render_oneof_narrows_primitives)
  3. If the branch raises ConversionError: add a unit test proving the error (e.g. test_render_unknown_ir_kind_raises)
  4. Compliance must not regress: run full compliance after any renderer change

Troubleshooting

pyright errors on src/

The adapter source must pass uv run pyright src/ with zero errors. Common issues:

  • reveal_type() left in source code — remove before committing
  • Missing type stubs — add to pyproject.toml [tool.pyright] config
  • Any in type annotations — use explicit types or object where possible

Compliance failures after renderer changes

Run the full compliance suite and compare against baseline. Common causes:

  • Changed runtime validation behavior (not just types) — the validator lambda must be functionally identical
  • Changed intersection mutation semantics — intersection validators must NOT reassign v
  • Type guard check too narrow — isinstance(v, (list, tuple)) not just isinstance(v, list) for array checks

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

valbridge_pydantic-0.4.1.tar.gz (61.7 kB view details)

Uploaded Source

Built Distribution

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

valbridge_pydantic-0.4.1-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file valbridge_pydantic-0.4.1.tar.gz.

File metadata

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

File hashes

Hashes for valbridge_pydantic-0.4.1.tar.gz
Algorithm Hash digest
SHA256 56cd63959711535e1d8f09d076e879a3099d5f54423561d6b9b3a0c2076f8007
MD5 822ad464cee1181230d0827f789f3f6b
BLAKE2b-256 cf2bb32f9155870623a2f826b6cea5cf32788eddfdebf75d45600e8c90444e48

See more details on using hashes here.

Provenance

The following attestation bundles were made for valbridge_pydantic-0.4.1.tar.gz:

Publisher: release-please.yml on vectorfy-co/valbridge

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

File details

Details for the file valbridge_pydantic-0.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for valbridge_pydantic-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 70955227986e91a55d7b56c5c52ad4f6f19f47ee27114291b1bcc55363f9f75f
MD5 100286b09467ed169316c493030f96ac
BLAKE2b-256 2bde27d6934e5395fc052f4720c50445fc6689c50977c89727c18e0e37681d4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for valbridge_pydantic-0.4.1-py3-none-any.whl:

Publisher: release-please.yml on vectorfy-co/valbridge

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