haiway 0.24.3__py3-none-any.whl → 0.25.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- haiway/__init__.py +4 -1
- haiway/context/__init__.py +4 -0
- haiway/context/access.py +312 -70
- haiway/context/disposables.py +5 -119
- haiway/context/identifier.py +19 -44
- haiway/context/observability.py +22 -142
- haiway/context/presets.py +337 -0
- haiway/context/state.py +38 -84
- haiway/context/tasks.py +7 -10
- haiway/helpers/observability.py +4 -6
- haiway/opentelemetry/observability.py +5 -5
- haiway/state/__init__.py +2 -0
- haiway/state/immutable.py +127 -0
- haiway/state/structure.py +63 -117
- haiway/state/validation.py +95 -60
- {haiway-0.24.3.dist-info → haiway-0.25.1.dist-info}/METADATA +1 -1
- {haiway-0.24.3.dist-info → haiway-0.25.1.dist-info}/RECORD +19 -17
- {haiway-0.24.3.dist-info → haiway-0.25.1.dist-info}/WHEEL +0 -0
- {haiway-0.24.3.dist-info → haiway-0.25.1.dist-info}/licenses/LICENSE +0 -0
haiway/context/disposables.py
CHANGED
@@ -2,19 +2,15 @@ from asyncio import (
|
|
2
2
|
AbstractEventLoop,
|
3
3
|
gather,
|
4
4
|
get_running_loop,
|
5
|
-
iscoroutinefunction,
|
6
5
|
run_coroutine_threadsafe,
|
7
6
|
wrap_future,
|
8
7
|
)
|
9
|
-
from collections.abc import
|
8
|
+
from collections.abc import Collection, Iterable
|
10
9
|
from contextlib import AbstractAsyncContextManager
|
11
10
|
from itertools import chain
|
12
11
|
from types import TracebackType
|
13
|
-
from typing import Any, final
|
14
12
|
|
15
|
-
from haiway.
|
16
|
-
from haiway.state import State
|
17
|
-
from haiway.utils.mimic import mimic_function
|
13
|
+
from haiway.state import Immutable, State
|
18
14
|
|
19
15
|
__all__ = (
|
20
16
|
"Disposable",
|
@@ -57,8 +53,7 @@ Creating a disposable database connection:
|
|
57
53
|
"""
|
58
54
|
|
59
55
|
|
60
|
-
|
61
|
-
class Disposables:
|
56
|
+
class Disposables(Immutable):
|
62
57
|
"""
|
63
58
|
A container for multiple Disposable resources that manages their lifecycle.
|
64
59
|
|
@@ -112,11 +107,8 @@ class Disposables:
|
|
112
107
|
... # All resources cleaned up automatically
|
113
108
|
"""
|
114
109
|
|
115
|
-
|
116
|
-
|
117
|
-
"_loop",
|
118
|
-
"_state_context",
|
119
|
-
)
|
110
|
+
_disposables: Collection[Disposable]
|
111
|
+
_loop: AbstractEventLoop | None
|
120
112
|
|
121
113
|
def __init__(
|
122
114
|
self,
|
@@ -130,44 +122,17 @@ class Disposables:
|
|
130
122
|
*disposables: Disposable
|
131
123
|
Variable number of disposable resources to be managed together.
|
132
124
|
"""
|
133
|
-
self._disposables: tuple[Disposable, ...]
|
134
125
|
object.__setattr__(
|
135
126
|
self,
|
136
127
|
"_disposables",
|
137
128
|
disposables,
|
138
129
|
)
|
139
|
-
self._state_context: StateContext | None
|
140
|
-
object.__setattr__(
|
141
|
-
self,
|
142
|
-
"_state_context",
|
143
|
-
None,
|
144
|
-
)
|
145
|
-
self._loop: AbstractEventLoop | None
|
146
130
|
object.__setattr__(
|
147
131
|
self,
|
148
132
|
"_loop",
|
149
133
|
None,
|
150
134
|
)
|
151
135
|
|
152
|
-
def __setattr__(
|
153
|
-
self,
|
154
|
-
name: str,
|
155
|
-
value: Any,
|
156
|
-
) -> Any:
|
157
|
-
raise AttributeError(
|
158
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
159
|
-
f" attribute - '{name}' cannot be modified"
|
160
|
-
)
|
161
|
-
|
162
|
-
def __delattr__(
|
163
|
-
self,
|
164
|
-
name: str,
|
165
|
-
) -> None:
|
166
|
-
raise AttributeError(
|
167
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
168
|
-
f" attribute - '{name}' cannot be deleted"
|
169
|
-
)
|
170
|
-
|
171
136
|
def __bool__(self) -> bool:
|
172
137
|
"""
|
173
138
|
Check if this container has any disposables.
|
@@ -215,23 +180,6 @@ class Disposables:
|
|
215
180
|
)
|
216
181
|
)
|
217
182
|
|
218
|
-
async def __aenter__(self) -> None:
|
219
|
-
"""
|
220
|
-
Enter all contained disposables asynchronously.
|
221
|
-
|
222
|
-
Enters all disposables in parallel and collects any State objects they return updating
|
223
|
-
current state context.
|
224
|
-
"""
|
225
|
-
|
226
|
-
assert self._state_context is None, "Context reentrance is not allowed" # nosec: B101
|
227
|
-
state_context = StateContext.updated(await self.prepare())
|
228
|
-
state_context.__enter__()
|
229
|
-
object.__setattr__(
|
230
|
-
self,
|
231
|
-
"_state_context",
|
232
|
-
state_context,
|
233
|
-
)
|
234
|
-
|
235
183
|
async def _cleanup(
|
236
184
|
self,
|
237
185
|
/,
|
@@ -320,65 +268,3 @@ class Disposables:
|
|
320
268
|
|
321
269
|
case _:
|
322
270
|
raise BaseExceptionGroup("Disposables cleanup errors", exceptions)
|
323
|
-
|
324
|
-
async def __aexit__(
|
325
|
-
self,
|
326
|
-
exc_type: type[BaseException] | None,
|
327
|
-
exc_val: BaseException | None,
|
328
|
-
exc_tb: TracebackType | None,
|
329
|
-
) -> None:
|
330
|
-
"""
|
331
|
-
Exit all contained disposables asynchronously.
|
332
|
-
|
333
|
-
Properly disposes of all resources by calling their __aexit__ methods in parallel.
|
334
|
-
If multiple disposables raise exceptions, they are collected into a BaseExceptionGroup.
|
335
|
-
Additionally, produced state context will be also exited resetting state to previous.
|
336
|
-
|
337
|
-
Parameters
|
338
|
-
----------
|
339
|
-
exc_type: type[BaseException] | None
|
340
|
-
The type of exception that caused the context to be exited
|
341
|
-
exc_val: BaseException | None
|
342
|
-
The exception that caused the context to be exited
|
343
|
-
exc_tb: TracebackType | None
|
344
|
-
The traceback for the exception that caused the context to be exited
|
345
|
-
|
346
|
-
Raises
|
347
|
-
------
|
348
|
-
BaseExceptionGroup
|
349
|
-
If multiple disposables raise exceptions during exit
|
350
|
-
"""
|
351
|
-
assert self._state_context is not None, "Unbalanced context enter/exit" # nosec: B101
|
352
|
-
try:
|
353
|
-
self._state_context.__exit__(
|
354
|
-
exc_type,
|
355
|
-
exc_val,
|
356
|
-
exc_tb,
|
357
|
-
)
|
358
|
-
object.__setattr__(
|
359
|
-
self,
|
360
|
-
"_state_context",
|
361
|
-
None,
|
362
|
-
)
|
363
|
-
|
364
|
-
finally:
|
365
|
-
await self.dispose(
|
366
|
-
exc_type,
|
367
|
-
exc_val,
|
368
|
-
exc_tb,
|
369
|
-
)
|
370
|
-
|
371
|
-
def __call__[Result, **Arguments](
|
372
|
-
self,
|
373
|
-
function: Callable[Arguments, Coroutine[Any, Any, Result]],
|
374
|
-
) -> Callable[Arguments, Coroutine[Any, Any, Result]]:
|
375
|
-
assert iscoroutinefunction(function) # nosec: B101
|
376
|
-
|
377
|
-
async def async_context(
|
378
|
-
*args: Arguments.args,
|
379
|
-
**kwargs: Arguments.kwargs,
|
380
|
-
) -> Result:
|
381
|
-
async with self:
|
382
|
-
return await function(*args, **kwargs)
|
383
|
-
|
384
|
-
return mimic_function(function, within=async_context)
|
haiway/context/identifier.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
from contextvars import ContextVar, Token
|
2
2
|
from types import TracebackType
|
3
|
-
from typing import Any,
|
3
|
+
from typing import Any, ClassVar, Self
|
4
4
|
from uuid import UUID, uuid4
|
5
5
|
|
6
|
+
from haiway.state import Immutable
|
7
|
+
|
6
8
|
__all__ = ("ScopeIdentifier",)
|
7
9
|
|
8
10
|
|
9
|
-
|
10
|
-
class ScopeIdentifier:
|
11
|
+
class ScopeIdentifier(Immutable):
|
11
12
|
"""
|
12
13
|
Identifies and manages scope context identities.
|
13
14
|
|
@@ -18,7 +19,7 @@ class ScopeIdentifier:
|
|
18
19
|
This class is immutable after instantiation.
|
19
20
|
"""
|
20
21
|
|
21
|
-
_context = ContextVar[Self]("ScopeIdentifier")
|
22
|
+
_context: ClassVar[ContextVar[Self]] = ContextVar[Self]("ScopeIdentifier")
|
22
23
|
|
23
24
|
@classmethod
|
24
25
|
def current(
|
@@ -30,7 +31,7 @@ class ScopeIdentifier:
|
|
30
31
|
@classmethod
|
31
32
|
def scope(
|
32
33
|
cls,
|
33
|
-
|
34
|
+
name: str,
|
34
35
|
/,
|
35
36
|
) -> Self:
|
36
37
|
"""
|
@@ -41,7 +42,7 @@ class ScopeIdentifier:
|
|
41
42
|
|
42
43
|
Parameters
|
43
44
|
----------
|
44
|
-
|
45
|
+
name: str
|
45
46
|
The name of the scope
|
46
47
|
|
47
48
|
Returns
|
@@ -58,82 +59,56 @@ class ScopeIdentifier:
|
|
58
59
|
|
59
60
|
scope_id: UUID = uuid4()
|
60
61
|
return cls(
|
61
|
-
|
62
|
+
name=name,
|
62
63
|
scope_id=scope_id,
|
63
64
|
parent_id=scope_id, # own id is parent_id for root
|
64
65
|
)
|
65
66
|
|
66
67
|
# create nested scope otherwise
|
67
68
|
return cls(
|
68
|
-
|
69
|
+
name=name,
|
69
70
|
scope_id=uuid4(),
|
70
71
|
parent_id=current.scope_id,
|
71
72
|
)
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
"unique_name",
|
79
|
-
)
|
74
|
+
parent_id: UUID
|
75
|
+
scope_id: UUID
|
76
|
+
name: str
|
77
|
+
unique_name: str
|
78
|
+
_token: Token[Self] | None = None
|
80
79
|
|
81
80
|
def __init__(
|
82
81
|
self,
|
83
82
|
parent_id: UUID,
|
84
83
|
scope_id: UUID,
|
85
|
-
|
84
|
+
name: str,
|
86
85
|
) -> None:
|
87
|
-
self.parent_id: UUID
|
88
86
|
object.__setattr__(
|
89
87
|
self,
|
90
88
|
"parent_id",
|
91
89
|
parent_id,
|
92
90
|
)
|
93
|
-
self.scope_id: UUID
|
94
91
|
object.__setattr__(
|
95
92
|
self,
|
96
93
|
"scope_id",
|
97
94
|
scope_id,
|
98
95
|
)
|
99
|
-
self.label: str
|
100
96
|
object.__setattr__(
|
101
97
|
self,
|
102
|
-
"
|
103
|
-
|
98
|
+
"name",
|
99
|
+
name,
|
104
100
|
)
|
105
|
-
self.unique_name: str
|
106
101
|
object.__setattr__(
|
107
102
|
self,
|
108
103
|
"unique_name",
|
109
|
-
f"[{
|
104
|
+
f"[{name}] [{scope_id}]",
|
110
105
|
)
|
111
|
-
self._token: Token[ScopeIdentifier] | None
|
112
106
|
object.__setattr__(
|
113
107
|
self,
|
114
108
|
"_token",
|
115
109
|
None,
|
116
110
|
)
|
117
111
|
|
118
|
-
def __setattr__(
|
119
|
-
self,
|
120
|
-
name: str,
|
121
|
-
value: Any,
|
122
|
-
) -> Any:
|
123
|
-
raise AttributeError(
|
124
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
125
|
-
f" attribute - '{name}' cannot be modified"
|
126
|
-
)
|
127
|
-
|
128
|
-
def __delattr__(
|
129
|
-
self,
|
130
|
-
name: str,
|
131
|
-
) -> None:
|
132
|
-
raise AttributeError(
|
133
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
134
|
-
f" attribute - '{name}' cannot be deleted"
|
135
|
-
)
|
136
|
-
|
137
112
|
@property
|
138
113
|
def is_root(self) -> bool:
|
139
114
|
"""
|
@@ -204,7 +179,7 @@ class ScopeIdentifier:
|
|
204
179
|
If this context is not active
|
205
180
|
"""
|
206
181
|
assert self._token is not None, "Unbalanced context enter/exit" # nosec: B101
|
207
|
-
ScopeIdentifier._context.reset(self._token)
|
182
|
+
ScopeIdentifier._context.reset(self._token) # pyright: ignore[reportArgumentType]
|
208
183
|
object.__setattr__(
|
209
184
|
self,
|
210
185
|
"_token",
|
haiway/context/observability.py
CHANGED
@@ -7,10 +7,11 @@ from logging import INFO as INFO_LOGGING
|
|
7
7
|
from logging import WARNING as WARNING_LOGGING
|
8
8
|
from logging import Logger, getLogger
|
9
9
|
from types import TracebackType
|
10
|
-
from typing import Any, Protocol, Self,
|
10
|
+
from typing import Any, ClassVar, Protocol, Self, runtime_checkable
|
11
11
|
from uuid import UUID, uuid4
|
12
12
|
|
13
13
|
from haiway.context.identifier import ScopeIdentifier
|
14
|
+
from haiway.state import Immutable
|
14
15
|
from haiway.types import Missing
|
15
16
|
from haiway.utils.formatting import format_str
|
16
17
|
|
@@ -190,7 +191,7 @@ class ObservabilityScopeExiting(Protocol):
|
|
190
191
|
) -> None: ...
|
191
192
|
|
192
193
|
|
193
|
-
class Observability: # avoiding State inheritance to prevent propagation as scope state
|
194
|
+
class Observability(Immutable): # avoiding State inheritance to prevent propagation as scope state
|
194
195
|
"""
|
195
196
|
Container for observability recording functions.
|
196
197
|
|
@@ -201,107 +202,13 @@ class Observability: # avoiding State inheritance to prevent propagation as sco
|
|
201
202
|
This class is immutable after initialization.
|
202
203
|
"""
|
203
204
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
"trace_identifying",
|
212
|
-
)
|
213
|
-
|
214
|
-
def __init__(
|
215
|
-
self,
|
216
|
-
trace_identifying: ObservabilityTraceIdentifying,
|
217
|
-
log_recording: ObservabilityLogRecording,
|
218
|
-
metric_recording: ObservabilityMetricRecording,
|
219
|
-
event_recording: ObservabilityEventRecording,
|
220
|
-
attributes_recording: ObservabilityAttributesRecording,
|
221
|
-
scope_entering: ObservabilityScopeEntering,
|
222
|
-
scope_exiting: ObservabilityScopeExiting,
|
223
|
-
) -> None:
|
224
|
-
"""
|
225
|
-
Initialize an Observability container with recording functions.
|
226
|
-
|
227
|
-
Parameters
|
228
|
-
----------
|
229
|
-
trace_identifying: ObservabilityTraceIdentifying
|
230
|
-
Function for identifying traces
|
231
|
-
log_recording: ObservabilityLogRecording
|
232
|
-
Function for recording log messages
|
233
|
-
metric_recording: ObservabilityMetricRecording
|
234
|
-
Function for recording metrics
|
235
|
-
event_recording: ObservabilityEventRecording
|
236
|
-
Function for recording events
|
237
|
-
attributes_recording: ObservabilityAttributesRecording
|
238
|
-
Function for recording attributes
|
239
|
-
scope_entering: ObservabilityScopeEntering
|
240
|
-
Function called when a scope is entered
|
241
|
-
scope_exiting: ObservabilityScopeExiting
|
242
|
-
Function called when a scope is exited
|
243
|
-
"""
|
244
|
-
self.trace_identifying: ObservabilityTraceIdentifying
|
245
|
-
object.__setattr__(
|
246
|
-
self,
|
247
|
-
"trace_identifying",
|
248
|
-
trace_identifying,
|
249
|
-
)
|
250
|
-
self.log_recording: ObservabilityLogRecording
|
251
|
-
object.__setattr__(
|
252
|
-
self,
|
253
|
-
"log_recording",
|
254
|
-
log_recording,
|
255
|
-
)
|
256
|
-
self.metric_recording: ObservabilityMetricRecording
|
257
|
-
object.__setattr__(
|
258
|
-
self,
|
259
|
-
"metric_recording",
|
260
|
-
metric_recording,
|
261
|
-
)
|
262
|
-
self.event_recording: ObservabilityEventRecording
|
263
|
-
object.__setattr__(
|
264
|
-
self,
|
265
|
-
"event_recording",
|
266
|
-
event_recording,
|
267
|
-
)
|
268
|
-
self.attributes_recording: ObservabilityAttributesRecording
|
269
|
-
object.__setattr__(
|
270
|
-
self,
|
271
|
-
"attributes_recording",
|
272
|
-
attributes_recording,
|
273
|
-
)
|
274
|
-
self.scope_entering: ObservabilityScopeEntering
|
275
|
-
object.__setattr__(
|
276
|
-
self,
|
277
|
-
"scope_entering",
|
278
|
-
scope_entering,
|
279
|
-
)
|
280
|
-
self.scope_exiting: ObservabilityScopeExiting
|
281
|
-
object.__setattr__(
|
282
|
-
self,
|
283
|
-
"scope_exiting",
|
284
|
-
scope_exiting,
|
285
|
-
)
|
286
|
-
|
287
|
-
def __setattr__(
|
288
|
-
self,
|
289
|
-
name: str,
|
290
|
-
value: Any,
|
291
|
-
) -> Any:
|
292
|
-
raise AttributeError(
|
293
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
294
|
-
f" attribute - '{name}' cannot be modified"
|
295
|
-
)
|
296
|
-
|
297
|
-
def __delattr__(
|
298
|
-
self,
|
299
|
-
name: str,
|
300
|
-
) -> None:
|
301
|
-
raise AttributeError(
|
302
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
303
|
-
f" attribute - '{name}' cannot be deleted"
|
304
|
-
)
|
205
|
+
trace_identifying: ObservabilityTraceIdentifying
|
206
|
+
log_recording: ObservabilityLogRecording
|
207
|
+
metric_recording: ObservabilityMetricRecording
|
208
|
+
event_recording: ObservabilityEventRecording
|
209
|
+
attributes_recording: ObservabilityAttributesRecording
|
210
|
+
scope_entering: ObservabilityScopeEntering
|
211
|
+
scope_exiting: ObservabilityScopeExiting
|
305
212
|
|
306
213
|
|
307
214
|
def _logger_observability(
|
@@ -408,7 +315,7 @@ def _logger_observability(
|
|
408
315
|
) -> None:
|
409
316
|
logger.log(
|
410
317
|
ObservabilityLevel.DEBUG,
|
411
|
-
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.
|
318
|
+
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.name}",
|
412
319
|
)
|
413
320
|
|
414
321
|
def scope_exiting(
|
@@ -419,7 +326,7 @@ def _logger_observability(
|
|
419
326
|
) -> None:
|
420
327
|
logger.log(
|
421
328
|
ObservabilityLevel.DEBUG,
|
422
|
-
f"{scope.unique_name} Exiting scope: {scope.
|
329
|
+
f"{scope.unique_name} Exiting scope: {scope.name}",
|
423
330
|
exc_info=exception,
|
424
331
|
)
|
425
332
|
|
@@ -434,8 +341,7 @@ def _logger_observability(
|
|
434
341
|
)
|
435
342
|
|
436
343
|
|
437
|
-
|
438
|
-
class ObservabilityContext:
|
344
|
+
class ObservabilityContext(Immutable):
|
439
345
|
"""
|
440
346
|
Context manager for observability within a scope.
|
441
347
|
|
@@ -446,7 +352,7 @@ class ObservabilityContext:
|
|
446
352
|
This class is immutable after initialization.
|
447
353
|
"""
|
448
354
|
|
449
|
-
_context = ContextVar[Self]("ObservabilityContext")
|
355
|
+
_context: ClassVar[ContextVar[Self]] = ContextVar[Self]("ObservabilityContext")
|
450
356
|
|
451
357
|
@classmethod
|
452
358
|
def scope(
|
@@ -486,7 +392,7 @@ class ObservabilityContext:
|
|
486
392
|
resolved_observability = observability
|
487
393
|
|
488
394
|
case None:
|
489
|
-
resolved_observability = _logger_observability(getLogger(scope.
|
395
|
+
resolved_observability = _logger_observability(getLogger(scope.name))
|
490
396
|
|
491
397
|
case Logger() as logger:
|
492
398
|
resolved_observability = _logger_observability(logger)
|
@@ -534,7 +440,7 @@ class ObservabilityContext:
|
|
534
440
|
Returns
|
535
441
|
-------
|
536
442
|
str
|
537
|
-
The
|
443
|
+
The string representation of the trace ID
|
538
444
|
|
539
445
|
Raises
|
540
446
|
------
|
@@ -542,12 +448,10 @@ class ObservabilityContext:
|
|
542
448
|
If called outside of any scope context
|
543
449
|
"""
|
544
450
|
try:
|
545
|
-
return (
|
546
|
-
cls._context.get()
|
547
|
-
.observability.trace_identifying(
|
451
|
+
return str(
|
452
|
+
cls._context.get().observability.trace_identifying(
|
548
453
|
scope_identifier if scope_identifier is not None else ScopeIdentifier.current()
|
549
454
|
)
|
550
|
-
.hex
|
551
455
|
)
|
552
456
|
|
553
457
|
except LookupError as exc:
|
@@ -728,55 +632,31 @@ class ObservabilityContext:
|
|
728
632
|
exception=exc,
|
729
633
|
)
|
730
634
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
"observability",
|
735
|
-
)
|
635
|
+
_scope: ScopeIdentifier
|
636
|
+
observability: Observability
|
637
|
+
_token: Token[Self] | None = None
|
736
638
|
|
737
639
|
def __init__(
|
738
640
|
self,
|
739
641
|
scope: ScopeIdentifier,
|
740
642
|
observability: Observability | None,
|
741
643
|
) -> None:
|
742
|
-
self._scope: ScopeIdentifier
|
743
644
|
object.__setattr__(
|
744
645
|
self,
|
745
646
|
"_scope",
|
746
647
|
scope,
|
747
648
|
)
|
748
|
-
self.observability: Observability
|
749
649
|
object.__setattr__(
|
750
650
|
self,
|
751
651
|
"observability",
|
752
652
|
observability,
|
753
653
|
)
|
754
|
-
self._token: Token[ObservabilityContext] | None
|
755
654
|
object.__setattr__(
|
756
655
|
self,
|
757
656
|
"_token",
|
758
657
|
None,
|
759
658
|
)
|
760
659
|
|
761
|
-
def __setattr__(
|
762
|
-
self,
|
763
|
-
name: str,
|
764
|
-
value: Any,
|
765
|
-
) -> Any:
|
766
|
-
raise AttributeError(
|
767
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
768
|
-
f" attribute - '{name}' cannot be modified"
|
769
|
-
)
|
770
|
-
|
771
|
-
def __delattr__(
|
772
|
-
self,
|
773
|
-
name: str,
|
774
|
-
) -> None:
|
775
|
-
raise AttributeError(
|
776
|
-
f"Can't modify immutable {self.__class__.__qualname__},"
|
777
|
-
f" attribute - '{name}' cannot be deleted"
|
778
|
-
)
|
779
|
-
|
780
660
|
def __enter__(self) -> None:
|
781
661
|
"""
|
782
662
|
Enter this observability context.
|
@@ -822,7 +702,7 @@ class ObservabilityContext:
|
|
822
702
|
If the context is not active
|
823
703
|
"""
|
824
704
|
assert self._token is not None, "Unbalanced context enter/exit" # nosec: B101
|
825
|
-
ObservabilityContext._context.reset(self._token)
|
705
|
+
ObservabilityContext._context.reset(self._token) # pyright: ignore[reportArgumentType]
|
826
706
|
object.__setattr__(
|
827
707
|
self,
|
828
708
|
"_token",
|