remote-store¶
A Store is a logical folder. Where files live is configuration.
remote-store provides a single interface for file storage across local filesystems, S3, SFTP, Azure, and more, using the libraries you would choose yourself.
Architecture¶
flowchart LR
Ext["Extensions"]
subgraph CORE[" "]
direction TB
API["Your Code"]
Store["Store API"]
Methods["Read/Write - List - Copy/Move - Config - Capabilities"]
API --> Store
Store -.-> Methods
end
subgraph INFRA[" "]
direction TB
Backends["Backends"]
B_list["Local - S3 - SFTP - Azure - Http - Memory - SQL - ...yours"]
Libs["Proven Libraries"]
L_list["stdlib - s3fs - pyarrow - paramiko - azure SDK"]
Backends -.-> B_list
Backends --> Libs
Libs -.-> L_list
end
Ext -. enhance .-> CORE
CORE --> INFRA
- The Store provides a portable API
- Backends implement storage-specific behavior
- Libraries do the actual I/O
- Extensions add optional capabilities alongside the core
The core idea¶
A Store scopes all operations to a root path. Everything is relative.
from remote_store import Store
from remote_store.backends import LocalBackend
store = Store(LocalBackend(root="/tmp/data"))
store.write_text("hello.txt", "Hello, world!")
print(store.read_text("hello.txt")) # 'Hello, world!'
Switch backend without changing application code:
from remote_store import Store
from remote_store.backends import S3Backend
store = Store(S3Backend(bucket="my-bucket"))
store.write_text("file.txt", "hello")
print(store.read_text("file.txt")) # same API, different backend
Narrow scope with child(); all paths inside are relative to the new root:
See Store child scoping for more.
Design principles¶
Zero dependencies in core¶
Install only what you use. pip install remote-store pulls in nothing.
Extras like [s3] or [sftp] bring in only the backend you need.
Proven libraries underneath¶
Established libraries like s3fs, paramiko, and the Azure SDK do the
real work: remote-store adapts, they execute.
Backends delegate to the packages you'd pick yourself.
Backend-native when possible¶
glob() and atomic writes work everywhere. Where the backend supports them
natively, remote-store uses that. Where not, a portable fallback steps in.
from remote_store import Capability
store.supports(Capability.GLOB) # True for most backends; see capabilities matrix
store.supports(Capability.ATOMIC_WRITE) # True for most backends; see capabilities matrix
Extensions sit beside, not around¶
Extensions like caching, observability, batch operations, and PyArrow
integration: import what you need from remote_store.ext.
Your Store code doesn't change.
Bring your own¶
Implement the Backend protocol for a new storage target. Or write an
extension. The hooks are public.
from remote_store import Backend, Store
class MyBackend(Backend):
"""Implement the Backend protocol for your storage."""
...
store = Store(MyBackend(...)) # works with all extensions
See the custom backend guide for a step-by-step walkthrough.
Quick start¶
from remote_store import Store
from remote_store.backends import S3Backend
store = Store(S3Backend(bucket="my-bucket"))
store.write_text("file.txt", "hello")
print(store.read_text("file.txt")) # 'hello'
See Getting Started for a complete walkthrough.
Where to go next¶
- Getting Started: install, tutorial, and runnable examples
- Guides: Backends · Extensions · Choosing a Backend · and more
- Reference: API · Features · Capabilities Matrix · Changelog
- Explanation: Architecture · Performance · Concurrency