Skip to main content

byoc-storage

PyPI Python Tests Types License

Python SDK for BYOC (Bring Your Own Cloud): one storage API for Google Drive, Nextcloud, and S3-compatible clouds, so files live in accounts the end user already owns.

Part of the BYOC monorepo. Peer implementation of @byoc/core on npm, verified interoperable by an automated cross-SDK suite.

Why

Rather than paying to host every file in one central bucket, BYOC lets an application read and write storage the end user already owns: a personal Google Drive, a company Nextcloud, an organization's own R2 bucket.

FastAPI / Django / Celery
   │
   ├── PostgreSQL  → users, jobs, metadata pointers
   │
   └── byoc        → the actual PDFs, images, audio, model artifacts
           │
           └── the user's own cloud

Use Postgres for application data. Use BYOC for the user's files.

Install

pip install byoc-storage

The distribution is named byoc-storage because byoc on PyPI belongs to an unrelated CLI framework. The import name is still byoc:

import byoc

If you also depend on the unrelated byoc CLI framework, do not install both into the same environment: they share the byoc import name and will shadow each other.

Usage

Start with no credentials at all. LocalFileSystemProvider and MemoryProvider are bundled, need no account and no network, and behave like every other provider:

from byoc import AsyncBYOC, LocalFileSystemProvider

storage = AsyncBYOC(provider=LocalFileSystemProvider("./storage"))

async with storage:
    await storage.write_text("documents/welcome.md", "# Hello from BYOC!")
    content = await storage.read_text("documents/welcome.md")

Swap in S3CompatibleProvider, WebDAVProvider, or GoogleDriveProvider and none of the calling code changes:

import os
from byoc import AsyncBYOC
from byoc.providers.s3 import S3CompatibleProvider

storage = AsyncBYOC(
    provider=S3CompatibleProvider(
        endpoint="https://<account_id>.r2.cloudflarestorage.com",
        bucket="user-assets",
        region="auto",
        access_key_id=os.environ["R2_ACCESS_KEY_ID"],
        secret_access_key=os.environ["R2_SECRET_ACCESS_KEY"],
    )
)

async with storage:
    await storage.write_text("documents/welcome.md", "# Hello from BYOC!")
    content = await storage.read_text("documents/welcome.md")

Testing without a cloud

MemoryProvider is a test double that behaves like a real provider, so your tests exercise the same code path production does:

from byoc import AsyncBYOC, MemoryProvider

async def test_report_is_archived():
    provider = MemoryProvider()
    await archive_report(AsyncBYOC(provider=provider), report)

    assert provider.snapshot() == {"reports/q3.pdf": b"..."}

Like S3, it models a flat object store and reports folders=False. If your production provider has real folders, use LocalFileSystemProvider against a tmp_path instead.

Multiple providers and migration

storage = AsyncBYOC(providers=[drive, r2, nextcloud], default_provider_id="s3-compatible")

storage.use_provider("webdav")
await storage.write_bytes("images/banner.png", data)

report = await storage.migrate(
    source="s3-compatible",
    target="webdav",
    paths=["documents/report.pdf"],
    on_progress=lambda p: print(f"{p.current_file} ({p.percentage}%)"),
)

report.files_partial counts files that reached the target but whose source cleanup failed. The transfer is done, so retrying those would re-upload for nothing.

Async only for now. A synchronous facade for Celery, Django, and scripts is planned but not yet implemented; use asyncio.run() in the meantime.

Google Drive

Drive needs a Google Cloud OAuth client. See Google Drive OAuth Setup, then verify your setup with:

.venv/bin/python scripts/validate_gdrive_live.py

Cross-SDK compatibility

This SDK and the TypeScript SDK are peer implementations of the same contract. Both run against the shared conformance vectors in spec/fixtures, so a file written by a Next.js frontend can be read by a FastAPI backend, including client-side encrypted files, whose envelope format is byte-identical across both.

Development

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

pytest              # unit + conformance suite
mypy src            # strict type checking
ruff check .        # lint

Without activating, call the venv binaries directly: .venv/bin/pytest, .venv/bin/mypy src, .venv/bin/ruff check .

License

Apache-2.0

Metadata

Release files for byoc-storage 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for byoc-storage 0.4.0
File Size Uploaded Provenance Actions
byoc_storage-0.4.0.tar.gz 95.0 kB Without provenance Details for byoc_storage-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for byoc-storage 0.4.0
File Interpreter ABI Platform Actions
byoc_storage-0.4.0-py3-none-any.whl Python 3 none any Details for byoc_storage-0.4.0-py3-none-any.whl

Total release size: 172.5 kB

Release files / byoc_storage-0.4.0.tar.gz

Download URL byoc_storage-0.4.0.tar.gz
Size 95.0 kB
Tags Source
SHA-256 checksum
How to use checksums
347575288dc3d230588ff6acf71dde4d6a0e97765c003312822cda758148e396
BLAKE2b-256 checksum
How to use checksums
1dc67c31afbbae91f09ab10b2a0ce8aa440d563cabef95bc2a98f99737a5047b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / byoc_storage-0.4.0-py3-none-any.whl

Download URL byoc_storage-0.4.0-py3-none-any.whl
Size 77.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
657ee76d148e9a22c3a1b6a25fd0758a4830f5ac07d8247077b5910416c4c43d
BLAKE2b-256 checksum
How to use checksums
f3e920430498ef5f685be9b6d35fa8805f7c74989ffdb5cf623f1b5a21629b04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for byoc-storage 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page