Skip to main content

kv-cache

A fast, persistent key-value store using SQLite as a backend. Zero dependencies beyond the Python standard library. Designed for CLI tools needing persistent cache storage.

Features

  • SQLite-based persistent storage with WAL mode for performance
  • Built-in TTL (Time-to-Live) support with automatic cleanup
  • Thread-safe operations via thread-local connections
  • Function caching decorator (scache) supporting both sync and async functions
  • Deterministic cache key generation using SHA-256
  • Context manager support

Installation

pip install kv-cache

Quick Start

Basic Key-Value Operations

from kv_cache import KVStore

# Initialize the store
store = KVStore("cache.db")

# Store a value
store.set("user:1", {"name": "Alice", "age": 30})

# Store a value with a 1-hour TTL
store.set("session:abc", {"token": "xyz"}, ttl=3600)

# Retrieve values
user = store.get("user:1")               # {'name': 'Alice', 'age': 30}
missing = store.get("no_key", default=0)  # 0

# Delete a key
store.delete("user:1")

# List all keys, values, or items
store.keys()    # ['session:abc']
store.values()  # [{'token': 'xyz'}]
store.items()   # [('session:abc', {'token': 'xyz'})]

# Clear all entries
store.clear()

# Close the connection
store.close()

Context Manager

with KVStore("cache.db") as store:
    store.set("key", "value", ttl=60)
    print(store.get("key"))  # "value"
# Connection is automatically closed

Function Caching with scache

The scache decorator caches function return values. Cache keys are automatically generated from the function name and arguments.

import time
from kv_cache import KVStore, scache

store = KVStore("~/.myapp/cache.db")

@scache(ttl=3600, store=store)
def fetch_data(user_id, include_details=False):
    time.sleep(2)  # Simulate slow API call
    return {"user_id": user_id, "details": include_details}

fetch_data(42, include_details=True)   # Takes 2 seconds
fetch_data(42, include_details=True)   # Instant (cached)
fetch_data(42, include_details=False)  # Takes 2 seconds (different args = different key)

Async Function Caching

scache automatically detects async functions and wraps them accordingly.

@scache(ttl=300, store=store)
async def fetch_remote(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.json()

Custom Cache Key Function

Override the default key generation with a custom function:

def my_key_func(func, args, kwargs):
    # Only cache based on the first argument
    return f"{func.__name__}:{args[0]}"

@scache(ttl=600, store=store, key_func=my_key_func)
def search(query, page=1):
    return api.search(query, page)

Conditional Caching

Disable caching dynamically by setting a flag in the store:

@scache(ttl=3600, store=store, conditional_key="enable_cache")
def get_config():
    return load_config_from_disk()

# Caching is active by default
get_config()  # cached

# Disable caching by setting the conditional key to False
store.set("enable_cache", False)
get_config()  # always calls load_config_from_disk()

CLI Autocomplete Example

from kv_cache import KVStore

def get_completions(prefix: str) -> list:
    store = KVStore("~/.mycli/cache.db")

    cache_key = f"auto:{prefix}"
    results = store.get(cache_key)

    if results is None:
        results = fetch_from_remote_server(prefix)
        store.set(cache_key, results, ttl=3600)

    return results

API Reference

KVStore

KVStore(db_path: str, table_name: str = "key_value_store")

A persistent key-value store backed by SQLite.

Parameter Type Default Description
db_path str (required) Path to the SQLite database file. Parent directories are created automatically.
table_name str "key_value_store" Name of the SQLite table. Allows multiple logical stores in one database.

Methods

Method Signature Description
set set(key: str, value: Any, ttl: Optional[int] = None) Store a JSON-serializable value. Optional ttl in seconds.
get get(key: str, default: Any = None) -> Any Retrieve a value. Returns default if the key is missing or expired.
delete delete(key: str) Remove a key from the store.
keys keys() -> list Return all keys (including expired ones pending cleanup).
values values() -> list Return all deserialized values.
items items() -> list Return all (key, value) tuples.
clear clear() Delete all entries from the store.
close close() Close the database connection.

Context manager: KVStore supports with statements. The connection is closed on exit.

Thread safety: Each thread gets its own SQLite connection via threading.local().

Values: Any JSON-serializable Python object (dicts, lists, strings, numbers, booleans, None).


scache

scache(
    ttl: Optional[int] = None,
    store: Optional[KVStore] = None,
    conditional_key: str = '',
    key_func: Optional[Callable] = None
) -> Callable

Decorator that caches function return values in a KVStore.

Parameter Type Default Description
ttl Optional[int] None Cache lifetime in seconds. None means no expiration.
store Optional[KVStore] None KVStore instance to use. If None, creates a default store at cache.db.
conditional_key str '' A key in the store that controls whether caching is active. If the key's value is False, caching is bypassed.
key_func Optional[Callable] None Custom key generation function with signature (func, args, kwargs) -> str.

Key generation: By default, the cache key is a SHA-256 hash of the function name, serialized positional arguments, and sorted keyword arguments. This means:

  • Keyword argument order doesn't matter: f(a=1, b=2) and f(b=2, a=1) hit the same cache entry.
  • Different argument values always produce different keys.
  • Non-JSON-serializable objects fall back to their str() representation.

Return value caveat: Since None is used as the cache-miss sentinel, functions that return None will not be cached (the decorator will always re-execute them).

SQLite Configuration

The store uses the following SQLite pragmas for performance:

Pragma Value Purpose
journal_mode WAL Write-Ahead Logging for concurrent reads
synchronous NORMAL Balance between safety and speed
mmap_size 512 MB Memory-mapped I/O
cache_size 128 MB In-memory page cache
page_size 4 KB Database page size

Development

# Clone and install
git clone https://github.com/lcances/kv_cache.git
cd kv_cache
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest tests/

# Format code
black src/ tests/
isort src/ tests/

Requirements

  • Python >= 3.7
  • No external dependencies (stdlib only)

License

MIT License - see LICENSE for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kv_cache-0.3.4.tar.gz (25.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kv_cache-0.3.4-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file kv_cache-0.3.4.tar.gz.

File metadata

  • Download URL: kv_cache-0.3.4.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kv_cache-0.3.4.tar.gz
Algorithm Hash digest
SHA256 d652a5d7ae451bdc1fca415fe348a645bf595ed6293fe995f084a3c27b51187f
MD5 9915c8b7c77613e7019c8af6ca438b85
BLAKE2b-256 c0b2a7cc1fd031d42d3c88036a7554f84d76603559724df54b9f9fde87df161f

See more details on using hashes here.

Provenance

The following attestation bundles were made for kv_cache-0.3.4.tar.gz:

Publisher: publish-pypi.yml on lcances/kv_cache

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kv_cache-0.3.4-py3-none-any.whl.

File metadata

  • Download URL: kv_cache-0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kv_cache-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 8f11148ce135047d830089bc8419d6c6abc87b3c1add3ae02a9026011f709a75
MD5 7dcd35d2825c0dac263c61ae3f58db7d
BLAKE2b-256 695e81363ae588c2d1bb8887a56440eb3063ee0a1e38486dd71d8f157f166545

See more details on using hashes here.

Provenance

The following attestation bundles were made for kv_cache-0.3.4-py3-none-any.whl:

Publisher: publish-pypi.yml on lcances/kv_cache

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.4 This release

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page