haiway 0.21.2__tar.gz → 0.21.4__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 (112) hide show
  1. {haiway-0.21.2 → haiway-0.21.4}/PKG-INFO +1 -1
  2. {haiway-0.21.2 → haiway-0.21.4}/junit/test-results.xml +1 -1
  3. {haiway-0.21.2 → haiway-0.21.4}/pyproject.toml +1 -1
  4. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/requirement.py +82 -1
  5. {haiway-0.21.2 → haiway-0.21.4}/uv.lock +1 -1
  6. {haiway-0.21.2 → haiway-0.21.4}/.github/workflows/ci.yml +0 -0
  7. {haiway-0.21.2 → haiway-0.21.4}/.github/workflows/publish.yml +0 -0
  8. {haiway-0.21.2 → haiway-0.21.4}/.gitignore +0 -0
  9. {haiway-0.21.2 → haiway-0.21.4}/CLAUDE.md +0 -0
  10. {haiway-0.21.2 → haiway-0.21.4}/LICENSE +0 -0
  11. {haiway-0.21.2 → haiway-0.21.4}/Makefile +0 -0
  12. {haiway-0.21.2 → haiway-0.21.4}/README.md +0 -0
  13. {haiway-0.21.2 → haiway-0.21.4}/config/pre-push +0 -0
  14. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/.dockerignore +0 -0
  15. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/Dockerfile +0 -0
  16. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/Makefile +0 -0
  17. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/README.md +0 -0
  18. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/config/.env.example +0 -0
  19. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/config/unit.json +0 -0
  20. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/docker-compose.yml +0 -0
  21. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/pyproject.toml +0 -0
  22. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/__int__.py +0 -0
  23. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/todos/__init__.py +0 -0
  24. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/todos/config.py +0 -0
  25. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/todos/state.py +0 -0
  26. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/todos/types.py +0 -0
  27. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/features/todos/user_tasks.py +0 -0
  28. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/__init__.py +0 -0
  29. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/postgres/__init__.py +0 -0
  30. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/postgres/client.py +0 -0
  31. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/postgres/config.py +0 -0
  32. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/postgres/state.py +0 -0
  33. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/integrations/postgres/types.py +0 -0
  34. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/__init__.py +0 -0
  35. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/__main__.py +0 -0
  36. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/postgres/__init__.py +0 -0
  37. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/postgres/execution.py +0 -0
  38. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/postgres/migration_0.py +0 -0
  39. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/migrations/postgres/types.py +0 -0
  40. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/__init__.py +0 -0
  41. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/__main__.py +0 -0
  42. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/application.py +0 -0
  43. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/config.py +0 -0
  44. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/middlewares/__init__.py +0 -0
  45. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/middlewares/context.py +0 -0
  46. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/routes/__init__.py +0 -0
  47. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/routes/technical.py +0 -0
  48. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/server/routes/todos.py +0 -0
  49. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/__init__.py +0 -0
  50. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/user_tasks/__init__.py +0 -0
  51. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/user_tasks/config.py +0 -0
  52. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/user_tasks/postgres.py +0 -0
  53. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/user_tasks/state.py +0 -0
  54. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/src/solutions/user_tasks/types.py +0 -0
  55. {haiway-0.21.2 → haiway-0.21.4}/examples/fastAPI/uv.lock +0 -0
  56. {haiway-0.21.2 → haiway-0.21.4}/guidelines/functionalities.md +0 -0
  57. {haiway-0.21.2 → haiway-0.21.4}/guidelines/llms.txt +0 -0
  58. {haiway-0.21.2 → haiway-0.21.4}/guidelines/packages.md +0 -0
  59. {haiway-0.21.2 → haiway-0.21.4}/guidelines/state.md +0 -0
  60. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/__init__.py +0 -0
  61. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/__init__.py +0 -0
  62. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/access.py +0 -0
  63. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/disposables.py +0 -0
  64. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/identifier.py +0 -0
  65. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/observability.py +0 -0
  66. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/state.py +0 -0
  67. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/tasks.py +0 -0
  68. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/context/types.py +0 -0
  69. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/__init__.py +0 -0
  70. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/asynchrony.py +0 -0
  71. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/caching.py +0 -0
  72. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/concurrent.py +0 -0
  73. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/observability.py +0 -0
  74. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/retries.py +0 -0
  75. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/throttling.py +0 -0
  76. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/timeouted.py +0 -0
  77. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/helpers/tracing.py +0 -0
  78. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/opentelemetry/__init__.py +0 -0
  79. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/opentelemetry/observability.py +0 -0
  80. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/py.typed +0 -0
  81. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/__init__.py +0 -0
  82. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/attributes.py +0 -0
  83. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/path.py +0 -0
  84. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/structure.py +0 -0
  85. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/state/validation.py +0 -0
  86. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/types/__init__.py +0 -0
  87. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/types/default.py +0 -0
  88. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/types/missing.py +0 -0
  89. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/__init__.py +0 -0
  90. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/always.py +0 -0
  91. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/collections.py +0 -0
  92. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/env.py +0 -0
  93. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/formatting.py +0 -0
  94. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/freezing.py +0 -0
  95. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/logs.py +0 -0
  96. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/mimic.py +0 -0
  97. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/noop.py +0 -0
  98. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/queue.py +0 -0
  99. {haiway-0.21.2 → haiway-0.21.4}/src/haiway/utils/stream.py +0 -0
  100. {haiway-0.21.2 → haiway-0.21.4}/tests/__init__.py +0 -0
  101. {haiway-0.21.2 → haiway-0.21.4}/tests/test_async_queue.py +0 -0
  102. {haiway-0.21.2 → haiway-0.21.4}/tests/test_async_stream.py +0 -0
  103. {haiway-0.21.2 → haiway-0.21.4}/tests/test_attribute_path.py +0 -0
  104. {haiway-0.21.2 → haiway-0.21.4}/tests/test_attribute_requirement.py +0 -0
  105. {haiway-0.21.2 → haiway-0.21.4}/tests/test_auto_retry.py +0 -0
  106. {haiway-0.21.2 → haiway-0.21.4}/tests/test_cache.py +0 -0
  107. {haiway-0.21.2 → haiway-0.21.4}/tests/test_context.py +0 -0
  108. {haiway-0.21.2 → haiway-0.21.4}/tests/test_process_concurrently.py +0 -0
  109. {haiway-0.21.2 → haiway-0.21.4}/tests/test_state.py +0 -0
  110. {haiway-0.21.2 → haiway-0.21.4}/tests/test_state_validation.py +0 -0
  111. {haiway-0.21.2 → haiway-0.21.4}/tests/test_streaming.py +0 -0
  112. {haiway-0.21.2 → haiway-0.21.4}/tests/test_timeout.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haiway
3
- Version: 0.21.2
3
+ Version: 0.21.4
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><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="126" time="1.863" timestamp="2025-05-23T15:40:02.453645+00:00" hostname="pkrvmf6wy0o8zjz"><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.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_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.201" /><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.001" /><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.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.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.001" /><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.000" /><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>
1
+ <?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="126" time="1.865" timestamp="2025-06-09T12:05:08.394673+00:00" hostname="pkrvmf6wy0o8zjz"><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.001" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_points_to_attribute" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_points_to_nested_attribute" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_path_points_to_attribute" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_points_to_item" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_points_to_item" time="0.001" /><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.001" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_set_updates_nested_attribute" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_set_updates_attribute" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_set_updates_item" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_set_updates_item" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_set_updates_item" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_set_updates_item" time="0.001" /><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.002" /><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.106" /><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_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.001" /><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.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_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.001" /><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_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.21.2"
8
+ version = "0.21.4"
9
9
  readme = "README.md"
10
10
  maintainers = [
11
11
  { name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
@@ -1,4 +1,6 @@
1
- from collections.abc import Callable, Collection, Iterable
1
+ import re
2
+ import unicodedata
3
+ from collections.abc import Callable, Collection, Iterable, Sequence, Set
2
4
  from typing import Any, Literal, Self, cast, final
3
5
 
4
6
  from haiway.state.path import AttributePath
@@ -66,6 +68,83 @@ class AttributeRequirement[Root]:
66
68
  check=check_equal,
67
69
  )
68
70
 
71
+ @classmethod
72
+ def text_match[Parameter](
73
+ cls,
74
+ value: str,
75
+ /,
76
+ path: AttributePath[Root, str] | str,
77
+ ) -> Self:
78
+ """
79
+ Create a requirement that performs text matching on an attribute.
80
+
81
+ Parameters
82
+ ----------
83
+ value : str
84
+ The search term (can contain multiple words separated by spaces/punctuation)
85
+ path : AttributePath[Root, str] | str
86
+ The path to the string attribute to search in
87
+
88
+ Returns
89
+ -------
90
+ Self
91
+ A new requirement instance
92
+
93
+ Raises
94
+ ------
95
+ AssertionError
96
+ If path is not an AttributePath
97
+ """
98
+ assert isinstance( # nosec: B101
99
+ path, AttributePath
100
+ ), "Prepare attribute path by using Self._.path.to.property or explicitly"
101
+
102
+ def check_text_match(root: Root) -> None:
103
+ checked: Any = cast(AttributePath[Root, str], path)(root)
104
+ if not isinstance(checked, str):
105
+ raise ValueError(
106
+ f"Attribute value must be a string for like operation, got {type(checked)}"
107
+ f" for '{path.__repr__()}'"
108
+ )
109
+
110
+ # Perform full text search with proper Unicode support and word boundaries
111
+ def tokenize_text(text: str) -> Sequence[str]:
112
+ # Normalize and case-fold the text
113
+ normalized = unicodedata.normalize("NFC", text).casefold()
114
+ # Split on word boundaries and filter out empty strings
115
+ # re.UNICODE handles international characters, multiline text works by default
116
+ tokens = re.findall(r"\b\w+\b", normalized, re.UNICODE)
117
+ return tokens
118
+
119
+ # Tokenize both search terms and target text
120
+ search_tokens: Sequence[str] = tokenize_text(value)
121
+ target_tokens: Sequence[str] = tokenize_text(checked)
122
+ target_tokens_set: Set[str] = set(target_tokens)
123
+
124
+ # Check if all search tokens are found as complete words in target text
125
+ missing_terms = [
126
+ original_term
127
+ for original_term, token in zip(
128
+ value.split(),
129
+ search_tokens,
130
+ strict=False,
131
+ )
132
+ if token not in target_tokens_set
133
+ ]
134
+
135
+ if missing_terms:
136
+ raise ValueError(
137
+ f"Text search failed: '{checked}' is not like '{value}'. "
138
+ f"Missing tokens: {missing_terms} for '{path.__repr__()}'"
139
+ )
140
+
141
+ return cls(
142
+ path,
143
+ "text_match",
144
+ value,
145
+ check=check_text_match,
146
+ )
147
+
69
148
  @classmethod
70
149
  def not_equal[Parameter](
71
150
  cls,
@@ -266,6 +345,7 @@ class AttributeRequirement[Root]:
266
345
  lhs: Any,
267
346
  operator: Literal[
268
347
  "equal",
348
+ "text_match",
269
349
  "not_equal",
270
350
  "contains",
271
351
  "contains_any",
@@ -298,6 +378,7 @@ class AttributeRequirement[Root]:
298
378
  )
299
379
  self.operator: Literal[
300
380
  "equal",
381
+ "text_match",
301
382
  "not_equal",
302
383
  "contains",
303
384
  "contains_any",
@@ -123,7 +123,7 @@ wheels = [
123
123
 
124
124
  [[package]]
125
125
  name = "haiway"
126
- version = "0.21.2"
126
+ version = "0.21.4"
127
127
  source = { editable = "." }
128
128
 
129
129
  [package.optional-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes