Skip to main content

Development-only caching and mocking library for expensive Python functions

Project description

cacheow

PyPI version Python versions

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.

Project details


Download files

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

Source Distribution

cacheow-0.1.1.tar.gz (37.5 kB view details)

Uploaded Source

Built Distribution

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

cacheow-0.1.1-py3-none-any.whl (28.3 kB view details)

Uploaded Python 3

File details

Details for the file cacheow-0.1.1.tar.gz.

File metadata

  • Download URL: cacheow-0.1.1.tar.gz
  • Upload date:
  • Size: 37.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for cacheow-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c181b6a8baef06abf97ab95331ea416bac8a48471eddd156f2932a1c8cc21034
MD5 a45bc4c076609e23e19569ed727cb31e
BLAKE2b-256 1b07efa6663cb84d2471b5a3588cfa61f818a5309244299d248f34386c9d3d13

See more details on using hashes here.

File details

Details for the file cacheow-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: cacheow-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 28.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for cacheow-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e68122b526c4ae7ac8ee62e5da58112484a66474c699616e9b97a0293cd845fa
MD5 ce0a5cbabcdd8ecdda7dc74afe413ee3
BLAKE2b-256 7e3f699ca564a7f84798020f56997879da50790379f149f92867f99ffe9984e8

See more details on using hashes here.

Supported by

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