PathBridge
Bridge validator locations (XPath/JSONPath/JSON Pointer) back to your application model paths, and emit structured errors (Marshmallow-ready).
Why
Validators (XSD/Schematron, JSON Schema) report failures at document locations (XPath/JSONPath).
Your users need errors on your model (Pydantic/Marshmallow/dataclasses). PathBridge converts between the two.
- Prefix & case tolerant (e.g.,
hd:,MTR:). - Fixes 1-based indices to Python 0-based.
- Works with plain mappings or an optional tracer (add-on) that learns rules from your converter.
- Includes
make_shape(shaper) andbuild_rules(tracer) to generate rules from destination classes and your converter.
Install
pip install pathbridge
Quick start
from pathbridge import compile_rules, translate_location, to_marshmallow
# 1. Provide or load rules: destination path -> facade (your app models) path
rules = {
"Return[1]/Contact[1]/Phone[1]": "person/phones[0]",
"Return[1]/Contact[1]/Phone[2]": "person/phones[1]",
}
compiled = compile_rules(rules)
# 2. Translate validator location (e.g. from Schematron SVRL)
loc = "/Return[1]/Contact[1]/Phone[2]"
print(translate_location(loc, compiled))
# "person/phones[1]"
# 3. Transform error location into a Marshmallow-style error dict
errors = to_marshmallow([(loc, "Invalid phone")], compiled)
# {'person': {'phones': {1: ['Invalid phone']}}}
Extras
pathbridge.extras provides helper utilities for generating rules from your
converter:
make_shape(...): build a populated sample facade object.build_rules(...): trace a sample conversion and produceDestination -> Facademapping rules.
Extras example
import dataclasses
import types
from pathbridge import compile_rules, to_marshmallow
from pathbridge.extras import build_rules, make_shape
@dataclasses.dataclass
class FacadeName:
first: str
last: str
@dataclasses.dataclass
class Facade:
name: FacadeName
phones: list[str]
@dataclasses.dataclass
class NameXml:
first_name: str = dataclasses.field(metadata={"name": "FirstName"})
surname: str = dataclasses.field(metadata={"name": "Surname"})
@dataclasses.dataclass
class ReturnXml:
name: NameXml = dataclasses.field(metadata={"name": "YourName"})
phones: list[str] = dataclasses.field(metadata={"name": "Phone"})
class Meta:
name = "Return"
def convert(src: Facade) -> ReturnXml:
return ReturnXml(
name=NameXml(first_name=src.name.first, surname=src.name.last),
phones=src.phones,
)
shape = make_shape(Facade, list_len=2)
rules = build_rules(
destination_module=types.SimpleNamespace(ReturnXml=ReturnXml, NameXml=NameXml),
facade_to_destination=convert,
facade_shape=shape,
facade_root_tag="facade",
)
compiled = compile_rules(rules)
errors = to_marshmallow(
[
("/Return[1]/NameXml[1]/FirstName[1]", "Required field"),
("/Return[1]/Phone[2]/Phone[1]", "Invalid phone"),
],
compiled,
)
print(rules)
# {
# 'Return[1]/NameXml[1]/FirstName[1]': 'facade/name/first',
# 'Return[1]/Phone[2]/Phone[1]': 'facade/phones[1]',
# ...
# }
print(errors)
# {
# 'facade': {
# 'name': {'first': ['Required field']},
# 'phones': {1: ['Invalid phone']},
# }
# }
Custom shape defaults
make_shape(...) accepts type_defaults so you can override generated defaults
for specific types:
from decimal import Decimal
shape = make_shape(
Facade,
list_len=2,
type_defaults={
str: "sample",
int: 42,
Decimal: Decimal("1.23"),
},
)
CLI
PathBridge provides a pathbridge CLI with a compile command that runs:
make_shape(...)build_rules(...)compile_rules(...)(when--emitincludes compiled output)- Python module generation
CLI example
Run from the repository root:
pathbridge compile \
--output-dir . \
--output-package mtr.translation_rules \
--output-module compiled \
--facade-class ./tests/integration/hmrc_main_tax_return/facade/mtr_facade.py:MTR \
--destination-module ./tests/integration/hmrc_main_tax_return/destination/mtr_v1_1.py \
--facade-to-destination ./tests/integration/hmrc_main_tax_return/converter/mtr_converter.py:to_mtr_v1_1 \
--shape-list-len 10 \
--facade-root-tag mtr \
--lift-functions _yes \
--lift-functions _yes_no \
--lift-functions _tax_payer_status \
--lift-functions _student_loan_plan \
--lift-functions _postgraduate_loan_plan \
--lift-functions _attachment_file_format \
--lift-functions decimal_str_or_none \
--lift-functions xml_date_or_none \
--lift-functions decode_attachment
Help
See documentation for more details.
Real-world examples
Real-life PathBridge integrations:
Metadata
Release files for PathBridge 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pathbridge-0.5.1.tar.gz | 19.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pathbridge-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.2 kB
Release files / pathbridge-0.5.1.tar.gz
| Download URL | pathbridge-0.5.1.tar.gz |
|---|---|
| Size | 19.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ad45b60947c9ff293013dbd8aacb176fb8ba3c50aae954349f8b8883d1954500
|
|
BLAKE2b-256 checksum How to use checksums |
884243c01505051cc43e1c4cf612d6a1e5f76028857fe7735d45e2e74c1e263f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pathbridge-0.5.1-py3-none-any.whl
| Download URL | pathbridge-0.5.1-py3-none-any.whl |
|---|---|
| Size | 22.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4cea237de8dcd840c3824ab59de8c7fe5d7ea97b063077dfd9af553f11dd60df
|
|
BLAKE2b-256 checksum How to use checksums |
3928fd4812f3f03f4831f3717929cb17c65903ea8b5a463b4e5953162a812caa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|