Skip to main content

tinydb-storage

CI PyPI Python

Note: this is an independent project. It is not an official TinyDB package and is not affiliated with or endorsed by the TinyDB project or its maintainers.

Storage extensions for TinyDB. Keep a TinyDB database in Redis or S3 (including S3-compatible services such as MinIO and Cloudflare R2) instead of a local file.

Both storages keep the whole database as one JSON value, like TinyDB's own JSONStorage, and they never silently lose data:

  • A failed read raises the error. It is never mistaken for an empty database, so the next write can't replace your data.
  • A write fails with StorageConflictError when another process changed the database after this one read it, instead of overwriting that change. Redis uses WATCH, S3 uses conditional writes (If-Match / If-None-Match).

Installation

Install the extra for the storage you use:

pip install "tinydbstorage[redis]"   # RedisStorage
pip install "tinydbstorage[s3]"      # S3Storage
pip install "tinydbstorage[all]"     # both

Requires Python 3.10+ and TinyDB 4.8+.

Redis storage example

from tinydb import TinyDB, Query
from tinydbstorage.storage import RedisStorage

db = TinyDB(storage=RedisStorage, redis_uri="redis://:secret@localhost:6379/0")
db.table("users").insert({"name": "John"})
db.table("users").search(Query().name == "John")

Options:

  • key: the Redis key holding the database. Default tiny_db.
  • client: an existing redis.Redis client instead of redis_uri. It is left open when the database closes.
  • Any other keyword argument goes to redis.Redis.from_url, for example socket_timeout=5.

S3 storage example

from tinydb import TinyDB
from tinydbstorage import S3Schema
from tinydbstorage.storage import S3Storage

config = S3Schema(bucket_name="foo", file_path="foo/bar/baz.json", region_name="ap-southeast-1")
db = TinyDB(storage=S3Storage, config=config)
db.table("users").insert({"name": "John"})

Credentials are optional. Left out, boto3 uses its default chain: environment variables, ~/.aws config, or the instance/task role. To pass them explicitly:

config = S3Schema.from_param(
    bucket_name="foo",
    file_path="foo/bar/baz.json",
    region_name="ap-southeast-1",
    access_key_id="bar",
    secret_access_key="secretkey",
)

For MinIO, Cloudflare R2 and other S3-compatible services, set endpoint_url:

config = S3Schema(bucket_name="foo", file_path="db.json", endpoint_url="http://localhost:9000")

You can also pass your own boto3 S3 client with client=.

Concurrent writers

Two processes can share one database. If one writes after the other read, the second write raises StorageConflictError and nothing is overwritten. Retry the operation, which reads the latest data first.

An insert needs one more step. TinyDB remembers the next document ID per table, so when another process inserted first, the insert can also fail with ValueError: Document with ID ... already exists. Nothing is written in that case either. Retry inserts with a new TinyDB, which reads the IDs again:

import redis
from tinydb import TinyDB
from tinydbstorage import StorageConflictError
from tinydbstorage.storage import RedisStorage

client = redis.Redis.from_url("redis://localhost:6379/0")

for attempt in range(5):
    try:
        TinyDB(storage=RedisStorage, client=client).insert({"name": "John"})
        break
    except (StorageConflictError, ValueError):
        if attempt == 4:
            raise

Updates and removes don't use the ID counter, so retrying them on the same db is enough.

If your service doesn't support conditional writes, or you want the old last-write-wins behaviour, pass check_conflicts=False to the storage.

Joining tables across storages

tinydbjoin joins TinyDB tables in memory, wherever each one is stored, for example customers in Redis and orders in a local JSON file:

from tinydb import TinyDB
from tinydbjoin import Join
from tinydbstorage.storage import RedisStorage

customers = TinyDB(storage=RedisStorage, redis_uri="redis://localhost:6379/0").table("customers")
orders = TinyDB("orders.json").table("orders")

Join.inner(orders, customers, on=("customer_id", "id"))  # [(order, customer), ...]

Upgrading from 0.1

  • Install the extra you need (tinydbstorage[redis] or [s3]). Redis and boto3 are no longer installed by default, and pydantic and python-dateutil are no longer dependencies.
  • Read errors are raised instead of returning an empty database, and conflicting writes raise StorageConflictError.
  • RedisStorage(prefix=...) still works and sets the key; prefer key=.
  • S3Schema is a frozen dataclass. S3Schema(...) and S3Schema.from_param(...) work as before, and the credentials are now optional.
  • MemoryStorage and FileStorage are deprecated, because TinyDB ships them: use tinydb.storages.MemoryStorage and tinydb.storages.JSONStorage.

Development

make install   # poetry install --all-extras
make test      # pytest with coverage
make format    # black

The tests run against in-process fakes (fakeredis and moto), so no Redis server or AWS account is needed.

Help & Bugs

contributions welcome

If you are still confused or found a bug, please open the issue. All bug reports are appreciated.

License

license

tinydb-storage released under MIT. See LICENSE for more details.

Metadata

Release files for tinydbstorage 0.2.1

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

Source distribution (sdist)

Source distribution for tinydbstorage 0.2.1
File Size Uploaded
tinydbstorage-0.2.1.tar.gz 9.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tinydbstorage 0.2.1
File Interpreter ABI Platform
tinydbstorage-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 20.0 kB

Release files / tinydbstorage-0.2.1.tar.gz

Download URL tinydbstorage-0.2.1.tar.gz
Size 9.6 kB
Tags Source
SHA-256 checksum
How to use checksums
1aea46f8a535b5273f9aabf03388cf92dc0417128a7fd8eced93bd7487cca43e
BLAKE2b-256 checksum
How to use checksums
d2d0c50ae26c185b285e76305faa9ef550b69a79af3c754c9c98ea1bdcb83e7f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.4 CPython/3.12.3 Linux/6.17.0-1022-azure

Release files / tinydbstorage-0.2.1-py3-none-any.whl

Download URL tinydbstorage-0.2.1-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e08a46a38982d2a3731be44f6ffd07eb23f2b72bc12f7dec8c369cd3388e59c
BLAKE2b-256 checksum
How to use checksums
af78aed3b077ad98998e42637f7d7b26a4fa989c4b9c75a9dbe480f07953a6ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.4 CPython/3.12.3 Linux/6.17.0-1022-azure

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

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