Skip to main content

Python library for uploading files to R2 and registering them with the r2index API

Project description

elaunira-r2index

Python library for uploading and downloading files to/from Cloudflare R2 with the r2index API.

Installation

pip install elaunira-r2index

Usage

Sync Client

from elaunira.r2index import R2IndexClient

client = R2IndexClient(
    index_api_url="https://r2index.example.com",
    index_api_token="your-bearer-token",
    r2_access_key_id="your-r2-access-key-id",
    r2_secret_access_key="your-r2-secret-access-key",
    r2_endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
)

# Upload and register a file
# extension is auto-detected from destination_filename
# media_type is auto-detected from file content
record = client.upload(
    bucket="my-bucket",
    source="./myfile.zip",
    category="software",
    entity="myapp",
    destination_path="/releases/myapp",
    destination_filename="myapp.zip",
    destination_version="v1",
    tags=["release", "stable"],
    create_checksum_files=True,  # Creates .md5, .sha1, .sha256, .sha512 files
)

# Download a file and record the download
# IP address is auto-detected, user agent defaults to "elaunira-r2index/<version>"
path, record = client.download(
    bucket="my-bucket",
    source_path="/releases/myapp",
    source_filename="myapp.zip",
    source_version="v1",
    destination="./downloads/myfile.zip",
    verify_checksum=True,  # Verify SHA-256 checksum after download
)

Async Client

from elaunira.r2index import AsyncR2IndexClient

async with AsyncR2IndexClient(
    index_api_url="https://r2index.example.com",
    index_api_token="your-bearer-token",
    r2_access_key_id="your-r2-access-key-id",
    r2_secret_access_key="your-r2-secret-access-key",
    r2_endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
) as client:
    # Upload (extension and media_type are auto-detected)
    record = await client.upload(
        bucket="my-bucket",
        source="./myfile.zip",
        category="software",
        entity="myapp",
        destination_path="/releases/myapp",
        destination_filename="myapp.zip",
        destination_version="v1",
        tags=["release", "stable"],
    )

    # Download
    path, record = await client.download(
        bucket="my-bucket",
        source_path="/releases/myapp",
        source_filename="myapp.zip",
        source_version="v1",
        destination="./downloads/myfile.zip",
    )

Transfer Configuration

Control multipart transfer settings with R2TransferConfig for both uploads and downloads:

from elaunira.r2index import R2IndexClient, R2TransferConfig

client = R2IndexClient(
    index_api_url="https://r2index.example.com",
    index_api_token="your-bearer-token",
    r2_access_key_id="your-r2-access-key-id",
    r2_secret_access_key="your-r2-secret-access-key",
    r2_endpoint_url="https://your-account-id.r2.cloudflarestorage.com",
)

# Custom transfer settings
transfer_config = R2TransferConfig(
    multipart_threshold=100 * 1024 * 1024,  # 100MB (default)
    multipart_chunksize=32 * 1024 * 1024,   # 32MB chunks
    max_concurrency=64,                      # 64 parallel threads
    use_threads=True,                        # Enable threading (default)
)

# Use with upload
record = client.upload(
    bucket="my-bucket",
    source="./largefile.zip",
    category="data",
    entity="archive",
    destination_path="/data/files",
    destination_filename="largefile.zip",
    destination_version="v1",
    transfer_config=transfer_config,
)

# Use with download
path, record = client.download(
    bucket="my-bucket",
    source_path="/data/files",
    source_filename="largefile.zip",
    source_version="v1",
    destination="./downloads/largefile.zip",
    transfer_config=transfer_config,
)

Default max_concurrency is 2x the number of CPU cores (minimum 4).

Progress Tracking

Uploads and downloads log progress to the elaunira.r2index.storage (or elaunira.r2index.async_storage) logger every 10 seconds by default, showing bytes transferred, percentage, and speed:

Uploading: 150.00 MB / 500.00 MB (30.0%) — 25.00 MB/s
Downloading: 1.20 GB / 3.50 GB (34.3%) — 45.00 MB/s

Control the interval or disable it:

# Log every 30 seconds
path, record = client.download(
    ...,
    progress_interval=30.0,
)

# Disable progress logging
path, record = client.download(
    ...,
    progress_interval=None,
)

You can also provide a custom callback for programmatic progress tracking:

def on_progress(bytes_transferred: int) -> None:
    print(f"Downloaded: {bytes_transferred / 1024 / 1024:.1f} MB")

path, record = client.download(
    bucket="my-bucket",
    source_path="/releases/myapp",
    source_filename="myapp.zip",
    source_version="v1",
    destination="./downloads/myfile.zip",
    progress_callback=on_progress,
)

Skip Existing Downloads

Skip downloading if the destination file already exists:

path, record = client.download(
    bucket="my-bucket",
    source_path="/releases/myapp",
    source_filename="myapp.zip",
    source_version="v1",
    destination="./downloads/myfile.zip",
    overwrite=False,
)

Deleting Files

# Delete from R2 storage (including checksum sidecar files if they exist)
client.delete_from_r2(
    bucket="my-bucket",
    path="/releases/myapp",
    filename="myapp.zip",
    version="v1",
    delete_checksum_files=True,  # Also delete .md5, .sha1, .sha256, .sha512 files
)

# Delete from index (metadata only)
client.delete(file_id)

# Or delete by remote tuple
client.delete_by_tuple(RemoteTuple(
    bucket="my-bucket",
    remote_path="/releases/myapp",
    remote_filename="myapp.zip",
    remote_version="v1",
))

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elaunira_r2index-0.10.7.tar.gz (24.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elaunira_r2index-0.10.7-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file elaunira_r2index-0.10.7.tar.gz.

File metadata

  • Download URL: elaunira_r2index-0.10.7.tar.gz
  • Upload date:
  • Size: 24.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for elaunira_r2index-0.10.7.tar.gz
Algorithm Hash digest
SHA256 5525bfc65a25c3d14619938645ff3a22a1e3407fc63d78c4fafedd13065df174
MD5 88be4e378e7a253a959a26a40a307b68
BLAKE2b-256 36bff513e23f141f170cda182f79666ca5ecd8797ec03ebad556047f3abd39e0

See more details on using hashes here.

File details

Details for the file elaunira_r2index-0.10.7-py3-none-any.whl.

File metadata

File hashes

Hashes for elaunira_r2index-0.10.7-py3-none-any.whl
Algorithm Hash digest
SHA256 d492d9f6ff70066d200d5d13adc077edad034d26ec2e01d99ff14d5bd0eb3a22
MD5 d1b24be70616db3b77a9d462eb35d084
BLAKE2b-256 64cedd92daa2e9ae20d3dce631614ea3cfacd0cd5fdfe66e4c3b361d219b079b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page