Bear Lake
A lightweight, file-based database built on Polars and Parquet, designed for fast analytics and easy data management.
Bear Lake provides a simple API for creating partitioned tables, inserting data, and running efficient queries using Polars' lazy evaluation. All data is stored as Parquet files with automatic partitioning support.
Installation
You can install bear-lake using pip.
pip install bear-lake
Usage
Quick Start
import polars as pl
import bear_lake as bl
# Connect to database
db = bl.connect("my_database")
# Create a table with schema and partitioning
schema = {
"date": pl.Date,
"ticker": pl.String,
"price": pl.Float64
}
db.create(
name="stocks",
schema=schema,
partition_keys=["ticker"],
primary_keys=["date", "ticker"],
mode="error"
)
# Insert data
data = pl.DataFrame({
"date": ["2024-01-01", "2024-01-02"],
"ticker": ["AAPL", "AAPL"],
"price": [150.0, 152.5]
})
db.insert("stocks", data, mode="append")
# Query data using Polars lazy evaluation
result = db.query(
bl.table("stocks")
.filter(pl.col("ticker") == "AAPL")
.select(["date", "price"])
)
print(result)
S3 Storage
Bear Lake supports storing your database on S3-compatible storage (AWS S3, MinIO, etc.) by providing storage options when connecting.
Configuration
First, set up your S3 credentials as environment variables:
export ACCESS_KEY_ID="your-access-key"
export SECRET_ACCESS_KEY="your-secret-key"
export REGION="us-east-1"
export ENDPOINT="https://s3.amazonaws.com" # Optional
export BUCKET="your-bucket-name"
Connecting to S3
import polars as pl
import bear_lake as bl
import os
# Configure storage options
storage_options = {
'aws_access_key_id': os.getenv("ACCESS_KEY_ID"),
'aws_secret_access_key': os.getenv("SECRET_ACCESS_KEY"),
'region': os.getenv("REGION"),
'endpoint_url': os.getenv("ENDPOINT") # Optional
}
# Connect to S3 database
url = f"s3://{os.getenv('BUCKET')}"
db = bl.connect_s3(path=url, storage_options=storage_options)
Usage with S3
Once connected, all database operations work identically to local storage:
# Create table
schema = {
"date": pl.Date,
"ticker": pl.String,
"close": pl.Float64
}
db.create(
name="stock_prices",
schema=schema,
partition_keys=["ticker"],
primary_keys=["date", "ticker"],
mode="replace"
)
# Insert data
data = pl.DataFrame({
"date": ["2024-01-01", "2024-01-02"],
"ticker": ["AAPL", "AAPL"],
"close": [150.0, 152.5]
})
db.insert("stock_prices", data, mode="append")
# Query data (works the same as local storage)
result = db.query(
bl.table("stock_prices")
.filter(pl.col("ticker") == "AAPL")
.select(["date", "close"])
)
All operations including insert, query, delete, optimize, and metadata operations work seamlessly with S3 storage.
API Reference
Database Connection
# Local file system
db = bl.connect(path: str) -> Database
# S3 storage
db = bl.connect_s3(path: str, storage_options: dict[str, str]) -> Database
Connect to a database at the specified path. For local storage, creates the directory if it doesn't exist. For S3 storage, provide storage options with credentials and configuration.
Creating Tables
db.create(
name: str,
schema: dict[str, pl.DataType],
partition_keys: list[str],
primary_keys: list[str],
mode: str = "error"
)
Parameters:
name: Table nameschema: Dictionary mapping column names to Polars data typespartition_keys: Columns to partition data by (creates hierarchical folder structure)primary_keys: Columns that form a unique identifier (used for deduplication)mode: How to handle existing tables -"error"(default),"replace", or"skip"
Inserting Data
db.insert(name: str, data: pl.DataFrame, mode: str = "append")
Parameters:
name: Table namedata: Polars DataFrame to insertmode: How to handle existing partitions -"append"(default),"overwrite", or"error"
Querying Data
result = db.query(expression: pl.LazyFrame) -> pl.DataFrame
Execute a lazy Polars query and return results. Use bl.table(name) to get a LazyFrame for a table.
# Get a LazyFrame for querying
lazy_df = bl.table("stocks")
# Build query with Polars operations
result = db.query(
lazy_df
.filter(pl.col("date") > "2024-01-01")
.group_by("ticker")
.agg(pl.col("price").mean())
)
Deleting Data
db.delete(name: str, expression: pl.Expr)
Delete rows matching the given expression from all partitions.
# Delete all rows where ticker is AAPL
db.delete("stocks", pl.col("ticker") == "AAPL")
Dropping Tables
db.drop(name: str)
Remove a table and all its data.
Table Metadata
# List all tables
tables = db.list_tables() -> list[str]
# Get table schema
schema = db.get_schema(name: str) -> dict[str, pl.DataType]
# Get partition keys
partition_keys = db.get_partition_keys(name: str) -> list[str]
# Get primary keys
primary_keys = db.get_primary_keys(name: str) -> list[str]
Optimizing Tables
db.optimize(name: str)
Deduplicate rows based on primary keys (keeping the last occurrence) and sort data. This compacts storage and improves query performance.
Metadata
Release files for bear-lake 0.1.5
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 | Actions |
|---|---|---|---|---|
| bear_lake-0.1.5.tar.gz | 16.5 kB | Without provenance | Details for bear_lake-0.1.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bear_lake-0.1.5-py3-none-any.whl | Python 3 | none | any | Details for bear_lake-0.1.5-py3-none-any.whl |
Total release size: 25.7 kB
Release files / bear_lake-0.1.5.tar.gz
| Download URL | bear_lake-0.1.5.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa36a7358f22fba5ad6ef09ca84da982691cd583e6fd3b70605e5dc4522eacfe
|
|
BLAKE2b-256 checksum How to use checksums |
88a17f23e3c3bdd32c992d708af9727f2a7f27cb69e6fd21bae6102fd577e57e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / bear_lake-0.1.5-py3-none-any.whl
| Download URL | bear_lake-0.1.5-py3-none-any.whl |
|---|---|
| Size | 9.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f8c0ad9d6a74055c3ebbcc4ac8d6c5c20bb3fec96a6c3531e44148bcb01ed9ae
|
|
BLAKE2b-256 checksum How to use checksums |
b97da96902c3af4bcdcee9b097aac58d7246da41e163bf53e4d5cab40443bb00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for bear-lake 0.1.5
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.