haiway 0.23.2__tar.gz → 0.24.0__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.
- haiway-0.24.0/CLAUDE.md +165 -0
- {haiway-0.23.2 → haiway-0.24.0}/PKG-INFO +1 -1
- {haiway-0.23.2 → haiway-0.24.0}/junit/test-results.xml +1 -1
- {haiway-0.23.2 → haiway-0.24.0}/pyproject.toml +1 -1
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/__init__.py +4 -2
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/access.py +9 -48
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/observability.py +2 -3
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/state.py +8 -2
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/types.py +0 -4
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/retries.py +2 -2
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/requirement.py +1 -1
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/types/__init__.py +2 -2
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/types/missing.py +66 -12
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/__init__.py +2 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/collections.py +4 -4
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/env.py +86 -7
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/formatting.py +1 -1
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/logs.py +9 -0
- haiway-0.24.0/uv.lock +491 -0
- haiway-0.23.2/CLAUDE.md +0 -163
- haiway-0.23.2/uv.lock +0 -491
- {haiway-0.23.2 → haiway-0.24.0}/.github/workflows/ci.yml +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/.github/workflows/publish.yml +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/.gitignore +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/LICENSE +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/Makefile +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/README.md +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/config/pre-push +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/guidelines/functionalities.md +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/guidelines/llms.txt +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/guidelines/packages.md +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/guidelines/state.md +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/__init__.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/disposables.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/identifier.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/context/tasks.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/__init__.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/asynchrony.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/caching.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/concurrent.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/files.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/observability.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/throttling.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/timeouting.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/helpers/tracing.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/opentelemetry/__init__.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/opentelemetry/observability.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/py.typed +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/__init__.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/attributes.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/path.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/structure.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/state/validation.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/types/default.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/always.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/mimic.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/noop.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/queue.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/src/haiway/utils/stream.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/__init__.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_async_queue.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_async_stream.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_attribute_path.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_attribute_requirement.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_auto_retry.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_cache.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_context.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_disposables.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_process_concurrently.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_state.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_state_validation.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_streaming.py +0 -0
- {haiway-0.23.2 → haiway-0.24.0}/tests/test_timeout.py +0 -0
haiway-0.24.0/CLAUDE.md
ADDED
@@ -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.
|
3
|
+
Version: 0.24.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 +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="159" time="1.980" timestamp="2025-07-04T08:00:18.241083+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.021" /><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.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.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.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.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>
|
@@ -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.
|
8
|
+
version = "0.24.0"
|
9
9
|
readme = "README.md"
|
10
10
|
maintainers = [
|
11
11
|
{ name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
|
@@ -32,7 +32,7 @@ from haiway.types import (
|
|
32
32
|
Missing,
|
33
33
|
is_missing,
|
34
34
|
not_missing,
|
35
|
-
|
35
|
+
unwrap_missing,
|
36
36
|
)
|
37
37
|
from haiway.utils import (
|
38
38
|
AsyncQueue,
|
@@ -44,6 +44,7 @@ from haiway.utils import (
|
|
44
44
|
as_tuple,
|
45
45
|
async_always,
|
46
46
|
async_noop,
|
47
|
+
getenv,
|
47
48
|
getenv_base64,
|
48
49
|
getenv_bool,
|
49
50
|
getenv_float,
|
@@ -89,6 +90,7 @@ __all__ = (
|
|
89
90
|
"asynchronous",
|
90
91
|
"cache",
|
91
92
|
"ctx",
|
93
|
+
"getenv",
|
92
94
|
"getenv_base64",
|
93
95
|
"getenv_bool",
|
94
96
|
"getenv_float",
|
@@ -104,6 +106,6 @@ __all__ = (
|
|
104
106
|
"throttle",
|
105
107
|
"timeout",
|
106
108
|
"traced",
|
107
|
-
"
|
109
|
+
"unwrap_missing",
|
108
110
|
"without_missing",
|
109
111
|
)
|
@@ -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
|
-
|
489
|
-
|
490
|
-
|
448
|
+
async with stream_scope:
|
449
|
+
try:
|
450
|
+
async for result in source(*args, **kwargs):
|
451
|
+
await output_stream.send(result)
|
491
452
|
|
492
|
-
|
493
|
-
|
453
|
+
except BaseException as exc:
|
454
|
+
output_stream.finish(exception=exc)
|
494
455
|
|
495
|
-
|
496
|
-
|
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__
|
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__
|
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__ = (
|
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(
|
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
|
@@ -207,7 +207,7 @@ def _wrap_sync[**Args, Result](
|
|
207
207
|
case float(strict):
|
208
208
|
sleep_sync(strict)
|
209
209
|
|
210
|
-
case make_delay:
|
210
|
+
case make_delay:
|
211
211
|
sleep_sync(make_delay(attempt, exc)) # pyright: ignore[reportCallIssue, reportUnknownArgumentType]
|
212
212
|
|
213
213
|
else:
|
@@ -253,7 +253,7 @@ def _wrap_async[**Args, Result](
|
|
253
253
|
case float(strict):
|
254
254
|
await sleep(strict)
|
255
255
|
|
256
|
-
case make_delay:
|
256
|
+
case make_delay:
|
257
257
|
await sleep(make_delay(attempt, exc)) # pyright: ignore[reportCallIssue, reportUnknownArgumentType]
|
258
258
|
|
259
259
|
else:
|
@@ -100,7 +100,7 @@ class AttributeRequirement[Root]:
|
|
100
100
|
), "Prepare attribute path by using Self._.path.to.property or explicitly"
|
101
101
|
|
102
102
|
def check_text_match(root: Root) -> None:
|
103
|
-
checked: Any =
|
103
|
+
checked: Any = path(root)
|
104
104
|
if not isinstance(checked, str):
|
105
105
|
raise ValueError(
|
106
106
|
f"Attribute value must be a string for like operation, got {type(checked)}"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from haiway.types.default import Default, DefaultValue
|
2
|
-
from haiway.types.missing import MISSING, Missing, is_missing, not_missing,
|
2
|
+
from haiway.types.missing import MISSING, Missing, is_missing, not_missing, unwrap_missing
|
3
3
|
|
4
4
|
__all__ = (
|
5
5
|
"MISSING",
|
@@ -8,5 +8,5 @@ __all__ = (
|
|
8
8
|
"Missing",
|
9
9
|
"is_missing",
|
10
10
|
"not_missing",
|
11
|
-
"
|
11
|
+
"unwrap_missing",
|
12
12
|
)
|
@@ -1,11 +1,12 @@
|
|
1
|
-
from
|
1
|
+
from collections.abc import Callable
|
2
|
+
from typing import Any, Final, TypeGuard, cast, final, overload
|
2
3
|
|
3
4
|
__all__ = (
|
4
5
|
"MISSING",
|
5
6
|
"Missing",
|
6
7
|
"is_missing",
|
7
8
|
"not_missing",
|
8
|
-
"
|
9
|
+
"unwrap_missing",
|
9
10
|
)
|
10
11
|
|
11
12
|
|
@@ -147,11 +148,12 @@ def not_missing[Value](
|
|
147
148
|
return check is not MISSING
|
148
149
|
|
149
150
|
|
150
|
-
|
151
|
+
@overload
|
152
|
+
def unwrap_missing[Value](
|
151
153
|
check: Value | Missing,
|
152
154
|
/,
|
153
155
|
*,
|
154
|
-
|
156
|
+
default: Value,
|
155
157
|
) -> Value:
|
156
158
|
"""
|
157
159
|
Substitute a default value when the input is MISSING.
|
@@ -162,10 +164,10 @@ def when_missing[Value](
|
|
162
164
|
|
163
165
|
Parameters
|
164
166
|
----------
|
165
|
-
|
166
|
-
The value to check
|
167
|
-
|
168
|
-
The default value to use if check is MISSING
|
167
|
+
value : Value | Missing
|
168
|
+
The value to check.
|
169
|
+
default : Value
|
170
|
+
The default value to use if check is MISSING.
|
169
171
|
|
170
172
|
Returns
|
171
173
|
-------
|
@@ -175,13 +177,65 @@ def when_missing[Value](
|
|
175
177
|
Examples
|
176
178
|
--------
|
177
179
|
```python
|
178
|
-
result =
|
180
|
+
result = unwrap_missing(optional_value, default=default_value)
|
179
181
|
# result will be default_value if optional_value is MISSING
|
180
182
|
# otherwise it will be optional_value
|
181
183
|
```
|
182
184
|
"""
|
183
|
-
|
184
|
-
|
185
|
+
|
186
|
+
|
187
|
+
@overload
|
188
|
+
def unwrap_missing[Value, Mapped](
|
189
|
+
value: Value | Missing,
|
190
|
+
/,
|
191
|
+
*,
|
192
|
+
default: Mapped,
|
193
|
+
mapping: Callable[[Value], Mapped],
|
194
|
+
) -> Value | Mapped:
|
195
|
+
"""
|
196
|
+
Substitute a default value when the input is MISSING or map the original.
|
197
|
+
|
198
|
+
This function provides a convenient way to replace the MISSING
|
199
|
+
sentinel with a default value, similar to how the or operator
|
200
|
+
works with None but specifically for the MISSING sentinel.
|
201
|
+
Original value is mapped using provided function when not missing.
|
202
|
+
|
203
|
+
Parameters
|
204
|
+
----------
|
205
|
+
value : Value | Missing
|
206
|
+
The value to check.
|
207
|
+
default : Mapped
|
208
|
+
The default value to use if check is MISSING.
|
209
|
+
mapping: Callable[[Value], Result] | None = None
|
210
|
+
Mapping to apply to the value.
|
211
|
+
|
212
|
+
Returns
|
213
|
+
-------
|
214
|
+
Mapped
|
215
|
+
The original value with mapping applied if not MISSING, otherwise the provided default.
|
216
|
+
|
217
|
+
Examples
|
218
|
+
--------
|
219
|
+
```python
|
220
|
+
result = unwrap_missing(optional_value, default=default_value, mapping=value_map)
|
221
|
+
# result will be default_value if optional_value is MISSING
|
222
|
+
# otherwise it will be optional_value after mapping
|
223
|
+
```
|
224
|
+
"""
|
225
|
+
|
226
|
+
|
227
|
+
def unwrap_missing[Value, Mapped](
|
228
|
+
value: Value | Missing,
|
229
|
+
/,
|
230
|
+
*,
|
231
|
+
default: Value | Mapped,
|
232
|
+
mapping: Callable[[Value], Mapped] | None = None,
|
233
|
+
) -> Value | Mapped:
|
234
|
+
if value is MISSING:
|
235
|
+
return default
|
236
|
+
|
237
|
+
elif mapping is not None:
|
238
|
+
return mapping(cast(Value, value))
|
185
239
|
|
186
240
|
else:
|
187
|
-
return cast(Value,
|
241
|
+
return cast(Value, value)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from haiway.utils.always import always, async_always
|
2
2
|
from haiway.utils.collections import as_dict, as_list, as_set, as_tuple, without_missing
|
3
3
|
from haiway.utils.env import (
|
4
|
+
getenv,
|
4
5
|
getenv_base64,
|
5
6
|
getenv_bool,
|
6
7
|
getenv_float,
|
@@ -26,6 +27,7 @@ __all__ = (
|
|
26
27
|
"async_always",
|
27
28
|
"async_noop",
|
28
29
|
"format_str",
|
30
|
+
"getenv",
|
29
31
|
"getenv_base64",
|
30
32
|
"getenv_bool",
|
31
33
|
"getenv_float",
|