Object Cache
Size-bounded object cache with pluggable eviction policies.
Overview
VCollab applications frequently need to hold computed or loaded objects in memory with a bounded size budget. When the budget is exceeded, old entries must be evicted according to a configurable policy.
The vcti-cache package provides ObjectCache, a generic,
size-bounded cache with a pluggable eviction policy defined by the
abstract CachePolicy base class. Implement CachePolicy to control
how item sizes are calculated and which items are evicted first.
This package has zero external dependencies.
Installation
From PyPI
pip install vcti-cache
In requirements.txt
vcti-cache>=2.0.0
In pyproject.toml dependencies
dependencies = [
"vcti-cache>=2.0.0",
]
Quick Start
from vcti.cache import ObjectCache, LruPolicy
# 1. Create a cache with a built-in LRU policy
cache = ObjectCache[str](max_size=100, cache_policy=LruPolicy(get_size=len))
# 2. Add, retrieve, and remove items
cache.add("greeting", "hello")
print(cache.get("greeting")) # "hello"
print(cache["greeting"]) # "hello" (bracket syntax)
print("greeting" in cache) # True
print(len(cache)) # 1
print(cache.current_size) # 5
# 3. Update (upsert) an existing item
cache.update("greeting", "hi there")
print(cache.get("greeting")) # "hi there"
# 4. Inspect statistics
print(cache.stats.hits) # 3 (two gets + one bracket access)
print(cache.stats.adds) # 2 (original add + update)
cache.remove("greeting")
print(cache.get("greeting")) # None
Five bundled policies are available — FifoPolicy, LruPolicy,
LfuPolicy, MruPolicy, and RrPolicy — each accepting a get_size
callable. Give each cache its own policy instance; policies keep
per-key bookkeeping, and constructing a second cache around one raises
ValueError. For custom eviction logic, subclass CachePolicy[T]
directly (see Extending).
get_size is called once per insertion, and that number is what the
cache budgets against from then on. Mutating a cached value in place does
not re-measure it — call update(key, value) to record the new size.
Eviction policies receive those recorded sizes and must not call
get_size themselves.
Thread Safety
ObjectCache is not thread-safe. If you share a cache across threads,
wrap it with an external lock (e.g. threading.Lock).
Public API
| Symbol | Kind | Description |
|---|---|---|
ObjectCache[T] |
Class | Size-bounded cache with eviction support |
CachePolicy[T] |
ABC | Abstract base for eviction strategies |
FifoPolicy[T] |
Policy | First-in-first-out eviction |
LruPolicy[T] |
Policy | Least-recently-used eviction |
LfuPolicy[T] |
Policy | Least-frequently-used eviction |
MruPolicy[T] |
Policy | Most-recently-used eviction (scan-resistant) |
RrPolicy[T] |
Policy | Random replacement (no adversarial worst case) |
CacheStats |
Dataclass | Immutable hit/miss/eviction/removal statistics |
CacheOverflowError |
Exception | Raised when an item cannot fit |
ObjectCache[T]
| Method / Property | Description |
|---|---|
add(key, value) |
Insert an item; evicts if needed, raises on duplicate key |
update(key, value) |
Insert or replace an item (upsert); evicts if needed. Replacing fires on_replace |
| — | Capacity failures are atomic: a write that cannot fit evicts nothing and leaves any existing value in place. A policy callback that raises is not covered — callbacks must not raise |
get(key) |
Retrieve by key or None |
cache[key] |
Retrieve by key or raise KeyError |
remove(key) |
Remove a single item (fires on_remove) |
clear() |
Remove all items |
keys() |
List of current keys |
values() |
List of current values |
items() |
List of (key, value) pairs |
iter(cache) |
Iterate over keys |
max_size |
Maximum capacity in bytes |
current_size |
Total size of cached items (bytes) |
get_item_size(key) |
Cached size of an item (bytes), or None if missing |
stats |
CacheStats instance with hit/miss/eviction counters |
policy |
The active CachePolicy instance |
key in cache |
Membership test |
len(cache) |
Number of cached items |
CachePolicy[T] (abstract)
| Method | Override | Description |
|---|---|---|
get_size(item) |
Required | Return item size in bytes (>= 0) |
get_eviction_items(space, items, sizes) |
Required | Rank keys to evict, sized from sizes |
on_add(key, item) |
Optional | Called after an item is added |
on_access(key, item) |
Optional | Called when an item is retrieved |
on_evict(key, item) |
Optional | Called when an item is evicted by the policy |
on_remove(key, item) |
Optional | Called on remove() / clear() |
on_replace(key, old, new) |
Optional | Called when update() replaces an existing key; defaults to on_remove + on_add |
CacheStats
| Field | Description |
|---|---|
hits |
Successful get(key) / cache[key] calls |
misses |
get(key) returning None, or cache[key] raising KeyError |
adds |
Successful add / update insertions |
evictions |
Items removed by the eviction policy |
removals |
Items removed by remove() / clear(), plus values displaced by an update() replacement |
Bundled Policies
All bundled policies accept get_size: Callable[[T], int] in their
constructor.
| Policy | Eviction Rule | Internal Structure |
|---|---|---|
FifoPolicy[T] |
Oldest insertion first | OrderedDict |
LruPolicy[T] |
Least recently accessed | OrderedDict (moves on access) |
LfuPolicy[T] |
Lowest access count (ties: oldest) | defaultdict(int) + OrderedDict |
MruPolicy[T] |
Most recently accessed | OrderedDict (evicts from end) |
RrPolicy[T] |
Random (accepts optional seed) |
dict as ordered set + random.Random |
Each policy also decides what a replacing update() means for its
eviction order: LruPolicy and MruPolicy treat the write as a use and
refresh recency, while FifoPolicy, LfuPolicy, and RrPolicy leave
the entry's standing untouched — refreshing a hot LFU entry does not
reset its access count.
Start with LruPolicy — it's the best general-purpose default.
See Choosing a Policy for a detailed
comparison of performance, trade-offs, and when to use each.
Dependencies
None. vcti-cache is pure Python with zero runtime dependencies.
Documentation
| If you want to… | Read |
|---|---|
| Get started using the package | Quick Start above |
| Understand the architecture and design decisions | docs/design.md |
| Navigate and understand the source | docs/source-guide.md |
| See practical, real-world usage | docs/patterns.md |
| Write a custom eviction policy | docs/extending.md |
Metadata
Release files for vcti-cache 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vcti_cache-2.0.0.tar.gz | 48.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vcti_cache-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.9 kB
Release files / vcti_cache-2.0.0.tar.gz
| Download URL | vcti_cache-2.0.0.tar.gz |
|---|---|
| Size | 48.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecece905d6a1a8fa6b4270c052fec49dde8306bf76b749f891ff8cb33ac7c5ab
|
|
BLAKE2b-256 checksum How to use checksums |
e76e370b30e91b99967a2eb8c4327a8c1ce376c1e11d3fe89d64817a2beddd86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logRelease files / vcti_cache-2.0.0-py3-none-any.whl
| Download URL | vcti_cache-2.0.0-py3-none-any.whl |
|---|---|
| Size | 16.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
04ef8e7b01079504bc70c378510e69615ceef58afe25d9767738d742c5052fa1
|
|
BLAKE2b-256 checksum How to use checksums |
0366bf13c0b0ce89a56b0dbec96abccb297c02f5b8d3ddcc1aefb216610b6263
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency log