0
# Context Management
1
2
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.
3
4
## Capabilities
5
6
### Global Context Object
7
8
The main interface for accessing request-scoped data throughout your application.
9
10
```python { .api }
11
context: _Context
12
```
13
14
The global `context` object behaves like a dictionary and is available anywhere in your request handling code:
15
16
```python
17
from starlette_context import context
18
19
# Access like a dictionary
20
value = context["key"]
21
value = context.get("key", default_value)
22
23
# Store data
24
context["user_id"] = "12345"
25
context.update({"session": "abc", "role": "admin"})
26
27
# Check existence
28
if "user_id" in context:
29
print("User ID exists")
30
31
# Get all data
32
all_data = context.data
33
```
34
35
### Context Lifecycle Management
36
37
Manual context creation and management for testing or custom scenarios.
38
39
```python { .api }
40
def request_cycle_context(initial_data: Optional[dict] = None) -> Iterator[None]:
41
"""
42
Creates and resets a starlette-context context.
43
44
Used in the Context and Raw middlewares, but can also be used to create a
45
context out of a proper request cycle, such as in unit tests.
46
47
Parameters:
48
- initial_data: Optional dict of initial context data
49
50
Returns:
51
Context manager that creates isolated context scope
52
"""
53
```
54
55
Usage example:
56
57
```python
58
from starlette_context import request_cycle_context, context
59
60
# Create context for testing
61
with request_cycle_context({"user_id": "123", "role": "admin"}):
62
# Context is available here
63
user_id = context["user_id"]
64
context["additional_data"] = "value"
65
66
# Do work that requires context
67
process_user_request()
68
69
# Context is automatically cleaned up
70
```
71
72
### Context Object Methods
73
74
The context object extends Python's UserDict and provides all standard dictionary methods plus additional context-specific functionality.
75
76
```python { .api }
77
class _Context(UserDict):
78
@property
79
def data(self) -> dict:
80
"""
81
Dump this to json. Object itself is not serializable.
82
83
Returns:
84
dict: Current context data
85
86
Raises:
87
ContextDoesNotExistError: If accessed outside request cycle
88
"""
89
90
def exists(self) -> bool:
91
"""
92
Check if context exists in current execution scope.
93
94
Returns:
95
bool: True if context is available, False otherwise
96
"""
97
98
def copy(self) -> dict:
99
"""
100
Read only context data.
101
102
Returns:
103
dict: Copy of current context data
104
"""
105
```
106
107
Standard dictionary methods available:
108
109
```python
110
# Access methods
111
value = context["key"]
112
value = context.get("key", default)
113
keys = context.keys()
114
values = context.values()
115
items = context.items()
116
117
# Modification methods
118
context["key"] = "value"
119
context.update({"key1": "value1", "key2": "value2"})
120
context.setdefault("key", "default_value")
121
del context["key"]
122
value = context.pop("key", default)
123
key, value = context.popitem()
124
context.clear()
125
126
# Info methods
127
length = len(context)
128
exists = "key" in context
129
for key in context:
130
print(key, context[key])
131
```
132
133
## Usage Examples
134
135
### Basic Context Access
136
137
```python
138
from starlette_context import context
139
140
async def my_handler(request):
141
# Access data stored by middleware plugins
142
request_id = context.get("X-Request-ID")
143
correlation_id = context["X-Correlation-ID"]
144
145
# Store custom data
146
context["user_id"] = extract_user_id(request)
147
context["processing_start"] = time.time()
148
149
# Use context data in logging
150
logger.info("Processing request", extra=context.data)
151
152
return response
153
```
154
155
### Testing with Manual Context
156
157
```python
158
import pytest
159
from starlette_context import request_cycle_context, context
160
161
def test_my_function():
162
test_data = {
163
"X-Request-ID": "test-123",
164
"user_id": "user-456"
165
}
166
167
with request_cycle_context(test_data):
168
result = my_function_that_uses_context()
169
assert result is not None
170
171
# Verify context was used
172
assert context["X-Request-ID"] == "test-123"
173
```
174
175
### Context Existence Checking
176
177
```python
178
from starlette_context import context
179
180
def safe_context_access():
181
if context.exists():
182
user_id = context.get("user_id")
183
if user_id:
184
return f"User: {user_id}"
185
return "No context available"
186
```
187
188
## Error Handling
189
190
```python { .api }
191
class ContextDoesNotExistError(RuntimeError, StarletteContextError):
192
"""
193
Raised when context is accessed outside of a request-response cycle.
194
195
This occurs when:
196
- Context is accessed before middleware has created it
197
- Context is accessed after request processing is complete
198
- Context is accessed in code not running within a request context
199
"""
200
```
201
202
Common scenarios that raise `ContextDoesNotExistError`:
203
204
```python
205
from starlette_context import context, ContextDoesNotExistError
206
207
# This will raise an error - no middleware context
208
try:
209
value = context["key"]
210
except ContextDoesNotExistError:
211
print("Context not available outside request cycle")
212
213
# Safe access
214
if context.exists():
215
value = context.get("key")
216
```