cadence-python-client 0.2.0__tar.gz → 0.2.2__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 (191) hide show
  1. cadence_python_client-0.2.2/.cursorrules +49 -0
  2. cadence_python_client-0.2.2/.github/dco.yml +2 -0
  3. cadence_python_client-0.2.2/.github/pull_request_template.md +20 -0
  4. cadence_python_client-0.2.2/.github/workflows/ci_checks.yml +97 -0
  5. cadence_python_client-0.2.2/.github/workflows/python-publish.yml +62 -0
  6. cadence_python_client-0.2.2/.github/workflows/semantic-pr.yml +72 -0
  7. cadence_python_client-0.2.2/.gitignore +114 -0
  8. cadence_python_client-0.2.2/.gitmodules +3 -0
  9. cadence_python_client-0.2.2/CONTRIBUTING.md +31 -0
  10. cadence_python_client-0.2.2/Makefile +55 -0
  11. {cadence_python_client-0.2.0/cadence_python_client.egg-info → cadence_python_client-0.2.2}/PKG-INFO +8 -1
  12. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/activity/_activity_executor.py +20 -4
  13. cadence_python_client-0.2.2/cadence/_internal/activity/_context.py +95 -0
  14. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/activity/_definition.py +33 -5
  15. cadence_python_client-0.2.2/cadence/_internal/activity/_heartbeat.py +42 -0
  16. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/fn_signature.py +31 -1
  17. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/rpc/retry.py +13 -5
  18. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/rpc/yarpc.py +6 -3
  19. cadence_python_client-0.2.2/cadence/_internal/workflow/active_cluster_selection_policy.py +32 -0
  20. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/context.py +41 -10
  21. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/deterministic_event_loop.py +25 -2
  22. cadence_python_client-0.2.2/cadence/_internal/workflow/retry_policy.py +62 -0
  23. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/event_dispatcher.py +3 -2
  24. cadence_python_client-0.2.2/cadence/_internal/workflow/waiter.py +37 -0
  25. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/workflow_engine.py +52 -25
  26. cadence_python_client-0.2.2/cadence/_internal/workflow/workflow_instance.py +105 -0
  27. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/activity.py +22 -0
  28. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/__init__.py +12 -0
  29. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/common_pb2.py +30 -12
  30. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/common_pb2.pyi +29 -2
  31. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/domain_pb2.py +22 -10
  32. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/domain_pb2.pyi +24 -2
  33. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/error_pb2.py +3 -1
  34. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/error_pb2.pyi +4 -0
  35. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/history_pb2.py +44 -44
  36. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/history_pb2.pyi +6 -2
  37. cadence_python_client-0.2.2/cadence/api/v1/schedule_pb2.py +61 -0
  38. cadence_python_client-0.2.2/cadence/api/v1/schedule_pb2.pyi +154 -0
  39. cadence_python_client-0.2.2/cadence/api/v1/schedule_pb2_grpc.py +24 -0
  40. cadence_python_client-0.2.2/cadence/api/v1/service_domain_pb2.py +94 -0
  41. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_domain_pb2.pyi +68 -2
  42. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_domain_pb2_grpc.py +88 -0
  43. cadence_python_client-0.2.2/cadence/api/v1/service_schedule_pb2.py +72 -0
  44. cadence_python_client-0.2.2/cadence/api/v1/service_schedule_pb2.pyi +163 -0
  45. cadence_python_client-0.2.2/cadence/api/v1/service_schedule_pb2_grpc.py +409 -0
  46. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_workflow_pb2.py +9 -9
  47. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_workflow_pb2.pyi +4 -2
  48. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_workflow_pb2_grpc.py +2 -2
  49. cadence_python_client-0.2.2/cadence/api/v1/workflow_pb2.py +91 -0
  50. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/workflow_pb2.pyi +29 -2
  51. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/client.py +64 -14
  52. cadence_python_client-0.2.2/cadence/contrib/__init__.py +0 -0
  53. cadence_python_client-0.2.2/cadence/contrib/openai/README.md +124 -0
  54. cadence_python_client-0.2.2/cadence/contrib/openai/__init__.py +15 -0
  55. cadence_python_client-0.2.2/cadence/contrib/openai/cadence_agent_runner.py +133 -0
  56. cadence_python_client-0.2.2/cadence/contrib/openai/cadence_handoff.py +42 -0
  57. cadence_python_client-0.2.2/cadence/contrib/openai/cadence_model.py +71 -0
  58. cadence_python_client-0.2.2/cadence/contrib/openai/cadence_registry.py +6 -0
  59. cadence_python_client-0.2.2/cadence/contrib/openai/cadence_tool.py +54 -0
  60. cadence_python_client-0.2.2/cadence/contrib/openai/images/cadence-web-agent-run.jpg +0 -0
  61. cadence_python_client-0.2.2/cadence/contrib/openai/openai_activities.py +51 -0
  62. cadence_python_client-0.2.2/cadence/contrib/openai/pydantic_data_converter.py +172 -0
  63. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/data_converter.py +21 -6
  64. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/error.py +46 -8
  65. cadence_python_client-0.2.2/cadence/signal.py +102 -0
  66. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_worker.py +25 -5
  67. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/workflow.py +102 -5
  68. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2/cadence_python_client.egg-info}/PKG-INFO +8 -1
  69. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence_python_client.egg-info/SOURCES.txt +83 -1
  70. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence_python_client.egg-info/requires.txt +8 -0
  71. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/pyproject.toml +10 -2
  72. cadence_python_client-0.2.2/scripts/dev.py +187 -0
  73. cadence_python_client-0.2.2/scripts/fix_pyi_imports.py +65 -0
  74. cadence_python_client-0.2.2/scripts/generate_proto.py +175 -0
  75. cadence_python_client-0.2.2/tests/cadence/_internal/activity/test_activity_executor.py +511 -0
  76. cadence_python_client-0.2.2/tests/cadence/_internal/activity/test_heartbeat.py +97 -0
  77. cadence_python_client-0.2.2/tests/cadence/_internal/rpc/test_error.py +199 -0
  78. cadence_python_client-0.2.2/tests/cadence/_internal/rpc/test_retry.py +190 -0
  79. cadence_python_client-0.2.2/tests/cadence/_internal/test_fn_signature.py +319 -0
  80. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/statemachine/test_activity_state_machine.py +199 -0
  81. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/statemachine/test_decision_manager.py +190 -0
  82. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/statemachine/test_nondeterminism.py +398 -0
  83. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/statemachine/test_timer_state_machine.py +75 -0
  84. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_context_retry_policy.py +53 -0
  85. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_decision_events_iterator.py +165 -0
  86. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_deterministic_event_loop.py +190 -0
  87. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_history_event_iterator.py +180 -0
  88. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_retry_policy.py +87 -0
  89. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_signal_handling.py +1387 -0
  90. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_waiter.py +121 -0
  91. cadence_python_client-0.2.2/tests/cadence/_internal/workflow/test_workflow_engine.py +94 -0
  92. cadence_python_client-0.2.2/tests/cadence/common_activities.py +80 -0
  93. cadence_python_client-0.2.2/tests/cadence/data_converter_test.py +111 -0
  94. cadence_python_client-0.2.2/tests/cadence/metrics/test_metrics.py +53 -0
  95. cadence_python_client-0.2.2/tests/cadence/metrics/test_prometheus.py +146 -0
  96. cadence_python_client-0.2.2/tests/cadence/test_activity.py +50 -0
  97. cadence_python_client-0.2.2/tests/cadence/test_client.py +183 -0
  98. cadence_python_client-0.2.2/tests/cadence/test_client_workflow.py +882 -0
  99. cadence_python_client-0.2.2/tests/cadence/worker/test_base_task_handler.py +117 -0
  100. cadence_python_client-0.2.2/tests/cadence/worker/test_decision_task_handler.py +457 -0
  101. cadence_python_client-0.2.2/tests/cadence/worker/test_decision_task_handler_integration.py +269 -0
  102. cadence_python_client-0.2.2/tests/cadence/worker/test_decision_worker_integration.py +312 -0
  103. cadence_python_client-0.2.2/tests/cadence/worker/test_poller.py +158 -0
  104. cadence_python_client-0.2.2/tests/cadence/worker/test_registry.py +293 -0
  105. cadence_python_client-0.2.2/tests/cadence/worker/test_task_handler_integration.py +379 -0
  106. cadence_python_client-0.2.2/tests/cadence/worker/test_worker.py +66 -0
  107. cadence_python_client-0.2.2/tests/conftest.py +16 -0
  108. cadence_python_client-0.2.2/tests/integration_tests/conftest.py +89 -0
  109. cadence_python_client-0.2.2/tests/integration_tests/docker-compose.yml +59 -0
  110. cadence_python_client-0.2.2/tests/integration_tests/helper.py +43 -0
  111. cadence_python_client-0.2.2/tests/integration_tests/nondeterminism/success.json +316 -0
  112. cadence_python_client-0.2.2/tests/integration_tests/nondeterminism/test_nondeterministic_workflows.py +571 -0
  113. cadence_python_client-0.2.2/tests/integration_tests/test_client.py +344 -0
  114. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_activities.py +243 -0
  115. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_continue_as_new.py +60 -0
  116. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_heartbeat.py +118 -0
  117. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_retry_policy.py +335 -0
  118. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_serialization.py +210 -0
  119. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_signals.py +349 -0
  120. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_timer.py +135 -0
  121. cadence_python_client-0.2.2/tests/integration_tests/workflow/test_workflows.py +123 -0
  122. cadence_python_client-0.2.2/uv.lock +2313 -0
  123. cadence_python_client-0.2.0/cadence/_internal/activity/_context.py +0 -60
  124. cadence_python_client-0.2.0/cadence/_internal/workflow/workflow_instance.py +0 -53
  125. cadence_python_client-0.2.0/cadence/api/v1/service_domain_pb2.py +0 -76
  126. cadence_python_client-0.2.0/cadence/api/v1/workflow_pb2.py +0 -89
  127. cadence_python_client-0.2.0/cadence/signal.py +0 -174
  128. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/LICENSE +0 -0
  129. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/NOTICE +0 -0
  130. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/README.md +0 -0
  131. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/__init__.py +0 -0
  132. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/__init__.py +0 -0
  133. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/activity/__init__.py +0 -0
  134. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/rpc/__init__.py +0 -0
  135. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/rpc/error.py +0 -0
  136. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/__init__.py +0 -0
  137. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/decision_events_iterator.py +0 -0
  138. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/history_event_iterator.py +0 -0
  139. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/__init__.py +0 -0
  140. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/activity_state_machine.py +0 -0
  141. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/cancellation.py +0 -0
  142. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/completion_state_machine.py +0 -0
  143. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/decision_manager.py +0 -0
  144. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/decision_state_machine.py +0 -0
  145. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/nondeterminism.py +0 -0
  146. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/_internal/workflow/statemachine/timer_state_machine.py +0 -0
  147. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/common_pb2_grpc.py +0 -0
  148. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/decision_pb2.py +0 -0
  149. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/decision_pb2.pyi +0 -0
  150. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/decision_pb2_grpc.py +0 -0
  151. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/domain_pb2_grpc.py +0 -0
  152. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/error_pb2_grpc.py +0 -0
  153. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/history_pb2_grpc.py +0 -0
  154. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/query_pb2.py +0 -0
  155. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/query_pb2.pyi +0 -0
  156. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/query_pb2_grpc.py +0 -0
  157. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_meta_pb2.py +0 -0
  158. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_meta_pb2.pyi +0 -0
  159. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_meta_pb2_grpc.py +0 -0
  160. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_visibility_pb2.py +0 -0
  161. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_visibility_pb2.pyi +0 -0
  162. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_visibility_pb2_grpc.py +0 -0
  163. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_worker_pb2.py +0 -0
  164. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_worker_pb2.pyi +0 -0
  165. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/service_worker_pb2_grpc.py +0 -0
  166. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/tasklist_pb2.py +0 -0
  167. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/tasklist_pb2.pyi +0 -0
  168. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/tasklist_pb2_grpc.py +0 -0
  169. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/visibility_pb2.py +0 -0
  170. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/visibility_pb2.pyi +0 -0
  171. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/visibility_pb2_grpc.py +0 -0
  172. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/api/v1/workflow_pb2_grpc.py +0 -0
  173. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/metrics/__init__.py +0 -0
  174. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/metrics/constants.py +0 -0
  175. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/metrics/metrics.py +0 -0
  176. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/metrics/prometheus.py +0 -0
  177. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/sample/__init__.py +0 -0
  178. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/sample/client_example.py +0 -0
  179. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/sample/grpc_usage_example.py +0 -0
  180. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/sample/simple_usage_example.py +0 -0
  181. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/__init__.py +0 -0
  182. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_activity.py +0 -0
  183. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_base_task_handler.py +0 -0
  184. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_decision.py +0 -0
  185. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_decision_task_handler.py +0 -0
  186. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_poller.py +0 -0
  187. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_registry.py +0 -0
  188. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence/worker/_types.py +0 -0
  189. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence_python_client.egg-info/dependency_links.txt +0 -0
  190. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/cadence_python_client.egg-info/top_level.txt +0 -0
  191. {cadence_python_client-0.2.0 → cadence_python_client-0.2.2}/setup.cfg +0 -0
@@ -0,0 +1,49 @@
1
+ # Cursor Rules for Cadence Python Client
2
+
3
+ ## Package Management
4
+ - **Always use `uv` for Python package management**
5
+ - Use `uv run` for running Python commands instead of `python` directly
6
+ - Use `uv sync` for installing dependencies instead of `pip install`
7
+ - Use `uv tool run` for running development tools (pytest, ruff, etc.); use `uv run mypy` so mypy uses the project environment (e.g. `types-grpcio`).
8
+ - Only use `pip` or `python` directly when specifically required by the tool or documentation
9
+
10
+ ## Examples
11
+ ```bash
12
+ # ✅ Correct
13
+ uv run python scripts/generate_proto.py
14
+ uv run python -m pytest tests/
15
+ uv run mypy cadence/
16
+ uv tool run ruff check
17
+
18
+ # ❌ Avoid
19
+ python scripts/generate_proto.py
20
+ pip install -e ".[dev]"
21
+ ```
22
+
23
+ ## Virtual Environment
24
+ - The project uses `uv` for virtual environment management
25
+ - Always activate the virtual environment using `uv` commands
26
+ - Dependencies are managed through `pyproject.toml` and `uv.lock`
27
+
28
+ ## Testing
29
+ - Run tests with `uv run python -m pytest`
30
+ - Use `uv run` for any Python script execution
31
+ - Development tools should be run with `uv tool run`
32
+
33
+ ## Code Generation
34
+ - Use `uv run python scripts/generate_proto.py` for protobuf generation
35
+ - Use `uv run python scripts/dev.py` for development tasks
36
+
37
+ ## Code Quality
38
+ - **ALWAYS run linter and type checker after making code changes**
39
+ - Run linter with auto-fix: `uv tool run ruff check --fix`
40
+ - Run type checking: `uv run mypy cadence/`
41
+ - Use `uv tool run ruff check --fix && uv run mypy cadence/` to run both together
42
+ - **Standard workflow**: Make changes → Run linter → Run type checker → Commit
43
+
44
+ ## Development Workflow
45
+ 1. Make code changes
46
+ 2. Run `uv tool run ruff check --fix` (fixes formatting and linting issues)
47
+ 3. Run `uv run mypy cadence/` (checks type safety)
48
+ 4. Run `uv run python -m pytest` (run tests)
49
+ 5. Commit changes
@@ -0,0 +1,2 @@
1
+ require:
2
+ members: false
@@ -0,0 +1,20 @@
1
+ <!-- Describe what has changed in this PR -->
2
+ **What changed?**
3
+
4
+
5
+ <!-- Tell your future self why have you made these changes -->
6
+ **Why?**
7
+
8
+
9
+ <!-- How have you verified this change? Tested locally? Added a unit test? Checked in staging env? -->
10
+ **How did you test it?**
11
+
12
+
13
+ <!-- Assuming the worst case, what can be broken when deploying this change to production? -->
14
+ **Potential risks**
15
+
16
+ <!-- Is it notable for release? e.g. schema updates, configuration or data migration required? If so, please mention it, and also update CHANGELOG.md -->
17
+ **Release notes**
18
+
19
+ <!-- Is there any documentation updates should be made for config, https://cadenceworkflow.io/docs/operation-guide/setup/ ? If so, please open an PR in https://github.com/cadence-workflow/cadence-docs -->
20
+ **Documentation Changes**
@@ -0,0 +1,97 @@
1
+ name: CI Checks
2
+ on:
3
+ push:
4
+ pull_request:
5
+
6
+ jobs:
7
+ lint:
8
+ name: Lint
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ with:
13
+ submodules: true
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.13"
18
+ - name: Set up uv
19
+ uses: astral-sh/setup-uv@v5
20
+ - name: Install dependencies
21
+ run: |
22
+ uv sync --extra dev
23
+ - name: Ensure Proto Files changes are committed
24
+ run: |
25
+ uv run python scripts/generate_proto.py
26
+ if [ -n "$(git status --porcelain 2>&1)" ]; then
27
+ echo "There are file changes after generating proto files."
28
+ echo "Please run this command and commit the changes:"
29
+ echo "\tuv run python scripts/generate_proto.py"
30
+ git status --porcelain
31
+ git --no-pager diff
32
+ exit 1
33
+ fi
34
+ - name: Run Ruff linter
35
+ run: |
36
+ uv tool run ruff check
37
+ uv tool run ruff format --check
38
+
39
+ type-check:
40
+ name: Type Safety Check
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ with:
45
+ submodules: true
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.13"
50
+ - name: Set up uv
51
+ uses: astral-sh/setup-uv@v5
52
+ - name: Install dependencies
53
+ run: |
54
+ uv sync --extra dev --extra openai
55
+ - name: Run mypy type checker
56
+ run: |
57
+ uv run mypy cadence/
58
+
59
+ test:
60
+ name: Unit Tests
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+ with:
65
+ submodules: true
66
+ - name: Set up Python
67
+ uses: actions/setup-python@v5
68
+ with:
69
+ python-version: "3.13"
70
+ - name: Set up uv
71
+ uses: astral-sh/setup-uv@v5
72
+ - name: Install dependencies
73
+ run: |
74
+ uv sync --extra dev
75
+ - name: Run unit tests
76
+ run: |
77
+ uv run pytest -v
78
+
79
+ integration_test:
80
+ name: Integration Tests
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ with:
85
+ submodules: true
86
+ - name: Set up Python
87
+ uses: actions/setup-python@v5
88
+ with:
89
+ python-version: "3.13"
90
+ - name: Set up uv
91
+ uses: astral-sh/setup-uv@v5
92
+ - name: Install dependencies
93
+ run: |
94
+ uv sync --extra dev
95
+ - name: Run unit tests
96
+ run: |
97
+ uv run pytest -v --integration-tests
@@ -0,0 +1,62 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ name: Upload Python Package
5
+
6
+ on:
7
+ release:
8
+ types:
9
+ - published
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ release-build:
16
+ runs-on: ubuntu-latest
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v4
23
+ with:
24
+ enable-cache: true
25
+ cache-dependency-glob: "uv.lock"
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version-file: "pyproject.toml"
31
+
32
+ - name: Build release distributions
33
+ run: uv build
34
+
35
+ - name: Upload distributions
36
+ uses: actions/upload-artifact@v4
37
+ with:
38
+ name: release-dists
39
+ path: dist/
40
+
41
+ pypi-publish:
42
+ runs-on: ubuntu-latest
43
+ needs:
44
+ - release-build
45
+ permissions:
46
+ # IMPORTANT: this permission is mandatory for trusted publishing
47
+ id-token: write
48
+
49
+ # Dedicated environments with protections for publishing are strongly recommended.
50
+ environment:
51
+ name: pypi
52
+ url: https://pypi.org/p/cadence-python-client
53
+
54
+ steps:
55
+ - name: Retrieve release distributions
56
+ uses: actions/download-artifact@v4
57
+ with:
58
+ name: release-dists
59
+ path: dist/
60
+
61
+ - name: Publish release distributions to PyPI
62
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,72 @@
1
+ name: Semantic Pull Request
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - synchronize
9
+
10
+ jobs:
11
+ semantic-pr:
12
+ name: Validate PR title follows conventional commit format
13
+ runs-on: ubuntu-latest
14
+ # TODO: Remove this once we commit to conventional commits
15
+ continue-on-error: true
16
+
17
+ steps:
18
+ - name: Validate PR title
19
+ id: lint_pr_title
20
+ uses: amannn/action-semantic-pull-request@v5.4.0
21
+ with:
22
+ # Allow standard conventional commit types
23
+ types: |
24
+ fix
25
+ feat
26
+ docs
27
+ style
28
+ refactor
29
+ perf
30
+ test
31
+ chore
32
+ ci
33
+ build
34
+ # TODO: Remove this once we've decided on scopes
35
+ requireScope: false
36
+ # Skip validation for certain labels if needed
37
+ ignoreLabels: |
38
+ skip-commit-format
39
+ env:
40
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
+
42
+ - name: Comment on PR if validation fails
43
+ if: steps.lint_pr_title.outputs.error_message != null
44
+ uses: actions/github-script@v7
45
+ with:
46
+ script: |
47
+ github.rest.issues.createComment({
48
+ issue_number: context.issue.number,
49
+ owner: context.repo.owner,
50
+ repo: context.repo.repo,
51
+ body: `⚠️ **Semantic PR Check Failed**
52
+
53
+ **Error Details:**
54
+ \`\`\`
55
+ ${{ steps.lint_pr_title.outputs.error_message }}
56
+ \`\`\`
57
+
58
+ **Required Format:**
59
+ \`\`\`
60
+ <type>: <description>
61
+ \`\`\`
62
+
63
+ **Allowed types:** fix, feat, docs, style, refactor, perf, test, chore, ci, build
64
+
65
+ **Examples:**
66
+ - \`feat: add user authentication system\`
67
+ - \`fix: resolve memory leak in worker pool\`
68
+ - \`docs: update API documentation\`
69
+ - \`test: add integration tests for auth flow\`
70
+
71
+ This is currently a **warning only** and won't block your PR from being merged.`
72
+ })
@@ -0,0 +1,114 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Logs
59
+ *.log
60
+
61
+ # Environments
62
+ .env
63
+ .venv
64
+ env/
65
+ venv/
66
+ ENV/
67
+ env.bak/
68
+ venv.bak/
69
+
70
+ # mypy
71
+ .mypy_cache/
72
+ .dmypy.json
73
+ dmypy.json
74
+
75
+ # Pyre type checker
76
+ .pyre/
77
+
78
+ # pytype static type analyzer
79
+ .pytype/
80
+
81
+ # Cython debug symbols
82
+ cython_debug/
83
+
84
+ # PyCharm
85
+ .idea/
86
+ *.iml
87
+ *.ipr
88
+ *.iws
89
+
90
+ # VS Code
91
+ .vscode/
92
+
93
+ # macOS
94
+ .DS_Store
95
+
96
+ # Windows
97
+ Thumbs.db
98
+ ehthumbs.db
99
+ Desktop.ini
100
+
101
+ # Project specific
102
+ .temp_gen/
103
+ *.pb.py
104
+ *.pb.pyi
105
+
106
+ # bin
107
+ .bin/
108
+
109
+ # Claude Code files
110
+ CLAUDE.md
111
+ settings.local.json
112
+ .python-version
113
+ *.bak
114
+ .mcp.json
@@ -0,0 +1,3 @@
1
+ [submodule "idls"]
2
+ path = idls
3
+ url = https://github.com/cadence-workflow/cadence-idl.git
@@ -0,0 +1,31 @@
1
+ # Contributing to Cadence Python Client
2
+
3
+ This doc is intended for contributors to the Cadence Python Client. Thanks for considering to contribute ❤️
4
+
5
+ > 📚 **New to contributing to Cadence?** Check out our [Contributing Guide](https://cadenceworkflow.io/community/how-to-contribute/getting-started) for an overview of the contribution process across all Cadence repositories. This document contains Python client specific setup and development instructions.
6
+
7
+ Once you go through the rest of this doc and get familiar with local development setup, take a look at the list of issues labeled with
8
+ [good first issue](https://github.com/cadence-workflow/cadence-python-client/labels/good%20first%20issue).
9
+ These issues are a great way to start contributing to Cadence Python Client.
10
+
11
+ Join our community on the CNCF Slack workspace at [cloud-native.slack.com](https://communityinviter.com/apps/cloud-native/cncf) in the **#cadence-users** channel to reach out and discuss issues with the team.
12
+
13
+ ## Submitting Pull Requests
14
+
15
+ 1. Fork the repository
16
+ 2. Create a feature branch from `main`
17
+ 3. Make your changes following the code quality guidelines above
18
+ 4. Write or update tests as needed
19
+ 5. Ensure all tests pass and there are no linting/type errors
20
+ 6. Submit a pull request with a clear description of your changes
21
+
22
+ ## Getting Help
23
+
24
+ - **GitHub Issues**: [Report bugs or request features](https://github.com/cadence-workflow/cadence-python-client/issues/new)
25
+ - **CNCF Slack**: Join the **#cadence-users** channel at [cloud-native.slack.com](https://communityinviter.com/apps/cloud-native/cncf)
26
+ - **Stack Overflow**: Tag questions with `cadence-workflow`
27
+
28
+ ## License
29
+
30
+ By contributing to Cadence Python Client, you agree that your contributions will be licensed under the Apache 2.0 License.
31
+
@@ -0,0 +1,55 @@
1
+ .PHONY: pr install lint type-check test integration-test clean generate help
2
+
3
+ # Run all PR checks locally
4
+ pr: install generate lint type-check test integration-test
5
+ @echo "All PR checks passed!"
6
+
7
+ # Install dependencies
8
+ install:
9
+ @echo "Installing dependencies..."
10
+ uv sync --all-extras
11
+
12
+ # Generate idl files
13
+ generate:
14
+ @echo "Generating type files based on IDL..."
15
+ uv run python scripts/generate_proto.py
16
+
17
+ # Run linter
18
+ lint:
19
+ @echo "Running Ruff linter and fixing lint issues..."
20
+ uv tool run ruff check --fix
21
+ uv tool run ruff format
22
+
23
+ # Run type checker
24
+ type-check:
25
+ @echo "Running mypy type checker..."
26
+ uv run mypy cadence/ tests/
27
+
28
+ # Run unit tests
29
+ test:
30
+ @echo "Running unit tests..."
31
+ uv run pytest -v
32
+
33
+ # Run integration tests
34
+ integration-test:
35
+ @echo "Running integration tests..."
36
+ uv run pytest -v --integration-tests
37
+
38
+ # Clean generated files and caches
39
+ clean:
40
+ @echo "Cleaning up..."
41
+ find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
42
+ find . -type f -name "*.pyc" -delete 2>/dev/null || true
43
+ find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
44
+
45
+ # Show help
46
+ help:
47
+ @echo "Available targets:"
48
+ @echo " make pr - Run all PR checks (recommended before submitting PR)"
49
+ @echo " make install - Install dependencies"
50
+ @echo " make lint - Run Ruff linter"
51
+ @echo " make type-check - Run mypy type checker"
52
+ @echo " make test - Run unit tests"
53
+ @echo " make integration-test - Run integration tests"
54
+ @echo " make clean - Remove generated files and caches"
55
+ @echo " make help - Show this help message"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cadence-python-client
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Python framework for authoring Cadence workflows and activities
5
5
  Author: Cadence
6
6
  License: Apache-2.0
@@ -40,6 +40,10 @@ Requires-Dist: flake8>=6.0.0; extra == "dev"
40
40
  Requires-Dist: mypy>=1.0.0; extra == "dev"
41
41
  Requires-Dist: pre-commit>=3.0.0; extra == "dev"
42
42
  Requires-Dist: pytest-docker>=3.2.3; extra == "dev"
43
+ Requires-Dist: opentelemetry-instrumentation-grpc==0.60b1; extra == "dev"
44
+ Requires-Dist: opentelemetry-sdk>=1.39.1; extra == "dev"
45
+ Requires-Dist: setuptools-scm[simple]>=9.2; extra == "dev"
46
+ Requires-Dist: types-grpcio>=1.0.0.20260408; extra == "dev"
43
47
  Provides-Extra: docs
44
48
  Requires-Dist: sphinx>=6.0.0; extra == "docs"
45
49
  Requires-Dist: sphinx-rtd-theme>=1.2.0; extra == "docs"
@@ -47,6 +51,9 @@ Requires-Dist: myst-parser>=1.0.0; extra == "docs"
47
51
  Provides-Extra: examples
48
52
  Requires-Dist: requests>=2.28.0; extra == "examples"
49
53
  Requires-Dist: aiohttp>=3.8.0; extra == "examples"
54
+ Provides-Extra: openai
55
+ Requires-Dist: openai>=0.27.10; extra == "openai"
56
+ Requires-Dist: openai-agents>=0.12.5; extra == "openai"
50
57
  Dynamic: license-file
51
58
 
52
59
  # Python framework for Cadence
@@ -1,12 +1,13 @@
1
1
  from concurrent.futures import ThreadPoolExecutor
2
2
  from logging import getLogger
3
3
  from traceback import format_exception
4
- from typing import Any, Callable, cast
4
+ from typing import Any, Callable, Union, cast
5
5
  from google.protobuf.duration import to_timedelta
6
6
  from google.protobuf.timestamp import to_datetime
7
7
 
8
8
  from cadence._internal.activity._context import _Context, _SyncContext
9
9
  from cadence._internal.activity._definition import BaseDefinition, ExecutionStrategy
10
+ from cadence._internal.activity._heartbeat import _HeartbeatSender
10
11
  from cadence.activity import ActivityInfo, ActivityDefinition
11
12
  from cadence.api.v1.common_pb2 import Failure
12
13
  from cadence.api.v1.service_worker_pb2 import (
@@ -46,7 +47,9 @@ class ActivityExecutor:
46
47
  _logger.exception("Activity failed")
47
48
  await self._report_failure(task, e)
48
49
 
49
- def _create_context(self, task: PollForActivityTaskResponse) -> _Context:
50
+ def _create_context(
51
+ self, task: PollForActivityTaskResponse
52
+ ) -> Union[_Context, _SyncContext]:
50
53
  activity_type = task.activity_type.name
51
54
  try:
52
55
  activity_def = cast(BaseDefinition, self._registry(activity_type))
@@ -54,11 +57,24 @@ class ActivityExecutor:
54
57
  raise KeyError(f"Activity type not found: {activity_type}") from None
55
58
 
56
59
  info = self._create_info(task)
60
+ heartbeat_sender = _HeartbeatSender(
61
+ self._client.worker_stub,
62
+ self._data_converter,
63
+ task.task_token,
64
+ self._identity,
65
+ task.heartbeat_details,
66
+ )
57
67
 
58
68
  if activity_def.strategy == ExecutionStrategy.ASYNC:
59
- return _Context(self._client, info, activity_def)
69
+ return _Context(self._client, info, activity_def, heartbeat_sender)
60
70
  else:
61
- return _SyncContext(self._client, info, activity_def, self._thread_pool)
71
+ return _SyncContext(
72
+ self._client,
73
+ info,
74
+ activity_def,
75
+ self._thread_pool,
76
+ heartbeat_sender,
77
+ )
62
78
 
63
79
  async def _report_failure(
64
80
  self, task: PollForActivityTaskResponse, error: Exception
@@ -0,0 +1,95 @@
1
+ import asyncio
2
+ from concurrent.futures.thread import ThreadPoolExecutor
3
+ from typing import Any, Type
4
+
5
+ from cadence import Client
6
+ from cadence._internal.activity._definition import BaseDefinition
7
+ from cadence._internal.activity._heartbeat import _HeartbeatSender
8
+ from cadence.activity import ActivityInfo, ActivityContext
9
+ from cadence.api.v1.common_pb2 import Payload
10
+
11
+
12
+ class _Context(ActivityContext):
13
+ def __init__(
14
+ self,
15
+ client: Client,
16
+ info: ActivityInfo,
17
+ activity_def: BaseDefinition[[Any], Any],
18
+ heartbeat_sender: _HeartbeatSender,
19
+ ):
20
+ self._client = client
21
+ self._info = info
22
+ self._activity_def = activity_def
23
+ self._heartbeat_sender = heartbeat_sender
24
+ self._heartbeat_tasks: set[asyncio.Future[None]] = set()
25
+
26
+ async def execute(self, payload: Payload) -> Any:
27
+ params = self._to_params(payload)
28
+ try:
29
+ with self._activate():
30
+ return await self._activity_def.impl_fn(*params)
31
+ finally:
32
+ await self._wait_pending_heartbeats()
33
+
34
+ async def _wait_pending_heartbeats(self) -> None:
35
+ if not self._heartbeat_tasks:
36
+ return
37
+ tasks = list(self._heartbeat_tasks)
38
+ await asyncio.gather(*tasks, return_exceptions=True)
39
+
40
+ def _to_params(self, payload: Payload) -> list[Any]:
41
+ return self._activity_def.signature.params_from_payload(
42
+ self._client.data_converter, payload
43
+ )
44
+
45
+ def client(self) -> Client:
46
+ return self._client
47
+
48
+ def info(self) -> ActivityInfo:
49
+ return self._info
50
+
51
+ def heartbeat(self, *details: Any) -> None:
52
+ heartbeat_task = asyncio.create_task(
53
+ self._heartbeat_sender.send_heartbeat(*details)
54
+ )
55
+ self._heartbeat_tasks.add(heartbeat_task)
56
+ heartbeat_task.add_done_callback(self._heartbeat_tasks.discard)
57
+
58
+ def heartbeat_details(self, *types: Type) -> list[Any]:
59
+ return self._heartbeat_sender.get_details(*types)
60
+
61
+
62
+ class _SyncContext(_Context):
63
+ def __init__(
64
+ self,
65
+ client: Client,
66
+ info: ActivityInfo,
67
+ activity_def: BaseDefinition[[Any], Any],
68
+ executor: ThreadPoolExecutor,
69
+ heartbeat_sender: _HeartbeatSender,
70
+ ):
71
+ super().__init__(client, info, activity_def, heartbeat_sender)
72
+ self._executor = executor
73
+
74
+ async def execute(self, payload: Payload) -> Any:
75
+ params = self._to_params(payload)
76
+ self._loop = asyncio.get_running_loop()
77
+ try:
78
+ return await self._loop.run_in_executor(self._executor, self._run, params)
79
+ finally:
80
+ await self._wait_pending_heartbeats()
81
+
82
+ def _run(self, args: list[Any]) -> Any:
83
+ with self._activate():
84
+ return self._activity_def.impl_fn(*args)
85
+
86
+ def client(self) -> Client:
87
+ raise RuntimeError("client is only supported in async activities")
88
+
89
+ def heartbeat(self, *details: Any) -> None:
90
+ future = asyncio.run_coroutine_threadsafe(
91
+ self._heartbeat_sender.send_heartbeat(*details), self._loop
92
+ )
93
+ wrapped = asyncio.wrap_future(future, loop=self._loop)
94
+ self._heartbeat_tasks.add(wrapped)
95
+ wrapped.add_done_callback(self._heartbeat_tasks.discard)