Python API
Use walrust from Python for programmatic SQLite backups and restores.
Installation
Section titled “Installation”pip install walrustQuick Start
Section titled “Quick Start”from walrust import Walrust
# Create instancews = Walrust("s3://my-bucket", endpoint="https://fly.storage.tigris.dev")
# Take a snapshotws.snapshot("/path/to/app.db")
# List backed up databasesdbs = ws.list()print(dbs) # ['app', 'users', 'analytics']
# Restore a databasews.restore("app", "/path/to/restored.db")Class: Walrust
Section titled “Class: Walrust”The main class for interacting with walrust.
Constructor
Section titled “Constructor”Walrust(bucket: str, endpoint: Optional[str] = None)Create a new Walrust instance.
Parameters:
bucket(str): S3 bucket URL. Can be:"s3://my-bucket"(AWS S3)"s3://my-bucket/prefix"(with prefix)"my-bucket"(without s3:// prefix)
endpoint(str, optional): S3 endpoint URL for non-AWS providers:- Tigris:
"https://fly.storage.tigris.dev" - MinIO:
"http://localhost:9000" - Cloudflare R2:
"https://<account-id>.r2.cloudflarestorage.com"
- Tigris:
Returns:
Walrustinstance
Raises:
RuntimeError: If unable to create runtime or invalid configuration
Example:
# AWS S3ws = Walrust("s3://my-backups")
# Tigris (Fly.io)ws = Walrust("s3://my-backups", endpoint="https://fly.storage.tigris.dev")
# With prefixws = Walrust("s3://my-backups/production")Methods
Section titled “Methods”snapshot()
Section titled “snapshot()”snapshot(database: str) -> NoneTake a snapshot of a database and upload to S3.
Parameters:
database(str): Path to the SQLite database file
Returns:
- None
Raises:
RuntimeError: If snapshot fails (database not found, S3 error, etc.)
Example:
ws = Walrust("s3://my-bucket")
# Snapshot a single databasews.snapshot("/data/app.db")
# Snapshot multiple databases in a loopfor db in ["/data/app.db", "/data/users.db"]: ws.snapshot(db)Notes:
- Database must exist and be readable
- Database should be in WAL mode (walrust will warn if not)
- Creates a full snapshot with all database pages
- Uploads to
s3://<bucket>/<db-name>/00000001-00000001.ltx
restore()
Section titled “restore()”restore(name: str, output: str, point_in_time: Optional[str] = None) -> NoneRestore a database from S3.
Parameters:
name(str): Database name as stored in S3 (usually the filename without extension)output(str): Output path for the restored databasepoint_in_time(str, optional): ISO 8601 timestamp for point-in-time recovery (e.g.,"2024-01-15T10:30:00Z")
Returns:
- None
Raises:
RuntimeError: If restore fails (no snapshot found, S3 error, checksum mismatch, etc.)
Example:
ws = Walrust("s3://my-bucket")
# Basic restorews.restore("app", "/data/restored.db")
# Point-in-time restorews.restore( "app", "/data/restored.db", point_in_time="2024-01-15T10:30:00Z")Notes:
- Downloads the latest snapshot and applies all incremental LTX files
- Verifies checksums during restore
- Point-in-time restore stops at the closest transaction before the specified time
- If
point_in_timeis before the first snapshot, raisesRuntimeError
list()
Section titled “list()”list() -> List[str]List databases stored in the S3 bucket.
Parameters:
- None
Returns:
List[str]: List of database names (as stored in S3)
Raises:
RuntimeError: If listing fails (S3 error, authentication failure, etc.)
Example:
ws = Walrust("s3://my-bucket")
# List all databasesdbs = ws.list()print(dbs)# Output: ['app', 'users', 'analytics']
# Check if a specific database existsif 'app' in ws.list(): print("app.db is backed up")Notes:
- Returns database names (prefixes), not full S3 keys
- Empty list if no databases found
- Requires
s3:ListBucketpermission
Module-Level Functions
Section titled “Module-Level Functions”Convenience functions for one-off operations without creating a Walrust instance.
snapshot()
Section titled “snapshot()”snapshot(database: str, bucket: str, endpoint: Optional[str] = None) -> NoneTake a snapshot without creating a Walrust instance.
Parameters:
database(str): Path to the SQLite database filebucket(str): S3 bucket URLendpoint(str, optional): S3 endpoint URL
Returns:
- None
Raises:
RuntimeError: If snapshot fails
Example:
from walrust import snapshot
# Quick snapshotsnapshot("/data/app.db", "s3://my-bucket")
# With custom endpointsnapshot( "/data/app.db", "s3://my-bucket", endpoint="https://fly.storage.tigris.dev")restore()
Section titled “restore()”restore( name: str, output: str, bucket: str, endpoint: Optional[str] = None, point_in_time: Optional[str] = None) -> NoneRestore a database without creating a Walrust instance.
Parameters:
name(str): Database name as stored in S3output(str): Output path for the restored databasebucket(str): S3 bucket URLendpoint(str, optional): S3 endpoint URLpoint_in_time(str, optional): ISO 8601 timestamp for PITR
Returns:
- None
Raises:
RuntimeError: If restore fails
Example:
from walrust import restore
# Quick restorerestore("app", "/data/restored.db", "s3://my-bucket")
# With point-in-timerestore( "app", "/data/restored.db", "s3://my-bucket", point_in_time="2024-01-15T10:30:00Z")list_databases()
Section titled “list_databases()”list_databases(bucket: str, endpoint: Optional[str] = None) -> List[str]List databases without creating a Walrust instance.
Parameters:
bucket(str): S3 bucket URLendpoint(str, optional): S3 endpoint URL
Returns:
List[str]: List of database names
Raises:
RuntimeError: If listing fails
Example:
from walrust import list_databases
# Quick listdbs = list_databases("s3://my-bucket")print(dbs)
# With custom endpointdbs = list_databases( "s3://my-bucket", endpoint="https://fly.storage.tigris.dev")Error Handling
Section titled “Error Handling”All methods raise RuntimeError on failure. Catch exceptions to handle errors gracefully:
from walrust import Walrust
ws = Walrust("s3://my-bucket")
try: ws.snapshot("/data/app.db")except RuntimeError as e: print(f"Snapshot failed: {e}") # Handle error (retry, alert, etc.)Common error scenarios:
- Database not found: File doesn’t exist or not readable
- S3 authentication failure: Invalid credentials or missing env vars
- Network error: Can’t reach S3 endpoint
- Checksum mismatch: Corrupted backup during restore
- No snapshot found: Database name doesn’t exist in S3
Environment Variables
Section titled “Environment Variables”Walrust reads standard AWS environment variables:
import os
# Set credentialsos.environ["AWS_ACCESS_KEY_ID"] = "your-key"os.environ["AWS_SECRET_ACCESS_KEY"] = "your-secret"os.environ["AWS_ENDPOINT_URL_S3"] = "https://fly.storage.tigris.dev"
# Now use walrustfrom walrust import Walrustws = Walrust("s3://my-bucket")ws.snapshot("/data/app.db")Required environment variables:
AWS_ACCESS_KEY_ID- S3 access keyAWS_SECRET_ACCESS_KEY- S3 secret keyAWS_ENDPOINT_URL_S3- S3 endpoint (optional for AWS S3, required for Tigris/MinIO/R2)AWS_REGION- AWS region (optional, defaults tous-east-1)
Complete Examples
Section titled “Complete Examples”Automated Backup Script
Section titled “Automated Backup Script”#!/usr/bin/env python3from walrust import Walrustimport sys
DATABASES = [ "/data/app.db", "/data/users.db", "/data/analytics.db",]
def main(): ws = Walrust("s3://my-bucket", endpoint="https://fly.storage.tigris.dev")
failed = [] for db in DATABASES: try: print(f"Snapshotting {db}...") ws.snapshot(db) print(f"✓ {db}") except RuntimeError as e: print(f"✗ {db}: {e}") failed.append(db)
if failed: print(f"\nFailed to snapshot {len(failed)} database(s)") sys.exit(1) else: print(f"\n✓ All {len(DATABASES)} databases backed up") sys.exit(0)
if __name__ == "__main__": main()Disaster Recovery Script
Section titled “Disaster Recovery Script”#!/usr/bin/env python3from walrust import Walrustimport sys
def restore_all(bucket, endpoint, output_dir): """Restore all databases from S3""" ws = Walrust(bucket, endpoint=endpoint)
# List all backed up databases dbs = ws.list() print(f"Found {len(dbs)} database(s) in {bucket}")
# Restore each one for name in dbs: output = f"{output_dir}/{name}.db" try: print(f"Restoring {name} to {output}...") ws.restore(name, output) print(f"✓ {name}") except RuntimeError as e: print(f"✗ {name}: {e}") return False
print(f"\n✓ Restored all {len(dbs)} databases to {output_dir}") return True
if __name__ == "__main__": success = restore_all( bucket="s3://my-bucket", endpoint="https://fly.storage.tigris.dev", output_dir="/recovery" ) sys.exit(0 if success else 1)Flask Integration
Section titled “Flask Integration”from flask import Flaskfrom walrust import Walrustimport os
app = Flask(__name__)
# Initialize walrustws = Walrust( os.environ["S3_BUCKET"], endpoint=os.environ.get("S3_ENDPOINT"))
@app.route("/backup", methods=["POST"])def backup(): """Trigger manual backup""" try: ws.snapshot("/data/app.db") return {"status": "success"}, 200 except RuntimeError as e: return {"status": "error", "message": str(e)}, 500
@app.route("/backups", methods=["GET"])def list_backups(): """List available backups""" try: dbs = ws.list() return {"databases": dbs}, 200 except RuntimeError as e: return {"status": "error", "message": str(e)}, 500
if __name__ == "__main__": app.run()Jupyter Notebook Usage
Section titled “Jupyter Notebook Usage”# Cell 1: Setupfrom walrust import Walrustimport pandas as pdimport sqlite3
ws = Walrust("s3://my-bucket", endpoint="https://fly.storage.tigris.dev")
# Cell 2: Analyze dataconn = sqlite3.connect("analysis.db")df = pd.read_sql("SELECT * FROM results", conn)df.describe()
# Cell 3: Backup resultsws.snapshot("analysis.db")print("Analysis backed up to S3")
# Cell 4: Later... restorews.restore("analysis", "analysis-restored.db")conn_restored = sqlite3.connect("analysis-restored.db")df_restored = pd.read_sql("SELECT * FROM results", conn_restored)assert df.equals(df_restored), "Backup verification failed!"print("✓ Backup verified")Best Practices
Section titled “Best Practices”-
Reuse Walrust instances - Creating instances is cheap, but reusing them avoids repeated authentication
-
Use try/except - Always wrap walrust calls in error handling
-
Check WAL mode - Ensure your database uses WAL mode:
import sqlite3conn = sqlite3.connect("app.db")conn.execute("PRAGMA journal_mode=WAL")conn.close()- Validate backups - Periodically test restores to ensure backups work:
import tempfileimport os
def validate_backup(ws, name): """Restore to temp location and verify""" with tempfile.NamedTemporaryFile(delete=False) as tmp: try: ws.restore(name, tmp.name) # Run integrity check conn = sqlite3.connect(tmp.name) result = conn.execute("PRAGMA integrity_check").fetchone() conn.close() return result[0] == "ok" finally: os.unlink(tmp.name)- Set environment variables - Don’t hardcode credentials:
# Goodws = Walrust(os.environ["S3_BUCKET"])
# Badws = Walrust("s3://my-bucket") # Credentials in env varsSee Also
Section titled “See Also”- CLI Reference - Command-line interface
- Configuration Reference - Config file options
- Troubleshooting - Common issues