Extend boto3 with Tigris-specific features like snapshots and bucket forking, while maintaining full boto3 compatibility.
- Snapshot Support: Create, list, and read from bucket snapshots
- Bucket Forking: Create forked buckets from existing buckets or snapshots
- Multiple Usage Patterns: Context managers, decorators, helper functions, or wrapper client
- Zero Configuration: Works with existing boto3 code
- Type Safe: Full type hints for IDE support
- Pythonic API: Uses familiar Python patterns
pip install tigris-boto3-extfrom tigris_boto3_ext import TigrisSnapshotEnabled
with TigrisSnapshotEnabled(s3_client):
s3_client.create_bucket(Bucket='my-snapshot-bucket')from tigris_boto3_ext import TigrisSnapshot
# List snapshots for a bucket
with TigrisSnapshot(s3_client, 'my-bucket'):
snapshots = s3_client.list_buckets()
# Read objects from a specific snapshot
with TigrisSnapshot(s3_client, 'my-bucket', snapshot_version='12345'):
obj = s3_client.get_object(Bucket='my-bucket', Key='file.txt')
objects = s3_client.list_objects_v2(Bucket='my-bucket')from tigris_boto3_ext import TigrisFork
# Fork from current state
with TigrisFork(s3_client, 'source-bucket'):
s3_client.create_bucket(Bucket='forked-bucket')
# Fork from specific snapshot
with TigrisFork(s3_client, 'source-bucket', snapshot_version='12345'):
s3_client.create_bucket(Bucket='forked-from-snapshot')from tigris_boto3_ext import snapshot_enabled, with_snapshot, forked_from
@snapshot_enabled
def create_snapshot_enabled_bucket(s3_client, bucket_name):
return s3_client.create_bucket(Bucket=bucket_name)
# List available snapshots
@with_snapshot('my-bucket')
def list_snapshots(s3_client):
return s3_client.list_buckets()
# Read from specific snapshot
@with_snapshot('my-bucket', snapshot_version='12345')
def read_from_snapshot(s3_client, key):
return s3_client.get_object(Bucket='my-bucket', Key=key)
@forked_from('source-bucket', snapshot_version='12345')
def create_my_fork(s3_client, new_bucket):
return s3_client.create_bucket(Bucket=new_bucket)
# Use the decorated functions
create_snapshot_enabled_bucket(s3_client, 'my-bucket')
snapshots = list_snapshots(s3_client)
obj = read_from_snapshot(s3_client, 'file.txt')
create_my_fork(s3_client, 'my-fork')from tigris_boto3_ext import (
create_snapshot_bucket,
create_snapshot,
list_snapshots,
create_fork,
get_object_from_snapshot,
get_snapshot_version,
list_objects_from_snapshot,
head_object_from_snapshot,
has_snapshot_enabled,
get_bucket_info,
)
# Create snapshot-enabled bucket
create_snapshot_bucket(s3_client, 'my-bucket')
# Check if bucket has snapshots enabled
if has_snapshot_enabled(s3_client, 'my-bucket'):
print("Snapshots are enabled!")
# Get comprehensive bucket information
info = get_bucket_info(s3_client, 'my-bucket')
print(f"Snapshot enabled: {info['snapshot_enabled']}")
# Create snapshots
result = create_snapshot(s3_client, 'my-bucket', snapshot_name='backup-1')
version = get_snapshot_version(result)
# List snapshots
snapshots = list_snapshots(s3_client, 'my-bucket')
# Create forks
create_fork(s3_client, 'new-bucket', 'source-bucket', snapshot_version=version)
# Access snapshot data
obj = get_object_from_snapshot(s3_client, 'my-bucket', 'file.txt', version)
objects = list_objects_from_snapshot(s3_client, 'my-bucket', '12345', Prefix='data/')
metadata = head_object_from_snapshot(s3_client, 'my-bucket', 'file.txt', '12345')import boto3
from tigris_boto3_ext import (
create_snapshot_bucket,
create_snapshot,
list_snapshots,
create_fork,
get_snapshot_version,
)
s3 = boto3.client('s3')
# Create a snapshot-enabled bucket
create_snapshot_bucket(s3, 'production-data')
# Add some data
s3.put_object(Bucket='production-data', Key='important.txt', Body=b'critical data')
# Create a snapshot
snapshot_result = create_snapshot(s3, 'production-data', snapshot_name='daily-backup')
snapshot_version = get_snapshot_version(snapshot_result)
# List all snapshots
snapshots = list_snapshots(s3, 'production-data')
for bucket in snapshots.get('Buckets', []):
print(f"Snapshot: {bucket['Name']}")
# Restore from snapshot by creating a fork
create_fork(s3, 'restored-data', 'production-data', snapshot_version=snapshot_version)import boto3
from tigris_boto3_ext import create_fork, create_snapshot, get_snapshot_version
s3 = boto3.client('s3')
# Create a snapshot of production data
snapshot_result = create_snapshot(s3, 'production-data', snapshot_name='test-snapshot')
snapshot_version = get_snapshot_version(snapshot_result)
# Fork for testing (isolated copy)
create_fork(s3, 'test-data', 'production-data', snapshot_version=snapshot_version)
# Run tests against test-db without affecting production
s3.put_object(Bucket='test-data', Key='test-data.txt', Body=b'test data')
# Clean up test bucket when done
s3.delete_bucket(Bucket='test-data')import boto3
from tigris_boto3_ext import get_object_from_snapshot, list_objects_from_snapshot
s3 = boto3.client('s3')
# Get object as it was at a specific snapshot
historical_obj = get_object_from_snapshot(
s3,
'my-bucket',
'config.json',
snapshot_version='12345'
)
old_config = historical_obj['Body'].read()
# List all objects in historical snapshot
historical_objects = list_objects_from_snapshot(
s3,
'my-bucket',
snapshot_version='12345',
Prefix='logs/2024/'
)
for obj in historical_objects.get('Contents', []):
print(f"Historical object: {obj['Key']}")import boto3
from tigris_boto3_ext import (
create_snapshot_bucket,
create_snapshot,
create_fork,
get_snapshot_version,
has_snapshot_enabled,
get_bucket_info,
)
s3 = boto3.client('s3')
# Check if a bucket has snapshots enabled
bucket_name = 'my-bucket'
create_snapshot_bucket(s3, bucket_name)
if has_snapshot_enabled(s3, bucket_name):
print(f"✓ Snapshots are enabled for {bucket_name}")
else:
print(f"✗ Snapshots are not enabled for {bucket_name}")
# Get comprehensive bucket information
info = get_bucket_info(s3, bucket_name)
print(f"Snapshot enabled: {info['snapshot_enabled']}")
# Example: Check fork lineage
source_bucket = 'production-data'
create_snapshot_bucket(s3, source_bucket)
# Create a snapshot
snapshot_result = create_snapshot(s3, source_bucket, snapshot_name='v1')
snapshot_version = get_snapshot_version(snapshot_result)
# Create a fork
forked_bucket = 'test-data'
create_fork(s3, forked_bucket, source_bucket, snapshot_version=snapshot_version)
# Inspect the fork
fork_info = get_bucket_info(s3, forked_bucket)
print(f"Forked from: {fork_info['fork_source_bucket']}")
print(f"Snapshot version: {fork_info['fork_source_snapshot']}")This library uses boto3's event system to inject Tigris-specific headers into S3 API requests:
X-Tigris-Enable-Snapshot: true- Enables snapshot support for bucket creationX-Tigris-Snapshot: true; name=<name>- Creates a snapshotX-Tigris-Snapshot: <bucket_name>- Lists snapshots for a bucketX-Tigris-Snapshot-Version: <version>- Reads from specific snapshot versionX-Tigris-Fork-Source-Bucket: <bucket>- Specifies fork sourceX-Tigris-Fork-Source-Bucket-Snapshot: <version>- Forks from specific snapshot
The following custom headers are returned in HeadBucket responses and can be accessed via get_bucket_info() and has_snapshot_enabled():
X-Tigris-Enable-Snapshot: true- Present when snapshots are enabled for the bucketX-Tigris-Fork-Source-Bucket: <bucket_name>- Present on forked buckets, indicates the parent bucketX-Tigris-Fork-Source-Bucket-Snapshot: <version>- Present on forked buckets, indicates the snapshot version
The library registers event handlers on before-sign.s3.* events to add request headers transparently.
- Python 3.9+
- boto3 >= 1.26.0
# Clone the repository
git clone https://github.com/tigrisdata/tigris-boto3-ext.git
cd tigris-boto3-ext
# Install with dev dependencies using uv
uv sync --all-extras
# Or with pip
pip install -e ".[dev]"Integration tests run against a real Tigris S3 service. See tests/integration/README.md for detailed setup instructions.
# Set up environment variables
export AWS_ENDPOINT_URL_S3="https://t3.storage.dev"
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
# Run integration tests
uv run pytest tests/integration/ -v# Type checking
uv run mypy tigris_boto3_ext
# Linting
uv run ruff check tigris_boto3_ext
# Auto-fix linting issues
uv run ruff check --fix tigris_boto3_ext
# Code formatting
uv run ruff format tigris_boto3_ext
# Check formatting without making changes
uv run ruff format --check tigris_boto3_extApache-2.0
Contributions welcome! Please open an issue or PR on GitHub.
For issues and questions:
- GitHub Issues: https://github.com/tigrisdata/tigris-boto3-ext/issues
- Documentation: https://www.tigrisdata.com/docs