cacheow
Development-only caching and mocking for expensive Python functions. Add one decorator, then control runtime behavior through persisted disk storage and a small web UI.
Development use only. Do not use cacheow in production. When disabled, the decorator is a no-op with near-zero overhead.
Requirements
- Python 3.13+
Installation
pip install cacheow
Quick start
Enable cacheow with an environment variable:
export CACHEOW_ENABLE=1
from cacheow import cacheow
@cacheow()
def expensive_function(x: int) -> int:
return x * x
expensive_function(3) # recorded to disk in default mode
When CACHEOW_ENABLE is not 1, @cacheow() returns the original function unchanged.
A control panel starts automatically at http://127.0.0.1:8765/ (configurable via environment variables below).
Runtime modes
Each decorated function has one mode, persisted in SQLite:
| Mode | Behavior |
|---|---|
default |
Call the function normally; persist every outcome to disk. Never read cache. |
cache |
Return cached outcomes matching call arguments; call the function on miss. |
mock |
Never call the original; replay stored outcomes (weighted random by default). |
Always set mode using function.cacheow_function_id on the wrapped function. Do not look up functions by name in SQLite; stale registrations can remain after source edits.
Modes can also be changed via the web UI or JSON API (see below).
Complete example
Save as cacheow_example.py and run with python cacheow_example.py:
import asyncio
import os
import time
os.environ.setdefault("CACHEOW_ENABLE", "1")
os.environ.setdefault("CACHEOW_DATA_DIR", ".cacheow")
os.environ.setdefault("CACHEOW_START_SERVER", "1")
from cacheow import cacheow
from cacheow.manager import get_manager
@cacheow()
def sync_compute(n: int) -> int:
print(f"computing {n}")
time.sleep(0.1)
return n * n
@cacheow()
async def async_compute(n: int) -> int:
print(f"async computing {n}")
await asyncio.sleep(0.1)
return n + 10
def main() -> None:
print("=== Default mode: record outcomes ===")
print("sync_compute(3) =", sync_compute(3))
print("async_compute(5) =", asyncio.run(async_compute(5)))
manager = get_manager()
assert manager is not None
fn_id: str = sync_compute.cacheow_function_id # type: ignore[attr-defined]
print("\n=== Cache mode: replay from disk ===")
manager.db.set_mode(fn_id, "cache")
start = time.perf_counter()
print(
"sync_compute(3) cached =",
sync_compute(3),
f"in {(time.perf_counter() - start) * 1000:.1f}ms",
)
print("\n=== Mock mode: never call original ===")
manager.db.set_mode(fn_id, "mock")
print("sync_compute(999) mocked =", sync_compute(999))
host = manager.settings.server_host
port = manager.settings.server_port
print(f"\nControl panel: http://{host}:{port}/")
print(f"Data directory: {manager.settings.data_dir}")
if __name__ == "__main__":
main()
Expected output (approximate):
=== Default mode: record outcomes ===
computing 3
sync_compute(3) = 9
async computing 5
async_compute(5) = 15
=== Cache mode: replay from disk ===
sync_compute(3) cached = 9 in 0.5ms
=== Mock mode: never call original ===
sync_compute(999) mocked = 9
Control panel: http://127.0.0.1:8765/
Data directory: /path/to/.cacheow
In cache and mock modes, computing ... is not printed — the original function is not called.
Environment variables
| Variable | Default | Description |
|---|---|---|
CACHEOW_ENABLE |
unset | Set to 1 to enable cacheow |
CACHEOW_DATA_DIR |
.cacheow |
Persistence directory |
CACHEOW_SERVER_HOST |
127.0.0.1 |
HTTP server bind address |
CACHEOW_SERVER_PORT |
8765 |
HTTP server port |
CACHEOW_START_SERVER |
1 |
Set to 0 to disable auto-start |
Supported function types
- Sync and async functions
- Sync and async generators
- Functions that raise exceptions
- Arbitrary return types (JSON-first serialization with pickle fallback)
On-disk layout
.cacheow/
cacheow.db # SQLite: metadata, modes, stats, outcome index
functions/
<function-id>/
outcomes/
<outcome-id>.json # Human-inspectable outcome payloads
SQLite stores registration, modes, configuration, stats, and an index of outcome files. JSON files store the actual return values, exceptions, and generator sequences so outcomes stay easy to inspect, diff, and edit manually.
HTTP API
| Endpoint | Description |
|---|---|
GET /api/functions |
List all decorated functions |
GET /api/functions/{id} |
Function detail, outcomes, stats |
POST /api/functions/{id}/mode |
Set mode (default, cache, mock) |
POST /api/functions/{id}/latency |
Set artificial delay (ms) |
POST /api/functions/{id}/mock-outcomes |
Configure weighted mock selection |
POST /api/functions/{id}/outcomes/manual |
Add manual return/exception outcome |
POST /api/functions/{id}/rebuild-index |
Rebuild outcome index from disk |
HTML UI: / and /ui/functions/{id}.
Safety
In default mode, persistence or stats failures log a warning and never prevent the wrapped function from returning its result. In cache mode, cache read failures fall back to executing the original function when safe.
Public API
from cacheow import cacheow
That is the intended user-facing entry point. Wrapped functions expose cacheow_function_id for runtime control.
Metadata
Release files for cacheow 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cacheow-0.1.1.tar.gz | 37.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cacheow-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.8 kB
Release files / cacheow-0.1.1.tar.gz
| Download URL | cacheow-0.1.1.tar.gz |
|---|---|
| Size | 37.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c181b6a8baef06abf97ab95331ea416bac8a48471eddd156f2932a1c8cc21034
|
|
BLAKE2b-256 checksum How to use checksums |
1b07efa6663cb84d2471b5a3588cfa61f818a5309244299d248f34386c9d3d13
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.13
|
Release files / cacheow-0.1.1-py3-none-any.whl
| Download URL | cacheow-0.1.1-py3-none-any.whl |
|---|---|
| Size | 28.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e68122b526c4ae7ac8ee62e5da58112484a66474c699616e9b97a0293cd845fa
|
|
BLAKE2b-256 checksum How to use checksums |
7e3f699ca564a7f84798020f56997879da50790379f149f92867f99ffe9984e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.13
|