A Python library for managing Snowflake workflows
Project description
snowforge-py
Simplify the creation and management of Snowflake objects and data pipeline processes.
Note: This is an alpha release. The API is subject to change.
Features
-
Database Operations
- Table creation and management with comprehensive column types
- Internal and external stage management
- File format handling (CSV, JSON, Avro, Parquet, ORC, XML)
- Stream creation and monitoring
- Task scheduling and management
-
Data Loading
- PUT operations with compression support
- COPY INTO operations with extensive options
- Pattern matching and file format specifications
-
Workflow Orchestration
- Transaction management
- Multi-step workflow support
- Database and schema management
- Tag management and application
Installation
pip install snowforge
Quick Start
from snowforge import (
Forge, SnowflakeConfig,
FileFormat, Stage, Table, Stream, Task,
CopyInto, CopyIntoSource, CopyIntoTarget,
TaskType, WarehouseSize
)
from snowforge.copy_into import OnError
from snowforge.file_format import CsvOptions, CompressionType, FileFormatSpecification
from snowforge.stage import InternalStageParams, InternalStageEncryptionType
from snowforge.table import Column, ColumnType
from snowforge.task import Schedule
# 1. Create file format for CSV files
csv_format = (
FileFormat.builder("SALES_CSV_FORMAT")
.with_create_or_replace()
.with_options(
CsvOptions(
compression=CompressionType.AUTO,
field_delimiter=",",
skip_header=1,
null_if=["NULL", ""],
)
)
.with_comment("CSV format for sales data")
.build()
)
# 2. Create internal stage for data loading
sales_stage = (
Stage.builder("SALES_STAGE")
.with_create_or_replace()
.with_stage_params(
InternalStageParams(encryption=InternalStageEncryptionType.SSE)
)
.with_file_format(FileFormatSpecification.named("SALES_CSV_FORMAT"))
.with_comment("Stage for sales data files")
.build()
)
# 3. Create sales table
sales_table = (
Table.builder("SALES")
.with_create_or_replace()
.with_column(Column("sale_id", ColumnType.NUMBER, nullable=False, identity=True))
.with_column(Column("product_id", ColumnType.NUMBER, nullable=False))
.with_column(Column("customer_id", ColumnType.NUMBER, nullable=False))
.with_column(Column("quantity", ColumnType.NUMBER))
.with_column(Column("amount", ColumnType.NUMBER(15, 2)))
.with_column(Column("sale_date", ColumnType.TIMESTAMP, default="CURRENT_TIMESTAMP()"))
.with_cluster_by(["sale_date"])
.with_comment("Sales transactions table")
.build()
)
# 4. Create stream to track changes
sales_stream = (
Stream.builder("SALES_CHANGES")
.with_create_or_replace()
.with_source("SALES")
.with_append_only(False)
.with_comment("Stream to capture changes in sales table")
.build()
)
# 5. Create task to process changes
sales_analytics_task = (
Task.builder("PROCESS_SALES_CHANGES")
.with_create_or_replace()
.with_warehouse_size(WarehouseSize.XSMALL)
.with_schedule(Schedule(cron_expr="0 */1 * * *", timezone="UTC"))
.with_task_type(TaskType.SQL)
.with_sql_statement("""
MERGE INTO SALES_ANALYTICS T USING (
SELECT
DATE_TRUNC('day', sale_date) as sale_day,
SUM(quantity) as total_quantity,
SUM(amount) as total_amount,
COUNT(*) as transaction_count
FROM SALES_CHANGES
GROUP BY DATE_TRUNC('day', sale_date)
) S
ON T.sale_day = S.sale_day
WHEN MATCHED THEN UPDATE SET
T.total_quantity = T.total_quantity + S.total_quantity,
T.total_amount = T.total_amount + S.total_amount,
T.transaction_count = T.transaction_count + S.transaction_count
WHEN NOT MATCHED THEN INSERT (
sale_day, total_quantity, total_amount, transaction_count
) VALUES (
S.sale_day, S.total_quantity, S.total_amount, S.transaction_count
)
""")
.with_comment("Task to aggregate sales data hourly")
.build()
)
# 6. Execute the complete workflow
with Forge(SnowflakeConfig.from_env()) as forge:
(forge.workflow()
.use_database("SALES_DB", create_if_not_exists=True)
.use_schema("SALES_SCHEMA", create_if_not_exists=True)
.add_file_format(csv_format)
.add_stage(sales_stage)
.add_table(sales_table)
.add_stream(sales_stream)
.add_task(sales_analytics_task)
.execute()
)
# 7. Load data using COPY INTO
copy_sales = (
CopyInto.builder()
.with_source(CopyIntoSource.stage("SALES_STAGE"))
.with_target(CopyIntoTarget.table("SALES"))
.with_pattern(".*sales[.]csv")
.with_file_format(FileFormatSpecification.named("SALES_CSV_FORMAT"))
.with_on_error(OnError.CONTINUE)
.build()
)
forge.workflow().copy_into(copy_sales).execute()
Documentation
For detailed documentation and examples, see the docs directory:
Contributing
We welcome contributions! Please see our Contributing Guide for details.
License
This project is licensed under the GPL-3.0 License - see the 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 snowforge-0.1.0a1.tar.gz.
File metadata
- Download URL: snowforge-0.1.0a1.tar.gz
- Upload date:
- Size: 71.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be41495ad40ff11fa251c51c78d3412dbef2370090ae843c205bc4cbce99b0ae
|
|
| MD5 |
b66365e7166916a122074a7e9ba7b3ec
|
|
| BLAKE2b-256 |
6d1563cb090be8fe3aeb2e571882f4b9f7702a9a41d546cb4eaba9ba35ba382b
|
Provenance
The following attestation bundles were made for snowforge-0.1.0a1.tar.gz:
Publisher:
publish.yml on Francisco-Montanez/snowforge-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
snowforge-0.1.0a1.tar.gz -
Subject digest:
be41495ad40ff11fa251c51c78d3412dbef2370090ae843c205bc4cbce99b0ae - Sigstore transparency entry: 150349912
- Sigstore integration time:
-
Permalink:
Francisco-Montanez/snowforge-py@ddc7090a80e33f915315b1704d4091c661465675 -
Branch / Tag:
refs/tags/v0.1.0-alpha.1 - Owner: https://github.com/Francisco-Montanez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ddc7090a80e33f915315b1704d4091c661465675 -
Trigger Event:
push
-
Statement type:
File details
Details for the file snowforge-0.1.0a1-py3-none-any.whl.
File metadata
- Download URL: snowforge-0.1.0a1-py3-none-any.whl
- Upload date:
- Size: 43.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49ddcd50c76fc8383f951f7144ed5a98b9be877e337e3dec0b1e42547b3e1e62
|
|
| MD5 |
583bbde4047fc4d39678230b514baefa
|
|
| BLAKE2b-256 |
5c68fae1da568aee2c3a6cc66eee8935abb804f40657fd7b5a988c1f5b6b887d
|
Provenance
The following attestation bundles were made for snowforge-0.1.0a1-py3-none-any.whl:
Publisher:
publish.yml on Francisco-Montanez/snowforge-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
snowforge-0.1.0a1-py3-none-any.whl -
Subject digest:
49ddcd50c76fc8383f951f7144ed5a98b9be877e337e3dec0b1e42547b3e1e62 - Sigstore transparency entry: 150349913
- Sigstore integration time:
-
Permalink:
Francisco-Montanez/snowforge-py@ddc7090a80e33f915315b1704d4091c661465675 -
Branch / Tag:
refs/tags/v0.1.0-alpha.1 - Owner: https://github.com/Francisco-Montanez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ddc7090a80e33f915315b1704d4091c661465675 -
Trigger Event:
push
-
Statement type: