Releases: Saevarl/Kontra
Release list
Kontra 0.14.2
Bugfix release: SQL Server query-vs-table and table-vs-query compares now use set-based SQL pushdown, including cross-database table references. Mixed pairs execute through the query-side connection while cross-database query pairs continue to fall back safely.
v0.12.2
Performance: faster PostgreSQL validation.
- A validate() against a PostgreSQL URI now opens one connection instead of three (shared across preplan, execution, and introspection).
- Redundant SQL round-trips removed:
COUNT(*)is folded into the tally aggregate (the whole contract becomes a single query), the compiled plan supplies required columns instead of aninformation_schemalookup, and preplan catalog queries are skipped when no rule can be resolved from metadata. - Small-table validation is substantially faster locally (exact-count path ~40ms → ~8ms).
Behavior note: in the default fail-fast mode, total_rows and derived rates are now taken from the PostgreSQL reltuples estimate rather than a separate exact COUNT(*). Rule pass/fail and failed_count are unchanged; only fail-fast totals/rates may now be estimates (fail-fast results are already lower bounds). Use tally=True for exact totals.
v0.12.1
Fix: probe key alignment no longer fails when a side carries a non-key column named like the join key (compare / profile_relationship, and the MCP compare_datasets/profile_relationship tools). Both sides are aligned onto collision-safe internal aliases; original key names are preserved in all output.
Metadata: project URLs now point to https://kontrakit.io and https://kontrakit.dev.
v0.10.0
Kontra 0.10.0
Transformation probes gain FK→PK key support, profile history becomes a first‑class Python API, and a batch of database‑path fixes land for SQL Server and Entra ID auth.
✨ New features
- Different‑named join keys for transformation probes. compare() accepts before_key=/after_key= and profile_relationship() accepts left_on=/right_on= (pandas‑merge naming) for the common FK→PK case. The symmetric key=/on= forms still work; composite keys pair positionally.
kontra.compare(tickets, orgs, before_key="organization_id", after_key="id")
kontra.profile_relationship(tickets, orgs, left_on="organization_id", right_on="id") - Profile history in the Python API. kontra.profile(..., save=True), get_profile(), list_profiles(), and profile_diff() are now fully wired to the same store the CLI uses — profiles saved from Python and from kontra profile --save-profile are interchangeable.
- PostgreSQL profile store. get_profile_store("postgres", uri=...) persists profiles to a shared kontra_profiles table for multi‑host setups (local .kontra/profiles/ remains the default).
- Open annotation vocabulary. Any non‑empty annotation_type is accepted; two new documented types — diagnosis (first‑responder assessment) and expected (owner adjudication verdict).
🐛 Fixes
- SQL Server Entra ID on Windows. msodbcsql18 rejects the Authentication=ActiveDirectory* keywords for token modes on Windows; Kontra now acquires the token via azure-identity and passes it through pyodbc attrs_before. entra_password remains the azure‑identity‑free fallback on all platforms.
- Entra entra_password now correctly retains URI userinfo (UID/PWD).
- Transformation‑probe materialization on SQL Server (pyodbc). Fixed a ShapeError (Row→tuple) and truncated dtype inference (columns NULL in the first 100 rows now infer correctly).
- SQL Server scan profiling overflow. Numeric aggregates are widened (AVG/SUM args cast) so wide‑range integer columns no longer raise "Arithmetic overflow converting expression to data type int".
- Trustworthy uniqueness on identifier columns. Estimated distinct counts for id‑like columns on tables ≤ 1M rows are refined with an exact COUNT(DISTINCT) — no more phantom duplicates (uniqueness_ratio < 1.0 on a genuinely unique key).
- Constant columns surface their value. A distinct_count == 1 column now reports its single value in top_values/values on every backend.
- kontra.set_config() is honored everywhere. Config‑path overrides now apply across validate(), datasource resolution, and state — previously only health() respected them.
- kontra.profile(save=...) now defaults to False. The kwarg was previously accepted but never acted on; it now works, and defaults to off to avoid surprise writes. Pass save=True to persist. Inline DataFrame profiles have no stable identity and are not saved.
- The sqlserver-entra extra now also installs azure-identity (for the Windows token path).
📚 Docs
Updated across transformation probes, the Python API, profile history & store backends, SQL Server Entra config, and profiling‑estimate semantics.
Install
pip install --upgrade kontra # or: pip install kontra==0.10.0
Full changeset: everything above shipped under a single squashed commit gated by the full suite (1585 tests, 0 failures) across live PostgreSQL, SQL Server, and DuckDB.
v0.6.2
Glob Pattern Validation - Validate multiple files with s3://bucket/*.parquet
Cloud Sampling - sample_failures() now works with S3 and Azure parquet files
Simpler API
- validate("contract.yml") extracts datasource automatically
- draft("data.parquet") profiles internally
- Dict-of-lists columnar input format supported
Bug Fixes
- unique rule NULL handling consistency between SQL and Polars
- dry_run=True and health() now properly load builtin rules
- Empty DataFrame compare() no longer crashes
- allowed_values("active") gives helpful error (expects list)
- freshness suggestions default to severity: warning
v0.6.0
Highlights
🚀 Tally Mode - Control the trade-off between speed and precision
--tallyfor exact violation counts--no-tallyfor fast early-stop- Per-rule
tally:setting in contracts
⚡ 2x Faster Cold Start - Lazy loading of heavy dependencies
import kontranow <200ms (was 500ms+)- Polars, DuckDB, database drivers loaded on-demand
✨ UX Improvements - Better outputs everywhere
- JSON validation output is now pretty-printed
- Helpful hints:
≥1 failure (use --tally for exact count) - Cleaner profile displays
📚 Documentation Overhaul - Completely rewritten and restructured
Other Changes
- EXISTS optimization for fast violation detection
rules.dtype()acceptsdtype=parameter alias- Interrogate preset shows percentiles (p25, p75, p99)
DatasetProfile.to_json()method- MSSQL named datasource resolution
- Config displays
profile:instead ofscout: to_llm()suppresses top values for unique columns