# SQLite-based key-value storage
--------------------------------
## TOC
1. [Abstract](#1-abstract)
2. [Get Started](#2-get-started)
2.1 [Install the Package](#21-install-the-package)
2.2 [SQLiteKVDB Implementation Details](#22-sqlitekvdb-implementation-details)
2.3 [SQLiteKVDB Use Case Example](#23-sqlitekvdb-use-case-example)
## 1. Abstract
--------------
The package provides an implementation of SQLite-based key-value storage with dict-like interface.
Storage can save values of any type supported by Python. Yet you must choose proper serialization method, corresponding
planned use case before creating storage. Keys are to be strings.
Storage instances can hold identity (name and version) of an application (DB controller) which created it. It might be
useful to have a possibility to verify these data when loading saved DB instances to avoid data misinterpretation or
corruption.
[[TOC]](#toc "Back to Table Of Content")
## 2. Get Started
-----------------
### 2.1 Install the Package
-------------------------------------
You install the `sqlite-kvdb` package like any other regular Python package:
```terminal
pip install sqlite-kvdb
```
[[TOC]](#toc "Table Of Content")
### 2.2 SQLiteKVDB Implementation details
-----------------------------------------
Please keep in mind a few points about SQLiteKVDB implementation:
* SQLiteKVDB objects do not do any internal data caching.
Data is directly fetched from the underlying SQLite database at the access time.
* SQLiteKVDB objects use the `auto_commit` parameter to control when data modifications are actually stored to
underlying SQLite database. It's set at SQLiteKVDB object instantiation time and defaults to `True`.
If the `auto_commit` is `True` changes immediately saved to the underlying database at the moment of assigning
a `value` to a `key`.
If the `auto_commit` is `False` changes are internally cached by the SQLite engine (within a WRITE TRANSACTION
scope) until the `SQLiteKVDB.commit()` method is called.
This mode is useful when multiple values to be assigned at once.
**NOTE.** The SQLiteKVDB does not explicitly control transaction behaviour of the SQLite engine. That means it
remains in the default implicit transaction management DEFFERED mode [1][2]. I.e. SQLiteKVDB.auto_commit=True
basically means that SQLiteKVDB implicitly calls SQLiteKVDB.commit() under the hood for each value assignment
operation.
* in case when a `value` is a complex object direct assignment to its attributes won't be auto-propagated to
underlying SQLite database. You have to instantiate a copy of such a `value`, modify attributes as appropriate, and
then assign it back to the same `key` it was initially assigned to.
Please check the example below:
```python
from pydantic import BaseModel
from sqlite_construct import DBReference, DB_SCHEME
from sqlite_kvdb import SQLiteKVDB
class ComplexObject(BaseModel):
attr1: str
kvdb = SQLiteKVDB(db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path=":memory:"), auto_commit=True)
object1 = ComplexObject(attr1="1")
kvdb["key1"] = object1
print(list(kvdb.items())) # Would print "[('key1', ComplexObject(attr1='1'))]"
object1.attr1 = "2" # This won't work
kvdb["key1"].attr1 = "3" # This won't work either
print(list(kvdb.items())) # Sill would print "[('key1', ComplexObject(attr1='1'))]"
db_object1 = kvdb["key1"]
db_object1.attr1 = "4"
kvdb["key1"] = db_object1
print(list(kvdb.items())) # Would print "[('key1', ComplexObject(attr1='4'))]"
```
>**_Reference:_**
[1] [(sqlite3) Transaction control](https://docs.python.org/3.11/library/sqlite3.html#transaction-control)
[2] [(SQLite) Transactions](https://www.sqlite.org/lang_transaction.html#transactions)
[[TOC]](#toc "Table Of Content")
### 2.3 SQLiteKVDB Use Case Example
-----------------------------------
```python
from datetime import datetime, timedelta, timezone
from enum import Enum
from time import sleep
from pydantic import BaseModel
from sqlite_construct import DBReference, DB_SCHEME
from sqlite_kvdb import SQLiteKVDB, SQLiteKVDBError
class Sex(Enum):
MALE = "male"
FEMALE = "female"
class AbilityType(Enum):
BASIC = "basic"
EXTRA = "extra"
class Ability(BaseModel):
type: AbilityType
active: bool = False
grade: int = 0
class CharacterState(BaseModel):
abilities: dict[str, Ability]
level: int
lives: int
health: int
class Character(BaseModel):
name: str
sex: Sex
state: CharacterState
class PlayerState(BaseModel):
last_login: datetime
last_ingame_period: timedelta
character: Character
class Mission(BaseModel):
name: str
progress: int
state_player_init = PlayerState(
last_login=datetime.now(timezone.utc),
last_ingame_period=timedelta(),
character=Character(
name="wizard",
sex=Sex.MALE,
state=CharacterState(
abilities=dict(
strength=Ability(type=AbilityType.BASIC, active=True, grade=2),
speed=Ability(type=AbilityType.BASIC, active=True, grade=2),
witchcraft=Ability(type=AbilityType.BASIC, active=True, grade=10),
range=Ability(type=AbilityType.BASIC, active=True, grade=2),
),
level=1,
lives=5,
health=100,
)
)
)
# Initialize state object
try:
state = SQLiteKVDB(
db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path="adventure-state.sqlite3"),
auto_commit=False,
app_codename="adventure",
app_version="1.2.3"
)
state["player"] = state_player_init
state["mission"] = Mission(name="TakeoverTheWorld", progress=0)
state["location"] = "Midland"
state.commit()
except SQLiteKVDBError as e:
raise RuntimeError(f"Save state: {e.__class__.__name__}: {e}") from e
# Few hours later ...
# Gain new abilities
state_player = state["player"]
state_player.character.state.abilities["prediction"] = Ability(
type=AbilityType.EXTRA, active=False, grade=1
)
state_player.character.state.abilities["flight"] = Ability(
type=AbilityType.EXTRA, active=False, grade=1
)
state["player"] = state_player
state.commit()
sleep(5)
# Few hours later ...
# Exit game
try:
state_player = state["player"]
state_player.last_ingame_period = datetime.now(timezone.utc) - state["player"].last_login
state_player.character.state.level = 2
state_player.character.state.lives = 4
state_player.character.state.health = 80
state_player.character.state.abilities["range"] = 5
state_player.character.state.abilities["prediction"].active = True
state["player"] = state_player
state_mission = state["mission"]
state_mission.progress = 14
state["mission"] = state_mission
state["location"] = "Highland"
state.close() # Commits all pending transactions
except SQLiteKVDBError as e:
raise RuntimeError(f"Save state: {e.__class__.__name__}: {e}") from e
sleep(5)
# Few hours later ...
# Back to the game
try:
state = SQLiteKVDB(
db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path="adventure-state.sqlite3"),
auto_commit=False,
app_codename="adventure",
app_version="1.2.3"
)
state["player"].last_login = datetime.now(timezone.utc)
state.commit()
except SQLiteKVDBError as e:
raise RuntimeError(f"Load state: {e.__class__.__name__}: {e}") from e
# Exit game ...
# Assign actual state values here
state.close()
```
[[TOC]](#toc "Table Of Content")
Raw data
{
"_id": null,
"home_page": null,
"name": "sqlite-kvdb",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "sqlite, database",
"author": "ambient@mailbox.org",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/49/03/f3aca293bb0185645764ee585dbfc3158619db4d1ef2ad7ef0a567ad6da7/sqlite_kvdb-0.1.0.tar.gz",
"platform": null,
"description": "# SQLite-based key-value storage\n\n--------------------------------\n\n## TOC\n\n1. [Abstract](#1-abstract) \n2. [Get Started](#2-get-started) \n 2.1 [Install the Package](#21-install-the-package) \n 2.2 [SQLiteKVDB Implementation Details](#22-sqlitekvdb-implementation-details) \n 2.3 [SQLiteKVDB Use Case Example](#23-sqlitekvdb-use-case-example)\n \n\n## 1. Abstract\n\n--------------\n The package provides an implementation of SQLite-based key-value storage with dict-like interface.\nStorage can save values of any type supported by Python. Yet you must choose proper serialization method, corresponding\nplanned use case before creating storage. Keys are to be strings.\n\n Storage instances can hold identity (name and version) of an application (DB controller) which created it. It might be\nuseful to have a possibility to verify these data when loading saved DB instances to avoid data misinterpretation or \ncorruption.\n\n[[TOC]](#toc \"Back to Table Of Content\")\n\n\n## 2. Get Started\n\n-----------------\n\n### 2.1 Install the Package\n\n-------------------------------------\n You install the `sqlite-kvdb` package like any other regular Python package:\n\n```terminal\npip install sqlite-kvdb\n```\n\n[[TOC]](#toc \"Table Of Content\")\n\n\n### 2.2 SQLiteKVDB Implementation details\n\n-----------------------------------------\n Please keep in mind a few points about SQLiteKVDB implementation:\n\n * SQLiteKVDB objects do not do any internal data caching. \n Data is directly fetched from the underlying SQLite database at the access time.\n \n \n * SQLiteKVDB objects use the `auto_commit` parameter to control when data modifications are actually stored to \n underlying SQLite database. It's set at SQLiteKVDB object instantiation time and defaults to `True`.\n \n If the `auto_commit` is `True` changes immediately saved to the underlying database at the moment of assigning \n a `value` to a `key`. \n \n If the `auto_commit` is `False` changes are internally cached by the SQLite engine (within a WRITE TRANSACTION \n scope) until the `SQLiteKVDB.commit()` method is called. \n This mode is useful when multiple values to be assigned at once.\n\n **NOTE.** The SQLiteKVDB does not explicitly control transaction behaviour of the SQLite engine. That means it\n remains in the default implicit transaction management DEFFERED mode [1][2]. I.e. SQLiteKVDB.auto_commit=True \n basically means that SQLiteKVDB implicitly calls SQLiteKVDB.commit() under the hood for each value assignment\n operation.\n \n \n * in case when a `value` is a complex object direct assignment to its attributes won't be auto-propagated to \n underlying SQLite database. You have to instantiate a copy of such a `value`, modify attributes as appropriate, and \n then assign it back to the same `key` it was initially assigned to.\n \n Please check the example below:\n\n ```python\n from pydantic import BaseModel\n \n from sqlite_construct import DBReference, DB_SCHEME\n from sqlite_kvdb import SQLiteKVDB\n \n class ComplexObject(BaseModel):\n attr1: str\n \n kvdb = SQLiteKVDB(db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path=\":memory:\"), auto_commit=True)\n \n object1 = ComplexObject(attr1=\"1\")\n kvdb[\"key1\"] = object1 \n print(list(kvdb.items())) # Would print \"[('key1', ComplexObject(attr1='1'))]\"\n \n object1.attr1 = \"2\" # This won't work\n kvdb[\"key1\"].attr1 = \"3\" # This won't work either\n print(list(kvdb.items())) # Sill would print \"[('key1', ComplexObject(attr1='1'))]\"\n \n db_object1 = kvdb[\"key1\"]\n db_object1.attr1 = \"4\"\n kvdb[\"key1\"] = db_object1\n print(list(kvdb.items())) # Would print \"[('key1', ComplexObject(attr1='4'))]\" \n ```\n\n>**_Reference:_** \n[1] [(sqlite3) Transaction control](https://docs.python.org/3.11/library/sqlite3.html#transaction-control) \n[2] [(SQLite) Transactions](https://www.sqlite.org/lang_transaction.html#transactions) \n\n[[TOC]](#toc \"Table Of Content\")\n\n\n### 2.3 SQLiteKVDB Use Case Example\n\n-----------------------------------\n\n```python\nfrom datetime import datetime, timedelta, timezone\nfrom enum import Enum\nfrom time import sleep\n\nfrom pydantic import BaseModel\n\nfrom sqlite_construct import DBReference, DB_SCHEME\nfrom sqlite_kvdb import SQLiteKVDB, SQLiteKVDBError\n\n\nclass Sex(Enum):\n MALE = \"male\"\n FEMALE = \"female\"\n\n\nclass AbilityType(Enum):\n BASIC = \"basic\"\n EXTRA = \"extra\"\n\n\nclass Ability(BaseModel):\n type: AbilityType\n active: bool = False\n grade: int = 0\n\n\nclass CharacterState(BaseModel):\n abilities: dict[str, Ability]\n level: int\n lives: int\n health: int\n\n\nclass Character(BaseModel):\n name: str\n sex: Sex\n state: CharacterState\n\n\nclass PlayerState(BaseModel):\n last_login: datetime\n last_ingame_period: timedelta\n character: Character\n\n\nclass Mission(BaseModel):\n name: str\n progress: int\n\n\nstate_player_init = PlayerState(\n last_login=datetime.now(timezone.utc),\n last_ingame_period=timedelta(),\n character=Character(\n name=\"wizard\",\n sex=Sex.MALE,\n state=CharacterState(\n abilities=dict(\n strength=Ability(type=AbilityType.BASIC, active=True, grade=2),\n speed=Ability(type=AbilityType.BASIC, active=True, grade=2),\n witchcraft=Ability(type=AbilityType.BASIC, active=True, grade=10),\n range=Ability(type=AbilityType.BASIC, active=True, grade=2),\n ),\n level=1,\n lives=5,\n health=100,\n )\n )\n)\n\n# Initialize state object\ntry:\n state = SQLiteKVDB(\n db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path=\"adventure-state.sqlite3\"),\n auto_commit=False,\n app_codename=\"adventure\",\n app_version=\"1.2.3\"\n )\n\n state[\"player\"] = state_player_init\n state[\"mission\"] = Mission(name=\"TakeoverTheWorld\", progress=0)\n state[\"location\"] = \"Midland\"\n\n state.commit()\nexcept SQLiteKVDBError as e:\n raise RuntimeError(f\"Save state: {e.__class__.__name__}: {e}\") from e\n\n# Few hours later ...\n# Gain new abilities\nstate_player = state[\"player\"]\nstate_player.character.state.abilities[\"prediction\"] = Ability(\n type=AbilityType.EXTRA, active=False, grade=1\n)\nstate_player.character.state.abilities[\"flight\"] = Ability(\n type=AbilityType.EXTRA, active=False, grade=1\n)\nstate[\"player\"] = state_player\nstate.commit()\n\nsleep(5)\n# Few hours later ...\n# Exit game\ntry:\n state_player = state[\"player\"]\n state_player.last_ingame_period = datetime.now(timezone.utc) - state[\"player\"].last_login\n state_player.character.state.level = 2\n state_player.character.state.lives = 4\n state_player.character.state.health = 80\n state_player.character.state.abilities[\"range\"] = 5\n state_player.character.state.abilities[\"prediction\"].active = True\n state[\"player\"] = state_player\n\n state_mission = state[\"mission\"]\n state_mission.progress = 14\n state[\"mission\"] = state_mission\n\n state[\"location\"] = \"Highland\"\n\n state.close() # Commits all pending transactions\nexcept SQLiteKVDBError as e:\n raise RuntimeError(f\"Save state: {e.__class__.__name__}: {e}\") from e\n\nsleep(5)\n# Few hours later ...\n# Back to the game\ntry:\n state = SQLiteKVDB(\n db_ref=DBReference(scheme=DB_SCHEME.SQLITE3, path=\"adventure-state.sqlite3\"),\n auto_commit=False,\n app_codename=\"adventure\",\n app_version=\"1.2.3\"\n )\n\n state[\"player\"].last_login = datetime.now(timezone.utc)\n state.commit()\nexcept SQLiteKVDBError as e:\n raise RuntimeError(f\"Load state: {e.__class__.__name__}: {e}\") from e\n\n# Exit game ...\n# Assign actual state values here\nstate.close()\n```\n\n[[TOC]](#toc \"Table Of Content\")\n\n",
"bugtrack_url": null,
"license": "0BSD",
"summary": "SQLite-based key-value storage",
"version": "0.1.0",
"project_urls": {
"Repository": "https://github.com/ambient5/sqlite-kvdb"
},
"split_keywords": [
"sqlite",
" database"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "720cfc7b4581cd39b89b49e8dc9306353739b3b2a234e9eb2633613458817717",
"md5": "fd389d382e534cae57a3a750d38b9bda",
"sha256": "65fc8c16fcf9fb0365b8290e037d7c92471050a98e0dc8cc803e6d33c2367ed1"
},
"downloads": -1,
"filename": "sqlite_kvdb-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fd389d382e534cae57a3a750d38b9bda",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 8094,
"upload_time": "2025-08-03T15:08:10",
"upload_time_iso_8601": "2025-08-03T15:08:10.626135Z",
"url": "https://files.pythonhosted.org/packages/72/0c/fc7b4581cd39b89b49e8dc9306353739b3b2a234e9eb2633613458817717/sqlite_kvdb-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4903f3aca293bb0185645764ee585dbfc3158619db4d1ef2ad7ef0a567ad6da7",
"md5": "343154d290a20f4c15c2e7cc9721ce2b",
"sha256": "b76847bde71515f7c9b199733dbf7bf4d2956445be19c8c354b88eba3401148a"
},
"downloads": -1,
"filename": "sqlite_kvdb-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "343154d290a20f4c15c2e7cc9721ce2b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 7527,
"upload_time": "2025-08-03T15:08:12",
"upload_time_iso_8601": "2025-08-03T15:08:12.202495Z",
"url": "https://files.pythonhosted.org/packages/49/03/f3aca293bb0185645764ee585dbfc3158619db4d1ef2ad7ef0a567ad6da7/sqlite_kvdb-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-03 15:08:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ambient5",
"github_project": "sqlite-kvdb",
"github_not_found": true,
"lcname": "sqlite-kvdb"
}