Skip to content

Classes

BaseCacheImpl(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

Base implementation for cache classes.

This abstract base class defines the generic structure for cache implementations.

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

maxsize: int property

The configured maxsize.

getsizeof: typing.Callable[[KT, VT], int] | None property

The configured getsizeof function.

current_size() -> int

Returns the current total cumulative size of all stored entries.

Returns:

  • int

    The sum of sizes of all entries currently in the cache.

Source code in cachebox/_core.pyi
def current_size(self) -> int:
    """
    Returns the current total cumulative size of all stored entries.

    Returns:
        The sum of sizes of all entries currently in the cache.
    """
    ...

remaining_size() -> int

Returns the remaining available size.

Returns:

  • int

    The result of maxsize - current_size.

Source code in cachebox/_core.pyi
def remaining_size(self) -> int:
    """
    Returns the remaining available size.

    Returns:
        The result of ``maxsize - current_size``.
    """
    ...

capacity() -> int

Returns the number of elements the map can hold without reallocating.

Returns:

  • int

    The current allocated capacity.

Source code in cachebox/_core.pyi
def capacity(self) -> int:
    """
    Returns the number of elements the map can hold without reallocating.

    Returns:
        The current allocated capacity.
    """
    ...

__len__() -> int

Returns the number of entries currently in the cache.

Returns:

  • int

    The number of entries in the cache.

Source code in cachebox/_core.pyi
def __len__(self) -> int:
    """
    Returns the number of entries currently in the cache.

    Returns:
        The number of entries in the cache.
    """
    ...

__contains__(key: KT) -> bool

Source code in cachebox/_core.pyi
def __contains__(self, key: KT) -> bool: ...

contains(key: KT) -> bool

Returns True if the cache contains an entry for key.

Equivalent to key in self. Prefer this method over key in self to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to look up.

Returns:

  • bool

    True if the key exists in the cache, False otherwise.

Source code in cachebox/_core.pyi
def contains(self, key: KT) -> bool:
    """
    Returns ``True`` if the cache contains an entry for ``key``.

    Equivalent to ``key in self``. Prefer this method over ``key in self``
    to keep code compatible across different cache policies.

    Args:
        key: The key to look up.

    Returns:
        ``True`` if the key exists in the cache, ``False`` otherwise.
    """
    ...

is_empty() -> bool

Returns True if the cache is empty.

Returns:

  • bool

    True if the cache contains no entries.

Source code in cachebox/_core.pyi
def is_empty(self) -> bool:
    """
    Returns ``True`` if the cache is empty.

    Returns:
        ``True`` if the cache contains no entries.
    """
    ...

is_full() -> bool

Returns True when the cumulative size has reached the maxsize limit.

Returns:

  • bool

    True if the cache is at capacity.

Source code in cachebox/_core.pyi
def is_full(self) -> bool:
    """
    Returns ``True`` when the cumulative size has reached the maxsize limit.

    Returns:
        ``True`` if the cache is at capacity.
    """
    ...

insert(key: KT, value: VT, *args: typing.Any, **kwargs: typing.Any) -> typing.Optional[VT]

Source code in cachebox/_core.pyi
def insert(
    self, key: KT, value: VT, *args: typing.Any, **kwargs: typing.Any
) -> typing.Optional[VT]: ...

__setitem__(key: KT, value: VT) -> None

Source code in cachebox/_core.pyi
def __setitem__(self, key: KT, value: VT) -> None: ...

update(iterable: _IterableType[KT, VT], *args: typing.Any, **kwargs: typing.Any) -> None

Source code in cachebox/_core.pyi
def update(
    self,
    iterable: _IterableType[KT, VT],
    *args: typing.Any,
    **kwargs: typing.Any,
) -> None: ...

get(key: KT, default: typing.Optional[DT] = None) -> typing.Union[VT, DT]

Source code in cachebox/_core.pyi
def get(
    self, key: KT, default: typing.Optional[DT] = None
) -> typing.Union[VT, DT]: ...

__getitem__(key: KT) -> VT

Source code in cachebox/_core.pyi
def __getitem__(self, key: KT) -> VT: ...

setdefault(key: KT, default: typing.Optional[DT] = None, *args: typing.Any, **kwargs: typing.Any) -> typing.Optional[VT | DT]

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
    *args: typing.Any,
    **kwargs: typing.Any,
) -> typing.Optional[VT | DT]: ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

__delitem__(key: KT) -> None

Source code in cachebox/_core.pyi
def __delitem__(self, key: KT) -> None: ...

popitem() -> typing.Tuple[KT, VT]

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]: ...

drain(n: int) -> int

Calls popitem() n times and returns the count of removed items.

Parameters:

  • n

    (int) –

    The number of items to remove.

Returns:

  • int

    The number of items successfully removed.

Source code in cachebox/_core.pyi
def drain(self, n: int) -> int:
    """
    Calls ``popitem()`` ``n`` times and returns the count of removed items.

    Args:
        n: The number of items to remove.

    Returns:
        The number of items successfully removed.
    """
    ...

shrink_to_fit() -> None

Shrinks the internal allocation as close to the current length as possible.

Source code in cachebox/_core.pyi
def shrink_to_fit(self) -> None:
    """Shrinks the internal allocation as close to the current length as possible."""
    ...

clear(*, reuse: bool = False) -> None

Removes all items from the cache.

Parameters:

  • reuse

    (bool, default: False ) –

    If True, retains the allocated memory for future reuse rather than freeing it. Defaults to False.

Source code in cachebox/_core.pyi
def clear(self, *, reuse: bool = False) -> None:
    """
    Removes all items from the cache.

    Args:
        reuse: If ``True``, retains the allocated memory for future reuse
            rather than freeing it. Defaults to ``False``.
    """
    ...

__eq__(other: typing.Any) -> bool

Source code in cachebox/_core.pyi
def __eq__(self, other: typing.Any) -> bool: ...

__ne__(other: typing.Any) -> bool

Source code in cachebox/_core.pyi
def __ne__(self, other: typing.Any) -> bool: ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]: ...

values() -> typing.Iterable[VT]

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]: ...

keys() -> typing.Iterable[KT]

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]: ...

__iter__() -> typing.Iterator[KT]

Source code in cachebox/_core.pyi
def __iter__(self) -> typing.Iterator[KT]: ...

copy() -> typing.Self

Source code in cachebox/_core.pyi
def copy(self) -> typing.Self: ...

__repr__() -> str

Source code in cachebox/_core.pyi
def __repr__(self) -> str: ...

Cache(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

A thread-safe, memory-efficient key-value cache with no eviction policy.

Items remain in the cache until manually removed or the cache is cleared.

Cache is essentially a configurable hashmap-like store. When an item is inserted, it is stored directly without any ordering, priority tracking, or access metadata. If a maximum size is configured, insertions beyond that limit are rejected with an OverflowError. All read and write operations are thread-safe.

Because no eviction logic runs in the background, there is no overhead from tracking usage order, frequency counters, or expiry timestamps.

get insert delete popitem
Worse-case O(1) O(1) O(1) N/A
Pros
  • Minimal overhead: no bookkeeping for eviction means lower CPU and memory usage per entry compared to policy-based caches.
  • Predictable behavior: items are never silently removed, so cache hits are deterministic once an item is stored.
  • Thread-safe: safe for concurrent reads and writes out of the box.
  • Configurable capacity: a hard size limit prevents unbounded memory growth.
Cons
  • No automatic eviction: the cache can fill up and stop accepting new entries if a max size is set, requiring manual management.
  • Unordered: unlike a standard dict (Python 3.7+), insertion order is not preserved.
  • Not suitable for volatile data: stale entries persist forever unless explicitly invalidated.

Use Cache when you have a fixed, well-known set of keys that are expensive to compute and never go stale (e.g. parsed config values, compiled regex patterns, loaded templates), and when the lowest possible overhead is required.

Avoid it when cached data can become stale, when the working set is unpredictable in size, or when automatic memory pressure relief is needed.

from cachebox import Cache

cache = Cache(maxsize=100, iterable=None, capacity=100)

# behaves like a regular dict
cache["key"] = "value"
# using `.insert(key, value)` is recommended
cache.insert("key", "value")

print(cache["key"])  # value

del cache["key"]
cache["key"]  # KeyError: key

# cachebox.Cache does not have any policy, so will raise OverflowError if the capacity is exceeded
cache.update({i:i for i in range(200)})
# OverflowError: The cache has reached the bound.

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Raises:

  • OverflowError

    If the cache has reached its maxsize limit, since this class has no eviction algorithm.

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).

    Raises:
        OverflowError: If the cache has reached its ``maxsize`` limit,
            since this class has no eviction algorithm.
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a given key from the cache.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def get(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a given key from the cache.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Always raises OverflowError.

Cache has no policy or algorithm to select an item for eviction.

Raises:

  • OverflowError

    Always, because Cache has no eviction policy.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Always raises ``OverflowError``.

    ``Cache`` has no policy or algorithm to select an item for eviction.

    Raises:
        OverflowError: Always, because ``Cache`` has no eviction policy.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating. Items are not ordered.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating. Items are not ordered.

    Returns:
        An iterable of ``(key, value)`` tuples.
    """
    ...

values() -> typing.Iterable[VT]

Returns an iterable of the cache's values.

Warning

Do not modify the cache while iterating. Values are not ordered.

Returns:

  • Iterable[VT]

    An iterable of values.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating. Values are not ordered.

    Returns:
        An iterable of values.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an iterable of the cache's keys.

Warning

Do not modify the cache while iterating. Keys are not ordered.

Returns:

  • Iterable[KT]

    An iterable of keys.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating. Keys are not ordered.

    Returns:
        An iterable of keys.
    """
    ...

FIFOCache(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

A cache with a First-In-First-Out (FIFO) eviction policy.

When the cache is full, the oldest inserted item is always the first to be removed, regardless of how often it has been accessed.

Items are stored in insertion order. When capacity is reached, the item that has been present the longest is evicted. There is no concept of "recently used" or "frequently used" - age alone determines eviction order. Conceptually it behaves like a queue: new items join the back and evictions come from the front.

This implementation backs that queue with a double-ended queue for O(1) front removal, paired with a hash map for O(1) key lookups. Logical indices (a monotonically increasing counter) are stored in the table rather than physical deque positions, so eviction never requires rewriting the index. A front_offset counter recovers physical positions at read time as entries[table[key] - front_offset].

get insert delete popitem
Worse-case O(1) O(1) O(min(i, n-i)) O(n) - very rare
Pros
  • Insert, lookup, and evict are all O(1) amortized.
  • Eviction order is fully deterministic and easy to reason about.
  • No per-read overhead: unlike LRU, FIFO requires no bookkeeping on cache hits.
Cons
  • Access-blind eviction: a hot item is evicted just as readily as one never read, hurting hit rates on workloads with temporal locality.
  • Logical-index indirection adds internal complexity vs. a naive queue.
  • A rare O(n) index rebase (when front_offset nears usize::MAX - isize::MAX) introduces an occasional latency spike.

Use FIFOCache when eviction order must be predictable and auditable, access patterns are roughly uniform, or read overhead must be minimal (insert-heavy workloads with infrequent re-reads).

Avoid it when the workload has strong temporal locality; in those cases LRU or LFU will deliver meaningfully better hit rates.

from cachebox import FIFOCache

cache = FIFOCache(5, {i:i*2 for i in range(5)})

print(len(cache)) # 5
cache["new-key"] = "new-value"
print(len(cache)) # 5

print(cache.get(3, "default-val")) # 6
print(cache.get(6, "default-val")) # default-val

print(cache.popitem()) # (1, 2)

# Returns the first key in cache; this is the one which will be removed by `popitem()`.
print(cache.first())

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = None) -> typing.Union[VT, DT]

Source code in cachebox/_core.pyi
def get(
    self, key: KT, default: typing.Optional[DT] = None
) -> typing.Union[VT, DT]: ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Removes and returns the oldest item in the cache.

Returns:

  • Tuple[KT, VT]

    A (key, value) tuple for the item that was inserted first.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Removes and returns the oldest item in the cache.

    Returns:
        A ``(key, value)`` tuple for the item that was inserted first.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an ordered iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples in insertion order.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in insertion order.
    """
    ...

values() -> typing.Iterable[VT]

Returns an ordered iterable of the cache's values.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[VT]

    An iterable of values in insertion order.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an ordered iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of values in insertion order.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an ordered iterable of the cache's keys.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[KT]

    An iterable of keys in insertion order.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an ordered iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of keys in insertion order.
    """
    ...

first(n: int = 0) -> typing.Optional[KT]

Returns the key at position n in insertion order.

The key at position 0 is the one that will be removed by popitem().

Parameters:

  • n

    (int, default: 0 ) –

    The index to look up. Defaults to 0 (the oldest item).

Returns:

  • Optional[KT]

    The key at the given index.

Raises:

  • IndexError

    If the cache is empty or n is out of range.

Source code in cachebox/_core.pyi
def first(self, n: int = 0) -> typing.Optional[KT]:
    """
    Returns the key at position ``n`` in insertion order.

    The key at position 0 is the one that will be removed by ``popitem()``.

    Args:
        n: The index to look up. Defaults to 0 (the oldest item).

    Returns:
        The key at the given index.

    Raises:
        IndexError: If the cache is empty or ``n`` is out of range.
    """
    ...

last() -> typing.Optional[KT]

Returns the most recently inserted key. Equivalent to self.first(-1).

Returns:

  • Optional[KT]

    The key of the most recently inserted item.

Raises:

  • IndexError

    If the cache is empty.

Source code in cachebox/_core.pyi
def last(self) -> typing.Optional[KT]:
    """
    Returns the most recently inserted key. Equivalent to ``self.first(-1)``.

    Returns:
        The key of the most recently inserted item.

    Raises:
        IndexError: If the cache is empty.
    """
    ...

RRCache(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

A thread-safe, memory-efficient cache with a Random Replacement eviction policy.

When the cache reaches its maximum size, a randomly selected item is evicted to make room for new entries.

Items are stored without any ordering or priority tracking. The Random Replacement policy selects entries for eviction uniformly at random, ensuring fair treatment across all cached items regardless of access patterns.

get insert delete popitem(i)
Worse-case O(1) O(1) O(1) O(min(i, n-i))
Pros
  • Low overhead: computationally cheap compared to tracking access order or frequency.
  • Thread-safe: safe for concurrent reads and writes out of the box.
  • Configurable capacity: a hard size limit prevents unbounded memory growth while allowing new entries through automatic eviction.
  • No indefinite staleness: items are eventually replaced by the eviction policy.
Cons
  • Non-deterministic eviction: random selection means recently cached or frequently accessed items may be unexpectedly removed.
  • Unordered: insertion order is not preserved.
  • Less optimal than LRU/LFU on skewed access patterns.

Use RRCache when the working set can grow unpredictably, access patterns are roughly uniform, and low overhead with simple eviction logic is preferred.

Avoid it when access patterns are highly skewed, cache hits are mission-critical, or fine-grained eviction control is required.

from cachebox import RRCache

cache = RRCache(10, {i:i for i in range(10)})
print(cache.is_full()) # True
print(cache.is_empty()) # False

# Returns a random key
print(cache.random_key()) # 4

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a given key from the cache.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def get(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a given key from the cache.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Randomly selects, removes, and returns a (key, value) pair.

Returns:

  • Tuple[KT, VT]

    A randomly chosen (key, value) tuple.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Randomly selects, removes, and returns a ``(key, value)`` pair.

    Returns:
        A randomly chosen ``(key, value)`` tuple.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating. Items are not ordered.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating. Items are not ordered.

    Returns:
        An iterable of ``(key, value)`` tuples.
    """
    ...

values() -> typing.Iterable[VT]

Returns an iterable of the cache's values.

Warning

Do not modify the cache while iterating. Values are not ordered.

Returns:

  • Iterable[VT]

    An iterable of values.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating. Values are not ordered.

    Returns:
        An iterable of values.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an iterable of the cache's keys.

Warning

Do not modify the cache while iterating. Keys are not ordered.

Returns:

  • Iterable[KT]

    An iterable of keys.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating. Keys are not ordered.

    Returns:
        An iterable of keys.
    """
    ...

LRUCache(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

A cache with a Least-Recently-Used (LRU) eviction policy.

When the cache is full, the item that has not been accessed for the longest time is removed first, regardless of how many times it was accessed in the past.

Items are tracked by access recency - every read or write promotes an item to "most recently used". When capacity is reached, the least recently used item (accessed longest ago) is evicted.

This implementation pairs a doubly-linked list with a hash map. The list maintains items in access order (most recently used at the back, least recently used at the front); the hash map stores cursors into the list for O(1) lookups. On every access the item is moved to the back. On eviction the front item is removed. A running total enables O(1) capacity checks.

get insert delete(i) popitem
Worse-case O(1)~ O(1)~ O(1)~ O(1)~
Pros
  • Excellent hit rates on temporal-locality workloads.
  • Insert, lookup, and evict are all O(1) amortized.
  • Automatically adapts to access patterns without manual tuning.
  • Per-hit cost is minimal (O(1) linked-list manipulation).
Cons
  • Per-read overhead from updating the linked list on every cache hit.
  • Burst traffic can keep a transiently hot item alive at the expense of items with better long-term utility.
  • Implementation complexity from doubly-linked list and cursor-based hash table.
  • Memory overhead from storing prev/next pointers for every entry.

Use LRUCache when the workload exhibits temporal locality, hit rate is the primary metric, or access patterns are unknown or unpredictable.

Avoid it for write-heavy workloads with few re-reads, ultra-low-latency requirements, or frequency-heavy bimodal access patterns (consider LFU instead).

from cachebox import LRUCache

cache = LRUCache(0, {i:i*2 for i in range(10)})

# access `1`
print(cache[0]) # 0
print(cache.least_recently_used()) # 1
print(cache.popitem()) # (1, 2)

# .peek() searches for a key-value in the cache and returns it without moving the key to recently used.
print(cache.peek(2)) # 4
print(cache.popitem()) # (3, 6)

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a given key from the cache.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def get(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a given key from the cache.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Removes and returns the least recently used item.

Returns:

  • Tuple[KT, VT]

    A (key, value) tuple for the least recently used item.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Removes and returns the least recently used item.

    Returns:
        A ``(key, value)`` tuple for the least recently used item.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an ordered iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples in access order.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in access order.
    """
    ...

values() -> typing.Iterable[VT]

Returns an ordered iterable of the cache's values.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[VT]

    An iterable of values in access order.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an ordered iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of values in access order.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an ordered iterable of the cache's keys.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[KT]

    An iterable of keys in access order.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an ordered iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of keys in access order.
    """
    ...

peek(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a key without updating its recency.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def peek(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a key without updating its recency.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

least_recently_used() -> typing.Optional[KT]

Returns the key that has not been accessed for the longest time.

Returns:

  • Optional[KT]

    The least recently used key.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def least_recently_used(self) -> typing.Optional[KT]:
    """
    Returns the key that has not been accessed for the longest time.

    Returns:
        The least recently used key.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

most_recently_used() -> typing.Optional[KT]

Returns the key that was accessed most recently.

Returns:

  • Optional[KT]

    The most recently used key.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def most_recently_used(self) -> typing.Optional[KT]:
    """
    Returns the key that was accessed most recently.

    Returns:
        The most recently used key.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

LFUCache(maxsize: int, iterable: _IterableType[KT, VT] | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None)

A cache with a Least-Frequently-Used (LFU) eviction policy.

When the cache is full, the item with the lowest access count is evicted first. Ties in frequency are broken by recency - among equally rare items, the oldest is evicted.

Access counts are tracked per key. This implementation uses a lazy binary min-heap keyed on access frequency, paired with a hash map that maps each key to its cursor (a stable pointer into the heap's backing buffer). The heap is "lazy": it does not restore the heap invariant after every frequency increment; instead it sets a dirty flag and defers re-sorting until the next eviction, amortising heap-maintenance cost across many hits.

On a cache hit the frequency counter is incremented in O(1) and the heap is marked dirty. On eviction the heap is sorted if dirty, then the minimum-frequency item is popped in O(n log n) worst-case (amortised O(log n) under typical distributions). Lookups are O(1) via the hash map.

get insert delete(i) popitem
Worse-case O(1)~ O(1)~ O(min(i, n-i)) O(1)~
Pros
  • Frequency-aware eviction protects hot items under heavy cache pressure.
  • O(1) cache hits: incrementing a counter and marking the heap dirty is constant-time work with no structural reorganisation.
  • Lazy heap sorting amortises the O(n log n) sort cost across many inserts and hits.
Cons
  • Eviction is O(n log n) worst-case, introducing latency spikes under adversarial access patterns.
  • Frequency counters accumulate indefinitely, causing "cache pollution" where historically hot but currently cold items monopolise capacity.
  • Access patterns must be skewed for LFU to outperform simpler policies; on uniform workloads the extra bookkeeping is pure overhead.

Use LFUCache when the workload has a stable hot set, cache pollution from one-time scans is a concern, or hit rate matters more than worst-case eviction latency.

Avoid it when access patterns shift rapidly (use LRU instead) or when all keys are accessed with roughly equal probability.

from cachebox import LFUCache

cache = cachebox.LFUCache(5)
cache.insert('first', 'A')
cache.insert('second', 'B')

# access 'first' twice
cache['first']
cache['first']

# access 'second' once
cache['second']

assert cache.least_frequently_used() == 'second'
assert cache.least_frequently_used(2) is None # 2 is out of range

for item in cache.items_with_frequency():
    print(item)
# ('second', 'B', 1)
# ('first', 'A', 2)

Initializes a new instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (_IterableType[KT, VT] | None, default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching - for example, sizing entries by memory footprint or byte length.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Source code in cachebox/_core.pyi
def __init__(
    self,
    maxsize: int,
    iterable: _IterableType[KT, VT] | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
) -> None:
    """
    Initializes a new instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching - for example, sizing entries by memory
            footprint or byte length.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.
    """
    ...

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a given key from the cache.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def get(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a given key from the cache.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Removes and returns the least frequently used item.

Returns:

  • Tuple[KT, VT]

    A (key, value) tuple for the item with the lowest access count.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Removes and returns the least frequently used item.

    Returns:
        A ``(key, value)`` tuple for the item with the lowest access count.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an ordered iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples in frequency order.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in frequency order.
    """
    ...

values() -> typing.Iterable[VT]

Returns an ordered iterable of the cache's values.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[VT]

    An iterable of values in frequency order.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an ordered iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of values in frequency order.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an ordered iterable of the cache's keys.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[KT]

    An iterable of keys in frequency order.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an ordered iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of keys in frequency order.
    """
    ...

items_with_frequency() -> typing.Iterable[typing.Tuple[KT, VT, int]]

Returns an ordered iterable of the cache's (key, value) pairs with their frequency counter.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT, int]]

    An iterable of (key, value) tuples in frequency order.

Source code in cachebox/_core.pyi
def items_with_frequency(self) -> typing.Iterable[typing.Tuple[KT, VT, int]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs with their
    frequency counter.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in frequency order.
    """
    ...

peek(key: KT, default: typing.Optional[DT] = ...) -> typing.Union[VT, DT]

Retrieves the value for a key without incrementing its frequency counter.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Source code in cachebox/_core.pyi
def peek(
    self,
    key: KT,
    default: typing.Optional[DT] = ...,
) -> typing.Union[VT, DT]:
    """
    Retrieves the value for a key without incrementing its frequency counter.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.
    """
    ...

least_frequently_used(n: int = 0) -> KT

Returns the key with the lowest access count.

Parameters:

  • n

    (int, default: 0 ) –

    If given, returns the n-th least frequently used key (0-indexed). Defaults to 0.

Returns:

  • KT

    The key with the n-th lowest access count.

Raises:

  • IndexError

    If the cache is empty or n is out of range.

Warning

This method may re-sort the cache. Do not call it while iterating over the cache.

Source code in cachebox/_core.pyi
def least_frequently_used(self, n: int = 0) -> KT:
    """
    Returns the key with the lowest access count.

    Args:
        n: If given, returns the ``n``-th least frequently used key
            (0-indexed). Defaults to 0.

    Returns:
        The key with the ``n``-th lowest access count.

    Raises:
        IndexError: If the cache is empty or ``n`` is out of range.

    Warning:
        This method may re-sort the cache. Do not call it while iterating
        over the cache.
    """
    ...

TTLCache(maxsize: int, global_ttl: float | timedelta, iterable: typing.Optional[_IterableType[KT, VT]] = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None, sweep_interval: float | timedelta | None = None)

A cache with a Time-To-Live (TTL) eviction policy.

Each entry carries an expiration timestamp and is considered stale — and eligible for eviction — once that deadline has passed, regardless of how recently or frequently it was accessed.

Every entry is stamped with an absolute expires_at timestamp at insertion time (computed as now + global_ttl). Entries are stored in insertion order and eviction proceeds from the front of that queue, but only after confirming the candidate has actually expired. A live entry at the front of the queue blocks eviction of everything behind it, so the cache may temporarily exceed capacity if the oldest entries are still fresh.

Like FIFOCache, this implementation backs the queue with a double-ended queue for O(1) front removal and a hash map for O(1) key lookups. The same logical-index trick applies: the table stores monotonically increasing counters rather than physical deque positions, and a front_offset counter converts a logical index back to a physical one at read time via entries[table[key] - front_offset]. This keeps eviction and lookup O(1) without rewriting the table on every eviction. Every read also checks expires_at against the current wall-clock time and treats any expired entry as a cache miss.

Without sweep_interval, an expiry sweep is triggered automatically on every call to insert, update, current_size, remaining_size, last, first, items, keys, values, and __iter__. A completely idle cache will accumulate stale entries between these calls, but any normal interaction is sufficient to reclaim them. When sweep_interval is set, a background thread performs the sweep on that interval instead, reclaiming expired entries independent of method calls.

get insert delete popitem
Worse-case O(1) O(1) O(min(i, n-i)) O(n) - very rare
Pros
  • Insert, lookup, and evict are all O(1) amortized: the front_offset trick eliminates the O(n) index-shifting that a naive implementation would require on every eviction.
  • Entries expire automatically without a background thread or explicit invalidation call; stale data is never returned to the caller.
  • TTL expiry and insertion-order eviction compose cleanly: the oldest expired entry is always evicted first.
  • A single global_ttl keeps configuration simple; every entry ages at the same rate.
Cons
  • Wall-clock dependency: correctness relies on a monotonically advancing system clock. Clock adjustments (NTP steps, suspend/resume) can cause entries to expire earlier or later than intended.
  • When sweep_interval is set, a background thread wakes on that interval to remove all expired entries, adding a small amount of background CPU usage for the lifetime of the cache.
  • No per-entry TTL override: all entries share global_ttl; mixed expiry requirements need a different policy or a wrapper layer.
  • A rare O(n) index rebase (triggered when front_offset nears usize::MAX - isize::MAX) introduces an occasional latency spike; amortised cost is negligible but worst-case latency is unbounded in principle.

Use TTLCache when cached data has a natural freshness window (API responses, auth tokens, DNS records, rate-limit counters), when automatic expiry without a background reaper is sufficient, or when access patterns are unpredictable enough that recency- or frequency-based eviction would offer no meaningful advantage.

Avoid it when strong temporal locality makes LRU a better fit, when per-entry TTL granularity is required (consider VTTLCache instead), or when the system clock is unreliable or subject to adjustment.

from cachebox import TTLCache
import time

cache = TTLCache(0, global_ttl=2)
cache.update({i:str(i) for i in range(10)})

print(cache.get_with_expire(2)) # ('2', 1.99)

# Returns the oldest key in cache; this is the one which will be removed by `popitem()`
print(cache.first()) # 0

cache["mykey"] = "value"
time.sleep(2)
cache["mykey"] # KeyError

Initializes a new TTLCache instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • global_ttl

    (float | timedelta) –

    Time-to-live for every entry, as seconds (float) or a timedelta. Applied at insertion time.

  • iterable

    (Optional[_IterableType[KT, VT]], default: None ) –

    Initial data to populate the cache.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching — for example, sizing entries by memory footprint or byte length.

  • sweep_interval

    (float | timedelta | None, default: None ) –

    If set, starts a background thread that sweeps and removes all expired entries on this interval (in seconds or as a timedelta). When None, expiry is lazy. Defaults to None. Must be greater than or equal to 1.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Raises:

  • ValueError

    If sweep_interval is set to a value less than 1.

Source code in cachebox/_cachebox.py
def __init__(
    self,
    maxsize: int,
    global_ttl: float | timedelta,
    iterable: typing.Optional["_IterableType[KT, VT]"] = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
    sweep_interval: float | timedelta | None = None,
) -> None:
    """
    Initializes a new TTLCache instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        global_ttl: Time-to-live for every entry, as seconds (float) or a
            ``timedelta``. Applied at insertion time.
        iterable: Initial data to populate the cache.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching — for example, sizing entries by memory
            footprint or byte length.
        sweep_interval: If set, starts a background thread that sweeps and
            removes all expired entries on this interval (in seconds or as
            a ``timedelta``). When ``None``, expiry is lazy. Defaults to
            ``None``. Must be greater than or equal to 1.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.

    Raises:
        ValueError: If ``sweep_interval`` is set to a value less than 1.
    """
    super().__init__(
        maxsize,
        global_ttl,
        iterable,
        capacity=capacity,
        getsizeof=getsizeof,
    )

    self._thread: threading.Thread | None = None
    self._thread_is_running: bool = False

    if sweep_interval is not None:
        if isinstance(sweep_interval, timedelta):
            sweep_interval = sweep_interval.total_seconds()

        if sweep_interval < 1:
            raise ValueError("sweep_interval must be more than 1 seconds.")

        self._thread_is_running = True
        self._thread = threading.Thread(
            target=self._sweeper_thread,
            args=(sweep_interval,),
            daemon=True,
        )
        self._thread.start()

    self._sweep_interval = sweep_interval

sweep_interval: float | None property

The configured sweep_interval in seconds.

global_ttl: float property

The configured global_ttl in seconds.

stop_sweeper() -> None

Signals the background sweeper thread to stop, if one is active.

Source code in cachebox/_cachebox.py
def stop_sweeper(self) -> None:
    """Signals the background sweeper thread to stop, if one is active."""
    self._thread_is_running = False

insert(key: KT, value: VT) -> typing.Optional[VT]

Inserts a key-value pair and returns the previous value if present.

Equivalent to self[key] = value, but returns a value. Prefer this method over direct assignment to keep code compatible across different cache policies.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(self, key: KT, value: VT) -> typing.Optional[VT]:
    """
    Inserts a key-value pair and returns the previous value if present.

    Equivalent to ``self[key] = value``, but returns a value. Prefer this
    method over direct assignment to keep code compatible across different
    cache policies.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT]) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

Source code in cachebox/_core.pyi
def update(self, iterable: _IterableType[KT, VT]) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
    """
    ...

get(key: KT, default: typing.Optional[DT] = None) -> typing.Union[VT, DT]

Source code in cachebox/_core.pyi
def get(
    self, key: KT, default: typing.Optional[DT] = None
) -> typing.Union[VT, DT]: ...

setdefault(key: KT, default: typing.Optional[DT] = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

pop(key: KT, default: DT = ...) -> typing.Union[VT, DT]

Removes the specified key and returns the corresponding value.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (DT, default: ... ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    The value associated with key, or default if not found.

Raises:

  • KeyError

    If the key is not found and no default is provided.

Source code in cachebox/_core.pyi
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
    """
    Removes the specified key and returns the corresponding value.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        The value associated with ``key``, or ``default`` if not found.

    Raises:
        KeyError: If the key is not found and no ``default`` is provided.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Removes and returns the item that has been in the cache the longest.

Returns:

  • Tuple[KT, VT]

    A (key, value) tuple for the oldest item.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Removes and returns the item that has been in the cache the longest.

    Returns:
        A ``(key, value)`` tuple for the oldest item.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an ordered iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples in insertion order.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in insertion order.
    """
    ...

values() -> typing.Iterable[VT]

Returns an ordered iterable of the cache's values.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[VT]

    An iterable of values in insertion order.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an ordered iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of values in insertion order.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an ordered iterable of the cache's keys.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[KT]

    An iterable of keys in insertion order.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an ordered iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of keys in insertion order.
    """
    ...

first(n: int = 0) -> typing.Optional[KT]

Returns the key at position n in insertion order.

The key at position 0 is the one that will be removed by popitem().

Parameters:

  • n

    (int, default: 0 ) –

    The index to look up. Defaults to 0 (the oldest item).

Returns:

  • Optional[KT]

    The key at the given index.

Raises:

  • IndexError

    If the cache is empty or n is out of range.

Source code in cachebox/_core.pyi
def first(self, n: int = 0) -> typing.Optional[KT]:
    """
    Returns the key at position ``n`` in insertion order.

    The key at position 0 is the one that will be removed by ``popitem()``.

    Args:
        n: The index to look up. Defaults to 0 (the oldest item).

    Returns:
        The key at the given index.

    Raises:
        IndexError: If the cache is empty or ``n`` is out of range.
    """
    ...

last() -> typing.Optional[KT]

Returns the most recently inserted key. Equivalent to self.first(-1).

Returns:

  • Optional[KT]

    The key of the most recently inserted item.

Raises:

  • IndexError

    If the cache is empty.

Source code in cachebox/_core.pyi
def last(self) -> typing.Optional[KT]:
    """
    Returns the most recently inserted key. Equivalent to ``self.first(-1)``.

    Returns:
        The key of the most recently inserted item.

    Raises:
        IndexError: If the cache is empty.
    """
    ...

expire(*, reuse: bool = False) -> None

Manually removes all expired key-value pairs from the cache.

Parameters:

  • reuse

    (bool, default: False ) –

    If True, retains the allocated memory for future reuse rather than freeing it. Defaults to False.

Source code in cachebox/_core.pyi
def expire(self, *, reuse: bool = False) -> None:
    """
    Manually removes all expired key-value pairs from the cache.

    Args:
        reuse: If ``True``, retains the allocated memory for future reuse
            rather than freeing it. Defaults to ``False``.
    """
    ...

get_with_expire(key: KT, default: typing.Optional[DT] = None) -> typing.Tuple[typing.Union[VT, DT], float]

Retrieves a value along with its remaining TTL.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: None ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    A tuple of (value, remaining_ttl) where remaining_ttl is

  • float

    the expiration duration in seconds, or 0.0 if the key was not

  • Tuple[Union[VT, DT], float]

    found.

Source code in cachebox/_core.pyi
def get_with_expire(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Tuple[typing.Union[VT, DT], float]:
    """
    Retrieves a value along with its remaining TTL.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        A tuple of ``(value, remaining_ttl)`` where ``remaining_ttl`` is
        the expiration duration in seconds, or ``0.0`` if the key was not
        found.
    """
    ...

pop_with_expire(key: KT, default: typing.Optional[DT] = None) -> typing.Tuple[typing.Union[VT, DT], float]

Removes a key and returns its value along with its remaining TTL.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (Optional[DT], default: None ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    A tuple of (value, remaining_ttl) where remaining_ttl is

  • float

    the expiration duration in seconds, or 0.0 if the key was not

  • Tuple[Union[VT, DT], float]

    found.

Source code in cachebox/_core.pyi
def pop_with_expire(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Tuple[typing.Union[VT, DT], float]:
    """
    Removes a key and returns its value along with its remaining TTL.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        A tuple of ``(value, remaining_ttl)`` where ``remaining_ttl`` is
        the expiration duration in seconds, or ``0.0`` if the key was not
        found.
    """
    ...

popitem_with_expire() -> typing.Tuple[VT, DT, float]

Removes and returns the oldest item along with its remaining TTL.

Returns:

  • VT

    A tuple of (key, value, remaining_ttl) where remaining_ttl

  • DT

    is the expiration duration in seconds.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem_with_expire(self) -> typing.Tuple[VT, DT, float]:
    """
    Removes and returns the oldest item along with its remaining TTL.

    Returns:
        A tuple of ``(key, value, remaining_ttl)`` where ``remaining_ttl``
        is the expiration duration in seconds.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items_with_expire() -> typing.Iterable[typing.Tuple[KT, VT, float]]

Returns an ordered iterable of items with their remaining TTL.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT, float]]

    An iterable of (key, value, remaining_ttl) tuples in insertion

  • Iterable[Tuple[KT, VT, float]]

    order, where remaining_ttl is in seconds.

Source code in cachebox/_core.pyi
def items_with_expire(self) -> typing.Iterable[typing.Tuple[KT, VT, float]]:
    """
    Returns an ordered iterable of items with their remaining TTL.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value, remaining_ttl)`` tuples in insertion
        order, where ``remaining_ttl`` is in seconds.
    """
    ...

VTTLCache(maxsize: int, iterable: typing.Optional[_IterableType[KT, VT]] = None, ttl: float | timedelta | datetime | None = None, *, capacity: int = 0, getsizeof: typing.Callable[[KT, VT], int] | None = None, sweep_interval: float | timedelta | None = None)

A cache with a Variable Time-To-Live (VTTL) eviction policy.

Each item can be inserted with its own individual TTL (time-to-live). When an item's TTL expires, it is considered stale and will be evicted. Items inserted without a TTL never expire and are only evicted when the cache reaches capacity.

Expiration is managed lazily by default: stale entries are not removed immediately when they expire, but are cleaned up on the next access or when the cache needs to reclaim capacity. Optionally, a sweep_interval can be configured to spawn a background thread that proactively removes expired items on a fixed schedule, bounding the window in which stale data can be observed or memory held unnecessarily.

Internally, a lazy-evaluated min-heap tracks expiration deadlines. The heap is only fully sorted when needed (e.g. during eviction), keeping insert costs low on average. A hash table stores cursors into the heap for O(1) key lookups. A running total enables O(1) capacity checks.

When the cache is full and eviction is needed, expired items are reclaimed first (in expiration order, cheapest deadline first). If no expired items exist, the item with the nearest upcoming expiration is evicted. Items with no TTL are the last resort and are evicted only when all expiring items have been exhausted.

get insert delete(i) popitem
Worse-case O(1)~ O(1)~ O(min(i, n-i)) O(1)~
Pros
  • Per-item TTL control: each entry can have a different lifetime.
  • Expired items are reclaimed before live items, maximising useful capacity.
  • Lazy expiry avoids background threads and timer overhead by default.
  • Optional background sweeping bounds stale-data visibility and memory retention when lazy eviction is insufficient.
  • Insert, lookup, and evict are O(1) amortized (O(log n) worst-case during heap rebalancing).
  • TTL-free items coexist naturally alongside expiring ones.
Cons
  • Without sweeping, stale items may linger in memory until the next access or eviction pressure forces a cleanup.
  • With sweeping, a background thread is running for the lifetime of the cache, adding concurrency overhead and requiring thread-safe internal locking.
  • Slightly higher per-insert cost compared to pure LRU/LFU.
  • No guarantee on the exact eviction moment for expired items in lazy mode; callers that require strict TTL enforcement should validate timestamps on read, or configure a sufficiently short sweep_interval.

Use VTTLCache when different items have different natural lifetimes (e.g. session tokens, API responses with varying freshness requirements, or multi-tier data with mixed staleness tolerances). Set sweep_interval when bounded staleness or proactive memory reclamation is required.

Avoid it when all items share a uniform TTL (consider TTLCache instead), when strict and immediate expiry is a hard requirement, or when memory pressure from temporarily lingering stale entries is unacceptable and a background thread is not an option.

from cachebox import VTTLCache
import time

cache = VTTLCache(100, iterable={i:i for i in range(4)}, ttl=3)
print(len(cache)) # 4
time.sleep(3)
print(len(cache)) # 0

# The "key1" is exists for 5 seconds
cache.insert("key1", "value", ttl=5)
# The "key2" is exists for 2 seconds
cache.insert("key2", "value", ttl=2)

time.sleep(2)
# "key1" is exists for 3 seconds
print(cache.get("key1")) # value

# "key2" has expired
print(cache.get("key2")) # None

Initializes a new TTLCache instance.

Parameters:

  • maxsize

    (int) –

    Maximum number of elements the cache can hold. If zero, the limit is set to sys.maxsize internally.

  • iterable

    (Optional[_IterableType[KT, VT]], default: None ) –

    Initial data to populate the cache.

  • ttl

    (float | timedelta | datetime | None, default: None ) –

    Time-to-live duration for iterable items. This is not a global ttl.

  • capacity

    (int, default: 0 ) –

    Pre-allocate cache capacity to minimize reallocations. Defaults to 0.

  • getsizeof

    (Callable[[KT, VT], int] | None, default: None ) –

    A callable that computes the size of a key-value pair. When None, each entry is assumed to have a size of 1 (equivalent to lambda k, v: 1). Use this to implement weighted caching — for example, sizing entries by memory footprint or byte length.

  • sweep_interval

    (float | timedelta | None, default: None ) –

    If set, starts a background thread that sweeps and removes all expired entries on this interval (in seconds or as a timedelta). When None, expiry is lazy. Defaults to None. Must be greater than or equal to 1.

Note

The cache can be pre-sized via capacity to reduce reallocations when the number of expected entries is known ahead of time.

Raises:

  • ValueError

    If sweep_interval is set to a value less than 1.

Source code in cachebox/_cachebox.py
def __init__(
    self,
    maxsize: int,
    iterable: typing.Optional["_IterableType[KT, VT]"] = None,
    ttl: float | timedelta | datetime | None = None,
    *,
    capacity: int = 0,
    getsizeof: typing.Callable[[KT, VT], int] | None = None,
    sweep_interval: float | timedelta | None = None,
) -> None:
    """
    Initializes a new TTLCache instance.

    Args:
        maxsize: Maximum number of elements the cache can hold. If zero,
            the limit is set to ``sys.maxsize`` internally.
        iterable: Initial data to populate the cache.
        ttl: Time-to-live duration for ``iterable`` items. This *is not* a global ttl.
        capacity: Pre-allocate cache capacity to minimize reallocations.
            Defaults to 0.
        getsizeof: A callable that computes the size of a key-value pair.
            When ``None``, each entry is assumed to have a size of 1
            (equivalent to ``lambda k, v: 1``). Use this to implement
            weighted caching — for example, sizing entries by memory
            footprint or byte length.
        sweep_interval: If set, starts a background thread that sweeps and
            removes all expired entries on this interval (in seconds or as
            a ``timedelta``). When ``None``, expiry is lazy. Defaults to
            ``None``. Must be greater than or equal to 1.

    Note:
        The cache can be pre-sized via ``capacity`` to reduce
        reallocations when the number of expected entries is known
        ahead of time.

    Raises:
        ValueError: If ``sweep_interval`` is set to a value less than 1.
    """
    super().__init__(
        maxsize,
        iterable,
        ttl,
        capacity=capacity,
        getsizeof=getsizeof,
    )

    self._thread: threading.Thread | None = None
    self._thread_is_running: bool = False

    if sweep_interval is not None:
        if isinstance(sweep_interval, timedelta):
            sweep_interval = sweep_interval.total_seconds()

        if sweep_interval < 1:
            raise ValueError("sweep_interval must be more than 1 seconds.")

        self._thread_is_running = True
        self._thread = threading.Thread(
            target=self._sweeper_thread,
            args=(sweep_interval,),
            daemon=True,
        )
        self._thread.start()

    self._sweep_interval = sweep_interval

sweep_interval: float | None property

The configured sweep_interval in seconds.

stop_sweeper() -> None

Signals the background sweeper thread to stop, if one is active.

Source code in cachebox/_cachebox.py
def stop_sweeper(self) -> None:
    """Signals the background sweeper thread to stop, if one is active."""
    self._thread_is_running = False

insert(key: KT, value: VT, ttl: float | timedelta | datetime | None = None) -> typing.Optional[VT]

Insert a key-value pair into the cache with an optional time-to-live (TTL). Returns the previous value associated with the key, if it existed.

Parameters:

  • key

    (KT) –

    The key to insert or update.

  • value

    (VT) –

    The value to associate with key.

  • ttl

    (float | timedelta | datetime | None, default: None ) –

    An optional time-to-live duration for the item.

Returns:

  • Optional[VT]

    None if the key was not previously present; the old value if

  • Optional[VT]

    the key already existed (the key itself is not updated).

Source code in cachebox/_core.pyi
def insert(
    self,
    key: KT,
    value: VT,
    ttl: float | timedelta | datetime | None = None,
) -> typing.Optional[VT]:
    """
    Insert a key-value pair into the cache with an optional time-to-live (TTL).
    Returns the previous value associated with the key, if it existed.

    Args:
        key: The key to insert or update.
        value: The value to associate with ``key``.
        ttl: An optional time-to-live duration for the item.

    Returns:
        ``None`` if the key was not previously present; the old value if
        the key already existed (the key itself is not updated).
    """
    ...

update(iterable: _IterableType[KT, VT], ttl: float | timedelta | datetime | None = None) -> None

Updates the cache with elements from a dictionary or iterable of key-value pairs.

Parameters:

  • iterable

    (_IterableType[KT, VT]) –

    A dictionary, object supporting items(), another cache instance, or an iterable of (key, value) tuples.

  • ttl

    (float | timedelta | datetime | None, default: None ) –

    An optional time-to-live duration for items.

Source code in cachebox/_core.pyi
def update(
    self,
    iterable: _IterableType[KT, VT],
    ttl: float | timedelta | datetime | None = None,
) -> None:
    """
    Updates the cache with elements from a dictionary or iterable of key-value pairs.

    Args:
        iterable: A dictionary, object supporting ``items()``, another
            cache instance, or an iterable of ``(key, value)`` tuples.
        ttl: An optional time-to-live duration for items.
    """
    ...

setdefault(key: KT, default: typing.Optional[DT] = None, ttl: float | timedelta | datetime | None = None) -> typing.Optional[VT | DT]

Inserts key with default as its value if the key is absent.

Parameters:

  • key

    (KT) –

    The key to look up or insert.

  • default

    (Optional[DT], default: None ) –

    The value to insert if key is not in the cache. Defaults to None.

  • ttl

    (float | timedelta | datetime | None, default: None ) –

    An optional time-to-live duration for items.

Returns:

  • Optional[VT | DT]

    The existing value if key is present, otherwise default.

Source code in cachebox/_core.pyi
def setdefault(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
    ttl: float | timedelta | datetime | None = None,
) -> typing.Optional[VT | DT]:
    """
    Inserts ``key`` with ``default`` as its value if the key is absent.

    Args:
        key: The key to look up or insert.
        default: The value to insert if ``key`` is not in the cache.
            Defaults to ``None``.
        ttl: An optional time-to-live duration for items.

    Returns:
        The existing value if ``key`` is present, otherwise ``default``.
    """
    ...

popitem() -> typing.Tuple[KT, VT]

Removes and returns the key-value pair that is closest to expiration.

Returns:

  • Tuple[KT, VT]

    A tuple containing the key and value of the removed item.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem(self) -> typing.Tuple[KT, VT]:
    """
    Removes and returns the key-value pair that is closest to expiration.

    Returns:
        A tuple containing the key and value of the removed item.

    Raises:
        KeyError: If the cache is empty.
    """

items() -> typing.Iterable[typing.Tuple[KT, VT]]

Returns an ordered iterable of the cache's (key, value) pairs.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT]]

    An iterable of (key, value) tuples in insertion order.

Source code in cachebox/_core.pyi
def items(self) -> typing.Iterable[typing.Tuple[KT, VT]]:
    """
    Returns an ordered iterable of the cache's ``(key, value)`` pairs.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value)`` tuples in insertion order.
    """
    ...

values() -> typing.Iterable[VT]

Returns an ordered iterable of the cache's values.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[VT]

    An iterable of values in insertion order.

Source code in cachebox/_core.pyi
def values(self) -> typing.Iterable[VT]:
    """
    Returns an ordered iterable of the cache's values.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of values in insertion order.
    """
    ...

keys() -> typing.Iterable[KT]

Returns an ordered iterable of the cache's keys.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[KT]

    An iterable of keys in insertion order.

Source code in cachebox/_core.pyi
def keys(self) -> typing.Iterable[KT]:
    """
    Returns an ordered iterable of the cache's keys.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of keys in insertion order.
    """
    ...

expire(*, reuse: bool = False) -> None

Manually removes all expired key-value pairs from the cache.

Parameters:

  • reuse

    (bool, default: False ) –

    If True, retains the allocated memory for future reuse rather than freeing it. Defaults to False.

Source code in cachebox/_core.pyi
def expire(self, *, reuse: bool = False) -> None:
    """
    Manually removes all expired key-value pairs from the cache.

    Args:
        reuse: If ``True``, retains the allocated memory for future reuse
            rather than freeing it. Defaults to ``False``.
    """
    ...

get_with_expire(key: KT, default: typing.Optional[DT] = None) -> typing.Tuple[typing.Union[VT, DT], float | None]

Retrieves a value along with its remaining TTL.

Parameters:

  • key

    (KT) –

    The key to look up.

  • default

    (Optional[DT], default: None ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    A tuple of (value, remaining_ttl) where remaining_ttl is

  • float | None

    the expiration duration in seconds, or 0.0 if the key was not

  • Tuple[Union[VT, DT], float | None]

    found.

Source code in cachebox/_core.pyi
def get_with_expire(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Tuple[typing.Union[VT, DT], float | None]:
    """
    Retrieves a value along with its remaining TTL.

    Args:
        key: The key to look up.
        default: Value to return if the key is not found.

    Returns:
        A tuple of ``(value, remaining_ttl)`` where ``remaining_ttl`` is
        the expiration duration in seconds, or ``0.0`` if the key was not
        found.
    """
    ...

pop_with_expire(key: KT, default: typing.Optional[DT] = None) -> typing.Tuple[typing.Union[VT, DT], float | None]

Removes a key and returns its value along with its remaining TTL.

Parameters:

  • key

    (KT) –

    The key to remove.

  • default

    (Optional[DT], default: None ) –

    Value to return if the key is not found.

Returns:

  • Union[VT, DT]

    A tuple of (value, remaining_ttl) where remaining_ttl is

  • float | None

    the expiration duration in seconds, or 0.0 if the key was not

  • Tuple[Union[VT, DT], float | None]

    found.

Source code in cachebox/_core.pyi
def pop_with_expire(
    self,
    key: KT,
    default: typing.Optional[DT] = None,
) -> typing.Tuple[typing.Union[VT, DT], float | None]:
    """
    Removes a key and returns its value along with its remaining TTL.

    Args:
        key: The key to remove.
        default: Value to return if the key is not found.

    Returns:
        A tuple of ``(value, remaining_ttl)`` where ``remaining_ttl`` is
        the expiration duration in seconds, or ``0.0`` if the key was not
        found.
    """
    ...

popitem_with_expire() -> typing.Tuple[VT, DT, float | None]

Removes and returns the oldest item along with its remaining TTL.

Returns:

  • VT

    A tuple of (key, value, remaining_ttl) where remaining_ttl

  • DT

    is the expiration duration in seconds.

Raises:

  • KeyError

    If the cache is empty.

Source code in cachebox/_core.pyi
def popitem_with_expire(self) -> typing.Tuple[VT, DT, float | None]:
    """
    Removes and returns the oldest item along with its remaining TTL.

    Returns:
        A tuple of ``(key, value, remaining_ttl)`` where ``remaining_ttl``
        is the expiration duration in seconds.

    Raises:
        KeyError: If the cache is empty.
    """
    ...

items_with_expire() -> typing.Iterable[typing.Tuple[KT, VT, float | None]]

Returns an ordered iterable of items with their remaining TTL.

Warning

Do not modify the cache while iterating.

Returns:

  • Iterable[Tuple[KT, VT, float | None]]

    An iterable of (key, value, remaining_ttl) tuples in insertion

  • Iterable[Tuple[KT, VT, float | None]]

    order, where remaining_ttl is in seconds.

Source code in cachebox/_core.pyi
def items_with_expire(self) -> typing.Iterable[typing.Tuple[KT, VT, float | None]]:
    """
    Returns an ordered iterable of items with their remaining TTL.

    Warning:
        Do not modify the cache while iterating.

    Returns:
        An iterable of ``(key, value, remaining_ttl)`` tuples in insertion
        order, where ``remaining_ttl`` is in seconds.
    """
    ...