haiway 0.18.2__tar.gz → 0.19.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. {haiway-0.18.2 → haiway-0.19.1}/PKG-INFO +1 -1
  2. {haiway-0.18.2 → haiway-0.19.1}/junit/test-results.xml +1 -1
  3. {haiway-0.18.2 → haiway-0.19.1}/pyproject.toml +1 -1
  4. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/__init__.py +0 -2
  5. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/access.py +53 -64
  6. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/observability.py +53 -48
  7. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/__init__.py +1 -2
  8. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/observability.py +53 -35
  9. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/tracing.py +50 -43
  10. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/opentelemetry/observability.py +53 -31
  11. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/structure.py +3 -151
  12. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/__init__.py +2 -0
  13. haiway-0.19.1/src/haiway/utils/formatting.py +151 -0
  14. {haiway-0.18.2 → haiway-0.19.1}/uv.lock +1 -1
  15. {haiway-0.18.2 → haiway-0.19.1}/.github/workflows/ci.yml +0 -0
  16. {haiway-0.18.2 → haiway-0.19.1}/.github/workflows/publish.yml +0 -0
  17. {haiway-0.18.2 → haiway-0.19.1}/.gitignore +0 -0
  18. {haiway-0.18.2 → haiway-0.19.1}/LICENSE +0 -0
  19. {haiway-0.18.2 → haiway-0.19.1}/Makefile +0 -0
  20. {haiway-0.18.2 → haiway-0.19.1}/README.md +0 -0
  21. {haiway-0.18.2 → haiway-0.19.1}/config/pre-push +0 -0
  22. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/.dockerignore +0 -0
  23. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/Dockerfile +0 -0
  24. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/Makefile +0 -0
  25. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/README.md +0 -0
  26. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/config/.env.example +0 -0
  27. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/config/unit.json +0 -0
  28. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/docker-compose.yml +0 -0
  29. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/pyproject.toml +0 -0
  30. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/__int__.py +0 -0
  31. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/__init__.py +0 -0
  32. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/config.py +0 -0
  33. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/state.py +0 -0
  34. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/types.py +0 -0
  35. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/user_tasks.py +0 -0
  36. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/__init__.py +0 -0
  37. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/__init__.py +0 -0
  38. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/client.py +0 -0
  39. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/config.py +0 -0
  40. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/state.py +0 -0
  41. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/types.py +0 -0
  42. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/__init__.py +0 -0
  43. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/__main__.py +0 -0
  44. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/__init__.py +0 -0
  45. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/execution.py +0 -0
  46. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/migration_0.py +0 -0
  47. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/types.py +0 -0
  48. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/__init__.py +0 -0
  49. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/__main__.py +0 -0
  50. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/application.py +0 -0
  51. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/config.py +0 -0
  52. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/middlewares/__init__.py +0 -0
  53. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/middlewares/context.py +0 -0
  54. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/__init__.py +0 -0
  55. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/technical.py +0 -0
  56. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/todos.py +0 -0
  57. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/__init__.py +0 -0
  58. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/__init__.py +0 -0
  59. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/config.py +0 -0
  60. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/postgres.py +0 -0
  61. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/state.py +0 -0
  62. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/types.py +0 -0
  63. {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/uv.lock +0 -0
  64. {haiway-0.18.2 → haiway-0.19.1}/guidelines/functionalities.md +0 -0
  65. {haiway-0.18.2 → haiway-0.19.1}/guidelines/packages.md +0 -0
  66. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/__init__.py +0 -0
  67. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/disposables.py +0 -0
  68. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/identifier.py +0 -0
  69. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/state.py +0 -0
  70. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/tasks.py +0 -0
  71. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/types.py +0 -0
  72. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/asynchrony.py +0 -0
  73. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/caching.py +0 -0
  74. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/retries.py +0 -0
  75. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/throttling.py +0 -0
  76. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/timeouted.py +0 -0
  77. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/opentelemetry/__init__.py +0 -0
  78. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/py.typed +0 -0
  79. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/__init__.py +0 -0
  80. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/attributes.py +0 -0
  81. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/path.py +0 -0
  82. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/requirement.py +0 -0
  83. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/validation.py +0 -0
  84. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/__init__.py +0 -0
  85. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/default.py +0 -0
  86. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/frozen.py +0 -0
  87. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/missing.py +0 -0
  88. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/always.py +0 -0
  89. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/collections.py +0 -0
  90. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/env.py +0 -0
  91. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/freezing.py +0 -0
  92. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/logs.py +0 -0
  93. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/mimic.py +0 -0
  94. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/noop.py +0 -0
  95. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/queue.py +0 -0
  96. {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/stream.py +0 -0
  97. {haiway-0.18.2 → haiway-0.19.1}/tests/__init__.py +0 -0
  98. {haiway-0.18.2 → haiway-0.19.1}/tests/test_async_queue.py +0 -0
  99. {haiway-0.18.2 → haiway-0.19.1}/tests/test_async_stream.py +0 -0
  100. {haiway-0.18.2 → haiway-0.19.1}/tests/test_attribute_path.py +0 -0
  101. {haiway-0.18.2 → haiway-0.19.1}/tests/test_auto_retry.py +0 -0
  102. {haiway-0.18.2 → haiway-0.19.1}/tests/test_cache.py +0 -0
  103. {haiway-0.18.2 → haiway-0.19.1}/tests/test_context.py +0 -0
  104. {haiway-0.18.2 → haiway-0.19.1}/tests/test_state.py +0 -0
  105. {haiway-0.18.2 → haiway-0.19.1}/tests/test_streaming.py +0 -0
  106. {haiway-0.18.2 → haiway-0.19.1}/tests/test_timeout.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haiway
3
- Version: 0.18.2
3
+ Version: 0.19.1
4
4
  Summary: Framework for dependency injection and state management within structured concurrency model.
5
5
  Project-URL: Homepage, https://miquido.com
6
6
  Project-URL: Repository, https://github.com/miquido/haiway.git
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="88" time="1.116" timestamp="2025-05-12T15:57:41.113378+00:00" hostname="pkrvmberfyhpb9w"><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_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.007" /><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.001" /><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_state" name="test_basic_initializes_with_arguments" time="0.002" /><testcase classname="tests.test_state" name="test_basic_initializes_with_defaults" time="0.001" /><testcase classname="tests.test_state" name="test_basic_equals_checks_properties" time="0.000" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments_and_defaults" time="0.000" /><testcase classname="tests.test_state" name="test_parametrized_initializes_with_proper_parameters" time="0.000" /><testcase classname="tests.test_state" name="test_nested_initializes_with_proper_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_dict_skips_missing_properties" time="0.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.002" /><testcase classname="tests.test_state" name="test_copying_leaves_same_object" time="0.001" /><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="88" time="1.104" timestamp="2025-05-13T10:10:00.079778+00:00" hostname="pkrvmberfyhpb9w"><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_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.005" /><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.001" /><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_state" name="test_basic_initializes_with_arguments" time="0.002" /><testcase classname="tests.test_state" name="test_basic_initializes_with_defaults" time="0.001" /><testcase classname="tests.test_state" name="test_basic_equals_checks_properties" time="0.000" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments_and_defaults" time="0.000" /><testcase classname="tests.test_state" name="test_parametrized_initializes_with_proper_parameters" time="0.000" /><testcase classname="tests.test_state" name="test_nested_initializes_with_proper_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_dict_skips_missing_properties" time="0.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_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.18.2"
8
+ version = "0.19.1"
9
9
  readme = "README.md"
10
10
  maintainers = [
11
11
  { name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
@@ -20,7 +20,6 @@ from haiway.context import (
20
20
  )
21
21
  from haiway.helpers import (
22
22
  LoggerObservability,
23
- ResultTrace,
24
23
  asynchronous,
25
24
  cache,
26
25
  retry,
@@ -87,7 +86,6 @@ __all__ = (
87
86
  "ObservabilityMetricRecording",
88
87
  "ObservabilityScopeEntering",
89
88
  "ObservabilityScopeExiting",
90
- "ResultTrace",
91
89
  "ScopeContext",
92
90
  "ScopeIdentifier",
93
91
  "State",
@@ -11,6 +11,7 @@ from collections.abc import (
11
11
  Callable,
12
12
  Coroutine,
13
13
  Iterable,
14
+ Mapping,
14
15
  )
15
16
  from logging import Logger
16
17
  from types import TracebackType
@@ -597,81 +598,69 @@ class ctx:
597
598
  ObservabilityLevel.DEBUG, message, *args, exception=exception, **extra
598
599
  )
599
600
 
601
+ @overload
600
602
  @staticmethod
601
- def event(
602
- event: State,
603
+ def record(
604
+ level: ObservabilityLevel = ObservabilityLevel.DEBUG,
603
605
  /,
604
606
  *,
605
- level: ObservabilityLevel = ObservabilityLevel.INFO,
606
- **extra: Any,
607
- ) -> None:
608
- """
609
- Record event within current scope context.
610
-
611
- Parameters
612
- ----------
613
- event: State
614
- contents of event to be recorded.
607
+ attributes: Mapping[str, ObservabilityAttribute],
608
+ ) -> None: ...
615
609
 
616
- Returns
617
- -------
618
- None
619
- """
620
-
621
- ObservabilityContext.record_event(
622
- event,
623
- level=level,
624
- **extra,
625
- )
610
+ @overload
611
+ @staticmethod
612
+ def record(
613
+ level: ObservabilityLevel = ObservabilityLevel.DEBUG,
614
+ /,
615
+ *,
616
+ event: str,
617
+ attributes: Mapping[str, ObservabilityAttribute] | None = None,
618
+ ) -> None: ...
626
619
 
620
+ @overload
627
621
  @staticmethod
628
- def metric(
629
- metric: str,
622
+ def record(
623
+ level: ObservabilityLevel = ObservabilityLevel.DEBUG,
630
624
  /,
631
625
  *,
626
+ metric: str,
632
627
  value: float | int,
633
628
  unit: str | None = None,
634
- **extra: Any,
635
- ) -> None:
636
- """
637
- Record metric within current scope context.
638
-
639
- Parameters
640
- ----------
641
- metric: State
642
- name of metric to be recorded.
643
- value: float | int
644
- value of metric to be recorded.
645
- unit: str | None = None
646
- unit of metric to be recorded.
647
-
648
- Returns
649
- -------
650
- None
651
- """
652
-
653
- ObservabilityContext.record_metric(
654
- metric,
655
- value=value,
656
- unit=unit,
657
- **extra,
658
- )
629
+ attributes: Mapping[str, ObservabilityAttribute] | None = None,
630
+ ) -> None: ...
659
631
 
660
632
  @staticmethod
661
- def attributes(**attributes: ObservabilityAttribute) -> None:
662
- """
663
- Record attributes within current scope context.
664
-
665
- Parameters
666
- ----------
667
- **attributes: ObservabilityAttribute,
668
- attributes to be recorded within current context.
633
+ def record(
634
+ level: ObservabilityLevel = ObservabilityLevel.DEBUG,
635
+ /,
636
+ *,
637
+ event: str | None = None,
638
+ metric: str | None = None,
639
+ value: float | int | None = None,
640
+ unit: str | None = None,
641
+ attributes: Mapping[str, ObservabilityAttribute] | None = None,
642
+ ) -> None:
643
+ if event is not None:
644
+ assert metric is None # nosec: B101
645
+ ObservabilityContext.record_event(
646
+ level,
647
+ event,
648
+ attributes=attributes or {},
649
+ )
669
650
 
670
- Returns
671
- -------
672
- None
673
- """
651
+ elif metric is not None:
652
+ assert event is None # nosec: B101
653
+ assert value is not None # nosec: B101
654
+ ObservabilityContext.record_metric(
655
+ level,
656
+ metric,
657
+ value=value,
658
+ unit=unit,
659
+ attributes=attributes or {},
660
+ )
674
661
 
675
- ObservabilityContext.record_attributes(
676
- **attributes,
677
- )
662
+ else:
663
+ ObservabilityContext.record_attributes(
664
+ level,
665
+ attributes=attributes or {},
666
+ )
@@ -1,4 +1,4 @@
1
- from collections.abc import Sequence
1
+ from collections.abc import Mapping, Sequence
2
2
  from contextvars import ContextVar, Token
3
3
  from enum import IntEnum
4
4
  from logging import DEBUG as DEBUG_LOGGING
@@ -7,17 +7,14 @@ from logging import INFO as INFO_LOGGING
7
7
  from logging import WARNING as WARNING_LOGGING
8
8
  from logging import Logger, getLogger
9
9
  from types import TracebackType
10
- from typing import Any, Final, Protocol, Self, final, runtime_checkable
10
+ from typing import Any, Protocol, Self, final, runtime_checkable
11
11
 
12
12
  from haiway.context.identifier import ScopeIdentifier
13
13
  from haiway.state import State
14
- from haiway.types import MISSING, Missing
14
+ from haiway.types import Missing
15
+ from haiway.utils.formatting import format_str
15
16
 
16
17
  __all__ = (
17
- "DEBUG",
18
- "ERROR",
19
- "INFO",
20
- "WARNING",
21
18
  "Observability",
22
19
  "ObservabilityAttribute",
23
20
  "ObservabilityAttributesRecording",
@@ -39,11 +36,6 @@ class ObservabilityLevel(IntEnum):
39
36
  DEBUG = DEBUG_LOGGING
40
37
 
41
38
 
42
- ERROR: Final[int] = ObservabilityLevel.ERROR
43
- WARNING: Final[int] = ObservabilityLevel.WARNING
44
- INFO: Final[int] = ObservabilityLevel.INFO
45
- DEBUG: Final[int] = ObservabilityLevel.DEBUG
46
-
47
39
  type ObservabilityAttribute = (
48
40
  Sequence[str]
49
41
  | Sequence[float]
@@ -68,7 +60,6 @@ class ObservabilityLogRecording(Protocol):
68
60
  message: str,
69
61
  *args: Any,
70
62
  exception: BaseException | None,
71
- **extra: Any,
72
63
  ) -> None: ...
73
64
 
74
65
 
@@ -78,10 +69,10 @@ class ObservabilityEventRecording(Protocol):
78
69
  self,
79
70
  scope: ScopeIdentifier,
80
71
  /,
81
- *,
82
72
  level: ObservabilityLevel,
83
- event: State,
84
- **extra: Any,
73
+ *,
74
+ event: str,
75
+ attributes: Mapping[str, ObservabilityAttribute],
85
76
  ) -> None: ...
86
77
 
87
78
 
@@ -91,11 +82,12 @@ class ObservabilityMetricRecording(Protocol):
91
82
  self,
92
83
  scope: ScopeIdentifier,
93
84
  /,
85
+ level: ObservabilityLevel,
94
86
  *,
95
87
  metric: str,
96
88
  value: float | int,
97
89
  unit: str | None,
98
- **extra: Any,
90
+ attributes: Mapping[str, ObservabilityAttribute],
99
91
  ) -> None: ...
100
92
 
101
93
 
@@ -105,7 +97,8 @@ class ObservabilityAttributesRecording(Protocol):
105
97
  self,
106
98
  scope: ScopeIdentifier,
107
99
  /,
108
- **attributes: ObservabilityAttribute,
100
+ level: ObservabilityLevel,
101
+ attributes: Mapping[str, ObservabilityAttribute],
109
102
  ) -> None: ...
110
103
 
111
104
 
@@ -217,7 +210,6 @@ def _logger_observability(
217
210
  message: str,
218
211
  *args: Any,
219
212
  exception: BaseException | None,
220
- **extra: Any,
221
213
  ) -> None:
222
214
  logger.log(
223
215
  level,
@@ -229,42 +221,51 @@ def _logger_observability(
229
221
  def event_recording(
230
222
  scope: ScopeIdentifier,
231
223
  /,
232
- *,
233
224
  level: ObservabilityLevel,
234
- event: State,
235
- **extra: Any,
225
+ *,
226
+ event: str,
227
+ attributes: Mapping[str, ObservabilityAttribute],
236
228
  ) -> None:
237
229
  logger.log(
238
230
  level,
239
- f"{scope.unique_name} Recorded event:\n{event.to_str(pretty=True)}",
231
+ f"{scope.unique_name} Recorded event: {event} {format_str(attributes)}",
240
232
  )
241
233
 
242
234
  def metric_recording(
243
235
  scope: ScopeIdentifier,
244
236
  /,
237
+ level: ObservabilityLevel,
245
238
  *,
246
239
  metric: str,
247
240
  value: float | int,
248
241
  unit: str | None,
249
- **extra: Any,
242
+ attributes: Mapping[str, ObservabilityAttribute],
250
243
  ) -> None:
251
- logger.log(
252
- INFO,
253
- f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}",
254
- )
244
+ if attributes:
245
+ logger.log(
246
+ level,
247
+ f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}"
248
+ f"\n{format_str(attributes)}",
249
+ )
250
+
251
+ else:
252
+ logger.log(
253
+ level,
254
+ f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}",
255
+ )
255
256
 
256
257
  def attributes_recording(
257
258
  scope: ScopeIdentifier,
258
259
  /,
259
- **attributes: ObservabilityAttribute,
260
+ level: ObservabilityLevel,
261
+ attributes: Mapping[str, ObservabilityAttribute],
260
262
  ) -> None:
261
263
  if not attributes:
262
264
  return
263
265
 
264
266
  logger.log(
265
- INFO,
266
- f"{scope.unique_name} Recorded attributes:"
267
- f"\n{'\n'.join(f'{k}: {v}' for k, v in attributes.items() if v is not None and v is not MISSING)}", # noqa: E501
267
+ level,
268
+ f"{scope.unique_name} Recorded attributes: {format_str(attributes)}",
268
269
  )
269
270
 
270
271
  def scope_entering[Metric: State](
@@ -272,7 +273,7 @@ def _logger_observability(
272
273
  /,
273
274
  ) -> None:
274
275
  logger.log(
275
- DEBUG,
276
+ ObservabilityLevel.DEBUG,
276
277
  f"{scope.unique_name} Entering scope: {scope.label}",
277
278
  )
278
279
 
@@ -283,7 +284,7 @@ def _logger_observability(
283
284
  exception: BaseException | None,
284
285
  ) -> None:
285
286
  logger.log(
286
- DEBUG,
287
+ ObservabilityLevel.DEBUG,
287
288
  f"{scope.unique_name} Exiting scope: {scope.label}",
288
289
  exc_info=exception,
289
290
  )
@@ -357,7 +358,6 @@ class ObservabilityContext:
357
358
  /,
358
359
  *args: Any,
359
360
  exception: BaseException | None,
360
- **extra: Any,
361
361
  ) -> None:
362
362
  try: # catch exceptions - we don't wan't to blow up on observability
363
363
  context: Self = cls._context.get()
@@ -369,7 +369,6 @@ class ObservabilityContext:
369
369
  message,
370
370
  *args,
371
371
  exception=exception,
372
- **extra,
373
372
  )
374
373
 
375
374
  except LookupError:
@@ -383,11 +382,11 @@ class ObservabilityContext:
383
382
  @classmethod
384
383
  def record_event(
385
384
  cls,
386
- event: State,
385
+ level: ObservabilityLevel,
386
+ event: str,
387
387
  /,
388
388
  *,
389
- level: ObservabilityLevel,
390
- **extra: Any,
389
+ attributes: Mapping[str, ObservabilityAttribute],
391
390
  ) -> None:
392
391
  try: # catch exceptions - we don't wan't to blow up on observability
393
392
  context: Self = cls._context.get()
@@ -397,12 +396,12 @@ class ObservabilityContext:
397
396
  context._scope,
398
397
  level=level,
399
398
  event=event,
400
- **extra,
399
+ attributes=attributes,
401
400
  )
402
401
 
403
402
  except Exception as exc:
404
403
  cls.record_log(
405
- ERROR,
404
+ ObservabilityLevel.ERROR,
406
405
  f"Failed to record event: {type(event).__qualname__}",
407
406
  exception=exc,
408
407
  )
@@ -410,12 +409,13 @@ class ObservabilityContext:
410
409
  @classmethod
411
410
  def record_metric(
412
411
  cls,
412
+ level: ObservabilityLevel,
413
413
  metric: str,
414
414
  /,
415
415
  *,
416
416
  value: float | int,
417
417
  unit: str | None,
418
- **extra: Any,
418
+ attributes: Mapping[str, ObservabilityAttribute],
419
419
  ) -> None:
420
420
  try: # catch exceptions - we don't wan't to blow up on observability
421
421
  context: Self = cls._context.get()
@@ -423,15 +423,16 @@ class ObservabilityContext:
423
423
  if context.observability is not None:
424
424
  context.observability.metric_recording(
425
425
  context._scope,
426
+ level=level,
426
427
  metric=metric,
427
428
  value=value,
428
429
  unit=unit,
429
- **extra,
430
+ attributes=attributes,
430
431
  )
431
432
 
432
433
  except Exception as exc:
433
434
  cls.record_log(
434
- ERROR,
435
+ ObservabilityLevel.ERROR,
435
436
  f"Failed to record metric: {metric}",
436
437
  exception=exc,
437
438
  )
@@ -439,7 +440,10 @@ class ObservabilityContext:
439
440
  @classmethod
440
441
  def record_attributes(
441
442
  cls,
442
- **attributes: ObservabilityAttribute,
443
+ level: ObservabilityLevel,
444
+ /,
445
+ *,
446
+ attributes: Mapping[str, ObservabilityAttribute],
443
447
  ) -> None:
444
448
  try: # catch exceptions - we don't wan't to blow up on observability
445
449
  context: Self = cls._context.get()
@@ -447,13 +451,14 @@ class ObservabilityContext:
447
451
  if context.observability is not None:
448
452
  context.observability.attributes_recording(
449
453
  context._scope,
450
- **attributes,
454
+ level=level,
455
+ attributes=attributes,
451
456
  )
452
457
 
453
458
  except Exception as exc:
454
459
  cls.record_log(
455
- ERROR,
456
- f"Failed to record attributes: {attributes}",
460
+ ObservabilityLevel.ERROR,
461
+ "Failed to record attributes",
457
462
  exception=exc,
458
463
  )
459
464
 
@@ -4,14 +4,13 @@ from haiway.helpers.observability import LoggerObservability
4
4
  from haiway.helpers.retries import retry
5
5
  from haiway.helpers.throttling import throttle
6
6
  from haiway.helpers.timeouted import timeout
7
- from haiway.helpers.tracing import ResultTrace, traced
7
+ from haiway.helpers.tracing import traced
8
8
 
9
9
  __all__ = (
10
10
  "CacheMakeKey",
11
11
  "CacheRead",
12
12
  "CacheWrite",
13
13
  "LoggerObservability",
14
- "ResultTrace",
15
14
  "asynchronous",
16
15
  "cache",
17
16
  "retry",