haiway 0.2.0__py3-none-any.whl → 0.3.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/__init__.py CHANGED
@@ -1,10 +1,12 @@
1
1
  from haiway.context import (
2
+ Disposable,
3
+ Disposables,
2
4
  MissingContext,
3
5
  MissingState,
4
6
  ScopeMetrics,
5
7
  ctx,
6
8
  )
7
- from haiway.helpers import Disposable, Disposables, asynchronous, cache, retry, throttle, timeout
9
+ from haiway.helpers import asynchronous, cache, retry, throttle, timeout
8
10
  from haiway.state import State
9
11
  from haiway.types import (
10
12
  MISSING,
@@ -1,9 +1,12 @@
1
1
  from haiway.context.access import ctx
2
+ from haiway.context.disposables import Disposable, Disposables
2
3
  from haiway.context.metrics import ScopeMetrics
3
4
  from haiway.context.types import MissingContext, MissingState
4
5
 
5
6
  __all__ = [
6
7
  "ctx",
8
+ "Disposable",
9
+ "Disposables",
7
10
  "MissingContext",
8
11
  "MissingState",
9
12
  "ScopeMetrics",
haiway/context/access.py CHANGED
@@ -5,11 +5,13 @@ from asyncio import (
5
5
  from collections.abc import (
6
6
  Callable,
7
7
  Coroutine,
8
+ Iterable,
8
9
  )
9
10
  from logging import Logger
10
11
  from types import TracebackType
11
12
  from typing import Any, final
12
13
 
14
+ from haiway.context.disposables import Disposable, Disposables
13
15
  from haiway.context.metrics import MetricsContext, ScopeMetrics
14
16
  from haiway.context.state import StateContext
15
17
  from haiway.context.tasks import TaskGroupContext
@@ -23,25 +25,41 @@ __all__ = [
23
25
 
24
26
  @final
25
27
  class ScopeContext:
26
- def __init__(
28
+ def __init__( # noqa: PLR0913
27
29
  self,
30
+ trace_id: str | None,
31
+ name: str,
32
+ logger: Logger | None,
33
+ state: tuple[State, ...],
34
+ disposables: Disposables | None,
28
35
  task_group: TaskGroupContext,
29
- state: StateContext,
30
- metrics: MetricsContext,
31
36
  completion: Callable[[ScopeMetrics], Coroutine[None, None, None]] | None,
32
37
  ) -> None:
33
38
  self._task_group: TaskGroupContext = task_group
34
- self._state: StateContext = state
35
- self._metrics: MetricsContext = metrics
39
+ self._logger: Logger | None = logger
40
+ self._trace_id: str | None = trace_id
41
+ self._name: str = name
42
+ self._state_context: StateContext
43
+ self._state: tuple[State, ...] = state
44
+ self._disposables: Disposables | None = disposables
45
+ self._metrics_context: MetricsContext
36
46
  self._completion: Callable[[ScopeMetrics], Coroutine[None, None, None]] | None = completion
37
47
 
38
48
  freeze(self)
39
49
 
40
50
  def __enter__(self) -> None:
41
51
  assert self._completion is None, "Can't enter synchronous context with completion" # nosec: B101
52
+ assert self._disposables is None, "Can't enter synchronous context with disposables" # nosec: B101
53
+
54
+ self._state_context = StateContext.updated(self._state)
55
+ self._metrics_context = MetricsContext.scope(
56
+ self._name,
57
+ logger=self._logger,
58
+ trace_id=self._trace_id,
59
+ )
42
60
 
43
- self._state.__enter__()
44
- self._metrics.__enter__()
61
+ self._state_context.__enter__()
62
+ self._metrics_context.__enter__()
45
63
 
46
64
  def __exit__(
47
65
  self,
@@ -49,49 +67,71 @@ class ScopeContext:
49
67
  exc_val: BaseException | None,
50
68
  exc_tb: TracebackType | None,
51
69
  ) -> None:
52
- self._metrics.__exit__(
70
+ self._metrics_context.__exit__(
53
71
  exc_type=exc_type,
54
72
  exc_val=exc_val,
55
73
  exc_tb=exc_tb,
56
74
  )
57
75
 
58
- self._state.__exit__(
76
+ self._state_context.__exit__(
59
77
  exc_type=exc_type,
60
78
  exc_val=exc_val,
61
79
  exc_tb=exc_tb,
62
80
  )
63
81
 
64
82
  async def __aenter__(self) -> None:
65
- self._state.__enter__()
66
- self._metrics.__enter__()
67
83
  await self._task_group.__aenter__()
68
84
 
85
+ if self._disposables:
86
+ self._state_context = StateContext.updated(
87
+ (*self._state, *await self._disposables.__aenter__())
88
+ )
89
+
90
+ else:
91
+ self._state_context = StateContext.updated(self._state)
92
+
93
+ self._metrics_context = MetricsContext.scope(
94
+ self._name,
95
+ logger=self._logger,
96
+ trace_id=self._trace_id,
97
+ )
98
+
99
+ self._state_context.__enter__()
100
+ self._metrics_context.__enter__()
101
+
69
102
  async def __aexit__(
70
103
  self,
71
104
  exc_type: type[BaseException] | None,
72
105
  exc_val: BaseException | None,
73
106
  exc_tb: TracebackType | None,
74
107
  ) -> None:
108
+ if self._disposables:
109
+ await self._disposables.__aexit__(
110
+ exc_type=exc_type,
111
+ exc_val=exc_val,
112
+ exc_tb=exc_tb,
113
+ )
114
+
75
115
  await self._task_group.__aexit__(
76
116
  exc_type=exc_type,
77
117
  exc_val=exc_val,
78
118
  exc_tb=exc_tb,
79
119
  )
80
120
 
81
- self._metrics.__exit__(
121
+ self._metrics_context.__exit__(
82
122
  exc_type=exc_type,
83
123
  exc_val=exc_val,
84
124
  exc_tb=exc_tb,
85
125
  )
86
126
 
87
- self._state.__exit__(
127
+ self._state_context.__exit__(
88
128
  exc_type=exc_type,
89
129
  exc_val=exc_val,
90
130
  exc_tb=exc_tb,
91
131
  )
92
132
 
93
133
  if completion := self._completion:
94
- await completion(self._metrics._metrics) # pyright: ignore[reportPrivateUsage]
134
+ await completion(self._metrics_context._metrics) # pyright: ignore[reportPrivateUsage]
95
135
 
96
136
 
97
137
  @final
@@ -101,6 +141,7 @@ class ctx:
101
141
  name: str,
102
142
  /,
103
143
  *state: State,
144
+ disposables: Disposables | Iterable[Disposable] | None = None,
104
145
  logger: Logger | None = None,
105
146
  trace_id: str | None = None,
106
147
  completion: Callable[[ScopeMetrics], Coroutine[None, None, None]] | None = None,
@@ -114,9 +155,14 @@ class ctx:
114
155
  name: Value
115
156
  name of the scope context
116
157
 
117
- *state: State
118
- state propagated within the scope context, will be merged with current if any\
119
- by replacing current with provided on conflict
158
+ *state: State | Disposable
159
+ state propagated within the scope context, will be merged with current state by\
160
+ replacing current with provided on conflict.
161
+
162
+ disposables: Disposables | list[Disposable] | None
163
+ disposables consumed within the context when entered. Produced state will automatically\
164
+ be added to the scope state. Using asynchronous context is required if any disposables\
165
+ were provided.
120
166
 
121
167
  logger: Logger | None
122
168
  logger used within the scope context, when not provided current logger will be used\
@@ -138,14 +184,24 @@ class ctx:
138
184
  context object intended to enter context manager with it
139
185
  """
140
186
 
187
+ resolved_disposables: Disposables | None
188
+ match disposables:
189
+ case None:
190
+ resolved_disposables = None
191
+
192
+ case Disposables() as disposables:
193
+ resolved_disposables = disposables
194
+
195
+ case iterable:
196
+ resolved_disposables = Disposables(*iterable)
197
+
141
198
  return ScopeContext(
199
+ trace_id=trace_id,
200
+ name=name,
201
+ logger=logger,
202
+ state=state,
203
+ disposables=resolved_disposables,
142
204
  task_group=TaskGroupContext(),
143
- metrics=MetricsContext.scope(
144
- name,
145
- logger=logger,
146
- trace_id=trace_id,
147
- ),
148
- state=StateContext.updated(state),
149
205
  completion=completion,
150
206
  )
151
207
 
@@ -53,6 +53,9 @@ class Disposables:
53
53
  elif exceptions:
54
54
  raise exceptions[0]
55
55
 
56
+ def __bool__(self) -> bool:
57
+ return len(self._disposables) > 0
58
+
56
59
  async def __aenter__(self) -> Iterable[State]:
57
60
  return await self.initialize()
58
61
 
@@ -1,6 +1,5 @@
1
1
  from haiway.helpers.asynchronous import asynchronous
2
2
  from haiway.helpers.cached import cache
3
- from haiway.helpers.disposables import Disposable, Disposables
4
3
  from haiway.helpers.retries import retry
5
4
  from haiway.helpers.throttling import throttle
6
5
  from haiway.helpers.timeouted import timeout
@@ -8,8 +7,6 @@ from haiway.helpers.timeouted import timeout
8
7
  __all__ = [
9
8
  "asynchronous",
10
9
  "cache",
11
- "Disposable",
12
- "Disposables",
13
10
  "retry",
14
11
  "throttle",
15
12
  "timeout",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: haiway
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Framework for dependency injection and state management within structured concurrency model.
5
5
  Maintainer-email: Kacper Kaliński <kacper.kalinski@miquido.com>
6
6
  License: MIT License
@@ -1,15 +1,15 @@
1
- haiway/__init__.py,sha256=Yw4Oh1N-xv2R9C-caH91DxB5I5tWLMuqYefIWxwpCX0,1130
1
+ haiway/__init__.py,sha256=tjFQ9bVnUHs2BMyCPxeNYxqHtqyIZQDk1Wk2nFB_G2U,1138
2
2
  haiway/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- haiway/context/__init__.py,sha256=8a2aiE9fmBBmkLL7_QzRKYdCac1ttt_KoPB62dWDDI8,236
4
- haiway/context/access.py,sha256=gVDUGvdX6yBUQjgVNotg7DugtqH1rE-efddEENBB16E,10672
3
+ haiway/context/__init__.py,sha256=21Y3zvRo1bHASZD6B_FNkU28k1-g88RdmUyqxvYXJxg,336
4
+ haiway/context/access.py,sha256=E9aIC1RUupKk2LXik5qb13oHpW2s_tNQC0UxGcO9xr0,12761
5
+ haiway/context/disposables.py,sha256=VQX9jVo1pjqkmOYzWpsbYyF45y0XtpjorIIaeMBCwTU,1771
5
6
  haiway/context/metrics.py,sha256=upkqUp47NymDJE8UQznr99AgaE9yw6i28l_cdCE1IeM,8612
6
7
  haiway/context/state.py,sha256=GxGwPQTK8FdSprBd83lQbA9veubp0o93_1Yk3gb7HMc,3000
7
8
  haiway/context/tasks.py,sha256=xXtXIUwXOra0EePTdkcEbMOmpWwFcO3hCRfR_IfvAHk,1978
8
9
  haiway/context/types.py,sha256=VvJA7wAPZ3ISpgyThVguioYUXqhHf0XkPfRd0M1ERiQ,142
9
- haiway/helpers/__init__.py,sha256=cZzbOjdodz4-CjCu2WqrTSJL5MqgaY10YRiWBizVZKA,418
10
+ haiway/helpers/__init__.py,sha256=G8cbw11yb7VxGkAqjVmXPcYKR0eGe-UHa0LUtgHA3Jc,318
10
11
  haiway/helpers/asynchronous.py,sha256=FYcV_ERrGy7f47y18oKeUk7fcbk-i_SOuPQ7lHhX5iI,6119
11
12
  haiway/helpers/cached.py,sha256=Ok_WE5Whe7XqnIuLZo4rNNBFeWap-aUWX799s4b1JAQ,9536
12
- haiway/helpers/disposables.py,sha256=zygeghLaQF77orawLpOjUOKKCsN1S5CwwVrNtS7A5G0,1696
13
13
  haiway/helpers/retries.py,sha256=gIkyUlqJLDYaxIZd3qzeqGFY9y5Gp8dgZLlZ6hs8hoc,7538
14
14
  haiway/helpers/throttling.py,sha256=zo0OwFq64si5KUwhd58cFHLmGAmYwRbFRJMbv9suhPs,3844
15
15
  haiway/helpers/timeouted.py,sha256=1xU09hQnFdj6p48BwZl5xUvtIr3zC0ZUXehkdrduCjs,3074
@@ -28,8 +28,8 @@ haiway/utils/logs.py,sha256=oDsc1ZdqKDjlTlctLbDcp9iX98Acr-1tdw-Pyg3DElo,1577
28
28
  haiway/utils/mimic.py,sha256=BkVjTVP2TxxC8GChPGyDV6UXVwJmiRiSWeOYZNZFHxs,1828
29
29
  haiway/utils/noop.py,sha256=qgbZlOKWY6_23Zs43OLukK2HagIQKRyR04zrFVm5rWI,344
30
30
  haiway/utils/queue.py,sha256=WGW8kSusIwRYHsYRIKD2CaqhhC1pUtVgtNHFDXDtYrw,2443
31
- haiway-0.2.0.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
32
- haiway-0.2.0.dist-info/METADATA,sha256=mKWhetnV8FpSXvtJra92P5bZHLo_UDZb2PjF-xf-2Kk,3872
33
- haiway-0.2.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
34
- haiway-0.2.0.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
35
- haiway-0.2.0.dist-info/RECORD,,
31
+ haiway-0.3.0.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
32
+ haiway-0.3.0.dist-info/METADATA,sha256=rABSQCD4Sboe2cC-p3hruWyxM0DrxggLozH0Ma-MIYM,3872
33
+ haiway-0.3.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
34
+ haiway-0.3.0.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
35
+ haiway-0.3.0.dist-info/RECORD,,
File without changes