haiway 0.4.0__py3-none-any.whl → 0.5.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 CHANGED
@@ -15,6 +15,7 @@ from haiway.helpers import (
15
15
  throttle,
16
16
  timeout,
17
17
  traced,
18
+ wrap_async,
18
19
  )
19
20
  from haiway.state import State
20
21
  from haiway.types import (
@@ -76,4 +77,5 @@ __all__ = [
76
77
  "timeout",
77
78
  "traced",
78
79
  "when_missing",
80
+ "wrap_async",
79
81
  ]
@@ -1,20 +1,19 @@
1
- from asyncio import gather, shield
1
+ from asyncio import gather
2
2
  from collections.abc import Iterable
3
+ from contextlib import AbstractAsyncContextManager
4
+ from itertools import chain
3
5
  from types import TracebackType
4
- from typing import Protocol, final, runtime_checkable
6
+ from typing import final
5
7
 
6
8
  from haiway.state import State
9
+ from haiway.utils import freeze
7
10
 
8
11
  __all__ = [
9
12
  "Disposable",
10
13
  "Disposables",
11
14
  ]
12
15
 
13
-
14
- @runtime_checkable
15
- class Disposable(Protocol):
16
- async def initialize(self) -> State | None: ...
17
- async def dispose(self) -> None: ...
16
+ type Disposable = AbstractAsyncContextManager[Iterable[State] | State | None]
18
17
 
19
18
 
20
19
  @final
@@ -25,39 +24,35 @@ class Disposables:
25
24
  ) -> None:
26
25
  self._disposables: tuple[Disposable, ...] = disposables
27
26
 
28
- async def initialize(self) -> Iterable[State]:
29
- return [
30
- state
31
- for state in await gather(
32
- *[disposable.initialize() for disposable in self._disposables],
33
- )
34
- if state is not None
35
- ]
36
-
37
- async def dispose(self) -> None:
38
- results: list[BaseException | None] = await shield(
39
- gather(
40
- *[disposable.dispose() for disposable in self._disposables],
41
- return_exceptions=True,
42
- ),
43
- )
27
+ freeze(self)
44
28
 
45
- self._disposables = ()
46
- exceptions: list[BaseException] = [
47
- exception for exception in results if exception is not None
48
- ]
29
+ def __bool__(self) -> bool:
30
+ return len(self._disposables) > 0
49
31
 
50
- if len(exceptions) > 1:
51
- raise BaseExceptionGroup("Disposing errors", exceptions)
32
+ async def _initialize(
33
+ self,
34
+ disposable: Disposable,
35
+ /,
36
+ ) -> Iterable[State]:
37
+ match await disposable.__aenter__():
38
+ case None:
39
+ return ()
52
40
 
53
- elif exceptions:
54
- raise exceptions[0]
41
+ case State() as single:
42
+ return (single,)
55
43
 
56
- def __bool__(self) -> bool:
57
- return len(self._disposables) > 0
44
+ case multiple:
45
+ return multiple
58
46
 
59
47
  async def __aenter__(self) -> Iterable[State]:
60
- return await self.initialize()
48
+ return [
49
+ *chain.from_iterable(
50
+ state
51
+ for state in await gather(
52
+ *[self._initialize(disposable) for disposable in self._disposables],
53
+ )
54
+ )
55
+ ]
61
56
 
62
57
  async def __aexit__(
63
58
  self,
@@ -65,4 +60,19 @@ class Disposables:
65
60
  exc_val: BaseException | None,
66
61
  exc_tb: TracebackType | None,
67
62
  ) -> None:
68
- await self.dispose()
63
+ results: list[bool | BaseException | None] = await gather(
64
+ *[
65
+ disposable.__aexit__(
66
+ exc_type,
67
+ exc_val,
68
+ exc_tb,
69
+ )
70
+ for disposable in self._disposables
71
+ ],
72
+ return_exceptions=True,
73
+ )
74
+
75
+ exceptions: list[BaseException] = [exc for exc in results if isinstance(exc, BaseException)]
76
+
77
+ if len(exceptions) > 1:
78
+ raise BaseExceptionGroup("Disposing errors", exceptions)
@@ -1,4 +1,4 @@
1
- from haiway.helpers.asynchrony import asynchronous
1
+ from haiway.helpers.asynchrony import asynchronous, wrap_async
2
2
  from haiway.helpers.caching import cache
3
3
  from haiway.helpers.retries import retry
4
4
  from haiway.helpers.throttling import throttle
@@ -14,4 +14,5 @@ __all__ = [
14
14
  "throttle",
15
15
  "timeout",
16
16
  "traced",
17
+ "wrap_async",
17
18
  ]
@@ -9,9 +9,26 @@ from haiway.types.missing import MISSING, Missing
9
9
 
10
10
  __all__ = [
11
11
  "asynchronous",
12
+ "wrap_async",
12
13
  ]
13
14
 
14
15
 
16
+ def wrap_async[**Args, Result](
17
+ function: Callable[Args, Coroutine[None, None, Result]] | Callable[Args, Result],
18
+ /,
19
+ ) -> Callable[Args, Coroutine[None, None, Result]]:
20
+ if iscoroutinefunction(function):
21
+ return function
22
+
23
+ else:
24
+
25
+ async def async_function(*args: Args.args, **kwargs: Args.kwargs) -> Result:
26
+ return cast(Callable[Args, Result], function)(*args, **kwargs)
27
+
28
+ _mimic_async(function, within=async_function)
29
+ return async_function
30
+
31
+
15
32
  @overload
16
33
  def asynchronous[**Args, Result]() -> (
17
34
  Callable[
haiway/state/structure.py CHANGED
@@ -16,7 +16,7 @@ from weakref import WeakValueDictionary
16
16
 
17
17
  from haiway.state.attributes import AttributeAnnotation, attribute_annotations
18
18
  from haiway.state.validation import attribute_type_validator
19
- from haiway.types.missing import MISSING, Missing
19
+ from haiway.types import MISSING, Missing, not_missing
20
20
 
21
21
  __all__ = [
22
22
  "State",
@@ -184,7 +184,13 @@ class State(metaclass=StateMeta):
184
184
  return self.__replace__(**kwargs)
185
185
 
186
186
  def as_dict(self) -> dict[str, Any]:
187
- return vars(self)
187
+ dict_result: dict[str, Any] = {}
188
+ for key in self.__ATTRIBUTES__.keys():
189
+ value: Any | Missing = getattr(self, key, MISSING)
190
+ if not_missing(value):
191
+ dict_result[key] = value
192
+
193
+ return dict_result
188
194
 
189
195
  def __str__(self) -> str:
190
196
  attributes: str = ", ".join([f"{key}: {value}" for key, value in vars(self).items()])
haiway/utils/queue.py CHANGED
@@ -1,7 +1,6 @@
1
1
  from asyncio import AbstractEventLoop, CancelledError, Future, get_running_loop
2
2
  from collections import deque
3
3
  from collections.abc import AsyncIterator
4
- from typing import Self
5
4
 
6
5
  __all__ = [
7
6
  "AsyncQueue",
@@ -63,9 +62,6 @@ class AsyncQueue[Element](AsyncIterator[Element]):
63
62
  def cancel(self) -> None:
64
63
  self.finish(exception=CancelledError())
65
64
 
66
- def __aiter__(self) -> Self:
67
- return self
68
-
69
65
  async def __anext__(self) -> Element:
70
66
  assert self._waiting is None, "Only a single queue consumer is supported!" # nosec: B101
71
67
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: haiway
3
- Version: 0.4.0
3
+ Version: 0.5.1
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,14 +1,14 @@
1
- haiway/__init__.py,sha256=hLc3-FDmNQEV4r-RLOiGjWtYSk7krU8vRMBaZyRU08g,1267
1
+ haiway/__init__.py,sha256=ll2vI5w5LYylT0jdTE8_clfQJ2rpL4GKh8tR3Lr80j0,1301
2
2
  haiway/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  haiway/context/__init__.py,sha256=21Y3zvRo1bHASZD6B_FNkU28k1-g88RdmUyqxvYXJxg,336
4
4
  haiway/context/access.py,sha256=zPQcQBp5XMlNuszbxhtzi-5mNpDLpZ6PT-gVFDBH0dA,14115
5
- haiway/context/disposables.py,sha256=VQX9jVo1pjqkmOYzWpsbYyF45y0XtpjorIIaeMBCwTU,1771
5
+ haiway/context/disposables.py,sha256=DZjnMp-wMfF-em2Wjhbm1MvXubNpuzFBT70BQNIxC7M,2019
6
6
  haiway/context/metrics.py,sha256=R6BIH3Pwtm_fQqPZmTei3nUGNDAZEnvUKaVxwjWxgS0,10755
7
7
  haiway/context/state.py,sha256=GxGwPQTK8FdSprBd83lQbA9veubp0o93_1Yk3gb7HMc,3000
8
8
  haiway/context/tasks.py,sha256=xXtXIUwXOra0EePTdkcEbMOmpWwFcO3hCRfR_IfvAHk,1978
9
9
  haiway/context/types.py,sha256=VvJA7wAPZ3ISpgyThVguioYUXqhHf0XkPfRd0M1ERiQ,142
10
- haiway/helpers/__init__.py,sha256=YYEORuo3xyce5_kGjfQVyaQHyp1dBh3ZlrZavR0hQzk,443
11
- haiway/helpers/asynchrony.py,sha256=FPqmFFRDtAn8migwYHFKViKHypNHZW3cJCrh9y03AwI,5526
10
+ haiway/helpers/__init__.py,sha256=ZKa1_xreEVRcYrPTuPn5MRe-WrVFZ_FojswEtMqD5Qw,473
11
+ haiway/helpers/asynchrony.py,sha256=rh_Hwo0MQHfKnw5dLUCFTAm3Fk3SVS8Or8cTcQFdPA8,6042
12
12
  haiway/helpers/caching.py,sha256=Ok_WE5Whe7XqnIuLZo4rNNBFeWap-aUWX799s4b1JAQ,9536
13
13
  haiway/helpers/retries.py,sha256=gIkyUlqJLDYaxIZd3qzeqGFY9y5Gp8dgZLlZ6hs8hoc,7538
14
14
  haiway/helpers/throttling.py,sha256=zo0OwFq64si5KUwhd58cFHLmGAmYwRbFRJMbv9suhPs,3844
@@ -16,7 +16,7 @@ haiway/helpers/timeouted.py,sha256=1xU09hQnFdj6p48BwZl5xUvtIr3zC0ZUXehkdrduCjs,3
16
16
  haiway/helpers/tracing.py,sha256=yiK8MdDyX_fmpK9Zu5-IiZae5E8ReKQtRBBenXIPVqQ,3326
17
17
  haiway/state/__init__.py,sha256=dh7l_ZImy0uHHDGD-fzMhQFmz_ej8WU8WEE2OmIoyVM,204
18
18
  haiway/state/attributes.py,sha256=kkIYNlvWCM1NkgiCbE6gZDwgBVOk_TkmqWv67MmU0to,13399
19
- haiway/state/structure.py,sha256=G-Ln72hoQtE0FmKHeZdNmXf_FA3f5-e5AGbmJ2yMNb4,7003
19
+ haiway/state/structure.py,sha256=l8iYMCLEg5v1JVMwZ4R-YAXoQQZWkbWZyN6LcnzKqPQ,7237
20
20
  haiway/state/validation.py,sha256=Z6kp_KjTnnP9eVWsLmzKkEQLZkhFCOSphjdbr6VxLFQ,3628
21
21
  haiway/types/__init__.py,sha256=cAJQzDgFi8AKRqpzY3HWrutaPR69tnJqeJK_mQVtYUk,252
22
22
  haiway/types/frozen.py,sha256=CZhFCXnWAKEhuWSfILxA8smfdpMd5Ku694ycfLh98R8,76
@@ -28,9 +28,9 @@ haiway/utils/immutable.py,sha256=K34ZIMzbkpgkHKH-KF73plEbXExsajNRkRTYp9nJEf4,620
28
28
  haiway/utils/logs.py,sha256=oDsc1ZdqKDjlTlctLbDcp9iX98Acr-1tdw-Pyg3DElo,1577
29
29
  haiway/utils/mimic.py,sha256=BkVjTVP2TxxC8GChPGyDV6UXVwJmiRiSWeOYZNZFHxs,1828
30
30
  haiway/utils/noop.py,sha256=qgbZlOKWY6_23Zs43OLukK2HagIQKRyR04zrFVm5rWI,344
31
- haiway/utils/queue.py,sha256=7gLpL07E4K_FnP1AygmpNnBpwfS5kgnw_6wakuRkmw4,2423
32
- haiway-0.4.0.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
33
- haiway-0.4.0.dist-info/METADATA,sha256=7inuv-8w44WoEhdlvmdPJkrbb-uz_pQ85KCpypIGf7w,3872
34
- haiway-0.4.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
35
- haiway-0.4.0.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
36
- haiway-0.4.0.dist-info/RECORD,,
31
+ haiway/utils/queue.py,sha256=oQ3GXCJ-PGNtMEr6EPdgqAvYZoj8lAa7Z2drBKBEoBM,2345
32
+ haiway-0.5.1.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
33
+ haiway-0.5.1.dist-info/METADATA,sha256=pI4SY2fIPlKlQzA-R5jXIPpg0Da0gyRaZQMZGipvh-U,3872
34
+ haiway-0.5.1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
35
+ haiway-0.5.1.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
36
+ haiway-0.5.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5