Strategy-based data warehouse transformations using Apache Spark with automatic metadata enrichment and schema evolution
Project description
A Python library for data warehouse transformations using Apache Spark with a strategy-based approach.
About
"Sneezingly fast data warehouse transformations! Bless you! 🤧"
SparkSneeze provides a strategy-based approach to common data warehouse operations using Apache Spark. Whether you need to drop and recreate tables, append new data, perform upserts, or implement slowly changing dimensions, SparkSneeze handles the complexity while automatically enriching your data with standardized metadata and applies schema evolution.
Key Features:
- 🎯 Five powerful strategies: DropCreate, Truncate, Append, Upsert, and Historize
- 🔄 Automatic schema evolution with configurable expand/shrink options
- ⚡ Spark-optimized for high-performance data processing
- 🔧 Highly configurable metadata and processing options
It is still in early development, it is not recommended using it in any kind of production environment.
Installation
Install using pip:
pip install sparksneeze
Or using uv:
uv add sparksneeze
For development with all optional dependencies:
uv add sparksneeze[dev]
Usage
Python Library
sparksneeze uses a strategy pattern to handle different data transformation approaches. The main entry point is the sparksneeze() factory function.
Basic Usage
from sparksneeze import sparksneeze
from sparksneeze.strategy import DropCreate, Append, Upsert
# Create a DataFrame (or use existing one)
# df = spark.createDataFrame([...])
# DropCreate: Replace target completely with source data
result = sparksneeze(df, "my_delta_table", DropCreate()).run()
print(f"Success: {result.success}, Message: {result.message}")
# Append: Add source data to target
result = sparksneeze(df, "my_delta_table", Append()).run()
# Upsert: Insert new and update existing records by key
result = sparksneeze(df, "my_delta_table", Upsert(key="id")).run()
Advanced Usage with Custom Spark Session
from pyspark.sql import SparkSession
from sparksneeze import sparksneeze
from sparksneeze.strategy import Truncate, Historize
# Use your existing Spark session
spark = SparkSession.builder.appName("MyApp").getOrCreate()
# Truncate: Clear target and load source data
strategy = Truncate(auto_expand=True, auto_shrink=False)
result = sparksneeze(df, "target_table", strategy).run(spark_session=spark)
# Historize: Track changes over time with validity periods
strategy = Historize(key=["user_id"], prefix="HIST_")
result = sparksneeze(df, "target_table", strategy).run(spark_session=spark)
Available Strategies
- DropCreate: Remove target and recreate with source schema
- Truncate: Clear target and load source data (with schema evolution)
- Append: Add source data to target (with schema evolution)
- Upsert: Insert/update based on keys (with schema evolution)
- Historize: Upsert with validity time tracking metadata
Automatic Metadata Enrichment
All strategies automatically add standardized metadata fields to track data lineage, validity, and changes:
from sparksneeze import sparksneeze
from sparksneeze.strategy import DropCreate
# Automatic metadata added to every record
result = sparksneeze(df, "my_table", DropCreate()).run()
# Results in columns like:
# _META_valid_from - Record validity start timestamp
# _META_valid_to - Record validity end timestamp
# _META_active - Active record indicator (True/False)
# _META_row_hash - Hash of data columns (excludes keys/metadata)
# _META_system_info - JSON with strategy, version, timestamp info
Custom Metadata Configuration
from sparksneeze.metadata import MetadataConfig
from sparksneeze.strategy import Upsert
# Customize metadata fields and behavior
config = MetadataConfig(
prefix="_AUDIT", # Custom prefix instead of _META
hash_columns=["name", "email"] # Only hash specific columns
)
# Use with any strategy
strategy = Upsert(key="user_id", metadata_config=config)
result = sparksneeze(df, "users_table", strategy).run()
# Key columns (user_id) automatically excluded from hash
Schema Evolution
Most strategies support automatic schema evolution:
from sparksneeze.strategy import Append
# Automatically add new columns from source
strategy = Append(auto_expand=True, auto_shrink=False)
# Also remove columns not in source
strategy = Append(auto_expand=True, auto_shrink=True)
Command Line Interface
The CLI provides access to all strategies with their specific parameters.
Basic Commands
# Show help
sparksneeze --help
# Show version
sparksneeze --version
# Basic usage pattern
sparksneeze source_path target_path --strategy StrategyName [options]
Strategy Examples
# DropCreate: Replace target completely
sparksneeze /path/to/source.parquet my_table --strategy DropCreate
# Append with schema evolution
sparksneeze source.parquet target_table --strategy Append --auto_expand true
# Upsert by key
sparksneeze source.parquet target_table --strategy Upsert --key user_id
# Historize with multiple keys and custom prefix
sparksneeze source.parquet target_table --strategy Historize \
--key user_id,version --prefix HIST_ --auto_expand true
# Enable verbose output
sparksneeze source.parquet target_table --strategy DropCreate --verbose
Available Strategy Options
--auto_expand true/false: Add new columns from source (Truncate, Append, Upsert, Historize)--auto_shrink true/false: Remove columns not in source (Truncate, Append, Upsert, Historize)--key column_name: Single key for Upsert/Historize--key col1,col2: Multiple keys for Upsert/Historize--valid_from "YYYY-MM-DD": Start date for Historize validity--valid_to "YYYY-MM-DD": End date for Historize validity--prefix "PREFIX_": Metadata column prefix for Historize
Development
Setup
- Clone the repository:
git clone <your-repo-url>
cd sparksneeze
- Install development dependencies:
uv sync --extra dev
Running in Development
CLI Development
# Run CLI directly
uv run sparksneeze --help
# Run with Python module syntax
uv run python -m sparksneeze.cli --help
Testing
Run the full test suite:
uv run pytest
Run tests with coverage:
uv run pytest --cov=sparksneeze --cov-report=html
Run specific test files:
uv run pytest tests/test_core.py
uv run pytest tests/test_cli.py
Run tests with verbose output:
uv run pytest -v
Mark and run specific test types:
# Run only fast tests (exclude slow ones)
uv run pytest -m "not slow"
Code Quality
Format code:
uv run black src tests
Lint code:
uv run ruff check src tests
Documentation
Build documentation locally:
cd docs
uv run sphinx-build -b html . _build/html
Or using make:
cd docs
make html
View documentation:
# Open docs/_build/html/index.html in your browser
ReadTheDocs Setup
This project is configured for ReadTheDocs with:
.readthedocs.yamlconfiguration file- Sphinx documentation in
docs/directory - Auto-generated API documentation
- Support for both RST and Markdown files
To publish on ReadTheDocs:
- Push your code to a Git repository
- Connect your repository to ReadTheDocs
- Documentation will be automatically built and deployed
Building and Distribution
Build the package:
uv build
The built packages will be in the dist/ directory.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sparksneeze-0.1.4.tar.gz.
File metadata
- Download URL: sparksneeze-0.1.4.tar.gz
- Upload date:
- Size: 815.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
097570cdcc9d81b531ff61412ffb80bdc37d76d292df84b49aafe3432faf026b
|
|
| MD5 |
922646556aae2b7483125d840e414e70
|
|
| BLAKE2b-256 |
f47883846aa38c2a023b54f701c5dd2918ac66451e6348358bb1c03db8009465
|
Provenance
The following attestation bundles were made for sparksneeze-0.1.4.tar.gz:
Publisher:
release.yml on mdouwes/sparksneeze
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sparksneeze-0.1.4.tar.gz -
Subject digest:
097570cdcc9d81b531ff61412ffb80bdc37d76d292df84b49aafe3432faf026b - Sigstore transparency entry: 264398037
- Sigstore integration time:
-
Permalink:
mdouwes/sparksneeze@7bf179ef7731c9f1738445409d6f762e91580dc2 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/mdouwes
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7bf179ef7731c9f1738445409d6f762e91580dc2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sparksneeze-0.1.4-py3-none-any.whl.
File metadata
- Download URL: sparksneeze-0.1.4-py3-none-any.whl
- Upload date:
- Size: 49.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bf6f1c797743e21004fe5b13f97600793692865b4d6c12038a1ec7468c3ea67
|
|
| MD5 |
b6a45534fa1d1760fe14e5e95602fd48
|
|
| BLAKE2b-256 |
487ce89107dedba318eb117dcb7ee744c7e13683b4a4668365b737a6af885d6c
|
Provenance
The following attestation bundles were made for sparksneeze-0.1.4-py3-none-any.whl:
Publisher:
release.yml on mdouwes/sparksneeze
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sparksneeze-0.1.4-py3-none-any.whl -
Subject digest:
5bf6f1c797743e21004fe5b13f97600793692865b4d6c12038a1ec7468c3ea67 - Sigstore transparency entry: 264398039
- Sigstore integration time:
-
Permalink:
mdouwes/sparksneeze@7bf179ef7731c9f1738445409d6f762e91580dc2 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/mdouwes
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7bf179ef7731c9f1738445409d6f762e91580dc2 -
Trigger Event:
push
-
Statement type: