A Python descriptor that caches property values per context variable, providing isolated caches for concurrent contexts like asyncio tasks.
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.
pip install contextually-cached-propertyRequires Python 3.14+.
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())Delete the attribute to clear the cached value for the current context:
del instance.cached_property_nameThis project uses Poetry for dependency management.
# Install dependencies
poetry install
# Run tests
pytest
# Run linting
ruff check
# Run type checking
mypy .See LICENSE for details.