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.1.0.tar.gz (59.9 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.1.0-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for valbridge_pydantic-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4acf70baec92f34e4dc943288a2804040bfd93e7a9dd3d53ad268d63a98bce16
MD5 999704871fee3cf803851d2ae225accd
BLAKE2b-256 d7c23cf1eb0137348e86daed1f7285af9ce80f355dc2a53981307df45328f828

See more details on using hashes here.

Provenance

The following attestation bundles were made for valbridge_pydantic-0.1.0.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.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for valbridge_pydantic-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1bced99ca7f76b7abcef395c04252253b4b72e2dc515387c94e1222b89de90e6
MD5 ac471d01b5834df93a57888c2e912e53
BLAKE2b-256 d6cb69bd9f6a8e6148c656c43f9609a701bbe18b30f26df2e342f6bef32f0ad8

See more details on using hashes here.

Provenance

The following attestation bundles were made for valbridge_pydantic-0.1.0-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