Middleware for Starlette that allows you to store and access the context data of a request.
Core functionality for accessing and managing request-scoped context data. The context object provides a global dictionary-like interface that automatically manages request isolation using Python's contextvars.
The main interface for accessing request-scoped data throughout your application.
context: _ContextThe global context object behaves like a dictionary and is available anywhere in your request handling code:
from starlette_context import context
# Access like a dictionary
value = context["key"]
value = context.get("key", default_value)
# Store data
context["user_id"] = "12345"
context.update({"session": "abc", "role": "admin"})
# Check existence
if "user_id" in context:
print("User ID exists")
# Get all data
all_data = context.dataManual context creation and management for testing or custom scenarios.
def request_cycle_context(initial_data: Optional[dict] = None) -> Iterator[None]:
"""
Creates and resets a starlette-context context.
Used in the Context and Raw middlewares, but can also be used to create a
context out of a proper request cycle, such as in unit tests.
Parameters:
- initial_data: Optional dict of initial context data
Returns:
Context manager that creates isolated context scope
"""Usage example:
from starlette_context import request_cycle_context, context
# Create context for testing
with request_cycle_context({"user_id": "123", "role": "admin"}):
# Context is available here
user_id = context["user_id"]
context["additional_data"] = "value"
# Do work that requires context
process_user_request()
# Context is automatically cleaned upThe context object extends Python's UserDict and provides all standard dictionary methods plus additional context-specific functionality.
class _Context(UserDict):
@property
def data(self) -> dict:
"""
Dump this to json. Object itself is not serializable.
Returns:
dict: Current context data
Raises:
ContextDoesNotExistError: If accessed outside request cycle
"""
def exists(self) -> bool:
"""
Check if context exists in current execution scope.
Returns:
bool: True if context is available, False otherwise
"""
def copy(self) -> dict:
"""
Read only context data.
Returns:
dict: Copy of current context data
"""Standard dictionary methods available:
# Access methods
value = context["key"]
value = context.get("key", default)
keys = context.keys()
values = context.values()
items = context.items()
# Modification methods
context["key"] = "value"
context.update({"key1": "value1", "key2": "value2"})
context.setdefault("key", "default_value")
del context["key"]
value = context.pop("key", default)
key, value = context.popitem()
context.clear()
# Info methods
length = len(context)
exists = "key" in context
for key in context:
print(key, context[key])from starlette_context import context
async def my_handler(request):
# Access data stored by middleware plugins
request_id = context.get("X-Request-ID")
correlation_id = context["X-Correlation-ID"]
# Store custom data
context["user_id"] = extract_user_id(request)
context["processing_start"] = time.time()
# Use context data in logging
logger.info("Processing request", extra=context.data)
return responseimport pytest
from starlette_context import request_cycle_context, context
def test_my_function():
test_data = {
"X-Request-ID": "test-123",
"user_id": "user-456"
}
with request_cycle_context(test_data):
result = my_function_that_uses_context()
assert result is not None
# Verify context was used
assert context["X-Request-ID"] == "test-123"from starlette_context import context
def safe_context_access():
if context.exists():
user_id = context.get("user_id")
if user_id:
return f"User: {user_id}"
return "No context available"class ContextDoesNotExistError(RuntimeError, StarletteContextError):
"""
Raised when context is accessed outside of a request-response cycle.
This occurs when:
- Context is accessed before middleware has created it
- Context is accessed after request processing is complete
- Context is accessed in code not running within a request context
"""Common scenarios that raise ContextDoesNotExistError:
from starlette_context import context, ContextDoesNotExistError
# This will raise an error - no middleware context
try:
value = context["key"]
except ContextDoesNotExistError:
print("Context not available outside request cycle")
# Safe access
if context.exists():
value = context.get("key")Install with Tessl CLI
npx tessl i tessl/pypi-starlette-context