hatchet-sdk 0.47.0__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. hatchet_sdk/__init__.py +25 -16
  2. hatchet_sdk/client.py +14 -39
  3. hatchet_sdk/clients/admin.py +203 -362
  4. hatchet_sdk/clients/dispatcher/action_listener.py +106 -84
  5. hatchet_sdk/clients/dispatcher/dispatcher.py +21 -21
  6. hatchet_sdk/clients/event_ts.py +23 -10
  7. hatchet_sdk/clients/events.py +96 -99
  8. hatchet_sdk/clients/rest/__init__.py +24 -0
  9. hatchet_sdk/clients/rest/api/__init__.py +2 -0
  10. hatchet_sdk/clients/rest/api/task_api.py +2174 -0
  11. hatchet_sdk/clients/rest/api/workflow_runs_api.py +638 -106
  12. hatchet_sdk/clients/rest/api_client.py +1 -1
  13. hatchet_sdk/clients/rest/configuration.py +8 -1
  14. hatchet_sdk/clients/rest/exceptions.py +21 -0
  15. hatchet_sdk/clients/rest/models/__init__.py +22 -0
  16. hatchet_sdk/clients/rest/models/tenant.py +4 -0
  17. hatchet_sdk/clients/rest/models/tenant_version.py +37 -0
  18. hatchet_sdk/clients/rest/models/update_tenant_request.py +7 -0
  19. hatchet_sdk/clients/rest/models/v1_cancel_task_request.py +104 -0
  20. hatchet_sdk/clients/rest/models/v1_dag_children.py +102 -0
  21. hatchet_sdk/clients/rest/models/v1_replay_task_request.py +104 -0
  22. hatchet_sdk/clients/rest/models/v1_task.py +174 -0
  23. hatchet_sdk/clients/rest/models/v1_task_event.py +118 -0
  24. hatchet_sdk/clients/rest/models/v1_task_event_list.py +110 -0
  25. hatchet_sdk/clients/rest/models/v1_task_event_type.py +55 -0
  26. hatchet_sdk/clients/rest/models/v1_task_filter.py +106 -0
  27. hatchet_sdk/clients/rest/models/v1_task_point_metric.py +92 -0
  28. hatchet_sdk/clients/rest/models/v1_task_point_metrics.py +100 -0
  29. hatchet_sdk/clients/rest/models/v1_task_run_metric.py +88 -0
  30. hatchet_sdk/clients/rest/models/v1_task_run_status.py +40 -0
  31. hatchet_sdk/clients/rest/models/v1_task_status.py +40 -0
  32. hatchet_sdk/clients/rest/models/v1_task_summary.py +212 -0
  33. hatchet_sdk/clients/rest/models/v1_task_summary_list.py +110 -0
  34. hatchet_sdk/clients/rest/models/v1_workflow_run.py +171 -0
  35. hatchet_sdk/clients/rest/models/v1_workflow_run_details.py +145 -0
  36. hatchet_sdk/clients/rest/models/v1_workflow_type.py +37 -0
  37. hatchet_sdk/clients/rest/models/workflow_run_shape_item_for_workflow_run_details.py +99 -0
  38. hatchet_sdk/clients/rest/rest.py +37 -26
  39. hatchet_sdk/clients/rest/tenacity_utils.py +1 -1
  40. hatchet_sdk/clients/rest_client.py +141 -116
  41. hatchet_sdk/clients/run_event_listener.py +66 -60
  42. hatchet_sdk/clients/workflow_listener.py +75 -66
  43. hatchet_sdk/config.py +117 -0
  44. hatchet_sdk/connection.py +27 -13
  45. hatchet_sdk/context/__init__.py +0 -1
  46. hatchet_sdk/context/context.py +118 -218
  47. hatchet_sdk/features/cron.py +43 -57
  48. hatchet_sdk/features/scheduled.py +60 -74
  49. hatchet_sdk/hatchet.py +192 -195
  50. hatchet_sdk/labels.py +4 -6
  51. hatchet_sdk/metadata.py +1 -1
  52. hatchet_sdk/opentelemetry/instrumentor.py +9 -5
  53. hatchet_sdk/rate_limit.py +9 -18
  54. hatchet_sdk/token.py +13 -9
  55. hatchet_sdk/utils/aio_utils.py +0 -40
  56. hatchet_sdk/utils/proto_enums.py +54 -0
  57. hatchet_sdk/utils/typing.py +9 -1
  58. hatchet_sdk/v0/__init__.py +251 -0
  59. hatchet_sdk/v0/client.py +119 -0
  60. hatchet_sdk/v0/clients/admin.py +541 -0
  61. hatchet_sdk/v0/clients/dispatcher/action_listener.py +422 -0
  62. hatchet_sdk/v0/clients/dispatcher/dispatcher.py +204 -0
  63. hatchet_sdk/v0/clients/event_ts.py +28 -0
  64. hatchet_sdk/v0/clients/events.py +182 -0
  65. hatchet_sdk/v0/clients/rest/__init__.py +307 -0
  66. hatchet_sdk/v0/clients/rest/api/__init__.py +19 -0
  67. hatchet_sdk/v0/clients/rest/api/api_token_api.py +858 -0
  68. hatchet_sdk/v0/clients/rest/api/default_api.py +2259 -0
  69. hatchet_sdk/v0/clients/rest/api/event_api.py +2548 -0
  70. hatchet_sdk/v0/clients/rest/api/github_api.py +331 -0
  71. hatchet_sdk/v0/clients/rest/api/healthcheck_api.py +483 -0
  72. hatchet_sdk/v0/clients/rest/api/log_api.py +449 -0
  73. hatchet_sdk/v0/clients/rest/api/metadata_api.py +728 -0
  74. hatchet_sdk/v0/clients/rest/api/rate_limits_api.py +423 -0
  75. hatchet_sdk/v0/clients/rest/api/slack_api.py +577 -0
  76. hatchet_sdk/v0/clients/rest/api/sns_api.py +872 -0
  77. hatchet_sdk/v0/clients/rest/api/step_run_api.py +2202 -0
  78. hatchet_sdk/v0/clients/rest/api/tenant_api.py +4430 -0
  79. hatchet_sdk/v0/clients/rest/api/user_api.py +2888 -0
  80. hatchet_sdk/v0/clients/rest/api/worker_api.py +858 -0
  81. hatchet_sdk/v0/clients/rest/api/workflow_api.py +6312 -0
  82. hatchet_sdk/v0/clients/rest/api/workflow_run_api.py +1932 -0
  83. hatchet_sdk/v0/clients/rest/api/workflow_runs_api.py +610 -0
  84. hatchet_sdk/v0/clients/rest/api_client.py +759 -0
  85. hatchet_sdk/v0/clients/rest/api_response.py +22 -0
  86. hatchet_sdk/v0/clients/rest/configuration.py +611 -0
  87. hatchet_sdk/v0/clients/rest/exceptions.py +200 -0
  88. hatchet_sdk/v0/clients/rest/models/__init__.py +274 -0
  89. hatchet_sdk/v0/clients/rest/models/accept_invite_request.py +83 -0
  90. hatchet_sdk/v0/clients/rest/models/api_error.py +102 -0
  91. hatchet_sdk/v0/clients/rest/models/api_errors.py +100 -0
  92. hatchet_sdk/v0/clients/rest/models/api_meta.py +144 -0
  93. hatchet_sdk/v0/clients/rest/models/api_meta_auth.py +85 -0
  94. hatchet_sdk/v0/clients/rest/models/api_meta_integration.py +88 -0
  95. hatchet_sdk/v0/clients/rest/models/api_meta_posthog.py +90 -0
  96. hatchet_sdk/v0/clients/rest/models/api_resource_meta.py +98 -0
  97. hatchet_sdk/v0/clients/rest/models/api_token.py +105 -0
  98. hatchet_sdk/v0/clients/rest/models/bulk_create_event_request.py +100 -0
  99. hatchet_sdk/v0/clients/rest/models/bulk_create_event_response.py +110 -0
  100. hatchet_sdk/v0/clients/rest/models/cancel_event_request.py +85 -0
  101. hatchet_sdk/v0/clients/rest/models/cancel_step_run_request.py +83 -0
  102. hatchet_sdk/v0/clients/rest/models/concurrency_limit_strategy.py +39 -0
  103. hatchet_sdk/v0/clients/rest/models/create_api_token_request.py +92 -0
  104. hatchet_sdk/v0/clients/rest/models/create_api_token_response.py +83 -0
  105. hatchet_sdk/v0/clients/rest/models/create_cron_workflow_trigger_request.py +98 -0
  106. hatchet_sdk/v0/clients/rest/models/create_event_request.py +95 -0
  107. hatchet_sdk/v0/clients/rest/models/create_pull_request_from_step_run.py +83 -0
  108. hatchet_sdk/v0/clients/rest/models/create_sns_integration_request.py +85 -0
  109. hatchet_sdk/v0/clients/rest/models/create_tenant_alert_email_group_request.py +83 -0
  110. hatchet_sdk/v0/clients/rest/models/create_tenant_invite_request.py +86 -0
  111. hatchet_sdk/v0/clients/rest/models/create_tenant_request.py +84 -0
  112. hatchet_sdk/v0/clients/rest/models/cron_workflows.py +131 -0
  113. hatchet_sdk/v0/clients/rest/models/cron_workflows_list.py +110 -0
  114. hatchet_sdk/v0/clients/rest/models/cron_workflows_method.py +37 -0
  115. hatchet_sdk/v0/clients/rest/models/cron_workflows_order_by_field.py +37 -0
  116. hatchet_sdk/v0/clients/rest/models/event.py +143 -0
  117. hatchet_sdk/v0/clients/rest/models/event_data.py +83 -0
  118. hatchet_sdk/v0/clients/rest/models/event_key_list.py +98 -0
  119. hatchet_sdk/v0/clients/rest/models/event_list.py +110 -0
  120. hatchet_sdk/v0/clients/rest/models/event_order_by_direction.py +37 -0
  121. hatchet_sdk/v0/clients/rest/models/event_order_by_field.py +36 -0
  122. hatchet_sdk/v0/clients/rest/models/event_update_cancel200_response.py +85 -0
  123. hatchet_sdk/v0/clients/rest/models/event_workflow_run_summary.py +116 -0
  124. hatchet_sdk/v0/clients/rest/models/events.py +110 -0
  125. hatchet_sdk/v0/clients/rest/models/get_step_run_diff_response.py +100 -0
  126. hatchet_sdk/v0/clients/rest/models/github_app_installation.py +107 -0
  127. hatchet_sdk/v0/clients/rest/models/github_branch.py +86 -0
  128. hatchet_sdk/v0/clients/rest/models/github_repo.py +86 -0
  129. hatchet_sdk/v0/clients/rest/models/info_get_version200_response.py +83 -0
  130. hatchet_sdk/v0/clients/rest/models/job.py +132 -0
  131. hatchet_sdk/v0/clients/rest/models/job_run.py +176 -0
  132. hatchet_sdk/v0/clients/rest/models/job_run_status.py +41 -0
  133. hatchet_sdk/v0/clients/rest/models/link_github_repository_request.py +106 -0
  134. hatchet_sdk/v0/clients/rest/models/list_api_tokens_response.py +110 -0
  135. hatchet_sdk/v0/clients/rest/models/list_github_app_installations_response.py +112 -0
  136. hatchet_sdk/v0/clients/rest/models/list_pull_requests_response.py +100 -0
  137. hatchet_sdk/v0/clients/rest/models/list_slack_webhooks.py +110 -0
  138. hatchet_sdk/v0/clients/rest/models/list_sns_integrations.py +110 -0
  139. hatchet_sdk/v0/clients/rest/models/log_line.py +94 -0
  140. hatchet_sdk/v0/clients/rest/models/log_line_level.py +39 -0
  141. hatchet_sdk/v0/clients/rest/models/log_line_list.py +110 -0
  142. hatchet_sdk/v0/clients/rest/models/log_line_order_by_direction.py +37 -0
  143. hatchet_sdk/v0/clients/rest/models/log_line_order_by_field.py +36 -0
  144. hatchet_sdk/v0/clients/rest/models/pagination_response.py +95 -0
  145. hatchet_sdk/v0/clients/rest/models/pull_request.py +112 -0
  146. hatchet_sdk/v0/clients/rest/models/pull_request_state.py +37 -0
  147. hatchet_sdk/v0/clients/rest/models/queue_metrics.py +97 -0
  148. hatchet_sdk/v0/clients/rest/models/rate_limit.py +117 -0
  149. hatchet_sdk/v0/clients/rest/models/rate_limit_list.py +110 -0
  150. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_direction.py +37 -0
  151. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_field.py +38 -0
  152. hatchet_sdk/v0/clients/rest/models/recent_step_runs.py +118 -0
  153. hatchet_sdk/v0/clients/rest/models/reject_invite_request.py +83 -0
  154. hatchet_sdk/v0/clients/rest/models/replay_event_request.py +85 -0
  155. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_request.py +85 -0
  156. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_response.py +100 -0
  157. hatchet_sdk/v0/clients/rest/models/rerun_step_run_request.py +83 -0
  158. hatchet_sdk/v0/clients/rest/models/schedule_workflow_run_request.py +92 -0
  159. hatchet_sdk/v0/clients/rest/models/scheduled_run_status.py +42 -0
  160. hatchet_sdk/v0/clients/rest/models/scheduled_workflows.py +149 -0
  161. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_list.py +110 -0
  162. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_method.py +37 -0
  163. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
  164. hatchet_sdk/v0/clients/rest/models/semaphore_slots.py +113 -0
  165. hatchet_sdk/v0/clients/rest/models/slack_webhook.py +127 -0
  166. hatchet_sdk/v0/clients/rest/models/sns_integration.py +114 -0
  167. hatchet_sdk/v0/clients/rest/models/step.py +123 -0
  168. hatchet_sdk/v0/clients/rest/models/step_run.py +202 -0
  169. hatchet_sdk/v0/clients/rest/models/step_run_archive.py +142 -0
  170. hatchet_sdk/v0/clients/rest/models/step_run_archive_list.py +110 -0
  171. hatchet_sdk/v0/clients/rest/models/step_run_diff.py +91 -0
  172. hatchet_sdk/v0/clients/rest/models/step_run_event.py +122 -0
  173. hatchet_sdk/v0/clients/rest/models/step_run_event_list.py +110 -0
  174. hatchet_sdk/v0/clients/rest/models/step_run_event_reason.py +52 -0
  175. hatchet_sdk/v0/clients/rest/models/step_run_event_severity.py +38 -0
  176. hatchet_sdk/v0/clients/rest/models/step_run_status.py +44 -0
  177. hatchet_sdk/v0/clients/rest/models/tenant.py +118 -0
  178. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group.py +98 -0
  179. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group_list.py +112 -0
  180. hatchet_sdk/v0/clients/rest/models/tenant_alerting_settings.py +143 -0
  181. hatchet_sdk/v0/clients/rest/models/tenant_invite.py +120 -0
  182. hatchet_sdk/v0/clients/rest/models/tenant_invite_list.py +110 -0
  183. hatchet_sdk/v0/clients/rest/models/tenant_list.py +110 -0
  184. hatchet_sdk/v0/clients/rest/models/tenant_member.py +123 -0
  185. hatchet_sdk/v0/clients/rest/models/tenant_member_list.py +110 -0
  186. hatchet_sdk/v0/clients/rest/models/tenant_member_role.py +38 -0
  187. hatchet_sdk/v0/clients/rest/models/tenant_queue_metrics.py +116 -0
  188. hatchet_sdk/v0/clients/rest/models/tenant_resource.py +40 -0
  189. hatchet_sdk/v0/clients/rest/models/tenant_resource_limit.py +135 -0
  190. hatchet_sdk/v0/clients/rest/models/tenant_resource_policy.py +102 -0
  191. hatchet_sdk/v0/clients/rest/models/tenant_step_run_queue_metrics.py +83 -0
  192. hatchet_sdk/v0/clients/rest/models/trigger_workflow_run_request.py +91 -0
  193. hatchet_sdk/v0/clients/rest/models/update_tenant_alert_email_group_request.py +83 -0
  194. hatchet_sdk/v0/clients/rest/models/update_tenant_invite_request.py +85 -0
  195. hatchet_sdk/v0/clients/rest/models/update_tenant_request.py +137 -0
  196. hatchet_sdk/v0/clients/rest/models/update_worker_request.py +87 -0
  197. hatchet_sdk/v0/clients/rest/models/user.py +126 -0
  198. hatchet_sdk/v0/clients/rest/models/user_change_password_request.py +88 -0
  199. hatchet_sdk/v0/clients/rest/models/user_login_request.py +86 -0
  200. hatchet_sdk/v0/clients/rest/models/user_register_request.py +91 -0
  201. hatchet_sdk/v0/clients/rest/models/user_tenant_memberships_list.py +110 -0
  202. hatchet_sdk/v0/clients/rest/models/user_tenant_public.py +86 -0
  203. hatchet_sdk/v0/clients/rest/models/webhook_worker.py +100 -0
  204. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_request.py +94 -0
  205. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_response.py +98 -0
  206. hatchet_sdk/v0/clients/rest/models/webhook_worker_created.py +102 -0
  207. hatchet_sdk/v0/clients/rest/models/webhook_worker_list_response.py +110 -0
  208. hatchet_sdk/v0/clients/rest/models/webhook_worker_request.py +102 -0
  209. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_list_response.py +104 -0
  210. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_method.py +38 -0
  211. hatchet_sdk/v0/clients/rest/models/worker.py +239 -0
  212. hatchet_sdk/v0/clients/rest/models/worker_label.py +102 -0
  213. hatchet_sdk/v0/clients/rest/models/worker_list.py +110 -0
  214. hatchet_sdk/v0/clients/rest/models/worker_runtime_info.py +103 -0
  215. hatchet_sdk/v0/clients/rest/models/worker_runtime_sdks.py +38 -0
  216. hatchet_sdk/v0/clients/rest/models/worker_type.py +38 -0
  217. hatchet_sdk/v0/clients/rest/models/workflow.py +165 -0
  218. hatchet_sdk/v0/clients/rest/models/workflow_concurrency.py +107 -0
  219. hatchet_sdk/v0/clients/rest/models/workflow_deployment_config.py +136 -0
  220. hatchet_sdk/v0/clients/rest/models/workflow_kind.py +38 -0
  221. hatchet_sdk/v0/clients/rest/models/workflow_list.py +120 -0
  222. hatchet_sdk/v0/clients/rest/models/workflow_metrics.py +97 -0
  223. hatchet_sdk/v0/clients/rest/models/workflow_run.py +188 -0
  224. hatchet_sdk/v0/clients/rest/models/workflow_run_cancel200_response.py +85 -0
  225. hatchet_sdk/v0/clients/rest/models/workflow_run_list.py +110 -0
  226. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_direction.py +37 -0
  227. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_field.py +39 -0
  228. hatchet_sdk/v0/clients/rest/models/workflow_run_shape.py +186 -0
  229. hatchet_sdk/v0/clients/rest/models/workflow_run_status.py +42 -0
  230. hatchet_sdk/v0/clients/rest/models/workflow_run_triggered_by.py +112 -0
  231. hatchet_sdk/v0/clients/rest/models/workflow_runs_cancel_request.py +85 -0
  232. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics.py +94 -0
  233. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics_counts.py +104 -0
  234. hatchet_sdk/v0/clients/rest/models/workflow_tag.py +84 -0
  235. hatchet_sdk/v0/clients/rest/models/workflow_trigger_cron_ref.py +86 -0
  236. hatchet_sdk/v0/clients/rest/models/workflow_trigger_event_ref.py +86 -0
  237. hatchet_sdk/v0/clients/rest/models/workflow_triggers.py +141 -0
  238. hatchet_sdk/v0/clients/rest/models/workflow_update_request.py +85 -0
  239. hatchet_sdk/v0/clients/rest/models/workflow_version.py +170 -0
  240. hatchet_sdk/v0/clients/rest/models/workflow_version_concurrency.py +114 -0
  241. hatchet_sdk/v0/clients/rest/models/workflow_version_definition.py +85 -0
  242. hatchet_sdk/v0/clients/rest/models/workflow_version_meta.py +123 -0
  243. hatchet_sdk/v0/clients/rest/models/workflow_workers_count.py +95 -0
  244. hatchet_sdk/v0/clients/rest/rest.py +187 -0
  245. hatchet_sdk/v0/clients/rest/tenacity_utils.py +39 -0
  246. hatchet_sdk/v0/clients/rest_client.py +613 -0
  247. hatchet_sdk/v0/clients/run_event_listener.py +260 -0
  248. hatchet_sdk/v0/clients/workflow_listener.py +277 -0
  249. hatchet_sdk/v0/connection.py +63 -0
  250. hatchet_sdk/v0/context/__init__.py +1 -0
  251. hatchet_sdk/v0/context/context.py +446 -0
  252. hatchet_sdk/v0/context/worker_context.py +28 -0
  253. hatchet_sdk/v0/contracts/dispatcher_pb2.py +102 -0
  254. hatchet_sdk/v0/contracts/dispatcher_pb2.pyi +387 -0
  255. hatchet_sdk/v0/contracts/dispatcher_pb2_grpc.py +621 -0
  256. hatchet_sdk/v0/contracts/events_pb2.py +46 -0
  257. hatchet_sdk/v0/contracts/events_pb2.pyi +87 -0
  258. hatchet_sdk/v0/contracts/events_pb2_grpc.py +274 -0
  259. hatchet_sdk/v0/contracts/workflows_pb2.py +80 -0
  260. hatchet_sdk/v0/contracts/workflows_pb2.pyi +312 -0
  261. hatchet_sdk/v0/contracts/workflows_pb2_grpc.py +277 -0
  262. hatchet_sdk/v0/features/cron.py +286 -0
  263. hatchet_sdk/v0/features/scheduled.py +248 -0
  264. hatchet_sdk/v0/hatchet.py +310 -0
  265. hatchet_sdk/v0/labels.py +10 -0
  266. hatchet_sdk/v0/logger.py +13 -0
  267. hatchet_sdk/v0/metadata.py +2 -0
  268. hatchet_sdk/v0/opentelemetry/instrumentor.py +396 -0
  269. hatchet_sdk/v0/rate_limit.py +126 -0
  270. hatchet_sdk/v0/semver.py +30 -0
  271. hatchet_sdk/v0/token.py +27 -0
  272. hatchet_sdk/v0/utils/aio_utils.py +137 -0
  273. hatchet_sdk/v0/utils/backoff.py +9 -0
  274. hatchet_sdk/v0/utils/typing.py +12 -0
  275. hatchet_sdk/{v2 → v0/v2}/callable.py +8 -8
  276. hatchet_sdk/{v2 → v0/v2}/concurrency.py +2 -2
  277. hatchet_sdk/{v2 → v0/v2}/hatchet.py +10 -10
  278. hatchet_sdk/v0/worker/__init__.py +1 -0
  279. hatchet_sdk/v0/worker/action_listener_process.py +278 -0
  280. hatchet_sdk/v0/worker/runner/run_loop_manager.py +112 -0
  281. hatchet_sdk/v0/worker/runner/runner.py +460 -0
  282. hatchet_sdk/v0/worker/runner/utils/capture_logs.py +81 -0
  283. hatchet_sdk/v0/worker/runner/utils/error_with_traceback.py +6 -0
  284. hatchet_sdk/v0/worker/worker.py +391 -0
  285. hatchet_sdk/v0/workflow.py +261 -0
  286. hatchet_sdk/v0/workflow_run.py +59 -0
  287. hatchet_sdk/worker/__init__.py +0 -1
  288. hatchet_sdk/worker/action_listener_process.py +36 -33
  289. hatchet_sdk/worker/runner/run_loop_manager.py +18 -16
  290. hatchet_sdk/worker/runner/runner.py +32 -60
  291. hatchet_sdk/worker/runner/utils/capture_logs.py +25 -14
  292. hatchet_sdk/worker/runner/utils/error_with_traceback.py +1 -1
  293. hatchet_sdk/worker/worker.py +61 -75
  294. hatchet_sdk/workflow.py +473 -207
  295. hatchet_sdk/workflow_run.py +5 -18
  296. {hatchet_sdk-0.47.0.dist-info → hatchet_sdk-1.0.0.dist-info}/METADATA +2 -1
  297. hatchet_sdk-1.0.0.dist-info/RECORD +485 -0
  298. hatchet_sdk/utils/serialization.py +0 -18
  299. hatchet_sdk-0.47.0.dist-info/RECORD +0 -237
  300. /hatchet_sdk/{loader.py → v0/loader.py} +0 -0
  301. /hatchet_sdk/{utils → v0/utils}/types.py +0 -0
  302. {hatchet_sdk-0.47.0.dist-info → hatchet_sdk-1.0.0.dist-info}/WHEEL +0 -0
  303. {hatchet_sdk-0.47.0.dist-info → hatchet_sdk-1.0.0.dist-info}/entry_points.txt +0 -0
@@ -1 +0,0 @@
1
- from .worker import Worker, WorkerStartOptions, WorkerStatus
@@ -4,22 +4,22 @@ import signal
4
4
  import time
5
5
  from dataclasses import dataclass, field
6
6
  from multiprocessing import Queue
7
- from typing import Any, List, Mapping, Optional
7
+ from typing import Any, List, Literal
8
8
 
9
9
  import grpc
10
10
 
11
- from hatchet_sdk.clients.dispatcher.action_listener import Action
12
- from hatchet_sdk.clients.dispatcher.dispatcher import (
11
+ from hatchet_sdk.clients.dispatcher.action_listener import (
12
+ Action,
13
13
  ActionListener,
14
+ ActionType,
14
15
  GetActionListenerRequest,
15
- new_dispatcher,
16
16
  )
17
+ from hatchet_sdk.clients.dispatcher.dispatcher import DispatcherClient
18
+ from hatchet_sdk.config import ClientConfig
17
19
  from hatchet_sdk.contracts.dispatcher_pb2 import (
18
20
  GROUP_KEY_EVENT_TYPE_STARTED,
19
21
  STEP_EVENT_TYPE_STARTED,
20
- ActionType,
21
22
  )
22
- from hatchet_sdk.loader import ClientConfig
23
23
  from hatchet_sdk.logger import logger
24
24
  from hatchet_sdk.utils.backoff import exp_backoff_sleep
25
25
 
@@ -30,10 +30,11 @@ ACTION_EVENT_RETRY_COUNT = 5
30
30
  class ActionEvent:
31
31
  action: Action
32
32
  type: Any # TODO type
33
- payload: Optional[str] = None
33
+ payload: str
34
34
 
35
35
 
36
- STOP_LOOP = "STOP_LOOP" # Sentinel object to stop the loop
36
+ STOP_LOOP_TYPE = Literal["STOP_LOOP"]
37
+ STOP_LOOP: STOP_LOOP_TYPE = "STOP_LOOP" # Sentinel object to stop the loop
37
38
 
38
39
  # TODO link to a block post
39
40
  BLOCKED_THREAD_WARNING = (
@@ -41,7 +42,7 @@ BLOCKED_THREAD_WARNING = (
41
42
  )
42
43
 
43
44
 
44
- def noop_handler():
45
+ def noop_handler() -> None:
45
46
  pass
46
47
 
47
48
 
@@ -51,22 +52,22 @@ class WorkerActionListenerProcess:
51
52
  actions: List[str]
52
53
  max_runs: int
53
54
  config: ClientConfig
54
- action_queue: Queue
55
- event_queue: Queue
55
+ action_queue: "Queue[Action]"
56
+ event_queue: "Queue[ActionEvent | STOP_LOOP_TYPE]"
56
57
  handle_kill: bool = True
57
58
  debug: bool = False
58
- labels: dict = field(default_factory=dict)
59
+ labels: dict[str, str | int] = field(default_factory=dict)
59
60
 
60
- listener: ActionListener = field(init=False, default=None)
61
+ listener: ActionListener = field(init=False)
61
62
 
62
63
  killing: bool = field(init=False, default=False)
63
64
 
64
- action_loop_task: asyncio.Task = field(init=False, default=None)
65
- event_send_loop_task: asyncio.Task = field(init=False, default=None)
65
+ action_loop_task: asyncio.Task[None] | None = field(init=False, default=None)
66
+ event_send_loop_task: asyncio.Task[None] | None = field(init=False, default=None)
66
67
 
67
- running_step_runs: Mapping[str, float] = field(init=False, default_factory=dict)
68
+ running_step_runs: dict[str, float] = field(init=False, default_factory=dict)
68
69
 
69
- def __post_init__(self):
70
+ def __post_init__(self) -> None:
70
71
  if self.debug:
71
72
  logger.setLevel(logging.DEBUG)
72
73
 
@@ -77,7 +78,7 @@ class WorkerActionListenerProcess:
77
78
  signal.SIGQUIT, lambda: asyncio.create_task(self.exit_gracefully())
78
79
  )
79
80
 
80
- async def start(self, retry_attempt=0):
81
+ async def start(self, retry_attempt: int = 0) -> None:
81
82
  if retry_attempt > 5:
82
83
  logger.error("could not start action listener")
83
84
  return
@@ -85,7 +86,7 @@ class WorkerActionListenerProcess:
85
86
  logger.debug(f"starting action listener: {self.name}")
86
87
 
87
88
  try:
88
- self.dispatcher_client = new_dispatcher(self.config)
89
+ self.dispatcher_client = DispatcherClient(self.config)
89
90
 
90
91
  self.listener = await self.dispatcher_client.get_action_listener(
91
92
  GetActionListenerRequest(
@@ -108,13 +109,13 @@ class WorkerActionListenerProcess:
108
109
  self.blocked_main_loop = asyncio.create_task(self.start_blocked_main_loop())
109
110
 
110
111
  # TODO move event methods to separate class
111
- async def _get_event(self):
112
+ async def _get_event(self) -> ActionEvent | STOP_LOOP_TYPE:
112
113
  loop = asyncio.get_running_loop()
113
114
  return await loop.run_in_executor(None, self.event_queue.get)
114
115
 
115
- async def start_event_send_loop(self):
116
+ async def start_event_send_loop(self) -> None:
116
117
  while True:
117
- event: ActionEvent = await self._get_event()
118
+ event = await self._get_event()
118
119
  if event == STOP_LOOP:
119
120
  logger.debug("stopping event send loop...")
120
121
  break
@@ -122,11 +123,11 @@ class WorkerActionListenerProcess:
122
123
  logger.debug(f"tx: event: {event.action.action_id}/{event.type}")
123
124
  asyncio.create_task(self.send_event(event))
124
125
 
125
- async def start_blocked_main_loop(self):
126
+ async def start_blocked_main_loop(self) -> None:
126
127
  threshold = 1
127
128
  while not self.killing:
128
129
  count = 0
129
- for step_run_id, start_time in self.running_step_runs.items():
130
+ for _, start_time in self.running_step_runs.items():
130
131
  diff = self.now() - start_time
131
132
  if diff > threshold:
132
133
  count += 1
@@ -135,7 +136,7 @@ class WorkerActionListenerProcess:
135
136
  logger.warning(f"{BLOCKED_THREAD_WARNING}: Waiting Steps {count}")
136
137
  await asyncio.sleep(1)
137
138
 
138
- async def send_event(self, event: ActionEvent, retry_attempt: int = 1):
139
+ async def send_event(self, event: ActionEvent, retry_attempt: int = 1) -> None:
139
140
  try:
140
141
  match event.action.action_type:
141
142
  # FIXME: all events sent from an execution of a function are of type ActionType.START_STEP_RUN since
@@ -185,10 +186,10 @@ class WorkerActionListenerProcess:
185
186
  await exp_backoff_sleep(retry_attempt, 1)
186
187
  await self.send_event(event, retry_attempt + 1)
187
188
 
188
- def now(self):
189
+ def now(self) -> float:
189
190
  return time.time()
190
191
 
191
- async def start_action_loop(self):
192
+ async def start_action_loop(self) -> None:
192
193
  try:
193
194
  async for action in self.listener:
194
195
  if action is None:
@@ -201,6 +202,7 @@ class WorkerActionListenerProcess:
201
202
  ActionEvent(
202
203
  action=action,
203
204
  type=STEP_EVENT_TYPE_STARTED, # TODO ack type
205
+ payload="",
204
206
  )
205
207
  )
206
208
  logger.info(
@@ -220,6 +222,7 @@ class WorkerActionListenerProcess:
220
222
  ActionEvent(
221
223
  action=action,
222
224
  type=GROUP_KEY_EVENT_TYPE_STARTED, # TODO ack type
225
+ payload="",
223
226
  )
224
227
  )
225
228
  logger.info(
@@ -239,9 +242,9 @@ class WorkerActionListenerProcess:
239
242
  finally:
240
243
  logger.info("action loop closed")
241
244
  if not self.killing:
242
- await self.exit_gracefully(skip_unregister=True)
245
+ await self.exit_gracefully()
243
246
 
244
- async def cleanup(self):
247
+ async def cleanup(self) -> None:
245
248
  self.killing = True
246
249
 
247
250
  if self.listener is not None:
@@ -249,7 +252,7 @@ class WorkerActionListenerProcess:
249
252
 
250
253
  self.event_queue.put(STOP_LOOP)
251
254
 
252
- async def exit_gracefully(self, skip_unregister=False):
255
+ async def exit_gracefully(self) -> None:
253
256
  if self.killing:
254
257
  return
255
258
 
@@ -262,13 +265,13 @@ class WorkerActionListenerProcess:
262
265
 
263
266
  logger.info("action listener closed")
264
267
 
265
- def exit_forcefully(self):
268
+ def exit_forcefully(self) -> None:
266
269
  asyncio.run(self.cleanup())
267
270
  logger.debug("forcefully closing listener...")
268
271
 
269
272
 
270
- def worker_action_listener_process(*args, **kwargs):
271
- async def run():
273
+ def worker_action_listener_process(*args: Any, **kwargs: Any) -> None:
274
+ async def run() -> None:
272
275
  process = WorkerActionListenerProcess(*args, **kwargs)
273
276
  await process.start()
274
277
  # Keep the process running
@@ -2,18 +2,20 @@ import asyncio
2
2
  import logging
3
3
  from dataclasses import dataclass, field
4
4
  from multiprocessing import Queue
5
- from typing import Callable, TypeVar
5
+ from typing import Any, Literal, TypeVar
6
6
 
7
- from hatchet_sdk import Context
8
7
  from hatchet_sdk.client import Client, new_client_raw
9
8
  from hatchet_sdk.clients.dispatcher.action_listener import Action
10
- from hatchet_sdk.loader import ClientConfig
9
+ from hatchet_sdk.config import ClientConfig
11
10
  from hatchet_sdk.logger import logger
12
- from hatchet_sdk.utils.types import WorkflowValidator
11
+ from hatchet_sdk.utils.typing import WorkflowValidator
12
+ from hatchet_sdk.worker.action_listener_process import ActionEvent
13
13
  from hatchet_sdk.worker.runner.runner import Runner
14
14
  from hatchet_sdk.worker.runner.utils.capture_logs import capture_logs
15
+ from hatchet_sdk.workflow import Step
15
16
 
16
- STOP_LOOP = "STOP_LOOP"
17
+ STOP_LOOP_TYPE = Literal["STOP_LOOP"]
18
+ STOP_LOOP: STOP_LOOP_TYPE = "STOP_LOOP"
17
19
 
18
20
  T = TypeVar("T")
19
21
 
@@ -21,32 +23,32 @@ T = TypeVar("T")
21
23
  @dataclass
22
24
  class WorkerActionRunLoopManager:
23
25
  name: str
24
- action_registry: dict[str, Callable[[Context], T]]
26
+ action_registry: dict[str, Step[Any]]
25
27
  validator_registry: dict[str, WorkflowValidator]
26
28
  max_runs: int | None
27
29
  config: ClientConfig
28
- action_queue: Queue
29
- event_queue: Queue
30
+ action_queue: "Queue[Action | STOP_LOOP_TYPE]"
31
+ event_queue: "Queue[ActionEvent]"
30
32
  loop: asyncio.AbstractEventLoop
31
33
  handle_kill: bool = True
32
34
  debug: bool = False
33
35
  labels: dict[str, str | int] = field(default_factory=dict)
34
36
 
35
- client: Client = field(init=False, default=None)
37
+ client: Client = field(init=False)
36
38
 
37
39
  killing: bool = field(init=False, default=False)
38
- runner: Runner = field(init=False, default=None)
40
+ runner: Runner | None = field(init=False, default=None)
39
41
 
40
- def __post_init__(self):
42
+ def __post_init__(self) -> None:
41
43
  if self.debug:
42
44
  logger.setLevel(logging.DEBUG)
43
45
  self.client = new_client_raw(self.config, self.debug)
44
46
  self.start()
45
47
 
46
- def start(self, retry_count=1):
47
- k = self.loop.create_task(self.async_start(retry_count))
48
+ def start(self, retry_count: int = 1) -> None:
49
+ k = self.loop.create_task(self.aio_start(retry_count)) # noqa: F841
48
50
 
49
- async def async_start(self, retry_count=1):
51
+ async def aio_start(self, retry_count: int = 1) -> None:
50
52
  await capture_logs(
51
53
  self.client.logInterceptor,
52
54
  self.client.event,
@@ -83,7 +85,7 @@ class WorkerActionRunLoopManager:
83
85
 
84
86
  logger.debug(f"'{self.name}' waiting for {list(self.action_registry.keys())}")
85
87
  while not self.killing:
86
- action: Action = await self._get_action()
88
+ action = await self._get_action()
87
89
  if action == STOP_LOOP:
88
90
  logger.debug("stopping action runner loop...")
89
91
  break
@@ -91,7 +93,7 @@ class WorkerActionRunLoopManager:
91
93
  self.runner.run(action)
92
94
  logger.debug("action runner loop stopped")
93
95
 
94
- async def _get_action(self):
96
+ async def _get_action(self) -> Action | STOP_LOOP_TYPE:
95
97
  return await self.loop.run_in_executor(None, self.action_queue.get)
96
98
 
97
99
  async def exit_gracefully(self) -> None:
@@ -3,23 +3,23 @@ import contextvars
3
3
  import ctypes
4
4
  import functools
5
5
  import json
6
- import time
7
6
  import traceback
8
7
  from concurrent.futures import ThreadPoolExecutor
9
8
  from enum import Enum
10
9
  from multiprocessing import Queue
11
10
  from threading import Thread, current_thread
12
- from typing import Any, Callable, Dict, cast
11
+ from typing import Any, Callable, Dict, TypeVar, cast
13
12
 
14
13
  from pydantic import BaseModel
15
14
 
16
15
  from hatchet_sdk.client import new_client_raw
17
- from hatchet_sdk.clients.admin import new_admin
18
- from hatchet_sdk.clients.dispatcher.action_listener import Action
19
- from hatchet_sdk.clients.dispatcher.dispatcher import new_dispatcher
20
- from hatchet_sdk.clients.run_event_listener import new_listener
16
+ from hatchet_sdk.clients.admin import AdminClient
17
+ from hatchet_sdk.clients.dispatcher.action_listener import Action, ActionType
18
+ from hatchet_sdk.clients.dispatcher.dispatcher import DispatcherClient
19
+ from hatchet_sdk.clients.run_event_listener import RunEventListenerClient
21
20
  from hatchet_sdk.clients.workflow_listener import PooledWorkflowRunListener
22
- from hatchet_sdk.context import Context # type: ignore[attr-defined]
21
+ from hatchet_sdk.config import ClientConfig
22
+ from hatchet_sdk.context.context import Context
23
23
  from hatchet_sdk.context.worker_context import WorkerContext
24
24
  from hatchet_sdk.contracts.dispatcher_pb2 import (
25
25
  GROUP_KEY_EVENT_TYPE_COMPLETED,
@@ -28,14 +28,14 @@ from hatchet_sdk.contracts.dispatcher_pb2 import (
28
28
  STEP_EVENT_TYPE_COMPLETED,
29
29
  STEP_EVENT_TYPE_FAILED,
30
30
  STEP_EVENT_TYPE_STARTED,
31
- ActionType,
32
31
  )
33
- from hatchet_sdk.loader import ClientConfig
34
32
  from hatchet_sdk.logger import logger
35
- from hatchet_sdk.utils.types import WorkflowValidator
36
- from hatchet_sdk.v2.callable import DurableContext
33
+ from hatchet_sdk.utils.typing import WorkflowValidator
37
34
  from hatchet_sdk.worker.action_listener_process import ActionEvent
38
35
  from hatchet_sdk.worker.runner.utils.capture_logs import copy_context_vars, sr, wr
36
+ from hatchet_sdk.workflow import Step
37
+
38
+ T = TypeVar("T")
39
39
 
40
40
 
41
41
  class WorkerStatus(Enum):
@@ -52,7 +52,7 @@ class Runner:
52
52
  event_queue: "Queue[Any]",
53
53
  max_runs: int | None = None,
54
54
  handle_kill: bool = True,
55
- action_registry: dict[str, Callable[..., Any]] = {},
55
+ action_registry: dict[str, Step[T]] = {},
56
56
  validator_registry: dict[str, WorkflowValidator] = {},
57
57
  config: ClientConfig = ClientConfig(),
58
58
  labels: dict[str, str | int] = {},
@@ -64,7 +64,7 @@ class Runner:
64
64
  self.max_runs = max_runs
65
65
  self.tasks: dict[str, asyncio.Task[Any]] = {} # Store run ids and futures
66
66
  self.contexts: dict[str, Context] = {} # Store run ids and contexts
67
- self.action_registry: dict[str, Callable[..., Any]] = action_registry
67
+ self.action_registry: dict[str, Step[T]] = action_registry
68
68
  self.validator_registry = validator_registry
69
69
 
70
70
  self.event_queue = event_queue
@@ -78,9 +78,9 @@ class Runner:
78
78
 
79
79
  # We need to initialize a new admin and dispatcher client *after* we've started the event loop,
80
80
  # otherwise the grpc.aio methods will use a different event loop and we'll get a bunch of errors.
81
- self.dispatcher_client = new_dispatcher(self.config)
82
- self.admin_client = new_admin(self.config)
83
- self.workflow_run_event_listener = new_listener(self.config)
81
+ self.dispatcher_client = DispatcherClient(self.config)
82
+ self.admin_client = AdminClient(self.config)
83
+ self.workflow_run_event_listener = RunEventListenerClient(self.config)
84
84
  self.client.workflow_listener = PooledWorkflowRunListener(self.config)
85
85
 
86
86
  self.worker_context = WorkerContext(
@@ -195,10 +195,7 @@ class Runner:
195
195
 
196
196
  return inner_callback
197
197
 
198
- ## TODO: Stricter type hinting here
199
- def thread_action_func(
200
- self, context: Context, action_func: Callable[..., Any], action: Action
201
- ) -> Any:
198
+ def thread_action_func(self, context: Context, step: Step[T], action: Action) -> T:
202
199
  if action.step_run_id is not None and action.step_run_id != "":
203
200
  self.threads[action.step_run_id] = current_thread()
204
201
  elif (
@@ -207,25 +204,22 @@ class Runner:
207
204
  ):
208
205
  self.threads[action.get_group_key_run_id] = current_thread()
209
206
 
210
- return action_func(context)
207
+ return step.call(context)
211
208
 
212
- ## TODO: Stricter type hinting here
213
209
  # We wrap all actions in an async func
214
210
  async def async_wrapped_action_func(
215
211
  self,
216
212
  context: Context,
217
- action_func: Callable[..., Any],
213
+ step: Step[T],
218
214
  action: Action,
219
215
  run_id: str,
220
- ) -> Any:
221
- wr.set(context.workflow_run_id())
216
+ ) -> T:
217
+ wr.set(context.workflow_run_id)
222
218
  sr.set(context.step_run_id)
223
219
 
224
220
  try:
225
- if (
226
- hasattr(action_func, "is_coroutine") and action_func.is_coroutine
227
- ) or asyncio.iscoroutinefunction(action_func):
228
- return await action_func(context)
221
+ if step.is_async_function:
222
+ return await step.aio_call(context)
229
223
  else:
230
224
  pfunc = functools.partial(
231
225
  # we must copy the context vars to the new thread, as only asyncio natively supports
@@ -234,7 +228,7 @@ class Runner:
234
228
  contextvars.copy_context().items(),
235
229
  self.thread_action_func,
236
230
  context,
237
- action_func,
231
+ step,
238
232
  action,
239
233
  )
240
234
 
@@ -261,23 +255,7 @@ class Runner:
261
255
  if run_id in self.contexts:
262
256
  del self.contexts[run_id]
263
257
 
264
- def create_context(
265
- self, action: Action, action_func: Callable[..., Any] | None
266
- ) -> Context | DurableContext:
267
- if hasattr(action_func, "durable") and getattr(action_func, "durable"):
268
- return DurableContext(
269
- action,
270
- self.dispatcher_client,
271
- self.admin_client,
272
- self.client.event,
273
- self.client.rest,
274
- self.client.workflow_listener,
275
- self.workflow_run_event_listener,
276
- self.worker_context,
277
- self.client.config.namespace,
278
- validator_registry=self.validator_registry,
279
- )
280
-
258
+ def create_context(self, action: Action) -> Context:
281
259
  return Context(
282
260
  action,
283
261
  self.dispatcher_client,
@@ -292,22 +270,19 @@ class Runner:
292
270
  )
293
271
 
294
272
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
295
- async def handle_start_step_run(self, action: Action) -> None | Exception:
273
+ async def handle_start_step_run(self, action: Action) -> None:
296
274
  action_name = action.action_id
297
275
 
298
276
  # Find the corresponding action function from the registry
299
277
  action_func = self.action_registry.get(action_name)
300
278
 
301
- context = self.create_context(action, action_func)
279
+ context = self.create_context(action)
302
280
 
303
281
  self.contexts[action.step_run_id] = context
304
282
 
305
283
  if action_func:
306
284
  self.event_queue.put(
307
- ActionEvent(
308
- action=action,
309
- type=STEP_EVENT_TYPE_STARTED,
310
- )
285
+ ActionEvent(action=action, type=STEP_EVENT_TYPE_STARTED, payload="")
311
286
  )
312
287
 
313
288
  loop = asyncio.get_event_loop()
@@ -322,10 +297,9 @@ class Runner:
322
297
 
323
298
  try:
324
299
  await task
325
- except Exception as e:
326
- return e
327
-
328
- return None
300
+ except Exception:
301
+ # do nothing, this should be caught in the callback
302
+ pass
329
303
 
330
304
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
331
305
  async def handle_start_group_key_run(self, action: Action) -> Exception | None:
@@ -351,8 +325,7 @@ class Runner:
351
325
  # send an event that the group key run has started
352
326
  self.event_queue.put(
353
327
  ActionEvent(
354
- action=action,
355
- type=GROUP_KEY_EVENT_TYPE_STARTED,
328
+ action=action, type=GROUP_KEY_EVENT_TYPE_STARTED, payload=""
356
329
  )
357
330
  )
358
331
 
@@ -434,7 +407,6 @@ class Runner:
434
407
  self.cleanup_run_id(run_id)
435
408
 
436
409
  def serialize_output(self, output: Any) -> str:
437
-
438
410
  if isinstance(output, BaseModel):
439
411
  return output.model_dump_json()
440
412
 
@@ -2,11 +2,12 @@ import contextvars
2
2
  import functools
3
3
  import logging
4
4
  from concurrent.futures import ThreadPoolExecutor
5
+ from contextvars import ContextVar
5
6
  from io import StringIO
6
- from typing import Any, Coroutine
7
+ from typing import Any, Awaitable, Callable, ItemsView, ParamSpec, TypeVar
7
8
 
8
- from hatchet_sdk import logger
9
9
  from hatchet_sdk.clients.events import EventClient
10
+ from hatchet_sdk.logger import logger
10
11
 
11
12
  wr: contextvars.ContextVar[str | None] = contextvars.ContextVar(
12
13
  "workflow_run_id", default=None
@@ -16,7 +17,16 @@ sr: contextvars.ContextVar[str | None] = contextvars.ContextVar(
16
17
  )
17
18
 
18
19
 
19
- def copy_context_vars(ctx_vars, func, *args, **kwargs):
20
+ T = TypeVar("T")
21
+ P = ParamSpec("P")
22
+
23
+
24
+ def copy_context_vars(
25
+ ctx_vars: ItemsView[ContextVar[Any], Any],
26
+ func: Callable[P, T],
27
+ *args: P.args,
28
+ **kwargs: P.kwargs,
29
+ ) -> T:
20
30
  for var, value in ctx_vars:
21
31
  var.set(value)
22
32
  return func(*args, **kwargs)
@@ -25,19 +35,20 @@ def copy_context_vars(ctx_vars, func, *args, **kwargs):
25
35
  class InjectingFilter(logging.Filter):
26
36
  # For some reason, only the InjectingFilter has access to the contextvars method sr.get(),
27
37
  # otherwise we would use emit within the CustomLogHandler
28
- def filter(self, record):
38
+ def filter(self, record: logging.LogRecord) -> bool:
39
+ ## TODO: Change how we do this to not assign to the log record
29
40
  record.workflow_run_id = wr.get()
30
41
  record.step_run_id = sr.get()
31
42
  return True
32
43
 
33
44
 
34
- class CustomLogHandler(logging.StreamHandler):
35
- def __init__(self, event_client: EventClient, stream=None):
45
+ class CustomLogHandler(logging.StreamHandler): # type: ignore[type-arg]
46
+ def __init__(self, event_client: EventClient, stream: StringIO | None = None):
36
47
  super().__init__(stream)
37
48
  self.logger_thread_pool = ThreadPoolExecutor(max_workers=1)
38
49
  self.event_client = event_client
39
50
 
40
- def _log(self, line: str, step_run_id: str | None):
51
+ def _log(self, line: str, step_run_id: str | None) -> None:
41
52
  try:
42
53
  if not step_run_id:
43
54
  return
@@ -46,20 +57,20 @@ class CustomLogHandler(logging.StreamHandler):
46
57
  except Exception as e:
47
58
  logger.error(f"Error logging: {e}")
48
59
 
49
- def emit(self, record):
60
+ def emit(self, record: logging.LogRecord) -> None:
50
61
  super().emit(record)
51
62
 
52
63
  log_entry = self.format(record)
53
- self.logger_thread_pool.submit(self._log, log_entry, record.step_run_id)
64
+
65
+ ## TODO: Change how we do this to not assign to the log record
66
+ self.logger_thread_pool.submit(self._log, log_entry, record.step_run_id) # type: ignore
54
67
 
55
68
 
56
69
  def capture_logs(
57
- logger: logging.Logger,
58
- event_client: EventClient,
59
- func: Coroutine[Any, Any, Any],
60
- ):
70
+ logger: logging.Logger, event_client: "EventClient", func: Callable[P, Awaitable[T]]
71
+ ) -> Callable[P, Awaitable[T]]:
61
72
  @functools.wraps(func)
62
- async def wrapper(*args, **kwargs):
73
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
63
74
  if not logger:
64
75
  raise Exception("No logger configured on client")
65
76
 
@@ -1,6 +1,6 @@
1
1
  import traceback
2
2
 
3
3
 
4
- def errorWithTraceback(message: str, e: Exception):
4
+ def errorWithTraceback(message: str, e: Exception) -> str:
5
5
  trace = "".join(traceback.format_exception(type(e), e, e.__traceback__))
6
6
  return f"{message}\n{trace}"