philiprehberger-data-pipeline
Composable data transformation pipeline with lazy evaluation.
Installation
pip install philiprehberger-data-pipeline
Usage
from philiprehberger_data_pipeline import Pipeline
data = [
{"name": " Alice ", "email": "alice@example.com", "status": "active", "age": 30},
{"name": "Bob", "email": "bob@example.com", "status": "inactive", "age": 25},
{"name": "Alice", "email": "alice@example.com", "status": "active", "age": 30},
]
result = (
Pipeline(data)
.filter(lambda r: r["status"] == "active")
.map(lambda r: {**r, "name": r["name"].strip()})
.unique_by("email")
.sort_by("name")
.collect()
)
Reusable Pipelines
from philiprehberger_data_pipeline import Pipeline
clean_users = (
Pipeline.define()
.filter(lambda r: r.get("email"))
.map(lambda r: {**r, "email": r["email"].lower()})
.unique_by("email")
)
active = clean_users.run(active_users)
archived = clean_users.run(archived_users)
Tap (Side Effects)
from philiprehberger_data_pipeline import Pipeline
result = (
Pipeline([1, 2, 3])
.tap(lambda x: print(f"Processing: {x}"))
.map(lambda x: x * 2)
.collect()
)
# Prints each item without altering the data
Branch (Parallel Splits)
from philiprehberger_data_pipeline import Pipeline
result = (
Pipeline([1, 2, 3])
.branch(
lambda p: p.map(lambda x: x * 2).collect(),
lambda p: p.filter(lambda x: x > 1).collect(),
)
.collect()
)
# [2, 4, 6, 2, 3]
Retry Wrapper
from philiprehberger_data_pipeline import Pipeline, retry
def fetch_url(url):
# might fail transiently
return requests.get(url).text
result = Pipeline(urls).map(retry(fetch_url, attempts=3, delay=1.0)).collect()
Pipeline Composition
from philiprehberger_data_pipeline import Pipeline
clean = Pipeline.define().filter(lambda x: x > 0).map(lambda x: x * 2)
limit = Pipeline.define().take(3)
combined = clean + limit
combined.run([−1, 5, 0, 3, 7, 2])
# [10, 6, 14]
Dry Run
from philiprehberger_data_pipeline import Pipeline
log = (
Pipeline([1, 2, 3, 4])
.filter(lambda x: x > 2)
.map(lambda x: x * 10)
.dry_run()
)
# [{"step": 0, "name": "filter", "input": [1,2,3,4], "output": [3,4]},
# {"step": 1, "name": "map", "input": [3,4], "output": [30,40]}]
Sliding Window
from philiprehberger_data_pipeline import Pipeline
Pipeline([1, 2, 3, 4, 5]).window(3, 1).collect()
# [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
Aggregations
from philiprehberger_data_pipeline import Pipeline
p = Pipeline(sales_data)
total = p.sum("amount")
average = p.avg("amount")
grouped = p.group_by("category")
Peek and count_by
peek(n) materializes the first n items for quick inspection without committing to a collect(). count_by(key) returns a per-key occurrence count, similar to group_by but without the per-value lists.
from philiprehberger_data_pipeline import Pipeline
Pipeline([10, 20, 30, 40, 50, 60]).filter(lambda x: x > 15).peek(3)
# [20, 30, 40]
Pipeline([
{"category": "fruit"},
{"category": "veg"},
{"category": "fruit"},
]).count_by("category")
# {"fruit": 2, "veg": 1}
Export
from philiprehberger_data_pipeline import Pipeline
Pipeline(data).filter(lambda x: x["active"]).to_csv("output.csv")
Pipeline(data).filter(lambda x: x["active"]).to_json("output.json")
API
| Function / Class | Description |
|---|---|
Pipeline(data) |
Composable, lazy data transformation pipeline |
.filter(fn) |
Keep items where fn returns True |
.map(fn) |
Transform each item |
.flat_map(fn) |
Transform and flatten |
.flatten() |
Flatten one level of nesting |
.sort_by(key) |
Sort by key (string or callable) |
.unique_by(key) |
Remove duplicates by key |
.take(n) |
Take first n items |
.skip(n) |
Skip first n items |
.chunk(size) |
Split into chunks |
.each(fn) |
Execute side effect for each item |
.tap(fn) |
Side effect without altering data, skipped in dry run |
.window(size, step) |
Sliding window grouping |
.deduplicate() |
Remove duplicate items preserving order |
.branch(*fns) |
Split into parallel branches and merge results |
.dry_run(data) |
Log each step's input/output without side effects |
pipeline_a + pipeline_b |
Compose two pipelines into one |
.collect() |
Execute and return list |
.first() |
Return first item |
.count() |
Count items |
.sum(key) |
Sum values |
.avg(key) |
Average values |
.min(key) |
Find minimum value |
.max(key) |
Find maximum value |
.reduce(fn, initial) |
Reduce to single value |
.group_by(key) |
Group into dict |
.count_by(key) |
Count occurrences per key value |
.peek(n) |
Return the first n items as a list (debugging) |
.to_csv(path) |
Export as CSV |
.to_json(path) |
Export as JSON |
.enumerate(start) |
Pair each item with its index |
.zip_with(other) |
Pair items with another iterable |
.take_while(fn) |
Take items while predicate is True |
.skip_while(fn) |
Skip items while predicate is True |
retry(fn, attempts, delay, on_error) |
Wrap a step function with configurable retry logic |
Development
pip install -e .
python -m pytest tests/ -v
Support
If you find this project useful:
License
Metadata
Release files for philiprehberger-data-pipeline 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| philiprehberger_data_pipeline-0.6.0.tar.gz | 189.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| philiprehberger_data_pipeline-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 199.1 kB
Release files / philiprehberger_data_pipeline-0.6.0.tar.gz
| Download URL | philiprehberger_data_pipeline-0.6.0.tar.gz |
|---|---|
| Size | 189.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
830746baa26c90a5e1439bdcf1aefd352c4fcd5b0671cf0e3d15c238da994617
|
|
BLAKE2b-256 checksum How to use checksums |
e1d8d4a05f4ab8ac2c09f03826a1aa83d0267cc705f25adfade2e532d208e0f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / philiprehberger_data_pipeline-0.6.0-py3-none-any.whl
| Download URL | philiprehberger_data_pipeline-0.6.0-py3-none-any.whl |
|---|---|
| Size | 9.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
955fda90b8e69aaa7d9cfec7b34ef2c78648df9313073cb1f229cbd22efbca1c
|
|
BLAKE2b-256 checksum How to use checksums |
a1be0b5b4d0bef33d790b929811bb2b27b3c486adef5b564ea3ad77903283c3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for philiprehberger-data-pipeline 0.6.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.