A dict-like SQLite wrapper with APSW for instant persistence and memory caching
Project description
NanaSQLite
A dict-like SQLite wrapper with instant persistence and intelligent caching.
English
🚀 Features
- Dict-like Interface: Use familiar
db["key"] = valuesyntax - Instant Persistence: All writes are immediately saved to SQLite
- Smart Caching: Lazy load (on-access) or bulk load (all at once)
- Nested Structures: Full support for nested dicts and lists (up to 30+ levels)
- High Performance: WAL mode, mmap, and batch operations for maximum speed
- Security & Stability (v1.2.0): SQL validation, ReDoS protection, and strict connection management
- Zero Configuration: Works out of the box with sensible defaults
📦 Installation
pip install nanasqlite
Optional installation extras:
# Performance boosters (orjson + lru-dict)
pip install "nanasqlite[speed]"
# Enable encryption features (AES-GCM/ChaCha20/Fernet)
pip install "nanasqlite[encryption]"
# Install all optional runtime features
pip install "nanasqlite[all]"
# Development tools (pytest, ruff, mypy, tox, etc.)
pip install -e ".[dev]"
⚡ Quick Start
from nanasqlite import NanaSQLite
# Create or open a database
db = NanaSQLite("mydata.db")
# Use it like a dict
db["user"] = {"name": "Nana", "age": 20, "tags": ["admin", "active"]}
print(db["user"]) # {'name': 'Nana', 'age': 20, 'tags': ['admin', 'active']}
# Data persists automatically
db.close()
# Reopen later - data is still there!
db = NanaSQLite("mydata.db")
print(db["user"]["name"]) # 'Nana'
🔧 Advanced Usage
# Bulk load for faster repeated access
db = NanaSQLite("mydata.db", bulk_load=True)
# Batch operations for high-speed reads/writes
db.batch_update({"k1": "v1", "k2": "v2"})
results = db.batch_get(["k1", "k2"])
# Context manager support
with NanaSQLite("mydata.db") as db:
db["temp"] = "value"
📚 Documentation
- Official Documentation Website ↗ (Best Experience)
- English Guide
- API Reference (Sync)
- API Reference (Async)
- Benchmark Trends 📊
- Migration Guide (v1.1.x to v1.2.0)
✨ v1.5.x New Features (Ultimate Hooks)
Ultimate Hooks: Flexible Validation & External Constraints Intercept database operations with custom hooks or built-in constraints. Easily validate data, enforce uniqueness, check foreign keys, or flawlessly integrate with Pydantic.
from nanasqlite import NanaSQLite
from nanasqlite.hooks import UniqueHook, CheckHook, PydanticHook
from pydantic import BaseModel
class UserConfig(BaseModel):
version: int
theme: str
db = NanaSQLite("config.db")
db.add_hook(UniqueHook("email"))
db.add_hook(CheckHook(lambda k, v: v.get("age", 0) >= 18, "Age must be >= 18"))
db.add_hook(PydanticHook(UserConfig))
# Write a dict, reads back as a Pydantic Model automatically!
db["user_conf"] = {"version": 1, "theme": "dark", "email": "test@example.com", "age": 20}
config = db["user_conf"]
print(config.theme) # 'dark'
✨ v1.4.x New Features (v2 Architecture)
Introduced an optional "Write-Back Cache" architecture where all KVS writes are instantly available in memory but saved to SQLite asynchronously in the background. Read latency remains exactly zero.
# Enable v2 mode with automatic background flushing
db = NanaSQLite("high_load.db", v2_mode=True, flush_mode="time", flush_interval=1.0)
# Optional: Use V2Config for cleaner initialization (v1.4.1+)
from nanasqlite import V2Config
cfg = V2Config(flush_mode="time", flush_interval=5.0, enable_metrics=True)
db = NanaSQLite("mydata.db", v2_mode=True, v2_config=cfg)
# The main thread is NEVER blocked by disk I/O!
db["heavy_key"] = validate_and_compute_data()
⚠️ WARNING: v2 mode is built for SINGLE-PROCESS systems. Do not use it with multi-worker setups (e.g., Gunicorn with multiple workers) as parallel background threads will corrupt the SQLite file.
✨ v1.3.x New Features
- Advanced Cache Strategies: LRU and TTL support. Learn more
- Data Encryption: Secure storage with AES-GCM (default), ChaCha20, or Fernet. Learn more
- Persistence TTL: Self-expiring data for sessions and temporary storage.
- Lock Timeout (v1.3.4b1): Raise
NanaSQLiteLockErrorif the lock is held too long, preventing indefinite hangs in multi-threaded apps. - Backup & Restore (v1.3.4b1): Online backup via APSW's SQLite backup API and one-call restore from any backup file.
- Security Audit & Hardening (v1.3.4): Whitelist-based column type validation, AEAD nonce validation, closed-instance safety on all dict methods. See CHANGELOG for full details.
- Security Audit & v2 Bug Fixes (v1.4.0): Fixed SQL injection in
create_table()column types, V2Engine callback ordering, async child attribute inheritance, and v2 mode read-query bypass. See CHANGELOG for full details. - Critical Bug Fix (v1.4.1): Fixed
AttributeErrorinupsert()/aupsert()when using specific call patterns withconflict_columns. Added negative caching for LRU/TTL to improve performance. - Refactoring & Quality (v1.4.1): Introduced
V2Configto group engine parameters and resolve SonarCloud warnings. Improved Docker CI robustness. See CHANGELOG for full details.
# Lock Timeout
db = NanaSQLite("app.db", lock_timeout=2.0)
# Backup
db.backup("snapshot.db")
# Restore
db.restore("snapshot.db")
✨ v1.2.0 New Features
Security Enhancements & Strict Connection Management:
# v1.2.0 Security Features
db = NanaSQLite("mydata.db",
strict_sql_validation=True, # Disallow unauthorized SQL functions
max_clause_length=500 # Limit SQL length to prevent ReDoS
)
# v1.2.0 Read-Only Connection Pool (Async only)
async with AsyncNanaSQLite("mydata.db", read_pool_size=5) as db:
# Heavy read operations (query, fetch_all) use the pool automatically
# allowing parallel execution without blocking writes or other reads
results = await asyncio.gather(
db.query("logs", where="level=?", parameters=("ERROR",)),
db.query("logs", where="level=?", parameters=("INFO",)),
db.query("logs", where="level=?", parameters=("WARN",))
)
# Strict Connection Management
with db.transaction():
sub_db = db.table("sub")
# ... operations ...
db.close()
# Accessing sub_db now raises NanaSQLiteClosedError for safety!
Read Secure Development Guide ↗
✨ v1.1.0 New Features
Safely operate multiple tables in the same database with shared connections:
from nanasqlite import NanaSQLite
# Create main table instance
main_db = NanaSQLite("mydata.db", table="users")
# Get another table instance sharing the same connection
products_db = main_db.table("products")
orders_db = main_db.table("orders")
# Each table has isolated cache and operations
main_db["user1"] = {"name": "Alice", "email": "alice@example.com"}
products_db["prod1"] = {"name": "Laptop", "price": 999}
orders_db["order1"] = {"user": "user1", "product": "prod1"}
Transaction Support & Error Handling (v1.1.0+):
from nanasqlite import NanaSQLite, NanaSQLiteTransactionError
with db.transaction():
db["key1"] = "value1"
db["key2"] = "value2"
Explore Multi-table & Transactions ↗
✨ v1.0.3+ Legacy Features
Pydantic Support & Direct SQL:
# Pydantic support
db.set_model("user", User(name="Nana", age=20))
# Direct SQL execution
db.execute("SELECT * FROM data WHERE key LIKE ?", ("user%",))
# 22 new SQLite wrapper functions (sql_insert, sql_update, count, etc.)
db.sql_insert("users", {"name": "Alice", "age": 25})
日本語
🚀 特徴
- dict風インターフェース: おなじみの
db["key"] = value構文で操作 - 即時永続化: 書き込みは即座にSQLiteに保存
- スマートキャッシュ: 遅延ロード(アクセス時)または一括ロード(起動時)
- ネスト構造対応: 30階層以上のネストしたdict/listをサポート
- 高性能: WALモード、mmap、バッチ操作で最高速度を実現
- セキュリティと安定性 (v1.2.0): SQL検証、ReDoS対策、厳格な接続管理を導入
- 設定不要: 合理的なデフォルト設定でそのまま動作
📦 インストール
pip install nanasqlite
オプション機能付きのインストール:
# 高速化オプション(orjson + lru-dict)
pip install "nanasqlite[speed]"
# 暗号化機能(AES-GCM/ChaCha20/Fernet)
pip install "nanasqlite[encryption]"
# すべてのランタイム用オプションを一括インストール
pip install "nanasqlite[all]"
# 開発用ツール(pytest, ruff, mypy, tox等)
pip install -e ".[dev]"
⚡ クイックスタート
from nanasqlite import NanaSQLite
# データベースを作成または開く
db = NanaSQLite("mydata.db")
# dictのように使う
db["user"] = {"name": "Nana", "age": 20, "tags": ["admin", "active"]}
print(db["user"]) # {'name': 'Nana', 'age': 20, 'tags': ['admin', 'active']}
# データは自動的に永続化
db.close()
# 後で再度開いても、データはそのまま!
db = NanaSQLite("mydata.db")
print(db["user"]["name"]) # 'Nana'
🔧 高度な使い方
# 一括ロードで繰り返しアクセスを高速化
db = NanaSQLite("mydata.db", bulk_load=True)
# バッチ操作で高速な読み書き
db.batch_update({"k1": "v1", "k2": "v2"})
results = db.batch_get(["k1", "k2"])
# コンテキストマネージャ対応
with NanaSQLite("mydata.db") as db:
db["temp"] = "value"
📚 ドキュメント
✨ v1.5.x 新機能 (Ultimate Hooks)
Ultimate Hooks: 柔軟なバリデーションと外部制約アーキテクチャ データベースの読み書き・削除をカスタムフックや組み込み制約でインターセプトできます。データの検証、一意性の保証、外部キー制約のチェック、Pydantic とのシームレスな統合などが容易に行えます。
from nanasqlite import NanaSQLite
from nanasqlite.hooks import UniqueHook, CheckHook, PydanticHook
from pydantic import BaseModel
class UserConfig(BaseModel):
version: int
theme: str
db = NanaSQLite("config.db")
db.add_hook(UniqueHook("email"))
db.add_hook(CheckHook(lambda k, v: v.get("age", 0) >= 18, "Age must be >= 18"))
db.add_hook(PydanticHook(UserConfig))
# dict を書き込むと、自動的に検証され Pydantic モデルとして読み出せます!
db["user_conf"] = {"version": 1, "theme": "dark", "email": "test@example.com", "age": 20}
config = db["user_conf"]
print(config.theme) # 'dark'
✨ v1.4.x 新機能 (v2 アーキテクチャ)
v2 アーキテクチャ: ノンブロッキング・バックグラウンド永続化 KVSの書き込みをすべて「Write-Back Cache(メモリ優先更新)」として処理し、SQLiteへの保存をバックグラウンドスレッドで非同期に行うオプションアーキテクチャを導入しました。読み込みレイテンシも引き続きゼロコストです。
# v2モードを有効化(1秒ごとのバックグラウンドフラッシュ)
db = NanaSQLite("high_load.db", v2_mode=True, flush_mode="time", flush_interval=1.0)
# オプション: V2Configを使用して設定をひとまとめに(v1.4.1+)
from nanasqlite import V2Config
cfg = V2Config(flush_mode="time", flush_interval=5.0, enable_metrics=True)
db = NanaSQLite("mydata.db", v2_mode=True, v2_config=cfg)
# どんなに重いI/Oが発生しても、メインスレッドは一切ブロックされません!
db["heavy_key"] = validate_and_compute_data()
⚠️ 警告: v2モードは「単一プロセス」システム専用に設計されています。Gunicornの複数ワーカー構成などでv2モードを使用すると、複数のバックグラウンドスレッドが同時にSQLiteファイルを上書きし、致命的なデータ破損を引き起こします。
✨ v1.3.x 新機能
- キャッシュ戦略: LRU / TTL サポート (ドキュメント)
- データ暗号化: AES-GCM / ChaCha20 / Fernet (ドキュメント)
- 永続化 TTL: SQLite上のデータの自動消去。
- ロックタイムアウト (v1.3.4b1): ロックが一定時間内に取得できない場合に
NanaSQLiteLockErrorを送出。マルチスレッドでのハング防止に最適。 - バックアップ / リストア (v1.3.4b1): APSW の SQLite バックアップ API によるオンラインバックアップと、一発でのリストアをサポート。
- セキュリティ監査・強化 (v1.3.4): column_type ホワイトリスト検証、AEAD nonce 検証、全 dict メソッドのクローズ済みインスタンス安全性。詳細は CHANGELOG を参照。
- セキュリティ監査・v2 バグ修正 (v1.4.0):
create_table()カラム型SQLインジェクション修正、V2Engineコールバック順序修正、非同期子インスタンス属性継承修正、v2モード読み取りクエリバイパス修正。詳細は CHANGELOG を参照。 - 致命的バグ修正・性能向上 (v1.4.1):
upsert()/aupsert()におけるAttributeErrorを修正。LRU/TTL キャッシュへのネガティブキャッシュ導入による性能向上。詳細は CHANGELOG を参照。 - リファクタリング・品質向上 (v1.4.1):
V2Configの導入による引数管理の整理と、Docker CI環境の安定化を実施。
# ロックタイムアウト
db = NanaSQLite("app.db", lock_timeout=2.0)
# バックアップ
db.backup("snapshot.db")
# リストア
db.restore("snapshot.db")
✨ v1.2.0 新機能
セキュリティ強化と厳格な接続管理:
# v1.2.0 セキュリティ機能
db = NanaSQLite("mydata.db",
strict_sql_validation=True, # 未許可のSQL関数を禁止
max_clause_length=500 # SQLの長さを制限してReDoSを防止
)
# v1.2.0 読み取り専用接続プール(非同期のみ)
async with AsyncNanaSQLite("mydata.db", read_pool_size=5) as db:
# 重い読み取り操作(query, fetch_all)は自動的にプールを使用
results = await asyncio.gather(
db.query("logs", where="level=?", parameters=("ERROR",)),
db.query("logs", where="level=?", parameters=("INFO",))
)
# 厳格な接続管理
db.close()
# 無効化されたインスタンスへのアクセスは NanaSQLiteClosedError を送出します。
✨ v1.1.0 新機能
同一データベース内の複数テーブルを接続共有で安全に操作:
from nanasqlite import NanaSQLite
# メインテーブルインスタンスを作成
main_db = NanaSQLite("mydata.db", table="users")
# 同じ接続を共有する別のテーブルインスタンスを取得
products_db = main_db.table("products")
orders_db = main_db.table("orders")
# 各テーブルは独立したキャッシュと操作を持つ
main_db["user1"] = {"name": "Alice"}
products_db["prod1"] = {"name": "Laptop"}
オプションのデータ暗号化 (v1.3.1a1+):
from nanasqlite import NanaSQLite
# 事前にインストール: pip install nanasqlite[encryption]
db = NanaSQLite("secure.db", encryption_key=b"your-32-byte-key") # デフォルトで AES-GCM
# モードを明示的に指定する場合
db_chacha = NanaSQLite("secure_cc.db",
encryption_key=b"your-32-byte-key",
encryption_mode="chacha20"
)
# SQLite内では暗号化されますが、メモリ上(キャッシュ)では平文で高速に扱えます
db["secret"] = {"password": "123"}
トランザクションサポートとエラーハンドリング (v1.1.0+):
from nanasqlite import NanaSQLite, NanaSQLiteTransactionError
with db.transaction():
db["key1"] = "value1"
db["key2"] = "value2"
✨ v1.0.3+ レガシー機能
Pydantic互換性と直接SQL実行:
# Pydantic互換性
db.set_model("user", User(name="Nana", age=20))
# 直接SQL実行
db.execute("SELECT * FROM data WHERE key LIKE ?", ("user%",))
# 22種類のSQLiteラッパー関数 (sql_insert, sql_update, count等)
db.sql_insert("users", {"name": "Alice", "age": 25})
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 nanasqlite-1.5.0.tar.gz.
File metadata
- Download URL: nanasqlite-1.5.0.tar.gz
- Upload date:
- Size: 181.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6bfbca4321695a91f82385ce7761dbcaed305b18fa5d4406ab22f1ab4989e7d8
|
|
| MD5 |
2dfb98dfa4f48d8c726e8305754db1b0
|
|
| BLAKE2b-256 |
00a6df0029b4d21d7db77ac1ca1d1fda756fb81f37bd0c15cee1c985a017a6b3
|
Provenance
The following attestation bundles were made for nanasqlite-1.5.0.tar.gz:
Publisher:
ci.yml on disnana/NanaSQLite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanasqlite-1.5.0.tar.gz -
Subject digest:
6bfbca4321695a91f82385ce7761dbcaed305b18fa5d4406ab22f1ab4989e7d8 - Sigstore transparency entry: 1236722600
- Sigstore integration time:
-
Permalink:
disnana/NanaSQLite@cd56dbd2ce862abb3809c04cc7f97a193527556f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/disnana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@cd56dbd2ce862abb3809c04cc7f97a193527556f -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanasqlite-1.5.0-py3-none-any.whl.
File metadata
- Download URL: nanasqlite-1.5.0-py3-none-any.whl
- Upload date:
- Size: 76.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e67ea4222fc6b1c8ad273db293e46b09375f6da3af177ead44d948b872737c1
|
|
| MD5 |
787a9ab977db6c1229ab9c6ae8e8bdb4
|
|
| BLAKE2b-256 |
a55928e862b90a41ea3fe6a5f3270f6a3064b5d7bbc001531ef3a12bbafc0137
|
Provenance
The following attestation bundles were made for nanasqlite-1.5.0-py3-none-any.whl:
Publisher:
ci.yml on disnana/NanaSQLite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanasqlite-1.5.0-py3-none-any.whl -
Subject digest:
7e67ea4222fc6b1c8ad273db293e46b09375f6da3af177ead44d948b872737c1 - Sigstore transparency entry: 1236722626
- Sigstore integration time:
-
Permalink:
disnana/NanaSQLite@cd56dbd2ce862abb3809c04cc7f97a193527556f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/disnana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@cd56dbd2ce862abb3809c04cc7f97a193527556f -
Trigger Event:
push
-
Statement type: