Skip to main content

Async-native in-memory cache with pluggable eviction backends. Pure Python, zero dependencies.

Project description

🗄️ purecache

Async-native in-memory cache with pluggable eviction backends — pure Python 3.12+, zero dependencies.

Just asyncio, collections.OrderedDict, and the irrational urge to understand what happens inside the black box.

Part of the pure-python-system-design project.


📦 Installation

pip install purecache

Or with uv:

uv add purecache

Python 3.12+ required.


⚡ Quick Start

Direct backend usage

from purecache.backends.lru import LRUCache

cache = LRUCache(capacity=128)

await cache.put("user:42", {"name": "Alice"})
value = await cache.get("user:42")  # {"name": "Alice"}
value = await cache.get("missing")  # None

Decorator

from purecache.decorators import cache
from purecache.backends.lru import LRUCache

@cache(backend=LRUCache, capacity=128)
async def get_user(user_id: str) -> dict:
    return await fetch_from_db(user_id)

# First call — executes get_user, caches result
user = await get_user("42")

# Second call — returns cached result, skips get_user
user = await get_user("42")

Cache keys are derived automatically from the function's arguments using pickle + SHA-256 — positional args keep their order, keyword args are sorted by name.


🧠 Backends

Backend Eviction Policy Time Memory Best For
LRUCache Least Recently Used O(1) O(n) General purpose
LFUCache Least Frequently Used O(1) O(n) Skewed access patterns
TTLCache Time-based expiry O(1) O(n) Sessions, tokens
LRUTTLCache LRU + TTL combined O(1) O(n) Production default

All backends implement the ICacheBackend protocol — swap them without touching your application code.


🔌 Framework Examples

The decorator integrates naturally with any async framework:

# FastAPI
from fastapi import FastAPI
from purecache.decorators import cache
from purecache.backends.lru import LRUCache

app = FastAPI()

@app.get("/user/{user_id}")
@cache(backend=LRUCache, capacity=512)
async def get_user(user_id: str):
    return await fetch_user_from_db(user_id)

TODO: Add more examples for aiohttp, Django, Flask, Litestar, and Sanic in examples/.


📐 Architecture

cache() decorator
  └── ICacheBackend (protocol)
        ├── LRUCache    — OrderedDict + move_to_end
        ├── LFUCache    — key_map + freq_map + min_freq pointer
        ├── TTLCache    — dict + expiry timestamps
        └── LRUTTLCache — LRU + TTL combined

The cache() decorator handles key generation and cache lookup. The backend handles storage and eviction. Swap the backend, keep everything else.


⚠️ Known Limitations

  • Caching None: The decorator uses if cached_res is not None as the cache-hit check. Functions that legitimately return None will always miss — the value won't be cached. Use a sentinel-aware backend or wrap the return value if needed.

📋 Requirements

  • Python 3.12+
  • Courage

🧪 Development

uv sync
pre-commit install

uv run pytest
uv run ruff check .
uv run mypy src/
uv run mkdocs serve

📖 Documentation

Full docs at https://pure-python-system-design.github.io/purecache/


More designs to come, if the pizza supply holds.

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

purecache-0.1.0.tar.gz (8.2 kB view details)

Uploaded Source

Built Distribution

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

purecache-0.1.0-py3-none-any.whl (5.2 kB view details)

Uploaded Python 3

File details

Details for the file purecache-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for purecache-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7a37e7e337d8cadc5f90e63467bd395fa182d3237e18807221b02adc9a826080
MD5 f9d784c7be877cacd265e5bd7681b5a9
BLAKE2b-256 03f9c5fb5db2dd4ed813af7eb7a0b639450aa49cdc9cc7092001c32a689816df

See more details on using hashes here.

Provenance

The following attestation bundles were made for purecache-0.1.0.tar.gz:

Publisher: publish.yml on pure-python-system-design/purecache

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

File details

Details for the file purecache-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for purecache-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6cf0a774f1d03e916ed2afceac52d98de9707d0197286764da305275dca55c87
MD5 8ac65784b17ac3d66689f46c450b12b3
BLAKE2b-256 ebce91e0774e1ebb20ecb247cda0fbeec4e36e34f2e04416ec684fb2518931de

See more details on using hashes here.

Provenance

The following attestation bundles were made for purecache-0.1.0-py3-none-any.whl:

Publisher: publish.yml on pure-python-system-design/purecache

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

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