dataprepkit metadata-driven SCD2 orchestrator
dataprepkit turns CSV snapshots into evolving dimensions by declaring the schema, keys, and dependency joins in metadata. The loader and scd2.apply_changes take care of schema evolution, dependency joins, normalizing datetimes, and the SCD2 workflow.
Metadata format
Each metadata entry registered via register_metadata(name, metadata) must include:
| Key | Description |
|---|---|
target_table |
Table name (schemaless or schema-qualified; target_schema can fill in the schema). |
target_schema |
Optional schema name. The loader auto-prefixes it during registration and creates the schema if missing. |
natural_key_cols |
List of natural key columns—required. |
natural_key_specs |
Optional overrides (ColumnSpec) for natural keys (type, nullable, unique, default). |
data_columns |
Map of column names → ColumnSpec. Required. |
surrogate_key / join_numeric_key |
System column names. |
filepath |
CSV path (or lakehouse path) to read. |
schema_handling.mode |
"suggest" (default) or "evolve" (auto-add missing columns). |
processing_class |
Optional callable that transforms the incoming pandas DataFrame. |
dependencies |
Optional dependency definitions (see below). |
run_policy |
Determines failure handling (continue or abort). |
archive_path |
Optional location for parquet archives. |
ColumnSpec fields:
type: SQL type (e.g.,NVARCHAR(4000),DATETIME2(3)).nullable: boolean.unique: boolean flag.default: SQL default expression.parse_format: optional format string for datetime parsing before staging.
Reserved NA convention:
- Any row whose natural key columns are all
"NA"is treated as the reservedNAmember automatically. - By default the reserved
NAmember uses-1for both the surrogate key and the join numeric key. - Duplicate
NArows fail the load. - Use
required_reserved_source_valuesto require special source rows likeNAorUNKNOWNto appear in a given dimension snapshot. - Use
reserved_source_memberswhen your pipeline contract needs different reserved key mappings, for exampleNA -> -1andUNKNOWN -> -2. - The reserved
NAmember does not participate in SCD2 history; it is stored as a single latest-value row and overwritten in place.
Example:
{
"schema_handling": {"mode": "evolve"},
"target_table": "tbl_d_company",
"target_schema": "Dimensions",
"natural_key_cols": ["Organisation_Cd"],
"data_columns": {
"Legacy_Company_Name": {"type": "NVARCHAR(4000)", "nullable": true},
"New_Column_From_Join": {"type": "NVARCHAR(4000)", "nullable": true}
},
"surrogate_key": "surrogate_key",
"join_numeric_key": "join_numeric_key",
"filepath": "/lakehouse/.../company_dim.csv",
"dependencies": [
{
"schema": "Dimensions",
"table": "tbl_d_company_service",
"on": [{"source": "Service_Type_Cd", "target": "Service_Type_Cd"}],
"select": {"Service_Description": "New_Column_From_Join"},
"where": {"target": ["Current_Ind == 1"]},
"how": "left",
"on_missing": "null"
}
]
}
Dependency joins
DependencyJoin entries support:
schema/table: lookup table to join to.on: list of{source, target}mappings between incoming and lookup columns.select: mapping of lookup column → alias added to the incoming frame.where: optional SQL filters applied before the join.filter_target_current: restricts toCurrent_Ind = 1rows (defaultTrue).how:"left"or"inner".on_missing:"null"or"error".
Joins run inside SQL; pandas only reads the filtered result set, renames columns, and maps the selected values to the incoming DataFrame.
Runtime flow
- Register metadata (see
examples/run_metadata_example_fabric.py). - Call
run_dimension(engine, metadata_name, csv_reader=...). - Loader steps:
- read CSV (custom reader may handle lakehouse authentication);
- cast datetimes using optional
parse_format; - ensure schema/table exist (auto-create/evolve if needed);
- run SQL dependency joins;
- apply SCD2 history for normal rows and latest-only handling for the reserved
NArow.
Tests
python -m pytest dataprepkit/tests/test_metadata_loader.py— metadata parsing, datetime casting, dependency joins, schema aliases.python -m pytest dataprepkit/tests/scd2/test_apply_changes.py::test_nullable_data_column_allows_null_staging— staging with nullable columns.
Examples
examples/run_metadata_example_fabric.py– registers multiple metadata objects and drives Fabric-based loading.examples/run_scd2_fabric.py– demo insert/update/delete/reinsert phases on Fabric tables.
Notes
- Metadata entries are validated via Pydantic; missing keys raise errors.
- Update metadata before rerunning
run_dimensionto maintain the registry. - The system is designed for declarative metadata so you can add dimensions by editing metadata, not code.
Helpers modules
dataprepkit.helpers exposes reusable utilities:
helpers/connectors/fabric.py– Fabric SQL connection builder that handles MSI tokens, driver selection, and pooling. Usecreate_engine_for_fabric(endpoint, database, preferred_driver, ...)plusvalidate(engine)before running any metadata loads.helpers/storage.py– Lakehouse/mount helpers (mounting, paths) used by the Fabric examples; consult it for paths when you need to read raw CSVs stored in your lakehouse.- Additional helper modules (e.g., connector-specific tooling) are referenced by the examples so you can replicate the Fabric patterns on other platforms.
Release files for ofwat-dataprepkit 0.19
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ofwat_dataprepkit-0.19.tar.gz | 62.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ofwat_dataprepkit-0.19-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 128.0 kB
Release files / ofwat_dataprepkit-0.19.tar.gz
| Download URL | ofwat_dataprepkit-0.19.tar.gz |
|---|---|
| Size | 62.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c6365a647df718792c2998f30847c4389bd890ca0c702e60a4dbd88405cd8f21
|
|
BLAKE2b-256 checksum How to use checksums |
fc238c75dd969cce0edb747ae14e686a2750644f588a26f313f0a7526dbae84b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency logRelease files / ofwat_dataprepkit-0.19-py3-none-any.whl
| Download URL | ofwat_dataprepkit-0.19-py3-none-any.whl |
|---|---|
| Size | 65.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4b45e17bc1fa0f35b729bed4f3ec611f8f0e2bac8ea44e2af26fc9dd044aa2c1
|
|
BLAKE2b-256 checksum How to use checksums |
2e385f5638fc377e8db34d26bce4abf75d64cf06aa48e4d45b9cdbe76ebe726a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 24, 2026.
Transparency log