Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
b19362f
Add MappedConstraint dataclass for constraint mapping
rich-iannone Jun 13, 2026
a4f2bfa
Add ContractImport dataclass for schema imports
rich-iannone Jun 13, 2026
3985521
Add ContractImport.to_validate() builder
rich-iannone Jun 13, 2026
3172452
Add to_contract() method to ContractImport
rich-iannone Jun 13, 2026
d2df1e2
Add ContractAdapter base class
rich-iannone Jun 13, 2026
7868b29
Add import/export contract methods to adapter
rich-iannone Jun 13, 2026
a783451
Add import_contract API for adapters
rich-iannone Jun 13, 2026
862f5d5
Add export_contract to adapters API
rich-iannone Jun 13, 2026
2dd9736
Add export and summary methods to ContractImport
rich-iannone Jun 13, 2026
cc172a7
Add Frictionless adapter module
rich-iannone Jun 13, 2026
0d2b29c
Add FrictionlessAdapter for Table Schema
rich-iannone Jun 13, 2026
c8003be
Add import_contract to FrictionlessAdapter
rich-iannone Jun 13, 2026
8c46d85
Add export_contract to FrictionlessAdapter
rich-iannone Jun 13, 2026
dbae922
Add _extract_table_schema() to FrictionlessAdapter
rich-iannone Jun 13, 2026
803d4cb
Add Frictionless Table Schema parser
rich-iannone Jun 13, 2026
81ac2ec
Add _export_from_contract() to FrictionlessAdapter
rich-iannone Jun 13, 2026
67b71bd
Add _export_from_validate() to FrictionlessAdapter
rich-iannone Jun 13, 2026
c94b8ce
Add dtype-to-Frictionless type mapper
rich-iannone Jun 13, 2026
fca1196
Add _apply_step_to_fields() to Frictionless adapter
rich-iannone Jun 13, 2026
160f4e6
Add helper to extract validate step kwargs
rich-iannone Jun 13, 2026
79385de
Add JSON Schema adapter skeleton
rich-iannone Jun 13, 2026
c94929c
Add JSONSchemaAdapter for JSON Schema
rich-iannone Jun 13, 2026
3b886cd
Add import_contract() to JSONSchemaAdapter
rich-iannone Jun 13, 2026
9c1a4dd
Add export_contract to JSONSchemaAdapter
rich-iannone Jun 13, 2026
1e97676
Update _json_schema.py
rich-iannone Jun 13, 2026
4e8aa55
Add JSONSchemaAdapter._parse_schema() method
rich-iannone Jun 13, 2026
fc2b88a
Add _export_from_contract() to JSONSchemaAdapter
rich-iannone Jun 13, 2026
5812774
Add _export_from_validate() to JSONSchemaAdapter
rich-iannone Jun 13, 2026
579852a
Add dtype to JSON Schema type mapper
rich-iannone Jun 13, 2026
61adc3a
Add _apply_step_to_properties() helper
rich-iannone Jun 13, 2026
9c23973
Add helper to extract step kwargs
rich-iannone Jun 13, 2026
3c65a6b
Add global adapter registry and register decorator
rich-iannone Jun 13, 2026
9aac72f
Add get_adapter() function to registry
rich-iannone Jun 13, 2026
bce845a
Add list_adapters to adapter registry
rich-iannone Jun 13, 2026
4d7cc6f
Add adapter format detection helper
rich-iannone Jun 13, 2026
4a63063
Add adapters package initializer
rich-iannone Jun 13, 2026
229f751
Expose adapter API at package root
rich-iannone Jun 13, 2026
830884b
Add contract import/export to __all__
rich-iannone Jun 13, 2026
d79f99a
Add Contract Import/Export docs section
rich-iannone Jun 13, 2026
6592072
Add adapter tests and fixtures
rich-iannone Jun 13, 2026
bbe4e97
Update test_adapters.py
rich-iannone Jun 13, 2026
e09ec23
Add tests for adapter registry
rich-iannone Jun 13, 2026
2a8bac4
Add tests for ContractImport
rich-iannone Jun 13, 2026
e273321
Add JSON Schema import tests
rich-iannone Jun 13, 2026
955b70d
Add JSON Schema and Frictionless adapter tests
rich-iannone Jun 13, 2026
0d6870c
Add adapter import/export and roundtrip tests
rich-iannone Jun 13, 2026
74b34ef
Create 04-importing-contracts.qmd
rich-iannone Jun 13, 2026
52e54a6
Create 05-custom-adapters.qmd
rich-iannone Jun 13, 2026
2a34d73
Update index.qmd
rich-iannone Jun 13, 2026
5c46500
Update 02-installation.qmd
rich-iannone Jun 13, 2026
30f5974
Update 02-cli-data-validation.qmd
rich-iannone Jun 13, 2026
2224ad0
Update 01-otel-integration.qmd
rich-iannone Jun 13, 2026
3e6d54f
Update 03-yaml-contracts.qmd
rich-iannone Jun 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion blog/validation-libs-2025/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ creating custom validation classes that fit into its modular validation catalog.

### Unique Strengths and When to Use

- beautiful, interactive HTML reports perfect for sharing with stakeholders
- beautiful, interactive HTML reports that are great for sharing with stakeholders
- threshold-based alerting system with configurable actions
- segmented validation for analyzing subsets of data
- LLM-powered validation suggestions via `DraftValidation`
Expand Down
16 changes: 16 additions & 0 deletions great-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,22 @@ reference:
- name: PipelineResult
members: true

- title: Contract Import/Export
desc: >
Import external schema definitions (JSON Schema, Frictionless Table Schema, and more)
into Pointblank validation workflows, or export Pointblank contracts to those formats.
Use `import_contract()` as the entry point, `export_contract()` for the reverse, and
`register_adapter()` to add support for custom formats.
contents:
- import_contract
- export_contract
- list_adapters
- register_adapter
- name: ContractImport
members: true
- name: ContractAdapter
members: true

- title: Validation Steps
desc: >
Validation steps are sequential validations on the target data. Call Validate's
Expand Down
15 changes: 15 additions & 0 deletions pointblank/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@

# Import objects from the module
from pointblank.actions import send_slack_notification
from pointblank.adapters import (
ContractAdapter,
ContractImport,
export_contract,
import_contract,
list_adapters,
register_adapter,
)
from pointblank.assistant import assistant
from pointblank.column import (
col,
Expand Down Expand Up @@ -147,4 +155,11 @@
"yaml_interrogate",
"validate_yaml",
"yaml_to_python",
# Contract import/export
"ContractAdapter",
"ContractImport",
"import_contract",
"export_contract",
"list_adapters",
"register_adapter",
]
24 changes: 24 additions & 0 deletions pointblank/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from __future__ import annotations

import pointblank.adapters._frictionless # noqa: F401

# Import adapter modules to trigger registration via @register_adapter
import pointblank.adapters._json_schema # noqa: F401
from pointblank.adapters._api import export_contract, import_contract
from pointblank.adapters._base import ContractAdapter, ContractImport, MappedConstraint
from pointblank.adapters._registry import (
get_adapter,
list_adapters,
register_adapter,
)

__all__ = [
"ContractAdapter",
"ContractImport",
"MappedConstraint",
"export_contract",
"get_adapter",
"import_contract",
"list_adapters",
"register_adapter",
]
118 changes: 118 additions & 0 deletions pointblank/adapters/_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from __future__ import annotations

from typing import Any

from pointblank.adapters._base import ContractImport
from pointblank.adapters._registry import _detect_format, get_adapter


def import_contract(source: Any, *, format: str | None = None, **kwargs: Any) -> ContractImport:
"""Import a contract/schema from an external format.

Reads an external schema definition (JSON Schema, Frictionless Table Schema, dbt schema.yml,
Pandera schema, Pydantic model, etc.) and produces a `ContractImport` with validation steps
mapped to Pointblank methods.

Parameters
----------
source
The source to import from. Can be: (1) a file path (str) to a schema/contract file, (2) a
Python dict with schema content already loaded, or (3) a Python object (e.g., a Pandera
`DataFrameSchema` or Pydantic model class).
format
The format identifier (e.g., `"json_schema"`, `"frictionless"`, `"dbt"`, etc.). If `None`,
the format is auto-detected from file extension or content.
**kwargs
Format-specific options passed to the adapter.

Returns
-------
ContractImport
An object containing the imported columns, constraints, and methods to generate `Validate`
objects, `Contract` objects, Python code, or YAML.

Raises
------
ValueError
If the format cannot be detected or no adapter is registered for it.

Examples
--------
```python
import pointblank as pb

# Import from JSON Schema
result = pb.import_contract("user_profile.schema.json", format="json_schema")
validation = result.to_validate(data=my_df)
validation.interrogate()

# Auto-detect format
result = pb.import_contract("datapackage.json")

# Import from a dict
schema_dict = {"type": "object", "properties": {"age": {"type": "integer", "minimum": 0}}}
result = pb.import_contract(schema_dict, format="json_schema")
```
"""
if format is None:
format = _detect_format(source)
if format is None:
raise ValueError(
f"Could not auto-detect format for source: {source!r}. "
"Please specify the format explicitly using the format= parameter."
)

adapter = get_adapter(format)

if not adapter.supports_import:
raise ValueError(f"Adapter '{format}' does not support import.")

return adapter.import_contract(source, **kwargs)


def export_contract(
validation_or_contract: Any,
destination: str | None = None,
*,
format: str,
**kwargs: Any,
) -> str | dict[str, Any]:
"""Export a Pointblank validation or contract to an external format.

Parameters
----------
validation_or_contract
A `Validate` or `Contract` object to export.
destination
Optional file path to write the output. If None, the result is returned without writing to
disk.
format
The target format identifier (e.g., `"json_schema"`, `"frictionless"`, `"dbt"`, etc.).
**kwargs
Format-specific options passed to the adapter.

Returns
-------
str | dict
The exported content.

Raises
------
ValueError
If no adapter is registered for the format, or the adapter doesn't support export.

Examples
--------
```python
import pointblank as pb

validation = pb.Validate(data=df).col_vals_gt(columns="age", value=0).interrogate()
pb.export_contract(validation, "output.schema.json", format="json_schema")
```
"""
adapter = get_adapter(format)

if not adapter.supports_export:
raise ValueError(f"Adapter '{format}' does not support export.")

return adapter.export_contract(validation_or_contract, destination, **kwargs)
Loading
Loading