What's This?
An asynchronous version of TinyDB with extended capabilities.
Almost every method is asynchronous. And it's based on TinyDB 4.7.0+.
Unlike TinyDB which has a minimal core, Async-TinyDB is designed to have max flexibility and performance.
Incompatible Changes
-
Asynchronous: Say goodbye to blocking IO. Don't forget to
awaitasync methods! -
Drop support: Only supports Python 3.10+.
-
ujson: Usingujsoninstead ofjson. Some arguments aren't compatible withjson1 -
Dev-Changes: Changes that only matter to developers (Who customise
Storage,Query, etc). -
Miscellaneous: Differences that only matter in edge cases.
New Features
-
Event Hooks: You can now use event hooks to hook into an operation. See Event Hooks for more details.
-
Redesigned ID & Doc Class: You can replace and customise them easily.
-
DB-level Caching: This significantly improves the performance of all operations. However, it may cause dirty reads with some types of storage 2.
-
Built-in
Modifier: UseModifierto easily compress, encrypt and extend types of your database. Sure you can do much more than these. (See Modifier) -
Isolation Level: Performance or ACID? It's up to you3.
-
Atomic Write: Shipped with
JSONStorage -
Batch Search By IDs:
searchmethod now takes an extradoc_idsargument (works like an additional condition)
How to use it?
Installation
- Minimum:
pip install async-tinydb - Encryption:
pip install async-tinydb[encryption] - Compression:
pip install async-tinydb[compression] - Full:
pip install async-tinydb[all]
Importing
import asynctinydb
Usage
Read the original TinyDB documents. Insert an await in front of async methods.
Notice that some codes are still blocking, for example, when calling len() on TinyDB or Table Objects.
That's it.
Documents For Advanced Usage
Replacing ID & Document Class
NOTICE: Mixing classes in one table may cause errors!
When a table exists in a file, Async-TinyDB won't determine its classes by itself, it is your duty to make sure classes are matching.
ID Classes
IncreID: Default ID class, mimics the behaviours of the originalintID but requires much fewer IO operations.UUID: Usesuuid.UUID4.
Document Class
Document: Default document class, usesdictunder the bonet.
from asynctinydb import TinyDB, UUID, IncreID, Document
db = TinyDB("database.db")
# Setting ID class to `UUID`, document class to `Document`
tab = db.table("table1", document_id_class=UUID, document_class=Document)
See Customisation for more details
Encryption
Currently only supports AES-GCM encryption.
There are two ways to use encryption:
1. Use EncryptedJSONStorage directly
from asynctinydb import EncryptedJSONStorage, TinyDB
async def main():
db = TinyDB("db.json", key="your key goes here", storage=EncryptedJSONStorage)
2. Use Modifier class
See Encryption
Isolation Level
When operating the TinyDB concurrently, there might be racing conditions.
Set a higher isolation level to mitigate this problem.
db.isolevel = 1
isolevel:
- No isolation, best performance.
- Serialised(Atomic) CRUD operations. (Also ensures thread safety) (default)
- Deepcopy documents on insertion and retrieving. (CRUD) (Ensures
Index&Query Cacheconsistency)
DB-level caching
DB-level caching improves performance dramatically.
However, this may cause data inconsistency between Storage and TinyDB if the file that Storage referred to is been shared.
To disable it:
db = TinyDB("./path", no_dbcache=True)
Example Codes:
Simple One
import asyncio
from asynctinydb import TinyDB, Query
async def main():
db = TinyDB('test.json')
await db.insert({"answer": 42})
print(await db.search(Query().answer == 42)) # >>> [{'answer': 42}]
asyncio.run(main())
Event Hooks Example
async def main():
db = TinyDB('test.json')
@db.storage.on.write.pre
async def mul(ev: str, s: Storage, data: dict):
data["_default"]["1"]['answer'] *= 2 # directly manipulate on data
@db.storage.on.write.post
async def _print(ev, s, anystr):
print(anystr) # print json dumped string
await db.insert({"answer": 21}) # insert() will trigger both write events
await db.close()
# Reload
db = TinyDB('test.json')
print(await db.search(Query().answer == 42)) # >>> [{'answer': 42}]
Customise ID Class
Inherit from BaseID and implement the following methods, and then you are good to go.
from asynctinydb import BaseID
class MyID(BaseID):
def __init__(self, value: Any):
"""
You should be able to convert str into MyID instance if you want to use JSONStorage.
"""
def __str__(self) -> str:
"""
Optional.
It should be implemented if you want to use JSONStorage.
"""
def __hash__(self) -> int:
...
def __eq__(self, other: object) -> bool:
...
@classmethod
def next_id(cls, table: Table, keys) -> MyID:
"""
It should return a unique ID.
"""
@classmethod
def mark_existed(cls, table: Table, new_id):
"""
Marks an ID as existing; the same ID shouldn't be generated by next_id.
"""
@classmethod
def clear_cache(cls, table: Table):
"""
Clear cache of existing IDs, if such cache exists.
"""
Customise Document Class
from asynctinydb import BaseDocument
class MyDoc(BaseDocument):
"""
I am too lazy to write those necessary methods.
"""
Anyways, a BaseDocument class looks like this:
class BaseDocument(Mapping[IDVar, Any]):
@property
@abstractmethod
def doc_id(self) -> IDVar:
raise NotImplementedError()
@doc_id.setter
def doc_id(self, value: IDVar):
raise NotImplementedError()
Make sure you have implemented all the methods required by BaseDocument class.
Dev-Changes
- Storage
closedproperty: OriginalTinyDBwon't raise exceptions when operating on a closed file. Now the propertyclosedofStorageclasses is required to be implemented56. - Storage data converting: The responsibility of converting the data to the correct type is transferred to the Storage7
is_cacheablemethod inQueryInstanceis changed tocacheableproperty and will be deprecated.
Misc
- Lazy-load: File loading & dirs creating are delayed to the first IO operation.
CachingMiddleWare:WRITE_CACHE_SIZEis now instance-specific.
Example:TinyDB("test.db", storage=CachingMiddleWare(JSONStorage, 1024))searchaccepts optionalcond, returns all docs if no arguments are providedgetandcontainsraisesValueErrorinstead ofRuntimeErrorwhencondanddoc_idare bothNoneLRUCachestorestuples of ids instead oflists of docssearchandgettreatdoc_idanddoc_idsas extra conditions instead of ignoring conditions when IDs are provided. That is to say, whencondanddoc_id(s)are passed, they return docs satisfiescondand is indoc_id(s).
-
Why not
orjson? Becauseujsonis fast enough and has more features. ↩ -
See DB-level caching to learn how to disable this feature if it causes dirty reads. ↩
-
Currently using UUID4 ↩
-
This is for
Middlewareclasses to reliably determine whether theStorageis closed, so they can raiseIOError↩ -
An
IOErrorshould be raised when operating on closed storage. ↩ -
e.g.
JSONStorageneeds to convert the keys tostrby itself. ↩
Metadata
Release files for async-tinydb 1.7.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| async_tinydb-1.7.3.tar.gz | 36.8 kB | Without provenance | Details for async_tinydb-1.7.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| async_tinydb-1.7.3-py3-none-any.whl | Python 3 | none | any | Details for async_tinydb-1.7.3-py3-none-any.whl |
Total release size: 74.6 kB
Release files / async_tinydb-1.7.3.tar.gz
| Download URL | async_tinydb-1.7.3.tar.gz |
|---|---|
| Size | 36.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e20d8d4aafe3321b38365026226eca0f89170828691ebccfe4ee00f1dd2d02ad
|
|
BLAKE2b-256 checksum How to use checksums |
1075f988e79d33102a6321d660fa0ee91f1a9d3526b53112b2c37b5252919cae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.12.2 Linux/6.5.0-1016-azure
|
Release files / async_tinydb-1.7.3-py3-none-any.whl
| Download URL | async_tinydb-1.7.3-py3-none-any.whl |
|---|---|
| Size | 37.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0a55c59cce44487849c787a2830f5a84263cbc306c6cdd58810258493d6b8ef2
|
|
BLAKE2b-256 checksum How to use checksums |
402f1446ce9245d3d924f64601dbd8cfbf440939a516065a30948773d297700c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.12.2 Linux/6.5.0-1016-azure
|
Security for async-tinydb 1.7.3
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.