S3-compatible storage library with automatic fallback support
Project description
fallbacks3
S3-compatible storage library with automatic fallback for the upload process.
Installation
pip install fallbacks3
For development:
pip install -e .
Configuration
You must configure a comma-separated list of providers, as well as the scheme of the fallback provider, with environment variables named PROVIDERS and FALLBACK_PROVIDER.
# Comma-separated list of provider URIs
PROVIDERS="ps3://access_key:secret_key@ps3.palver.com,r2://access_key:secret_key@account.r2.cloudflarestorage.com"
# Fallback provider scheme (must be one of the providers in PROVIDERS)
FALLBACK_PROVIDER="r2"
Provider URI Format
Provider URIs follow the format:
<provider_scheme>://<access_key>:<secret_key>@<endpoint>
Examples: r2://key:secret@account.r2.cloudflarestorage.com, local://test:testkey@localhost:9000
Remote File URI Format
File URIs should specify the exact location from a provider bucket:
<provider>://<bucket>/<file_path>
Examples: ps3://palver-whatsapp/audio.mp3, s3://my-bucket/documents/report.pdf
Usage
from fallbacks3 import Storage
# Initialize storage using environment variables (PROVIDERS and FALLBACK_PROVIDER)
storage = Storage()
# Upload a local file to the provided remote path
stored_file_uri = storage.upload_file(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
local_file_path="/local/path/audio.mp3"
)
print(uri) # "ps3://palver-whatsapp/audio.mp3"
# Async upload (for async environments)
stored_file_uri = await storage.upload_file_async(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
local_file_path="/local/path/audio.mp3"
)
# Download a file
downloaded_file_path = storage.download_file(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
local_file_path="/local/path/audio.mp3"
)
print(local_path) # "/local/path/audio.mp3"
# Generate a signed URL for temporary access (default: 60 seconds)
signed_url = storage.generate_signed_url(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
expiration=3600
)
print(signed_url) # "https://ps3.palver.com/palver-whatsapp/audio.mp3?signature=..."
Upload with Automatic Fallback
If the primary provider fails for the upload method, the library automatically retries with the fallback provider (using the same bucket and file path), as to ensure files are not lost.
# If ps3 fails, automatically falls back to r2
stored_file_path = storage.upload_file(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
local_file_path="/local/path/audio.mp3"
)
# Returns "r2://palver-whatsapp/audio.mp3" if ps3 failed
Raises an exception if both primary and fallback providers fail.
Async Upload
For async environments, use upload_file_async():
import asyncio
from fallbacks3 import Storage
storage = Storage()
async def upload():
stored_file_uri = await storage.upload_file_async(
remote_file_uri="ps3://palver-whatsapp/audio.mp3",
local_file_path="/local/path/audio.mp3"
)
print(stored_file_uri) # "ps3://palver-whatsapp/audio.mp3"
asyncio.run(upload())
The async method also supports automatic fallback, just like the synchronous version.
Download and Signed URLs
Download and signed URL generation use the provider specified in the remote file URI.
Development
Install development dependencies:
pip install -e ".[dev]"
You can also develop with uv if available.
uv pip install -e ".[dev]"
Run tests:
pytest --cov=fallbacks3
# alternatively, with uv:
uv run pytest --cov=fallbacks3
Publishing to PyPI
The project is set up to be automatically uploaded to PyPI when a new tag is pushed. For a successful push, all tests must pass and the project must pass the check and format requirements.
One-time setup
Before publishing for the first time:
- Configure Trusted Publishing on PyPI:
- Go to https://pypi.org/manage/account/publishing/
- Add a new pending publisher:
- PyPI Project Name:
fallbacks3 - Owner:
palverdata - Repository name:
fallbacks3 - Workflow name:
publish.yaml - Environment name:
pypi
- PyPI Project Name:
You must have access to the pypi GitHub environment or be approved by required reviewers (milasd or giancarlopro) to publish.
Publishing a new version
- Update version in
pyproject.toml - Create and push a tag:
git tag v[new version] # eg.: git tag v0.1.0 git push origin v[new version] # eg.: git push origin v0.1.0
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fallbacks3-0.4.0.tar.gz.
File metadata
- Download URL: fallbacks3-0.4.0.tar.gz
- Upload date:
- Size: 8.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b57b2b85c15e89095f0e30b729f7e2fea68d0dcb6ed5cb20e7463e255ed494a5
|
|
| MD5 |
595a6c0299cc79b8d414d8a1348ad5f1
|
|
| BLAKE2b-256 |
7e6e1ccfaad9a222dec85b3f67423effddab2ecb398915862442695f81544a4d
|
Provenance
The following attestation bundles were made for fallbacks3-0.4.0.tar.gz:
Publisher:
publish.yaml on palverdata/fallbacks3
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fallbacks3-0.4.0.tar.gz -
Subject digest:
b57b2b85c15e89095f0e30b729f7e2fea68d0dcb6ed5cb20e7463e255ed494a5 - Sigstore transparency entry: 1971335095
- Sigstore integration time:
-
Permalink:
palverdata/fallbacks3@29fc3edce59aca64dd2ae19abf3156691f62fb91 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/palverdata
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@29fc3edce59aca64dd2ae19abf3156691f62fb91 -
Trigger Event:
push
-
Statement type:
File details
Details for the file fallbacks3-0.4.0-py3-none-any.whl.
File metadata
- Download URL: fallbacks3-0.4.0-py3-none-any.whl
- Upload date:
- Size: 8.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbe55e8b29172ef155bb89a0400277588c024c43f5decf6ebd0927fbbe29e848
|
|
| MD5 |
ffa020327abb16ef534266981f33516d
|
|
| BLAKE2b-256 |
0783c484c891ed3d466acf9c10c2ff71fc24f340020ab800fe0a8ce00698dcf6
|
Provenance
The following attestation bundles were made for fallbacks3-0.4.0-py3-none-any.whl:
Publisher:
publish.yaml on palverdata/fallbacks3
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fallbacks3-0.4.0-py3-none-any.whl -
Subject digest:
dbe55e8b29172ef155bb89a0400277588c024c43f5decf6ebd0927fbbe29e848 - Sigstore transparency entry: 1971335206
- Sigstore integration time:
-
Permalink:
palverdata/fallbacks3@29fc3edce59aca64dd2ae19abf3156691f62fb91 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/palverdata
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@29fc3edce59aca64dd2ae19abf3156691f62fb91 -
Trigger Event:
push
-
Statement type: