Data is often already described somewhere outside of Pointblank: a JSON Schema for an API payload, a Frictionless Table Schema inside a Data Package, the schema.yml file of a dbt project, or an Open Data Contract Standard (ODCS) document. import_contract() reads such a definition and translates its rules into Pointblank validation steps. That way the existing definition can be checked against real data without rewriting it by hand, and the rules stay in the place where they’re already maintained.
The result is a ContractImport object. It holds the column names and types, the mapped constraints, any metadata from the source (such as a title and a description), and a warning for every rule that has no Pointblank equivalent. From there you can:
The definition to import. This can be a path to a file, given as a string, or a dictionary holding content that has already been loaded (e.g., with json.load() or yaml.safe_load()). pathlib.Path objects aren’t accepted, so pass str(path) instead.
format:str | None=None
The name of the adapter to use: "json_schema", "frictionless", "dbt", or "odcs" for the built-in formats, or the name of a custom adapter. If None (the default), the format is detected from the file name or the content (see the Format Detection section).
**kwargs:Any
Options for the adapter. The Frictionless adapter takes resource= (the name or position of the resource to use in a Data Package), the dbt adapter takes model= (the name of a model or source table), and the ODCS adapter takes table= (the name of a dataset table). Each defaults to the first entry in the document. The JSON Schema adapter takes no options. Options that an adapter doesn’t recognize are ignored.
Returns
ContractImport
The imported columns, constraints, metadata, and warnings, along with methods for turning them into a Validate object, a Contract, Python code, or a text summary.
Raises
ValueError
If the format can’t be detected, if no adapter is registered under format=, or if the adapter doesn’t support importing. Adapters also raise ValueError when the document lacks the content they need (e.g., a dbt file with no models) or when a resource=, model=, or table= value doesn’t match anything in it.
FileNotFoundError
If source is a path to a file that doesn’t exist.
Supported Formats
Each built-in adapter reads the column names and types and the following rules:
JSON Schema ("json_schema"): the properties of an object schema become the columns. required maps to col_vals_not_null(), minimum/maximum to col_vals_ge()/ col_vals_le(), exclusiveMinimum/exclusiveMaximum to col_vals_gt()/col_vals_lt(), enum to col_vals_in_set(), pattern to col_vals_regex(), and const to col_vals_eq(). The format values email, uri, uri-reference, ipv4, and ipv6 map to col_vals_within_spec(); other formats (such as date) produce a warning. The title and description keywords are kept as metadata and $schema is recorded as the source version.
Frictionless Table Schema ("frictionless"): a standalone Table Schema (with fields) or a Data Package (with resources). The field constraints required, unique, minimum, maximum, enum, and pattern are mapped, and a primaryKey becomes col_vals_not_null() on each key column plus rows_distinct() over all of them. Foreign keys produce a warning.
dbt ("dbt"): the models and source tables of a schema.yml file. The column tests not_null, unique, and accepted_values are mapped (from either data_tests: or the older tests: key), as is a model-level unique test with combination_of_columns. relationships and any other tests produce a warning. The model name becomes the title.
Open Data Contract Standard ("odcs"): documents with a dataset: list of tables and their columns. isNullable: false, isUnique, isPrimaryKey, enum (or values), pattern, and minimum/maximum are mapped. Length limits and checks/quality entries produce a warning.
Format Detection
When format= isn’t given, a file path is first matched against the file extensions of the registered adapters: .schema.json (JSON Schema), .resource.json and .datapackage.json (Frictionless), .yml and .yaml (dbt), and .odcs.yml, .odcs.yaml, and .odcs.json (ODCS). If no extension matches, each adapter in turn inspects the content of the file or dictionary (e.g., a fields list identifies a Table Schema and a models list a dbt file). Since the dbt adapter claims every .yml and .yaml file, pass format="odcs" when importing an ODCS document stored as YAML. Use list_adapters() to see the registered formats and their extensions.
Coverage And Warnings
Not every rule in an external format can be expressed as a Pointblank validation step. When the adapter recognizes a rule but can’t translate it, it adds a message to warnings and leaves the rule out. The coverage value is the share of recognized rules that were translated, so 1.0 means nothing recognized was dropped. Keywords that an adapter doesn’t look at all (such as minLength in a JSON Schema) are skipped without a warning and don’t count toward coverage, so it’s worth checking summary() against the source when importing a definition for the first time.
Examples
Suppose an API team publishes a JSON Schema for user profiles and we want to check a table of profiles against it. The schema can be passed as a dictionary (here it’s written inline, but it would usually come from json.load()). Because it has a $schema key, the format is detected without needing format=.
import pointblank as pbimport polars as pluser_schema = {"$schema": "https://json-schema.org/draft/2020-12/schema","title": "user_profile","description": "A registered user of the app.","type": "object","properties": {"user_id": {"type": "integer", "minimum": 1},"email": {"type": "string", "format": "email"},"country": {"type": "string", "pattern": "^[A-Z]{2}$"},"plan": {"type": "string", "enum": ["free", "pro", "team"]}, },"required": ["user_id", "email"],}imported = pb.import_contract(user_schema)imported
The printed form gives the counts at a glance: four columns, six constraints, and nothing left untranslated. The summary() method gives a little more detail, including the version of the source specification.
Now let’s validate some data. The to_validate() method builds a Validate object with a schema check followed by one step per constraint, and it accepts the usual Validate arguments such as tbl_name= and label=.
The table has the right columns and types, so the schema check passes. The remaining failures come straight from the JSON Schema rules: a user_id of 0 (below the minimum of 1), a missing email (which fails both the required check and the email format check), an email without a valid domain, a lowercase country code, and a plan that isn’t in the enum.
Files work the same way. In this next example a dbt schema.yml file with two models is written to the working directory. The .yml extension identifies it as a dbt file, and model= picks the model to import (without it, the first model would be used).
Four of the five tests were translated. The relationships test checks values against another model, which a single-table validation can’t do, so it was reported as a warning and the coverage is 80%. Note also that the dbt type varchar(20) was read as Pointblank’s String type.
The import can also be turned into a Contract with to_contract(), which accepts any Contract argument. Printing the contract as YAML shows that the schema, the steps, and the model’s description were all carried over.
The contract now has a name and an owner, and the dbt model’s four translated tests are its steps. From here it works like any other contract: it can be saved as YAML next to the dbt project, enforced with Contract.validate(), or used as a boundary in a Pipeline.