haiway 0.22.0__py3-none-any.whl → 0.23.0__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/context/access.py +9 -1
- haiway/context/disposables.py +32 -5
- haiway/context/observability.py +2 -2
- haiway/context/state.py +18 -2
- haiway/helpers/__init__.py +1 -1
- haiway/helpers/observability.py +2 -3
- haiway/opentelemetry/observability.py +50 -14
- haiway/state/structure.py +16 -6
- haiway/utils/__init__.py +0 -2
- {haiway-0.22.0.dist-info → haiway-0.23.0.dist-info}/METADATA +1 -1
- {haiway-0.22.0.dist-info → haiway-0.23.0.dist-info}/RECORD +14 -15
- haiway/utils/freezing.py +0 -46
- /haiway/helpers/{timeouted.py → timeouting.py} +0 -0
- {haiway-0.22.0.dist-info → haiway-0.23.0.dist-info}/WHEEL +0 -0
- {haiway-0.22.0.dist-info → haiway-0.23.0.dist-info}/licenses/LICENSE +0 -0
haiway/context/access.py
CHANGED
@@ -539,6 +539,8 @@ class ctx:
|
|
539
539
|
def check_state[StateType: State](
|
540
540
|
state: type[StateType],
|
541
541
|
/,
|
542
|
+
*,
|
543
|
+
instantiate_defaults: bool = False,
|
542
544
|
) -> bool:
|
543
545
|
"""
|
544
546
|
Check if state object is available in the current context.
|
@@ -551,12 +553,18 @@ class ctx:
|
|
551
553
|
state: type[StateType]
|
552
554
|
The type of state to check
|
553
555
|
|
556
|
+
instantiate_defaults: bool = False
|
557
|
+
Control if default value should be instantiated during check.
|
558
|
+
|
554
559
|
Returns
|
555
560
|
-------
|
556
561
|
bool
|
557
562
|
True if state is available, otherwise False.
|
558
563
|
"""
|
559
|
-
return StateContext.check_state(
|
564
|
+
return StateContext.check_state(
|
565
|
+
state,
|
566
|
+
instantiate_defaults=instantiate_defaults,
|
567
|
+
)
|
560
568
|
|
561
569
|
@staticmethod
|
562
570
|
def state[StateType: State](
|
haiway/context/disposables.py
CHANGED
@@ -12,7 +12,7 @@ from itertools import chain
|
|
12
12
|
from types import TracebackType
|
13
13
|
from typing import Any, final
|
14
14
|
|
15
|
-
from haiway.context.state import
|
15
|
+
from haiway.context.state import StateContext
|
16
16
|
from haiway.state import State
|
17
17
|
from haiway.utils.mimic import mimic_function
|
18
18
|
|
@@ -195,19 +195,25 @@ class Disposables:
|
|
195
195
|
return multiple
|
196
196
|
|
197
197
|
async def prepare(self) -> Iterable[State]:
|
198
|
+
"""
|
199
|
+
Enter all contained disposables asynchronously.
|
200
|
+
|
201
|
+
Enters all disposables in parallel and collects any State objects they return.
|
202
|
+
"""
|
198
203
|
assert self._loop is None # nosec: B101
|
199
204
|
object.__setattr__(
|
200
205
|
self,
|
201
206
|
"_loop",
|
202
207
|
get_running_loop(),
|
203
208
|
)
|
204
|
-
|
205
|
-
|
209
|
+
|
210
|
+
return tuple(
|
211
|
+
chain.from_iterable(
|
206
212
|
await gather(
|
207
213
|
*[self._setup(disposable) for disposable in self._disposables],
|
208
214
|
)
|
209
215
|
)
|
210
|
-
|
216
|
+
)
|
211
217
|
|
212
218
|
async def __aenter__(self) -> None:
|
213
219
|
"""
|
@@ -218,7 +224,7 @@ class Disposables:
|
|
218
224
|
"""
|
219
225
|
|
220
226
|
assert self._state_context is None, "Context reentrance is not allowed" # nosec: B101
|
221
|
-
state_context = StateContext(
|
227
|
+
state_context = StateContext.updated(await self.prepare())
|
222
228
|
state_context.__enter__()
|
223
229
|
object.__setattr__(
|
224
230
|
self,
|
@@ -252,6 +258,26 @@ class Disposables:
|
|
252
258
|
exc_val: BaseException | None = None,
|
253
259
|
exc_tb: TracebackType | None = None,
|
254
260
|
) -> None:
|
261
|
+
"""
|
262
|
+
Exit all contained disposables asynchronously.
|
263
|
+
|
264
|
+
Properly disposes of all resources by calling their __aexit__ methods in parallel.
|
265
|
+
If multiple disposables raise exceptions, they are collected into a BaseExceptionGroup.
|
266
|
+
|
267
|
+
Parameters
|
268
|
+
----------
|
269
|
+
exc_type: type[BaseException] | None
|
270
|
+
The type of exception that caused the context to be exited
|
271
|
+
exc_val: BaseException | None
|
272
|
+
The exception that caused the context to be exited
|
273
|
+
exc_tb: TracebackType | None
|
274
|
+
The traceback for the exception that caused the context to be exited
|
275
|
+
|
276
|
+
Raises
|
277
|
+
------
|
278
|
+
BaseExceptionGroup
|
279
|
+
If multiple disposables raise exceptions during exit
|
280
|
+
"""
|
255
281
|
assert self._loop is not None # nosec: B101
|
256
282
|
results: list[bool | BaseException | None]
|
257
283
|
|
@@ -306,6 +332,7 @@ class Disposables:
|
|
306
332
|
|
307
333
|
Properly disposes of all resources by calling their __aexit__ methods in parallel.
|
308
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.
|
309
336
|
|
310
337
|
Parameters
|
311
338
|
----------
|
haiway/context/observability.py
CHANGED
@@ -403,7 +403,7 @@ def _logger_observability(
|
|
403
403
|
f"[{trace_id_hex}] {scope.unique_name} Recorded attributes: {format_str(attributes)}",
|
404
404
|
)
|
405
405
|
|
406
|
-
def scope_entering
|
406
|
+
def scope_entering(
|
407
407
|
scope: ScopeIdentifier,
|
408
408
|
/,
|
409
409
|
) -> None:
|
@@ -412,7 +412,7 @@ def _logger_observability(
|
|
412
412
|
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.label}",
|
413
413
|
)
|
414
414
|
|
415
|
-
def scope_exiting
|
415
|
+
def scope_exiting(
|
416
416
|
scope: ScopeIdentifier,
|
417
417
|
/,
|
418
418
|
*,
|
haiway/context/state.py
CHANGED
@@ -37,6 +37,7 @@ class ScopeState:
|
|
37
37
|
"_state",
|
38
38
|
{type(element): element for element in state},
|
39
39
|
)
|
40
|
+
assert all(issubclass(key, State) for key in self._state.keys()) # nosec: B101
|
40
41
|
self._lock: Lock
|
41
42
|
object.__setattr__(
|
42
43
|
self,
|
@@ -67,6 +68,8 @@ class ScopeState:
|
|
67
68
|
self,
|
68
69
|
state: type[StateType],
|
69
70
|
/,
|
71
|
+
*,
|
72
|
+
instantiate_defaults: bool = False,
|
70
73
|
) -> bool:
|
71
74
|
"""
|
72
75
|
Check state object availability by its type.
|
@@ -79,6 +82,9 @@ class ScopeState:
|
|
79
82
|
state: type[StateType]
|
80
83
|
The type of state to check
|
81
84
|
|
85
|
+
instantiate_defaults: bool = False
|
86
|
+
Control if default value should be instantiated during check.
|
87
|
+
|
82
88
|
Returns
|
83
89
|
-------
|
84
90
|
bool
|
@@ -87,7 +93,7 @@ class ScopeState:
|
|
87
93
|
if state in self._state:
|
88
94
|
return True
|
89
95
|
|
90
|
-
|
96
|
+
elif instantiate_defaults:
|
91
97
|
with self._lock:
|
92
98
|
if state in self._state:
|
93
99
|
return True
|
@@ -100,6 +106,9 @@ class ScopeState:
|
|
100
106
|
except BaseException:
|
101
107
|
return False # unavailable, we don't care the exception
|
102
108
|
|
109
|
+
else:
|
110
|
+
return False
|
111
|
+
|
103
112
|
def state[StateType: State](
|
104
113
|
self,
|
105
114
|
state: type[StateType],
|
@@ -201,6 +210,7 @@ class StateContext:
|
|
201
210
|
cls,
|
202
211
|
state: type[StateType],
|
203
212
|
/,
|
213
|
+
instantiate_defaults: bool = False,
|
204
214
|
) -> bool:
|
205
215
|
"""
|
206
216
|
Check if state object is available in the current context.
|
@@ -212,13 +222,19 @@ class StateContext:
|
|
212
222
|
state: type[StateType]
|
213
223
|
The type of state to check
|
214
224
|
|
225
|
+
instantiate_defaults: bool = False
|
226
|
+
Control if default value should be instantiated during check.
|
227
|
+
|
215
228
|
Returns
|
216
229
|
-------
|
217
230
|
bool
|
218
231
|
True if state is available, otherwise False.
|
219
232
|
"""
|
220
233
|
try:
|
221
|
-
return cls._context.get().check_state(
|
234
|
+
return cls._context.get().check_state(
|
235
|
+
state,
|
236
|
+
instantiate_defaults=instantiate_defaults,
|
237
|
+
)
|
222
238
|
|
223
239
|
except LookupError:
|
224
240
|
return False # no context no state
|
haiway/helpers/__init__.py
CHANGED
@@ -5,7 +5,7 @@ from haiway.helpers.files import File, FileAccess
|
|
5
5
|
from haiway.helpers.observability import LoggerObservability
|
6
6
|
from haiway.helpers.retries import retry
|
7
7
|
from haiway.helpers.throttling import throttle
|
8
|
-
from haiway.helpers.
|
8
|
+
from haiway.helpers.timeouting import timeout
|
9
9
|
from haiway.helpers.tracing import traced
|
10
10
|
|
11
11
|
__all__ = (
|
haiway/helpers/observability.py
CHANGED
@@ -6,7 +6,6 @@ from uuid import UUID, uuid4
|
|
6
6
|
|
7
7
|
from haiway.context import Observability, ObservabilityLevel, ScopeIdentifier
|
8
8
|
from haiway.context.observability import ObservabilityAttribute
|
9
|
-
from haiway.state import State
|
10
9
|
from haiway.utils.formatting import format_str
|
11
10
|
|
12
11
|
__all__ = ("LoggerObservability",)
|
@@ -232,7 +231,7 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
232
231
|
f"[{trace_id_hex}] {scope.unique_name} {attributes_str}",
|
233
232
|
)
|
234
233
|
|
235
|
-
def scope_entering
|
234
|
+
def scope_entering(
|
236
235
|
scope: ScopeIdentifier,
|
237
236
|
/,
|
238
237
|
) -> None:
|
@@ -255,7 +254,7 @@ def LoggerObservability( # noqa: C901, PLR0915
|
|
255
254
|
f"[{trace_id_hex}] {scope.unique_name} Entering scope: {scope.label}",
|
256
255
|
)
|
257
256
|
|
258
|
-
def scope_exiting
|
257
|
+
def scope_exiting(
|
259
258
|
scope: ScopeIdentifier,
|
260
259
|
/,
|
261
260
|
*,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import os
|
2
|
-
from collections.abc import Mapping
|
2
|
+
from collections.abc import Mapping, Sequence
|
3
3
|
from typing import Any, ClassVar, Self, cast, final
|
4
4
|
from uuid import UUID
|
5
5
|
|
@@ -26,12 +26,16 @@ from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExpo
|
|
26
26
|
from opentelemetry.sdk.resources import Resource
|
27
27
|
from opentelemetry.sdk.trace import TracerProvider
|
28
28
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter, SpanExporter
|
29
|
-
from opentelemetry.trace import
|
30
|
-
from opentelemetry.trace
|
31
|
-
|
32
|
-
from haiway.context import
|
33
|
-
|
34
|
-
|
29
|
+
from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
|
30
|
+
from opentelemetry.trace import Link, Span, SpanContext, StatusCode, TraceFlags, Tracer
|
31
|
+
|
32
|
+
from haiway.context import (
|
33
|
+
Observability,
|
34
|
+
ObservabilityAttribute,
|
35
|
+
ObservabilityLevel,
|
36
|
+
ScopeIdentifier,
|
37
|
+
ctx,
|
38
|
+
)
|
35
39
|
from haiway.types import MISSING
|
36
40
|
|
37
41
|
__all__ = ("OpenTelemetry",)
|
@@ -437,6 +441,8 @@ class OpenTelemetry:
|
|
437
441
|
def observability( # noqa: C901, PLR0915
|
438
442
|
cls,
|
439
443
|
level: ObservabilityLevel = ObservabilityLevel.INFO,
|
444
|
+
*,
|
445
|
+
external_trace_id: str | None = None,
|
440
446
|
) -> Observability:
|
441
447
|
"""
|
442
448
|
Create an Observability implementation using OpenTelemetry.
|
@@ -449,6 +455,9 @@ class OpenTelemetry:
|
|
449
455
|
----------
|
450
456
|
level : ObservabilityLevel, default=ObservabilityLevel.INFO
|
451
457
|
The minimum observability level to record
|
458
|
+
external_trace_id : str | None, optional
|
459
|
+
External trace ID for distributed tracing context propagation.
|
460
|
+
If provided, the root span will be linked to this external trace.
|
452
461
|
|
453
462
|
Returns
|
454
463
|
-------
|
@@ -645,7 +654,7 @@ class OpenTelemetry:
|
|
645
654
|
|
646
655
|
scopes[scope.scope_id].record_attributes(attributes)
|
647
656
|
|
648
|
-
def scope_entering
|
657
|
+
def scope_entering(
|
649
658
|
scope: ScopeIdentifier,
|
650
659
|
/,
|
651
660
|
) -> None:
|
@@ -678,17 +687,44 @@ class OpenTelemetry:
|
|
678
687
|
scope_store: ScopeStore
|
679
688
|
if root_scope is None:
|
680
689
|
meter = metrics.get_meter(scope.label)
|
681
|
-
context: Context =
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
690
|
+
context: Context = get_current()
|
691
|
+
|
692
|
+
# Handle distributed tracing with external trace ID
|
693
|
+
links: Sequence[Link] | None = None
|
694
|
+
if external_trace_id is not None:
|
695
|
+
# Convert external trace ID to OpenTelemetry trace ID format
|
696
|
+
try:
|
697
|
+
# Generate a proper span ID for the external trace link
|
698
|
+
id_generator = RandomIdGenerator()
|
699
|
+
|
700
|
+
# Create a link to the external trace
|
701
|
+
links = (
|
702
|
+
Link(
|
703
|
+
SpanContext(
|
704
|
+
( # Assume external_trace_id is a hex string, convert to int
|
705
|
+
int(external_trace_id, 16)
|
706
|
+
if isinstance(external_trace_id, str)
|
707
|
+
else int(external_trace_id)
|
708
|
+
),
|
709
|
+
id_generator.generate_span_id(), # Generate proper span ID
|
710
|
+
True, # is_remote=True
|
711
|
+
TraceFlags.SAMPLED, # pyright: ignore[reportArgumentType]
|
712
|
+
)
|
713
|
+
),
|
714
|
+
)
|
715
|
+
|
716
|
+
except (ValueError, TypeError):
|
717
|
+
ctx.log_warning(
|
718
|
+
"Failed to convert external trace ID to OpenTelemetry format"
|
719
|
+
)
|
720
|
+
|
686
721
|
scope_store = ScopeStore(
|
687
722
|
scope,
|
688
723
|
context=context,
|
689
724
|
span=tracer.start_span(
|
690
725
|
name=scope.label,
|
691
726
|
context=context,
|
727
|
+
links=links,
|
692
728
|
),
|
693
729
|
meter=meter,
|
694
730
|
logger=get_logger(scope.label),
|
@@ -711,7 +747,7 @@ class OpenTelemetry:
|
|
711
747
|
|
712
748
|
scopes[scope.scope_id] = scope_store
|
713
749
|
|
714
|
-
def scope_exiting
|
750
|
+
def scope_exiting(
|
715
751
|
scope: ScopeIdentifier,
|
716
752
|
/,
|
717
753
|
*,
|
haiway/state/structure.py
CHANGED
@@ -729,12 +729,22 @@ class State(metaclass=StateMeta):
|
|
729
729
|
)
|
730
730
|
|
731
731
|
def __hash__(self) -> int:
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
732
|
+
hash_values: list[int] = []
|
733
|
+
for key in self.__ATTRIBUTES__.keys():
|
734
|
+
value: Any = getattr(self, key, MISSING)
|
735
|
+
|
736
|
+
# Skip MISSING values to ensure consistent hashing
|
737
|
+
if value is MISSING:
|
738
|
+
continue
|
739
|
+
|
740
|
+
# Convert to hashable representation
|
741
|
+
try:
|
742
|
+
hash_values.append(hash(value))
|
743
|
+
|
744
|
+
except TypeError:
|
745
|
+
continue # skip unhashable
|
746
|
+
|
747
|
+
return hash((self.__class__, tuple(hash_values)))
|
738
748
|
|
739
749
|
def __setattr__(
|
740
750
|
self,
|
haiway/utils/__init__.py
CHANGED
@@ -9,7 +9,6 @@ from haiway.utils.env import (
|
|
9
9
|
load_env,
|
10
10
|
)
|
11
11
|
from haiway.utils.formatting import format_str
|
12
|
-
from haiway.utils.freezing import freeze
|
13
12
|
from haiway.utils.logs import setup_logging
|
14
13
|
from haiway.utils.mimic import mimic_function
|
15
14
|
from haiway.utils.noop import async_noop, noop
|
@@ -27,7 +26,6 @@ __all__ = (
|
|
27
26
|
"async_always",
|
28
27
|
"async_noop",
|
29
28
|
"format_str",
|
30
|
-
"freeze",
|
31
29
|
"getenv_base64",
|
32
30
|
"getenv_bool",
|
33
31
|
"getenv_float",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: haiway
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.23.0
|
4
4
|
Summary: Framework for dependency injection and state management within structured concurrency model.
|
5
5
|
Project-URL: Homepage, https://miquido.com
|
6
6
|
Project-URL: Repository, https://github.com/miquido/haiway.git
|
@@ -1,46 +1,45 @@
|
|
1
1
|
haiway/__init__.py,sha256=FiOAMHHawyGk9FfZU-1UflT8nmwu9J0CrG2QwrJGccw,1917
|
2
2
|
haiway/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
haiway/context/__init__.py,sha256=1N_SvdPkTfIZDZybm3y0rY2dGrDLWTm0ryzUz2XD4f8,1174
|
4
|
-
haiway/context/access.py,sha256=
|
5
|
-
haiway/context/disposables.py,sha256=
|
4
|
+
haiway/context/access.py,sha256=QCabyZtqqJjGTgAod1ZC3Fz3IfPsyurLo_i68RnCm4Q,25736
|
5
|
+
haiway/context/disposables.py,sha256=AP9eZ0BPHJZfjrrfrjSzr4jONMKkR6YmhjOfnBp37so,11504
|
6
6
|
haiway/context/identifier.py,sha256=dCCwLneXJzH__ZWFlGRUHvoCmbT4lM0QVbyokYIbUHg,5255
|
7
|
-
haiway/context/observability.py,sha256=
|
8
|
-
haiway/context/state.py,sha256=
|
7
|
+
haiway/context/observability.py,sha256=E-TDqqJ_EnHkFTspEjyA61O0iIbEev15YUn5d3yHhvU,23692
|
8
|
+
haiway/context/state.py,sha256=Codc_F5Ngsk4x80nkNuwpvXpZ-mht3joOgcgJ7vKpVg,12000
|
9
9
|
haiway/context/tasks.py,sha256=pScFgeiyrXSJRDFZiYbBLi3k_DHkSlhB8rgAnYtgyrU,4925
|
10
10
|
haiway/context/types.py,sha256=VDWXJySihfvSSPzY09PaGk6j5S9HgmAUboBGCZ8o_4k,766
|
11
|
-
haiway/helpers/__init__.py,sha256=
|
11
|
+
haiway/helpers/__init__.py,sha256=PTWpavAveEB2V9Au1QuaRZwh3Rkb1bQSNvo_mxuGqlE,721
|
12
12
|
haiway/helpers/asynchrony.py,sha256=Ddj8UdXhVczAbAC-rLpyhWa4RJ_W2Eolo45Veorq7_4,5362
|
13
13
|
haiway/helpers/caching.py,sha256=BqgcUGQSAmXsuLi5V8EwlZzuGyutHOn1V4k7BHsGKeg,14347
|
14
14
|
haiway/helpers/concurrent.py,sha256=xGMcan_tiETAHQs1YFmgYpA4YMFo6rIbFKvNeMlRFG8,2551
|
15
15
|
haiway/helpers/files.py,sha256=L6vXd8gdgWx5jPL8azloU8IGoFq2xnxjMc4ufz-gdl4,11650
|
16
|
-
haiway/helpers/observability.py,sha256=
|
16
|
+
haiway/helpers/observability.py,sha256=jCJzOPJ5E3RKJsbbGRR1O-mZydaHNIGkIpppOH7nFBA,11012
|
17
17
|
haiway/helpers/retries.py,sha256=52LA85HejTiSmCmTMAA9c8oUqD_VnhbTn1b3kwlU52c,9032
|
18
18
|
haiway/helpers/throttling.py,sha256=KBWUSHdKVMC5_nRMmmoPNwfp-3AcerQ6OczJa9gNLM0,5796
|
19
|
-
haiway/helpers/
|
19
|
+
haiway/helpers/timeouting.py,sha256=GQ8-btb36f0Jq7TnorAPYXyKScNmf0nxHXCYxqGl-o8,3949
|
20
20
|
haiway/helpers/tracing.py,sha256=NHipA5UlngwFcAaKhXg1jTuJ-ti6AqSNxE7u7-92vWo,5409
|
21
21
|
haiway/opentelemetry/__init__.py,sha256=TV-1C14mDAtcHhFZ29ActFQdrGH6x5KuGV9w-JlKYJg,91
|
22
|
-
haiway/opentelemetry/observability.py,sha256=
|
22
|
+
haiway/opentelemetry/observability.py,sha256=akGAPX6_958BxCfzlLnoDJHPtEvztdMnfMA1oiJL48Y,27370
|
23
23
|
haiway/state/__init__.py,sha256=AaMqlMhO4zKS_XNevy3A7BHh5PxmguA-Sk_FnaNDY1Q,355
|
24
24
|
haiway/state/attributes.py,sha256=sububiFP23aBB8RGk6OvTUp7BEY6S0kER_uHC09yins,26733
|
25
25
|
haiway/state/path.py,sha256=bv5MI3HmUyku78k0Sz5lc7Q_Bay53iom1l3AL5KZs-4,32143
|
26
26
|
haiway/state/requirement.py,sha256=zNTx7s8FiMZKu9EV3T6f1SOJpR4SC9X5hhL--PVWPCY,15641
|
27
|
-
haiway/state/structure.py,sha256=
|
27
|
+
haiway/state/structure.py,sha256=CTf1l0TyKA7vkVDqA9RMdxaOVNSHwQduN2jb6H015hg,23798
|
28
28
|
haiway/state/validation.py,sha256=eDOZKRrfd-dmdbqoHcLacdCVKmVCEpwt239EG6ljNF8,23557
|
29
29
|
haiway/types/__init__.py,sha256=jFr5kf36SvVGdgngvik6_HzG8YNa3NVsdDDSqxVuGm4,281
|
30
30
|
haiway/types/default.py,sha256=59chcOaoGqI2to08RamCCLluimfYbJp5xbYl3fWaLrM,4153
|
31
31
|
haiway/types/missing.py,sha256=OfiyYUnzTk3arKWu8S6ORCEYGvcRu_mdL4j1ExdSvgI,4256
|
32
|
-
haiway/utils/__init__.py,sha256=
|
32
|
+
haiway/utils/__init__.py,sha256=Zs4mJnoRL_4ssGSZqvCFuhllxMDww_8-McsI2xB0mug,917
|
33
33
|
haiway/utils/always.py,sha256=dd6jDQ1j4DpJjTKO1J2Tv5xS8X1LnMC4kQ0D7DtKUvw,1230
|
34
34
|
haiway/utils/collections.py,sha256=gF5tC1EaEzBfPpXrHqR0mZh8e4pRwEPSVactvfN-30M,4737
|
35
35
|
haiway/utils/env.py,sha256=Z0uHJDFegvgzy-gM-f0uPMha9_1ldUglrD5SKNJsvYE,9445
|
36
36
|
haiway/utils/formatting.py,sha256=jgSIGalGUBZVo2ziiNC5Y7vBYbAEwPugOiwEOrNFTcI,4039
|
37
|
-
haiway/utils/freezing.py,sha256=HJH0SOgPCreb9o0wPeaMPMxhS9JDuzzey6UsKhuvUJU,1292
|
38
37
|
haiway/utils/logs.py,sha256=NuwoqKQnMNi1FMIA91cVFnAPefUFeg3UIT50IOl3sJk,1571
|
39
38
|
haiway/utils/mimic.py,sha256=xaZiUKp096QFfdSw7cNIKEWt2UIS7vf880KF54gny38,1831
|
40
39
|
haiway/utils/noop.py,sha256=U8ocfoCgt-pY0owJDPtrRrj53cabeIXH9qCKWMQnoRk,1336
|
41
40
|
haiway/utils/queue.py,sha256=6v2u3pA6A44IuCCTOjmCt3yLyOcm7PCRnrIGo25j-1o,6402
|
42
41
|
haiway/utils/stream.py,sha256=lXaeveTY0-AYG5xVzcQYaiC6SUD5fUtHoMXiQcrQAAM,5723
|
43
|
-
haiway-0.
|
44
|
-
haiway-0.
|
45
|
-
haiway-0.
|
46
|
-
haiway-0.
|
42
|
+
haiway-0.23.0.dist-info/METADATA,sha256=TAlSBtVIn8VCcK_qsmQ9how4K-ULVga-lP04ZS9M1AQ,4919
|
43
|
+
haiway-0.23.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
44
|
+
haiway-0.23.0.dist-info/licenses/LICENSE,sha256=3phcpHVNBP8jsi77gOO0E7rgKeDeu99Pi7DSnK9YHoQ,1069
|
45
|
+
haiway-0.23.0.dist-info/RECORD,,
|
haiway/utils/freezing.py
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
|
3
|
-
__all__ = ("freeze",)
|
4
|
-
|
5
|
-
|
6
|
-
def freeze(
|
7
|
-
instance: object,
|
8
|
-
/,
|
9
|
-
) -> None:
|
10
|
-
"""
|
11
|
-
Make an object instance immutable by preventing attribute modification.
|
12
|
-
|
13
|
-
This function modifies the given object to prevent further changes to its attributes.
|
14
|
-
It replaces the object's __setattr__ and __delattr__ methods with ones that raise
|
15
|
-
exceptions, effectively making the object immutable after this function is called.
|
16
|
-
|
17
|
-
Parameters
|
18
|
-
----------
|
19
|
-
instance : object
|
20
|
-
The object instance to make immutable
|
21
|
-
|
22
|
-
Returns
|
23
|
-
-------
|
24
|
-
None
|
25
|
-
The object is modified in-place
|
26
|
-
|
27
|
-
Notes
|
28
|
-
-----
|
29
|
-
- This only affects direct attribute assignments and deletions
|
30
|
-
- Mutable objects contained within the instance can still be modified internally
|
31
|
-
- The object's class remains unchanged, only the specific instance is affected
|
32
|
-
"""
|
33
|
-
|
34
|
-
def frozen_set(
|
35
|
-
__name: str,
|
36
|
-
__value: Any,
|
37
|
-
) -> None:
|
38
|
-
raise RuntimeError(f"{instance.__class__.__qualname__} is frozen and can't be modified")
|
39
|
-
|
40
|
-
def frozen_del(
|
41
|
-
__name: str,
|
42
|
-
) -> None:
|
43
|
-
raise RuntimeError(f"{instance.__class__.__qualname__} is frozen and can't be modified")
|
44
|
-
|
45
|
-
instance.__delattr__ = frozen_del
|
46
|
-
instance.__setattr__ = frozen_set
|
File without changes
|
File without changes
|
File without changes
|