haiway 0.23.2__tar.gz → 0.24.1__tar.gz

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.
Files changed (76) hide show
  1. haiway-0.24.1/.claude/settings.json +15 -0
  2. haiway-0.24.1/CLAUDE.md +165 -0
  3. {haiway-0.23.2 → haiway-0.24.1}/PKG-INFO +1 -1
  4. {haiway-0.23.2 → haiway-0.24.1}/junit/test-results.xml +1 -1
  5. {haiway-0.23.2 → haiway-0.24.1}/pyproject.toml +1 -1
  6. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/__init__.py +6 -2
  7. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/access.py +9 -48
  8. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/observability.py +2 -3
  9. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/state.py +8 -2
  10. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/types.py +0 -4
  11. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/__init__.py +2 -1
  12. haiway-0.24.1/src/haiway/helpers/concurrent.py +394 -0
  13. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/retries.py +2 -2
  14. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/requirement.py +1 -1
  15. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/types/__init__.py +2 -2
  16. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/types/missing.py +66 -12
  17. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/__init__.py +2 -0
  18. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/collections.py +4 -4
  19. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/env.py +86 -7
  20. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/formatting.py +1 -1
  21. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/logs.py +9 -0
  22. haiway-0.24.1/tests/test_execute_concurrently.py +198 -0
  23. {haiway-0.23.2 → haiway-0.24.1}/tests/test_process_concurrently.py +0 -2
  24. haiway-0.24.1/tests/test_stream_concurrently.py +281 -0
  25. {haiway-0.23.2 → haiway-0.24.1}/uv.lock +90 -90
  26. haiway-0.23.2/CLAUDE.md +0 -163
  27. haiway-0.23.2/src/haiway/helpers/concurrent.py +0 -85
  28. {haiway-0.23.2 → haiway-0.24.1}/.github/workflows/ci.yml +0 -0
  29. {haiway-0.23.2 → haiway-0.24.1}/.github/workflows/publish.yml +0 -0
  30. {haiway-0.23.2 → haiway-0.24.1}/.gitignore +0 -0
  31. {haiway-0.23.2 → haiway-0.24.1}/LICENSE +0 -0
  32. {haiway-0.23.2 → haiway-0.24.1}/Makefile +0 -0
  33. {haiway-0.23.2 → haiway-0.24.1}/README.md +0 -0
  34. {haiway-0.23.2 → haiway-0.24.1}/config/pre-push +0 -0
  35. {haiway-0.23.2 → haiway-0.24.1}/guidelines/functionalities.md +0 -0
  36. {haiway-0.23.2 → haiway-0.24.1}/guidelines/llms.txt +0 -0
  37. {haiway-0.23.2 → haiway-0.24.1}/guidelines/packages.md +0 -0
  38. {haiway-0.23.2 → haiway-0.24.1}/guidelines/state.md +0 -0
  39. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/__init__.py +0 -0
  40. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/disposables.py +0 -0
  41. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/identifier.py +0 -0
  42. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/context/tasks.py +0 -0
  43. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/asynchrony.py +0 -0
  44. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/caching.py +0 -0
  45. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/files.py +0 -0
  46. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/observability.py +0 -0
  47. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/throttling.py +0 -0
  48. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/timeouting.py +0 -0
  49. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/helpers/tracing.py +0 -0
  50. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/opentelemetry/__init__.py +0 -0
  51. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/opentelemetry/observability.py +0 -0
  52. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/py.typed +0 -0
  53. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/__init__.py +0 -0
  54. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/attributes.py +0 -0
  55. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/path.py +0 -0
  56. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/structure.py +0 -0
  57. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/state/validation.py +0 -0
  58. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/types/default.py +0 -0
  59. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/always.py +0 -0
  60. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/mimic.py +0 -0
  61. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/noop.py +0 -0
  62. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/queue.py +0 -0
  63. {haiway-0.23.2 → haiway-0.24.1}/src/haiway/utils/stream.py +0 -0
  64. {haiway-0.23.2 → haiway-0.24.1}/tests/__init__.py +0 -0
  65. {haiway-0.23.2 → haiway-0.24.1}/tests/test_async_queue.py +0 -0
  66. {haiway-0.23.2 → haiway-0.24.1}/tests/test_async_stream.py +0 -0
  67. {haiway-0.23.2 → haiway-0.24.1}/tests/test_attribute_path.py +0 -0
  68. {haiway-0.23.2 → haiway-0.24.1}/tests/test_attribute_requirement.py +0 -0
  69. {haiway-0.23.2 → haiway-0.24.1}/tests/test_auto_retry.py +0 -0
  70. {haiway-0.23.2 → haiway-0.24.1}/tests/test_cache.py +0 -0
  71. {haiway-0.23.2 → haiway-0.24.1}/tests/test_context.py +0 -0
  72. {haiway-0.23.2 → haiway-0.24.1}/tests/test_disposables.py +0 -0
  73. {haiway-0.23.2 → haiway-0.24.1}/tests/test_state.py +0 -0
  74. {haiway-0.23.2 → haiway-0.24.1}/tests/test_state_validation.py +0 -0
  75. {haiway-0.23.2 → haiway-0.24.1}/tests/test_streaming.py +0 -0
  76. {haiway-0.23.2 → haiway-0.24.1}/tests/test_timeout.py +0 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Write|Edit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "source .venv/bin/activate && make format"
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,165 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Setup
8
+
9
+ - `make venv` - Setup development environment and install git hooks
10
+ - `source .venv/bin/activate && make sync` - Sync dependencies with uv lock file
11
+ - `source .venv/bin/activate && make update` - Update and lock dependencies
12
+
13
+ ### Code Quality
14
+
15
+ - `source .venv/bin/activate && make format` - Format code with Ruff
16
+ - `source .venv/bin/activate && make lint` - Run linters (Ruff + Bandit + Pyright strict mode)
17
+ - `source .venv/bin/activate && make test` - Run pytest with coverage
18
+ - `source .venv/bin/activate && pytest tests/test_specific.py` - Run single test file
19
+ - `source .venv/bin/activate && pytest tests/test_specific.py::test_function` - Run specific test
20
+
21
+ ## Architecture Overview
22
+
23
+ Haiway is a Python framework (3.12+) designed for functional programming with structured concurrency. It emphasizes:
24
+
25
+ 1. **Immutable State Management**: Type-safe, immutable data structures with validation
26
+ 2. **Context-based Dependency Injection**: Safe state propagation in concurrent environments
27
+ 3. **Functional Approach**: Pure functions over objects with methods
28
+ 4. **Structured Concurrency**: Automatic task management and resource cleanup
29
+
30
+ ### Core Components
31
+
32
+ - **Context System**: Scoped execution environments with state access, task management, and observability
33
+ - **State Management**: Immutable data structures with validation, generic type support, and path-based access
34
+ - **Helpers**: Async utilities, caching, retries, timeouts, tracing, and concurrent operations
35
+ - **Types**: Base type definitions and missing value handling
36
+ - **OpenTelemetry Integration**: Optional distributed tracing support
37
+
38
+ ### Code Style
39
+
40
+ - Use absolute imports from `haiway` package
41
+ - Put exported symbols into `__init__.py`
42
+ - Follow Ruff import ordering (standard library, third party, local)
43
+ - Use Python 3.12+ type features (type unions with `|`, generic syntax)
44
+ - Use base and abstract types like `Sequence` or `Iterable` instead of concrete
45
+ - Use custom exceptions for specific errors
46
+
47
+ ### Testing Guidelines
48
+
49
+ - Uses pytest with async support. Tests are in `tests/` directory.
50
+ - Mock dependencies within scope using stubbed functionality state.
51
+
52
+ ## Examples
53
+
54
+ ### Immutability Rules
55
+
56
+ **ALWAYS use these types for collections in State classes:**
57
+ - Use `Sequence[T]` instead of `list[T]` (becomes tuple)
58
+ - Use `Mapping[K,V]` instead of `dict[K,V]` (becomes immutable)
59
+ - Use `Set[T]` instead of `set[T]` (becomes frozenset)
60
+
61
+ ```python
62
+ from typing import Sequence, Mapping, Set
63
+ from haiway import State
64
+
65
+ class UserData(State):
66
+ roles: Sequence[str] # Will be tuple
67
+ metadata: Mapping[str, Any] # Will be immutable
68
+ tags: Set[str] # Will be frozenset
69
+
70
+ ```
71
+
72
+ ### State Definition Patterns
73
+
74
+ ```python
75
+ from typing import Protocol, runtime_checkable
76
+ from haiway import State
77
+
78
+ # Basic data structure
79
+ class UserData(State):
80
+ id: str
81
+ name: str
82
+ email: str | None = None
83
+
84
+ # Generic state classes
85
+ class Container[Element](State):
86
+ items: Sequence[Element]
87
+ metadata: Mapping[str, Any]
88
+
89
+ # Function protocol
90
+ @runtime_checkable
91
+ class UserFetching(Protocol):
92
+ async def __call__(self, id: str) -> UserData: ...
93
+
94
+ # Functionality state pattern used for dependency injection
95
+ class UserService(State):
96
+ # Function implementations
97
+ user_fetching: UserFetching
98
+
99
+ # Class method interface to access functions within context
100
+ @classmethod
101
+ async def fetch_user(cls, *, id: str) -> UserData:
102
+ return await ctx.state(cls).user_fetching(id)
103
+ ```
104
+
105
+ ### State Updates
106
+
107
+ ```python
108
+ # Immutable updates through copy
109
+ user: UserData = ...
110
+ updated_user: UserData = user.updated(name="Updated")
111
+ ```
112
+
113
+ ### Resource Management
114
+
115
+ ```python
116
+ from contextlib import asynccontextmanager
117
+ from haiway import ctx, State
118
+
119
+ class ResourceAccess(State):
120
+ accessing: ResourceAccessing
121
+
122
+ @classmethod
123
+ def access(cls) -> ResourceData:
124
+ return ctx.state(cls).accessing()
125
+
126
+ @asynccontextmanager
127
+ async def create_resource_disposable():
128
+ # Create a disposable resource
129
+ resource: ResourceHandle = await open_resource()
130
+ try:
131
+ # Yield the state that will be made available in the context
132
+ yield ResourceState(accessing=resource.access)
133
+
134
+ finally:
135
+ # Cleanup happens automatically when context exits
136
+ await resource.close()
137
+
138
+ # Resources are automatically cleaned up and their state included in context
139
+ async with ctx.scope(
140
+ "work",
141
+ disposables=(create_resource_disposable(),)
142
+ ):
143
+ # ResourceAccess is now available in the context
144
+ resource_data: ResourceData = ResourceAccess.access()
145
+ # Cleanup happens automatically here
146
+ ```
147
+
148
+ ## Testing Patterns
149
+
150
+ ```python
151
+ import pytest
152
+ from haiway import ctx
153
+
154
+ @pytest.mark.asyncio
155
+ async def test_functionality():
156
+ # Set up test context
157
+ async with ctx.scope("test", TestState(value="test")):
158
+ result = await some_function()
159
+ assert result == expected_result
160
+
161
+ @pytest.mark.asyncio
162
+ async def test_with_mock():
163
+ async with ctx.scope("test", ServiceState(fetching=mock_fetching)):
164
+ # Test with mocked service
165
+ ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haiway
3
- Version: 0.23.2
3
+ Version: 0.24.1
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 +1 @@
1
- <?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="159" time="1.921" timestamp="2025-06-25T10:38:07.414407+00:00" hostname="pkrvmxyh4eaekms"><testcase classname="tests.test_async_queue" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_queue" name="test_buffers_values_when_not_reading" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_buffer_when_streaming_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_queue" name="test_fails_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_stream" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_stream" name="test_finishes_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_failed" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_all_when_sending_async" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_id_path_points_to_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_points_to_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_id_path_set_updates_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_set_updates_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_equal_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_not_equal_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contains_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contains_any_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contained_in_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_logical_and_or_requirements" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_filter" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_immutability" time="0.000" /><testcase classname="tests.test_auto_retry" name="test_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_logs_issue_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_when_cancelled" time="0.021" /><testcase classname="tests.test_auto_retry" name="test_async_uses_delay_with_errors" time="0.102" /><testcase classname="tests.test_auto_retry" name="test_async_uses_computed_delay_with_errors" time="0.107" /><testcase classname="tests.test_auto_retry" name="test_async_logs_issue_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_cache_value_with_same_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_different_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_limit_exceed" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_same_value_with_repeating_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_fails_with_error" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_expiration_time_exceed" time="0.020" /><testcase classname="tests.test_cache" name="test_async_returns_cache_value_with_same_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_different_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_limit_exceed" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_same_value_with_repeating_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_expiration_time_exceed" time="0.021" /><testcase classname="tests.test_cache" name="test_async_cancel_waiting_does_not_cancel_task" time="0.502" /><testcase classname="tests.test_cache" name="test_async_expiration_does_not_cancel_task" time="0.021" /><testcase classname="tests.test_cache" name="test_async_fails_with_error" time="0.001" /><testcase classname="tests.test_context" name="test_state_is_available_according_to_context" time="0.001" /><testcase classname="tests.test_context" name="test_state_update_updates_local_context" time="0.001" /><testcase classname="tests.test_context" name="test_exceptions_are_propagated" time="0.001" /><testcase classname="tests.test_disposables" name="test_empty_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_single_disposable_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_multiple_disposables_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_cannot_set_attributes" time="0.001" /><testcase classname="tests.test_disposables" name="test_cannot_delete_attributes" time="0.000" /><testcase classname="tests.test_disposables" name="test_empty_disposables_is_falsy" time="0.000" /><testcase classname="tests.test_disposables" name="test_non_empty_disposables_is_truthy" time="0.000" /><testcase classname="tests.test_disposables" name="test_setup_with_no_disposables" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_none" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_single_state" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_multiple_states" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_multiple_disposables_mixed_returns" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_sets_loop_correctly" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_no_disposables" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_successful_cleanup" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_exception_context" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_multiple_exceptions_creates_group" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_single_exception_is_risen" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_resets_loop_even_on_exception" time="0.001" /><testcase classname="tests.test_disposables" name="test_same_loop_cleanup" time="0.001" /><testcase classname="tests.test_disposables" name="test_with_real_async_context_managers" time="0.001" /><testcase classname="tests.test_disposables" name="test_nested_disposables_usage" time="0.001" /><testcase classname="tests.test_disposables" name="test_exception_during_setup_phase" time="0.001" /><testcase classname="tests.test_disposables" name="test_assertion_on_doubleprepare" time="0.001" /><testcase classname="tests.test_disposables" name="test_assertion_on_dispose_withoutprepare" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_processes_all_elements" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_processes_elements_concurrently" time="0.302" /><testcase classname="tests.test_process_concurrently" name="test_handles_empty_source" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_propagates_handler_exceptions" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_ignores_handler_exceptions_when_configured" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_handles_source_exception" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_cancels_running_tasks_on_cancellation" time="0.101" /><testcase classname="tests.test_process_concurrently" name="test_respects_concurrency_limit" time="0.202" /><testcase classname="tests.test_process_concurrently" name="test_processes_elements_from_queue" time="0.052" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_basic_initializes_with_defaults" time="0.001" /><testcase classname="tests.test_state" name="test_basic_equals_checks_properties" time="0.000" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments_and_defaults" time="0.000" /><testcase classname="tests.test_state" name="test_parametrized_initializes_with_proper_parameters" time="0.000" /><testcase classname="tests.test_state" name="test_nested_initializes_with_proper_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_dict_skips_missing_properties" time="0.000" /><testcase classname="tests.test_state" name="test_initialization_allows_missing_properties" time="0.001" /><testcase classname="tests.test_state" name="test_generic_subtypes_validation" time="0.001" /><testcase classname="tests.test_state" name="test_copying_leaves_same_object" time="0.000" /><testcase classname="tests.test_state" name="test_hash_consistency_with_missing_values" time="0.001" /><testcase classname="tests.test_state" name="test_hash_with_unhashable_attributes" time="0.001" /><testcase classname="tests.test_state" name="test_hash_with_dict_key_order_independence" time="0.000" /><testcase classname="tests.test_state" name="test_hash_with_custom_objects" time="0.000" /><testcase classname="tests.test_state" name="test_hash_performance_with_many_attributes" time="0.001" /><testcase classname="tests.test_state" name="test_hash_with_nested_unhashable_collections" time="0.000" /><testcase classname="tests.test_state" name="test_hash_stability_across_instances" time="0.000" /><testcase classname="tests.test_state" name="test_hash_excludes_missing_values" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_basic_types" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_none_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_missing_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_literal_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_enum_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_sequence_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_set_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_mapping_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_tuple_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_union_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_callable_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_typed_dict" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_state_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_complex_types" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_recursive_state" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_generic_state" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validation_error_messages" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validation_any_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_with_defaults" time="0.000" /><testcase classname="tests.test_state_validation" name="test_attribute_validator_direct_usage" time="0.000" /><testcase classname="tests.test_state_validation" name="test_unsupported_type_annotation" time="0.000" /><testcase classname="tests.test_streaming" name="test_fails_when_generator_fails" time="0.001" /><testcase classname="tests.test_streaming" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_streaming" name="test_ends_when_generator_ends" time="0.001" /><testcase classname="tests.test_streaming" name="test_delivers_updates_when_generating" time="0.001" /><testcase classname="tests.test_streaming" name="test_streaming_context_variables_access_is_preserved" time="0.001" /><testcase classname="tests.test_streaming" name="test_nested_streaming_streams_correctly" time="0.001" /><testcase classname="tests.test_timeout" name="test_returns_result_when_returning_value" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_error" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_cancel" time="0.011" /><testcase classname="tests.test_timeout" name="test_raises_with_timeout" time="0.011" /></testsuite></testsuites>
1
+ <?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="180" time="3.753" timestamp="2025-07-07T16:07:26.640817+00:00" hostname="pkrvmbietmlfzoi"><testcase classname="tests.test_async_queue" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_queue" name="test_buffers_values_when_not_reading" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_buffer_when_streaming_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_queue" name="test_fails_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_stream" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_stream" name="test_finishes_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_failed" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_all_when_sending_async" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_id_path_points_to_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_points_to_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_id_path_set_updates_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_set_updates_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_equal_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_not_equal_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contains_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contains_any_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_contained_in_requirement" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_logical_and_or_requirements" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_filter" time="0.000" /><testcase classname="tests.test_attribute_requirement" name="test_immutability" time="0.000" /><testcase classname="tests.test_auto_retry" name="test_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_logs_issue_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_when_cancelled" time="0.021" /><testcase classname="tests.test_auto_retry" name="test_async_uses_delay_with_errors" time="0.101" /><testcase classname="tests.test_auto_retry" name="test_async_uses_computed_delay_with_errors" time="0.107" /><testcase classname="tests.test_auto_retry" name="test_async_logs_issue_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_cache_value_with_same_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_different_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_limit_exceed" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_same_value_with_repeating_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_fails_with_error" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_expiration_time_exceed" time="0.020" /><testcase classname="tests.test_cache" name="test_async_returns_cache_value_with_same_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_different_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_limit_exceed" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_same_value_with_repeating_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_expiration_time_exceed" time="0.021" /><testcase classname="tests.test_cache" name="test_async_cancel_waiting_does_not_cancel_task" time="0.502" /><testcase classname="tests.test_cache" name="test_async_expiration_does_not_cancel_task" time="0.021" /><testcase classname="tests.test_cache" name="test_async_fails_with_error" time="0.001" /><testcase classname="tests.test_context" name="test_state_is_available_according_to_context" time="0.001" /><testcase classname="tests.test_context" name="test_state_update_updates_local_context" time="0.001" /><testcase classname="tests.test_context" name="test_exceptions_are_propagated" time="0.001" /><testcase classname="tests.test_disposables" name="test_empty_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_single_disposable_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_multiple_disposables_initialization" time="0.000" /><testcase classname="tests.test_disposables" name="test_cannot_set_attributes" time="0.000" /><testcase classname="tests.test_disposables" name="test_cannot_delete_attributes" time="0.000" /><testcase classname="tests.test_disposables" name="test_empty_disposables_is_falsy" time="0.000" /><testcase classname="tests.test_disposables" name="test_non_empty_disposables_is_truthy" time="0.000" /><testcase classname="tests.test_disposables" name="test_setup_with_no_disposables" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_none" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_single_state" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_disposable_returning_multiple_states" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_with_multiple_disposables_mixed_returns" time="0.001" /><testcase classname="tests.test_disposables" name="test_setup_sets_loop_correctly" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_no_disposables" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_successful_cleanup" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_exception_context" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_multiple_exceptions_creates_group" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_with_single_exception_is_risen" time="0.001" /><testcase classname="tests.test_disposables" name="test_dispose_resets_loop_even_on_exception" time="0.001" /><testcase classname="tests.test_disposables" name="test_same_loop_cleanup" time="0.001" /><testcase classname="tests.test_disposables" name="test_with_real_async_context_managers" time="0.001" /><testcase classname="tests.test_disposables" name="test_nested_disposables_usage" time="0.001" /><testcase classname="tests.test_disposables" name="test_exception_during_setup_phase" time="0.001" /><testcase classname="tests.test_disposables" name="test_assertion_on_doubleprepare" time="0.001" /><testcase classname="tests.test_disposables" name="test_assertion_on_dispose_withoutprepare" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_processes_all_elements" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_preserves_order" time="0.302" /><testcase classname="tests.test_execute_concurrently" name="test_handles_empty_collection" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_propagates_handler_exceptions" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_returns_exceptions_when_configured" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_cancels_running_tasks_on_cancellation" time="0.101" /><testcase classname="tests.test_execute_concurrently" name="test_respects_concurrency_limit" time="0.202" /><testcase classname="tests.test_execute_concurrently" name="test_works_with_different_types" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_handles_mixed_success_and_failure" time="0.002" /><testcase classname="tests.test_execute_concurrently" name="test_works_with_sets_and_tuples" time="0.001" /><testcase classname="tests.test_execute_concurrently" name="test_exception_details_preserved" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_processes_all_elements" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_processes_elements_concurrently" time="0.302" /><testcase classname="tests.test_process_concurrently" name="test_handles_empty_source" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_propagates_handler_exceptions" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_ignores_handler_exceptions_when_configured" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_handles_source_exception" time="0.001" /><testcase classname="tests.test_process_concurrently" name="test_cancels_running_tasks_on_cancellation" time="0.101" /><testcase classname="tests.test_process_concurrently" name="test_respects_concurrency_limit" time="0.202" /><testcase classname="tests.test_process_concurrently" name="test_processes_elements_from_queue" time="0.052" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments" time="0.002" /><testcase classname="tests.test_state" name="test_basic_initializes_with_defaults" time="0.001" /><testcase classname="tests.test_state" name="test_basic_equals_checks_properties" time="0.000" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments_and_defaults" time="0.000" /><testcase classname="tests.test_state" name="test_parametrized_initializes_with_proper_parameters" time="0.000" /><testcase classname="tests.test_state" name="test_nested_initializes_with_proper_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_dict_skips_missing_properties" time="0.001" /><testcase classname="tests.test_state" name="test_initialization_allows_missing_properties" time="0.000" /><testcase classname="tests.test_state" name="test_generic_subtypes_validation" time="0.002" /><testcase classname="tests.test_state" name="test_copying_leaves_same_object" time="0.000" /><testcase classname="tests.test_state" name="test_hash_consistency_with_missing_values" time="0.000" /><testcase classname="tests.test_state" name="test_hash_with_unhashable_attributes" time="0.001" /><testcase classname="tests.test_state" name="test_hash_with_dict_key_order_independence" time="0.000" /><testcase classname="tests.test_state" name="test_hash_with_custom_objects" time="0.000" /><testcase classname="tests.test_state" name="test_hash_performance_with_many_attributes" time="0.001" /><testcase classname="tests.test_state" name="test_hash_with_nested_unhashable_collections" time="0.000" /><testcase classname="tests.test_state" name="test_hash_stability_across_instances" time="0.000" /><testcase classname="tests.test_state" name="test_hash_excludes_missing_values" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_basic_types" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_none_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_missing_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_literal_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_enum_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_sequence_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_set_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_mapping_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_tuple_type" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_union_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_callable_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_typed_dict" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_state_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_complex_types" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validator_recursive_state" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_generic_state" time="0.001" /><testcase classname="tests.test_state_validation" name="test_validation_error_messages" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validation_any_type" time="0.000" /><testcase classname="tests.test_state_validation" name="test_validator_with_defaults" time="0.000" /><testcase classname="tests.test_state_validation" name="test_attribute_validator_direct_usage" time="0.000" /><testcase classname="tests.test_state_validation" name="test_unsupported_type_annotation" time="0.000" /><testcase classname="tests.test_stream_concurrently" name="test_merges_two_streams" time="0.001" /><testcase classname="tests.test_stream_concurrently" name="test_interleaves_based_on_timing" time="0.152" /><testcase classname="tests.test_stream_concurrently" name="test_handles_empty_iterators" time="0.001" /><testcase classname="tests.test_stream_concurrently" name="test_handles_different_lengths" time="0.001" /><testcase classname="tests.test_stream_concurrently" name="test_propagates_exceptions_from_source_a" time="0.012" /><testcase classname="tests.test_stream_concurrently" name="test_propagates_exceptions_from_source_b" time="0.001" /><testcase classname="tests.test_stream_concurrently" name="test_cancellation_cancels_both_sources" time="0.202" /><testcase classname="tests.test_stream_concurrently" name="test_works_with_different_types" time="0.001" /><testcase classname="tests.test_stream_concurrently" name="test_immediate_yield" time="0.601" /><testcase classname="tests.test_stream_concurrently" name="test_concurrent_execution" time="0.201" /><testcase classname="tests.test_streaming" name="test_fails_when_generator_fails" time="0.001" /><testcase classname="tests.test_streaming" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_streaming" name="test_ends_when_generator_ends" time="0.001" /><testcase classname="tests.test_streaming" name="test_delivers_updates_when_generating" time="0.001" /><testcase classname="tests.test_streaming" name="test_streaming_context_variables_access_is_preserved" time="0.001" /><testcase classname="tests.test_streaming" name="test_nested_streaming_streams_correctly" time="0.001" /><testcase classname="tests.test_timeout" name="test_returns_result_when_returning_value" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_error" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_cancel" time="0.011" /><testcase classname="tests.test_timeout" name="test_raises_with_timeout" time="0.011" /></testsuite></testsuites>
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
  [project]
6
6
  name = "haiway"
7
7
  description = "Framework for dependency injection and state management within structured concurrency model."
8
- version = "0.23.2"
8
+ version = "0.24.1"
9
9
  readme = "README.md"
10
10
  maintainers = [
11
11
  { name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
@@ -18,6 +18,7 @@ from haiway.helpers import (
18
18
  LoggerObservability,
19
19
  asynchronous,
20
20
  cache,
21
+ execute_concurrently,
21
22
  process_concurrently,
22
23
  retry,
23
24
  throttle,
@@ -32,7 +33,7 @@ from haiway.types import (
32
33
  Missing,
33
34
  is_missing,
34
35
  not_missing,
35
- when_missing,
36
+ unwrap_missing,
36
37
  )
37
38
  from haiway.utils import (
38
39
  AsyncQueue,
@@ -44,6 +45,7 @@ from haiway.utils import (
44
45
  as_tuple,
45
46
  async_always,
46
47
  async_noop,
48
+ getenv,
47
49
  getenv_base64,
48
50
  getenv_bool,
49
51
  getenv_float,
@@ -89,6 +91,8 @@ __all__ = (
89
91
  "asynchronous",
90
92
  "cache",
91
93
  "ctx",
94
+ "execute_concurrently",
95
+ "getenv",
92
96
  "getenv_base64",
93
97
  "getenv_bool",
94
98
  "getenv_float",
@@ -104,6 +108,6 @@ __all__ = (
104
108
  "throttle",
105
109
  "timeout",
106
110
  "traced",
107
- "when_missing",
111
+ "unwrap_missing",
108
112
  "without_missing",
109
113
  )
@@ -3,7 +3,6 @@ from asyncio import (
3
3
  Task,
4
4
  TaskGroup,
5
5
  current_task,
6
- iscoroutinefunction,
7
6
  )
8
7
  from collections.abc import (
9
8
  AsyncGenerator,
@@ -28,7 +27,6 @@ from haiway.context.observability import (
28
27
  from haiway.context.state import ScopeState, StateContext
29
28
  from haiway.context.tasks import TaskGroupContext
30
29
  from haiway.state import State
31
- from haiway.utils import mimic_function
32
30
  from haiway.utils.stream import AsyncStream
33
31
 
34
32
  __all__ = ("ctx",)
@@ -218,44 +216,6 @@ class ScopeContext:
218
216
  exc_tb=exc_tb,
219
217
  )
220
218
 
221
- @overload
222
- def __call__[Result, **Arguments](
223
- self,
224
- function: Callable[Arguments, Coroutine[Any, Any, Result]],
225
- ) -> Callable[Arguments, Coroutine[Any, Any, Result]]: ...
226
-
227
- @overload
228
- def __call__[Result, **Arguments](
229
- self,
230
- function: Callable[Arguments, Result],
231
- ) -> Callable[Arguments, Result]: ...
232
-
233
- def __call__[Result, **Arguments](
234
- self,
235
- function: Callable[Arguments, Coroutine[Any, Any, Result]] | Callable[Arguments, Result],
236
- ) -> Callable[Arguments, Coroutine[Any, Any, Result]] | Callable[Arguments, Result]:
237
- if iscoroutinefunction(function):
238
-
239
- async def async_context(
240
- *args: Arguments.args,
241
- **kwargs: Arguments.kwargs,
242
- ) -> Result:
243
- async with self:
244
- return await function(*args, **kwargs)
245
-
246
- return mimic_function(function, within=async_context)
247
-
248
- else:
249
-
250
- def sync_context(
251
- *args: Arguments.args,
252
- **kwargs: Arguments.kwargs,
253
- ) -> Result:
254
- with self:
255
- return function(*args, **kwargs) # pyright: ignore[reportReturnType]
256
-
257
- return mimic_function(function, within=sync_context) # pyright: ignore[reportReturnType]
258
-
259
219
 
260
220
  @final
261
221
  class ctx:
@@ -482,18 +442,19 @@ class ctx:
482
442
  """
483
443
 
484
444
  output_stream = AsyncStream[Element]()
445
+ stream_scope: ScopeContext = ctx.scope("stream")
485
446
 
486
- @ctx.scope("stream")
487
447
  async def stream() -> None:
488
- try:
489
- async for result in source(*args, **kwargs):
490
- await output_stream.send(result)
448
+ async with stream_scope:
449
+ try:
450
+ async for result in source(*args, **kwargs):
451
+ await output_stream.send(result)
491
452
 
492
- except BaseException as exc:
493
- output_stream.finish(exception=exc)
453
+ except BaseException as exc:
454
+ output_stream.finish(exception=exc)
494
455
 
495
- else:
496
- output_stream.finish()
456
+ else:
457
+ output_stream.finish()
497
458
 
498
459
  TaskGroupContext.run(stream)
499
460
  return output_stream
@@ -11,7 +11,6 @@ from typing import Any, Protocol, Self, final, runtime_checkable
11
11
  from uuid import UUID, uuid4
12
12
 
13
13
  from haiway.context.identifier import ScopeIdentifier
14
- from haiway.state import State
15
14
  from haiway.types import Missing
16
15
  from haiway.utils.formatting import format_str
17
16
 
@@ -166,7 +165,7 @@ class ObservabilityScopeEntering(Protocol):
166
165
  Implementations should record when execution enters a new scope.
167
166
  """
168
167
 
169
- def __call__[Metric: State](
168
+ def __call__(
170
169
  self,
171
170
  scope: ScopeIdentifier,
172
171
  /,
@@ -182,7 +181,7 @@ class ObservabilityScopeExiting(Protocol):
182
181
  including any exceptions that caused the exit.
183
182
  """
184
183
 
185
- def __call__[Metric: State](
184
+ def __call__(
186
185
  self,
187
186
  scope: ScopeIdentifier,
188
187
  /,
@@ -25,7 +25,10 @@ class ScopeState:
25
25
  This class is immutable after initialization.
26
26
  """
27
27
 
28
- __slots__ = ("_lock", "_state")
28
+ __slots__ = (
29
+ "_lock",
30
+ "_state",
31
+ )
29
32
 
30
33
  def __init__(
31
34
  self,
@@ -271,7 +274,10 @@ class StateContext:
271
274
  If state not found and default not provided or instantiation fails
272
275
  """
273
276
  try:
274
- return cls._context.get().state(state, default=default)
277
+ return cls._context.get().state(
278
+ state,
279
+ default=default,
280
+ )
275
281
 
276
282
  except LookupError as exc:
277
283
  raise MissingContext("StateContext requested but not defined!") from exc
@@ -13,8 +13,6 @@ class MissingContext(Exception):
13
13
  identifiers when no context has been established.
14
14
  """
15
15
 
16
- pass
17
-
18
16
 
19
17
  class MissingState(Exception):
20
18
  """
@@ -24,5 +22,3 @@ class MissingState(Exception):
24
22
  that is not present in the current context and cannot be automatically
25
23
  created (either because no default was provided or instantiation failed).
26
24
  """
27
-
28
- pass
@@ -1,6 +1,6 @@
1
1
  from haiway.helpers.asynchrony import asynchronous
2
2
  from haiway.helpers.caching import CacheMakeKey, CacheRead, CacheWrite, cache
3
- from haiway.helpers.concurrent import process_concurrently
3
+ from haiway.helpers.concurrent import execute_concurrently, process_concurrently
4
4
  from haiway.helpers.files import File, FileAccess
5
5
  from haiway.helpers.observability import LoggerObservability
6
6
  from haiway.helpers.retries import retry
@@ -17,6 +17,7 @@ __all__ = (
17
17
  "LoggerObservability",
18
18
  "asynchronous",
19
19
  "cache",
20
+ "execute_concurrently",
20
21
  "process_concurrently",
21
22
  "retry",
22
23
  "throttle",