Skip to content

quentinboudinel/contextually-cached-property

Repository files navigation

contextually-cached-property

A Python descriptor that caches property values per context variable, providing isolated caches for concurrent contexts like asyncio tasks.

Why?

Python's built-in functools.cached_property uses a single cache shared across all contexts. This can cause issues in concurrent applications where different tasks or threads need independent cached values.

contextually_cached_property solves this by using contextvars.ContextVar to maintain separate caches per context, while also using weak references to allow proper garbage collection of instances.

Installation

pip install contextually-cached-property

Requires Python 3.14+.

Usage

from contextually_cached_property import contextually_cached_property


class ExpensiveResource:
    @contextually_cached_property
    def connection(self) -> Connection:
        return create_connection()

The cached value is computed once per context per instance. Different asyncio tasks will each get their own cached value:

import asyncio


class TaskLocalData:
    @contextually_cached_property
    def request_id(self) -> str:
        return generate_unique_id()


data = TaskLocalData()


async def task_a():
    print(data.request_id)  # e.g., "abc123"


async def task_b():
    print(data.request_id)  # e.g., "xyz789" (different from task_a)


async def main():
    await asyncio.gather(task_a(), task_b())

Invalidating the cache

Delete the attribute to clear the cached value for the current context:

del instance.cached_property_name

Development

This project uses Poetry for dependency management.

# Install dependencies
poetry install

# Run tests
pytest

# Run linting
ruff check

# Run type checking
mypy .

License

See LICENSE for details.

About

A python lib implementing a cached property decorator with context-aware isolation

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages