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.11.0.tar.gz (28.3 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.11.0-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for elaunira_r2index-0.11.0.tar.gz
Algorithm Hash digest
SHA256 21b959887d8fba0da3d0d9b69b5bb755d19c4d54e1f22b147169c1433454655e
MD5 a274b80eb758d5ead0298fa5d1c9aa25
BLAKE2b-256 02158601b8373c1b54d10f52f89b51293c545143a2a7ade797ab22993fcef8c0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for elaunira_r2index-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 498f6e6d085a1134d369a162f2dd9751febdae294dbcd39eb4c1d2f13e2b1548
MD5 35bf7f7d54c54db35ab61c12369e14e9
BLAKE2b-256 299a5938cce49f508cf8faaeec2392447352d68102b4ccb4e3c48b7b67c27ea4

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