Python library for defining, building, and deploying data pipelines to AWS Step Functions
Project description
lokki
A Python library for defining, building, and deploying data pipelines to AWS Step Functions.
Features
- Simple Python decorators - Define pipelines using
@stepand@flowdecorators - Local execution - Test your flows locally before deploying
- AWS Step Functions - Deploy to AWS Step Functions with Distributed Map for parallel processing
- Lambda packaging - Auto-generates Docker images or ZIP archives for each step
- CloudFormation - Generates complete CloudFormation templates for deployment
- Retry configuration - Configure automatic retries for failed steps
- Flow parameters - Pass parameters to flows at runtime
Installation
pip install lokkiflow
Or install by uv (recommended):
uv add lokkiflow
Quick Start
Define a flow with steps:
from lokki import flow, step
@step
def get_birds() -> list[str]:
return ["goose", "duck", "seagull"]
@step
def flap_bird(bird: str) -> str:
return f"flappy {bird}"
@step
def join_birds(birds: list[str]) -> str:
return ", ".join(birds)
@flow
def birds_flow():
return get_birds().map(flap_bird).agg(join_birds)
if __name__ == "__main__":
from lokki import main
main(birds_flow)
Run locally:
python birds_flow.py run
# Output: flappy goose, flappy duck, flappy seagull
Build for deployment:
python birds_flow.py build
This creates:
lokki-build/lambdas/- One directory per step with Dockerfile or ZIPlokki-build/statemachine.json- AWS Step Functions state machinelokki-build/template.yaml- CloudFormation template
Configuration
Create a lokki.toml in your project:
# lokki.toml
build_dir = "lokki-build"
[aws]
artifact_bucket = "my-lokki-artifacts"
image_repository = "local" # or ECR prefix like "123456789.dkr.ecr.us-east-1.amazonaws.com/myproject"
endpoint = "" # for LocalStack: "http://localhost:4566"
[lambda]
package_type = "image" # or "zip" for simpler deployments
timeout = 900
memory = 512
image_tag = "latest"
[lambda.env]
LOG_LEVEL = "INFO"
[logging]
level = "INFO"
format = "human" # or "json"
Configuration Precedence
Environment variables override TOML config (highest to lowest):
| Environment Variable | Config Field |
|---|---|
LOKKI_ARTIFACT_BUCKET |
aws.artifact_bucket |
LOKKI_IMAGE_REPOSITORY |
aws.image_repository |
LOKKI_AWS_ENDPOINT |
aws.endpoint |
LOKKI_BUILD_DIR |
build_dir |
LOKKI_LOG_LEVEL |
logging.level |
Flow Syntax
Basic Example
from lokki import step, flow, main
@step
def get_data():
return [1, 2, 3]
@step
def process_item(item, mult):
return item * mult
@step
def process_item_2(item):
return item * item
@step
def sum_items(items):
return sum(items)
@flow
def my_flow(mult=2):
return get_data().map(process_item, mult=mult).next(process_item_2).agg(sum_items)
if __name__ == "__main__":
main(my_flow)
The example gets item list, maps them through two processing functions and aggregates the result.
Chaining Methods
.map(step)- Run step in parallel for each item in the list (fan-out).agg(step)- Aggregate results from map into a single value (fan-in).next(step)- Run step sequentially after the previous step
Chain multiple maps: step1().map(step2).next(step3).agg(agg_step)
Flow Parameters
Pass parameters to flows at runtime:
@step
def fetch_data(limit: int, offset: int = 0):
return list(range(limit))[offset:]
@step
def process(item, mult):
return item * mult
@flow
def paginated_flow(limit: int = 100, offset: int = 0, mult: int = 2):
return fetch_data(limit=limit, offset=offset).map(process, mult=mult)
if __name__ == "__main__":
main(paginated_flow)
Run with parameters:
python flow.py run --limit 50 --offset 10
Retry Configuration
Configure automatic retries for failed steps:
from lokki import flow, step
from lokki.decorators import RetryConfig
@step
def unreliable_step(data):
import random
if random.random() < 0.5:
raise ValueError("Random failure")
return data
@flow
def flow_with_retry():
return unreliable_step(retry=RetryConfig(retries=3, delay=1.0, backoff=2.0))
Retry options:
retries- Number of retry attempts (default: 0)delay- Initial delay between retries in seconds (default: 1.0)backoff- Backoff multiplier for delay (default: 2.0)
CLI Commands
python my_flow.py run # Run locally with optional params
python my_flow.py build # Build deployment artifacts
python my_flow.py deploy # Build and deploy to AWS
python my_flow.py show # Show execution status
python my_flow.py logs # Fetch CloudWatch logs
python my_flow.py destroy # Destroy the CloudFormation stack
python my_flow.py --help # Show help
Run Command
python flow.py run --param1 value1 --param2 value2
Deploy Command
python flow.py deploy --stack-name my-stack --region us-east-1
Show Command
python flow.py show # Show last 10 executions
python flow.py show --n 5 # Show last 5 executions
python flow.py show --run <run_id> # Show specific execution
Logs Command
python flow.py logs # Fetch logs from last hour
python flow.py logs --start 2024-01-15T10:00:00Z
python flow.py logs --tail # Tail logs in real-time
python flow.py logs --run <run_id> # Filter by run ID
Deployment
Option 1: Docker Images (Default)
-
Build your flow:
python my_flow.py build
-
Push Lambda images to ECR (from each
lokki-build/lambdas/<step>/directory):docker build -t <ecr-repo>/<step>:<tag> . docker push <ecr-repo>/<step>:<tag>
-
Deploy CloudFormation:
aws cloudformation deploy \ --template-file lokki-build/template.yaml \ --stack-name my-flow \ --parameter-overrides \ FlowName=my-flow \ S3Bucket=my-bucket \ ImageRepository=123456789.dkr.ecr.us-east-1.amazonaws.com/myproject
Option 2: ZIP Archives (Simpler)
For simpler deployments without Docker:
[lambda]
package_type = "zip"
python my_flow.py deploy
The Lambda code will be uploaded directly as ZIP archives - no ECR push needed.
Local Development with LocalStack
Test your flows locally before deploying to AWS:
-
Start LocalStack:
cd dev docker-compose up -d
-
Configure for LocalStack:
[aws] artifact_bucket = "lokki" endpoint = "http://localhost:4566" image_repository = "local" [lambda] package_type = "zip"
-
Build and deploy:
python flow.py build python flow.py deploy --confirm
See dev/README.md for more detailed LocalStack testing instructions.
Architecture
- @step - Decorator that marks a function as a pipeline step
- @flow - Decorator that wraps a function returning a FlowGraph
- FlowGraph - Resolved execution graph with TaskEntry, MapOpenEntry, MapCloseEntry
- LocalRunner - Executes flows locally using temporary files
- Builder - Generates Lambda packages, state machine, and CloudFormation
Development
# Install dev dependencies
uv sync --extra dev
# Run tests
uv run pytest
# Type check
uv run mypy lokki/
# Lint
uv run ruff check lokki/
License
MIT
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 lokkiflow-0.3.14.tar.gz.
File metadata
- Download URL: lokkiflow-0.3.14.tar.gz
- Upload date:
- Size: 237.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b61a41c419f5a5ed98bd06dfafb69dcd23ddd53b26f129b2872a7cd86cbde2ed
|
|
| MD5 |
3e77f18a01e768256386a177f84125f2
|
|
| BLAKE2b-256 |
531173323750eb25bc3f32afa27ad5de337c28fa1833b0a8d23ecd58883003bc
|
Provenance
The following attestation bundles were made for lokkiflow-0.3.14.tar.gz:
Publisher:
publish.yml on alamminsalo/lokki
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lokkiflow-0.3.14.tar.gz -
Subject digest:
b61a41c419f5a5ed98bd06dfafb69dcd23ddd53b26f129b2872a7cd86cbde2ed - Sigstore transparency entry: 983555236
- Sigstore integration time:
-
Permalink:
alamminsalo/lokki@0ff95bcc39bccb41877887b5a2fc03347a20abbe -
Branch / Tag:
refs/tags/v0.3.14 - Owner: https://github.com/alamminsalo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ff95bcc39bccb41877887b5a2fc03347a20abbe -
Trigger Event:
push
-
Statement type:
File details
Details for the file lokkiflow-0.3.14-py3-none-any.whl.
File metadata
- Download URL: lokkiflow-0.3.14-py3-none-any.whl
- Upload date:
- Size: 48.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9c53036589a25debb013f56b88719acc31882d089839715cb71b060ac7cb31d
|
|
| MD5 |
09773fa7fc9162e969e8b76ac90fa494
|
|
| BLAKE2b-256 |
22d86a15345faf6b32e4f32ba45fad5503472cccac13b050c4257aa9965065a6
|
Provenance
The following attestation bundles were made for lokkiflow-0.3.14-py3-none-any.whl:
Publisher:
publish.yml on alamminsalo/lokki
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lokkiflow-0.3.14-py3-none-any.whl -
Subject digest:
f9c53036589a25debb013f56b88719acc31882d089839715cb71b060ac7cb31d - Sigstore transparency entry: 983555241
- Sigstore integration time:
-
Permalink:
alamminsalo/lokki@0ff95bcc39bccb41877887b5a2fc03347a20abbe -
Branch / Tag:
refs/tags/v0.3.14 - Owner: https://github.com/alamminsalo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ff95bcc39bccb41877887b5a2fc03347a20abbe -
Trigger Event:
push
-
Statement type: