prefect-client 3.2.6__tar.gz → 3.2.8__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 (327) hide show
  1. {prefect_client-3.2.6 → prefect_client-3.2.8}/PKG-INFO +2 -2
  2. {prefect_client-3.2.6 → prefect_client-3.2.8}/pyproject.toml +1 -1
  3. prefect_client-3.2.8/src/prefect/_build_info.py +5 -0
  4. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/bundles.py +73 -0
  5. prefect_client-3.2.8/src/prefect/_waiters.py +254 -0
  6. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/__init__.py +21 -2
  7. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/subscriptions.py +2 -1
  8. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/clients.py +19 -17
  9. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/schemas/automations.py +1 -1
  10. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/flow_runs.py +67 -35
  11. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/flows.py +10 -2
  12. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/futures.py +192 -22
  13. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/configuration.py +3 -1
  14. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/runner.py +95 -34
  15. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/artifacts.py +5 -0
  16. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/automations.py +5 -0
  17. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/block_capabilities.py +5 -0
  18. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/block_documents.py +2 -0
  19. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/block_schemas.py +5 -0
  20. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/block_types.py +3 -1
  21. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/concurrency_limits.py +5 -0
  22. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/concurrency_limits_v2.py +5 -0
  23. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/deployments.py +2 -0
  24. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/events.py +5 -1
  25. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/flow_run_notification_policies.py +2 -0
  26. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/flow_run_states.py +2 -0
  27. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/flow_runs.py +2 -0
  28. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/flows.py +2 -0
  29. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/logs.py +5 -1
  30. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/server.py +9 -2
  31. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/task_run_states.py +2 -0
  32. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/task_runs.py +2 -0
  33. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/task_workers.py +5 -1
  34. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/variables.py +5 -0
  35. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/work_queues.py +2 -0
  36. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/workers.py +4 -0
  37. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/base.py +18 -3
  38. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/root.py +5 -1
  39. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/api.py +7 -1
  40. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/database.py +14 -0
  41. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/profiles.py +6 -5
  42. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/task_worker.py +3 -3
  43. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/instrumentation.py +2 -2
  44. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/templating.py +50 -11
  45. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/base.py +3 -3
  46. prefect_client-3.2.8/src/prefect/workers/process.py +230 -0
  47. prefect_client-3.2.6/src/prefect/_build_info.py +0 -5
  48. prefect_client-3.2.6/src/prefect/workers/process.py +0 -527
  49. {prefect_client-3.2.6 → prefect_client-3.2.8}/.gitignore +0 -0
  50. {prefect_client-3.2.6 → prefect_client-3.2.8}/LICENSE +0 -0
  51. {prefect_client-3.2.6 → prefect_client-3.2.8}/README.md +0 -0
  52. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/.prefectignore +0 -0
  53. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/__init__.py +0 -0
  54. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/__main__.py +0 -0
  55. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/__init__.py +0 -0
  56. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/lineage.py +0 -0
  57. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/sla/__init__.py +0 -0
  58. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/sla/client.py +0 -0
  59. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_experimental/sla/objects.py +0 -0
  60. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/__init__.py +0 -0
  61. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/_logging.py +0 -0
  62. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/compatibility/__init__.py +0 -0
  63. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/compatibility/async_dispatch.py +0 -0
  64. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/compatibility/deprecated.py +0 -0
  65. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/compatibility/migration.py +0 -0
  66. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/__init__.py +0 -0
  67. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/api.py +0 -0
  68. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/calls.py +0 -0
  69. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/cancellation.py +0 -0
  70. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/event_loop.py +0 -0
  71. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/inspection.py +0 -0
  72. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/primitives.py +0 -0
  73. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/services.py +0 -0
  74. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/threads.py +0 -0
  75. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/concurrency/waiters.py +0 -0
  76. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/integrations.py +0 -0
  77. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/__init__.py +0 -0
  78. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
  79. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
  80. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/schemas.py +0 -0
  81. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
  82. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
  83. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
  84. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/pytz.py +0 -0
  85. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/retries.py +0 -0
  86. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/schemas/__init__.py +0 -0
  87. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/schemas/bases.py +0 -0
  88. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/schemas/fields.py +0 -0
  89. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/schemas/serializers.py +0 -0
  90. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_internal/schemas/validators.py +0 -0
  91. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_result_records.py +0 -0
  92. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_vendor/croniter/__init__.py +0 -0
  93. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/_vendor/croniter/croniter.py +0 -0
  94. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/agent.py +0 -0
  95. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/artifacts.py +0 -0
  96. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/automations.py +0 -0
  97. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/__init__.py +0 -0
  98. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/abstract.py +0 -0
  99. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/core.py +0 -0
  100. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/fields.py +0 -0
  101. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/notifications.py +0 -0
  102. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/redis.py +0 -0
  103. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/system.py +0 -0
  104. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/blocks/webhook.py +0 -0
  105. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/cache_policies.py +0 -0
  106. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/__init__.py +0 -0
  107. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/base.py +0 -0
  108. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/cloud.py +0 -0
  109. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/collections.py +0 -0
  110. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/constants.py +0 -0
  111. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_artifacts/__init__.py +0 -0
  112. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_artifacts/client.py +0 -0
  113. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_automations/__init__.py +0 -0
  114. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_automations/client.py +0 -0
  115. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
  116. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_documents/client.py +0 -0
  117. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
  118. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_schemas/client.py +0 -0
  119. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_types/__init__.py +0 -0
  120. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_blocks_types/client.py +0 -0
  121. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_concurrency_limits/__init__.py +0 -0
  122. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_concurrency_limits/client.py +0 -0
  123. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_deployments/__init__.py +0 -0
  124. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_deployments/client.py +0 -0
  125. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_flow_runs/__init__.py +0 -0
  126. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_flow_runs/client.py +0 -0
  127. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_flows/__init__.py +0 -0
  128. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_flows/client.py +0 -0
  129. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_logs/__init__.py +0 -0
  130. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_logs/client.py +0 -0
  131. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_variables/__init__.py +0 -0
  132. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_variables/client.py +0 -0
  133. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_work_pools/__init__.py +0 -0
  134. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/_work_pools/client.py +0 -0
  135. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/base.py +0 -0
  136. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/orchestration/routes.py +0 -0
  137. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/__init__.py +0 -0
  138. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/actions.py +0 -0
  139. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/filters.py +0 -0
  140. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/objects.py +0 -0
  141. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/responses.py +0 -0
  142. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/schedules.py +0 -0
  143. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/schemas/sorting.py +0 -0
  144. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/types/__init__.py +0 -0
  145. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/types/flexible_schedule_list.py +0 -0
  146. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/client/utilities.py +0 -0
  147. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/__init__.py +0 -0
  148. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/_asyncio.py +0 -0
  149. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/_events.py +0 -0
  150. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/asyncio.py +0 -0
  151. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/context.py +0 -0
  152. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/services.py +0 -0
  153. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/sync.py +0 -0
  154. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/__init__.py +0 -0
  155. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/_asyncio.py +0 -0
  156. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/_events.py +0 -0
  157. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/asyncio.py +0 -0
  158. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/context.py +0 -0
  159. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/services.py +0 -0
  160. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/concurrency/v1/sync.py +0 -0
  161. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/context.py +0 -0
  162. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/__init__.py +0 -0
  163. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/base.py +0 -0
  164. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/deployments.py +0 -0
  165. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/flow_runs.py +0 -0
  166. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/runner.py +0 -0
  167. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/schedules.py +0 -0
  168. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/steps/__init__.py +0 -0
  169. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/steps/core.py +0 -0
  170. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/steps/pull.py +0 -0
  171. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/deployments/steps/utility.py +0 -0
  172. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/docker/__init__.py +0 -0
  173. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/docker/docker_image.py +0 -0
  174. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/engine.py +0 -0
  175. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/__init__.py +0 -0
  176. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/actions.py +0 -0
  177. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/cli/__init__.py +0 -0
  178. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/cli/automations.py +0 -0
  179. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/filters.py +0 -0
  180. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/related.py +0 -0
  181. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/schemas/__init__.py +0 -0
  182. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/schemas/deployment_triggers.py +0 -0
  183. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/schemas/events.py +0 -0
  184. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/schemas/labelling.py +0 -0
  185. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/utilities.py +0 -0
  186. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/events/worker.py +0 -0
  187. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/exceptions.py +0 -0
  188. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/filesystems.py +0 -0
  189. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/flow_engine.py +0 -0
  190. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/__init__.py +0 -0
  191. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/base.py +0 -0
  192. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
  193. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
  194. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/coiled.py +0 -0
  195. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
  196. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
  197. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/infrastructure/provisioners/modal.py +0 -0
  198. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/input/__init__.py +0 -0
  199. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/input/actions.py +0 -0
  200. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/input/run_input.py +0 -0
  201. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/locking/__init__.py +0 -0
  202. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/locking/filesystem.py +0 -0
  203. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/locking/memory.py +0 -0
  204. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/locking/protocol.py +0 -0
  205. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/__init__.py +0 -0
  206. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/filters.py +0 -0
  207. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/formatters.py +0 -0
  208. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/handlers.py +0 -0
  209. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/highlighters.py +0 -0
  210. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/loggers.py +0 -0
  211. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/logging/logging.yml +0 -0
  212. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/main.py +0 -0
  213. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/plugins.py +0 -0
  214. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/py.typed +0 -0
  215. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/results.py +0 -0
  216. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/__init__.py +0 -0
  217. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/server.py +0 -0
  218. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/storage.py +0 -0
  219. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/submit.py +0 -0
  220. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runner/utils.py +0 -0
  221. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runtime/__init__.py +0 -0
  222. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runtime/deployment.py +0 -0
  223. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runtime/flow_run.py +0 -0
  224. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/runtime/task_run.py +0 -0
  225. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/schedules.py +0 -0
  226. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/serializers.py +0 -0
  227. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/__init__.py +0 -0
  228. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/admin.py +0 -0
  229. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/clients.py +0 -0
  230. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/collections.py +0 -0
  231. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
  232. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/csrf_token.py +0 -0
  233. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/dependencies.py +0 -0
  234. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/middleware.py +0 -0
  235. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/root.py +0 -0
  236. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/run_history.py +0 -0
  237. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/saved_searches.py +0 -0
  238. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
  239. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/templates.py +0 -0
  240. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/ui/__init__.py +0 -0
  241. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/ui/flow_runs.py +0 -0
  242. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/ui/flows.py +0 -0
  243. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/ui/schemas.py +0 -0
  244. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/ui/task_runs.py +0 -0
  245. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/server/api/validation.py +0 -0
  246. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/__init__.py +0 -0
  247. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/constants.py +0 -0
  248. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/context.py +0 -0
  249. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/legacy.py +0 -0
  250. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/__init__.py +0 -0
  251. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/api.py +0 -0
  252. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/cli.py +0 -0
  253. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/client.py +0 -0
  254. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/cloud.py +0 -0
  255. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/deployments.py +0 -0
  256. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/experiments.py +0 -0
  257. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/flows.py +0 -0
  258. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/internal.py +0 -0
  259. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/logging.py +0 -0
  260. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/results.py +0 -0
  261. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/runner.py +0 -0
  262. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/__init__.py +0 -0
  263. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/deployments.py +0 -0
  264. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/ephemeral.py +0 -0
  265. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/events.py +0 -0
  266. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/flow_run_graph.py +0 -0
  267. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/root.py +0 -0
  268. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/services.py +0 -0
  269. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/tasks.py +0 -0
  270. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/server/ui.py +0 -0
  271. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/tasks.py +0 -0
  272. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/testing.py +0 -0
  273. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/models/worker.py +0 -0
  274. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/profiles.toml +0 -0
  275. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/settings/sources.py +0 -0
  276. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/states.py +0 -0
  277. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/task_engine.py +0 -0
  278. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/task_runners.py +0 -0
  279. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/task_runs.py +0 -0
  280. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/tasks.py +0 -0
  281. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/__init__.py +0 -0
  282. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/bootstrap.py +0 -0
  283. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/logging.py +0 -0
  284. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/processors.py +0 -0
  285. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/run_telemetry.py +0 -0
  286. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/telemetry/services.py +0 -0
  287. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/transactions.py +0 -0
  288. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/types/__init__.py +0 -0
  289. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/types/_datetime.py +0 -0
  290. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/types/entrypoint.py +0 -0
  291. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/__init__.py +0 -0
  292. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/_deprecated.py +0 -0
  293. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/_engine.py +0 -0
  294. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/_git.py +0 -0
  295. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/annotations.py +0 -0
  296. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/asyncutils.py +0 -0
  297. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/callables.py +0 -0
  298. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/collections.py +0 -0
  299. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/compat.py +0 -0
  300. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/context.py +0 -0
  301. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/dispatch.py +0 -0
  302. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/dockerutils.py +0 -0
  303. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/engine.py +0 -0
  304. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/filesystem.py +0 -0
  305. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/generics.py +0 -0
  306. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/hashing.py +0 -0
  307. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/importtools.py +0 -0
  308. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/math.py +0 -0
  309. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/names.py +0 -0
  310. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/processutils.py +0 -0
  311. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/pydantic.py +0 -0
  312. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/render_swagger.py +0 -0
  313. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/schema_tools/__init__.py +0 -0
  314. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/schema_tools/hydration.py +0 -0
  315. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/schema_tools/validation.py +0 -0
  316. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/services.py +0 -0
  317. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/slugify.py +0 -0
  318. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/text.py +0 -0
  319. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/timeout.py +0 -0
  320. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/urls.py +0 -0
  321. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/utilities/visualization.py +0 -0
  322. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/variables.py +0 -0
  323. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/__init__.py +0 -0
  324. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/block.py +0 -0
  325. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/cloud.py +0 -0
  326. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/server.py +0 -0
  327. {prefect_client-3.2.6 → prefect_client-3.2.8}/src/prefect/workers/utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.2.6
3
+ Version: 3.2.8
4
4
  Summary: Workflow orchestration and management.
5
5
  Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
6
6
  Project-URL: Documentation, https://docs.prefect.io
@@ -57,7 +57,7 @@ Requires-Dist: toml>=0.10.0
57
57
  Requires-Dist: typing-extensions<5.0.0,>=4.5.0
58
58
  Requires-Dist: ujson<6.0.0,>=5.8.0
59
59
  Requires-Dist: uvicorn!=0.29.0,>=0.14.0
60
- Requires-Dist: websockets<14.0,>=10.4
60
+ Requires-Dist: websockets<16.0,>=13.0
61
61
  Provides-Extra: notifications
62
62
  Requires-Dist: apprise<2.0.0,>=1.1.0; extra == 'notifications'
63
63
  Description-Content-Type: text/markdown
@@ -61,7 +61,7 @@ dependencies = [
61
61
  "typing_extensions>=4.5.0,<5.0.0",
62
62
  "ujson>=5.8.0,<6.0.0",
63
63
  "uvicorn>=0.14.0,!=0.29.0",
64
- "websockets>=10.4,<14.0",
64
+ "websockets>=13.0,<16.0",
65
65
  ]
66
66
  [project.urls]
67
67
  Changelog = "https://github.com/PrefectHQ/prefect/releases"
@@ -0,0 +1,5 @@
1
+ # Generated by versioningit
2
+ __version__ = "3.2.8"
3
+ __build_date__ = "2025-02-28 00:11:08.300212+00:00"
4
+ __git_commit__ = "2c0860d5dcd6156fc3fae75d53f7f48f4bd1a522"
5
+ __dirty__ = False
@@ -6,9 +6,12 @@ import gzip
6
6
  import multiprocessing
7
7
  import multiprocessing.context
8
8
  import os
9
+ import subprocess
10
+ import sys
9
11
  from typing import Any, TypedDict
10
12
 
11
13
  import cloudpickle
14
+ import uv
12
15
 
13
16
  from prefect.client.schemas.objects import FlowRun
14
17
  from prefect.context import SettingsContext, get_settings_context, serialize_context
@@ -17,6 +20,7 @@ from prefect.flow_engine import run_flow
17
20
  from prefect.flows import Flow
18
21
  from prefect.settings.context import get_current_settings
19
22
  from prefect.settings.models.root import Settings
23
+ from prefect.utilities.slugify import slugify
20
24
 
21
25
 
22
26
  class SerializedBundle(TypedDict):
@@ -28,6 +32,7 @@ class SerializedBundle(TypedDict):
28
32
  function: str
29
33
  context: str
30
34
  flow_run: dict[str, Any]
35
+ dependencies: str
31
36
 
32
37
 
33
38
  def _serialize_bundle_object(obj: Any) -> str:
@@ -66,6 +71,17 @@ def create_bundle_for_flow_run(
66
71
  "function": _serialize_bundle_object(flow),
67
72
  "context": _serialize_bundle_object(context),
68
73
  "flow_run": flow_run.model_dump(mode="json"),
74
+ "dependencies": subprocess.check_output(
75
+ [
76
+ uv.find_uv_bin(),
77
+ "pip",
78
+ "freeze",
79
+ # Exclude editable installs because we won't be able to install them in the execution environment
80
+ "--exclude-editable",
81
+ ]
82
+ )
83
+ .decode()
84
+ .strip(),
69
85
  }
70
86
 
71
87
 
@@ -129,6 +145,14 @@ def execute_bundle_in_subprocess(
129
145
 
130
146
  ctx = multiprocessing.get_context("spawn")
131
147
 
148
+ # Install dependencies if necessary
149
+ if dependencies := bundle.get("dependencies"):
150
+ subprocess.check_call(
151
+ [uv.find_uv_bin(), "pip", "install", *dependencies.split("\n")],
152
+ # Copy the current environment to ensure we install into the correct venv
153
+ env=os.environ,
154
+ )
155
+
132
156
  process = ctx.Process(
133
157
  target=_extract_and_run_flow,
134
158
  kwargs={
@@ -141,3 +165,52 @@ def execute_bundle_in_subprocess(
141
165
  process.start()
142
166
 
143
167
  return process
168
+
169
+
170
+ def convert_step_to_command(step: dict[str, Any], key: str) -> list[str]:
171
+ """
172
+ Converts a bundle upload or execution step to a command.
173
+
174
+ Args:
175
+ step: The step to convert.
176
+ key: The key to use for the remote file when downloading or uploading.
177
+
178
+ Returns:
179
+ A list of strings representing the command to run the step.
180
+ """
181
+ # Start with uv run
182
+ command = ["uv", "run"]
183
+
184
+ step_keys = list(step.keys())
185
+
186
+ if len(step_keys) != 1:
187
+ raise ValueError("Expected exactly one function in step")
188
+
189
+ function_fqn = step_keys[0]
190
+ function_args = step[function_fqn]
191
+
192
+ # Add the `--with` argument to handle dependencies for running the step
193
+ requires: list[str] | str = function_args.get("requires", [])
194
+ if isinstance(requires, str):
195
+ requires = [requires]
196
+ if requires:
197
+ command.extend(["--with", ",".join(requires)])
198
+
199
+ # Add the `--python` argument to handle the Python version for running the step
200
+ python_version = sys.version_info
201
+ command.extend(["--python", f"{python_version.major}.{python_version.minor}"])
202
+
203
+ # Add the `-m` argument to defined the function to run
204
+ command.extend(["-m", function_fqn])
205
+
206
+ # Add any arguments with values defined in the step
207
+ for arg_name, arg_value in function_args.items():
208
+ if arg_name == "requires":
209
+ continue
210
+
211
+ command.extend([f"--{slugify(arg_name)}", arg_value])
212
+
213
+ # Add the `--key` argument to specify the remote file name
214
+ command.extend(["--key", key])
215
+
216
+ return command
@@ -0,0 +1,254 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import atexit
5
+ import threading
6
+ import uuid
7
+ from typing import (
8
+ TYPE_CHECKING,
9
+ Callable,
10
+ )
11
+
12
+ import anyio
13
+ from cachetools import TTLCache
14
+ from typing_extensions import Self
15
+
16
+ from prefect._internal.concurrency.api import create_call, from_async, from_sync
17
+ from prefect._internal.concurrency.threads import get_global_loop
18
+ from prefect.client.schemas.objects import (
19
+ TERMINAL_STATES,
20
+ )
21
+ from prefect.events.clients import get_events_subscriber
22
+ from prefect.events.filters import EventFilter, EventNameFilter
23
+ from prefect.logging import get_logger
24
+
25
+ if TYPE_CHECKING:
26
+ import logging
27
+
28
+
29
+ class FlowRunWaiter:
30
+ """
31
+ A service used for waiting for a flow run to finish.
32
+
33
+ This service listens for flow run events and provides a way to wait for a specific
34
+ flow run to finish. This is useful for waiting for a flow run to finish before
35
+ continuing execution.
36
+
37
+ The service is a singleton and must be started before use. The service will
38
+ automatically start when the first instance is created. A single websocket
39
+ connection is used to listen for flow run events.
40
+
41
+ The service can be used to wait for a flow run to finish by calling
42
+ `FlowRunWaiter.wait_for_flow_run` with the flow run ID to wait for. The method
43
+ will return when the flow run has finished or the timeout has elapsed.
44
+
45
+ The service will automatically stop when the Python process exits or when the
46
+ global loop thread is stopped.
47
+
48
+ Example:
49
+ ```python
50
+ import asyncio
51
+ from uuid import uuid4
52
+
53
+ from prefect import flow
54
+ from prefect.flow_engine import run_flow_async
55
+ from prefect.flow_runs import FlowRunWaiter
56
+
57
+
58
+ @flow
59
+ async def test_flow():
60
+ await asyncio.sleep(5)
61
+ print("Done!")
62
+
63
+
64
+ async def main():
65
+ flow_run_id = uuid4()
66
+ asyncio.create_flow(run_flow_async(flow=test_flow, flow_run_id=flow_run_id))
67
+
68
+ await FlowRunWaiter.wait_for_flow_run(flow_run_id)
69
+ print("Flow run finished")
70
+
71
+
72
+ if __name__ == "__main__":
73
+ asyncio.run(main())
74
+ ```
75
+ """
76
+
77
+ _instance: Self | None = None
78
+ _instance_lock = threading.Lock()
79
+
80
+ def __init__(self):
81
+ self.logger: "logging.Logger" = get_logger("FlowRunWaiter")
82
+ self._consumer_task: asyncio.Task[None] | None = None
83
+ self._observed_completed_flow_runs: TTLCache[uuid.UUID, bool] = TTLCache(
84
+ maxsize=10000, ttl=600
85
+ )
86
+ self._completion_events: dict[uuid.UUID, asyncio.Event] = {}
87
+ self._completion_callbacks: dict[uuid.UUID, Callable[[], None]] = {}
88
+ self._loop: asyncio.AbstractEventLoop | None = None
89
+ self._observed_completed_flow_runs_lock = threading.Lock()
90
+ self._completion_events_lock = threading.Lock()
91
+ self._started = False
92
+
93
+ def start(self) -> None:
94
+ """
95
+ Start the FlowRunWaiter service.
96
+ """
97
+ if self._started:
98
+ return
99
+ self.logger.debug("Starting FlowRunWaiter")
100
+ loop_thread = get_global_loop()
101
+
102
+ if not asyncio.get_running_loop() == loop_thread.loop:
103
+ raise RuntimeError("FlowRunWaiter must run on the global loop thread.")
104
+
105
+ self._loop = loop_thread.loop
106
+ if TYPE_CHECKING:
107
+ assert self._loop is not None
108
+
109
+ consumer_started = asyncio.Event()
110
+ self._consumer_task = self._loop.create_task(
111
+ self._consume_events(consumer_started)
112
+ )
113
+ asyncio.run_coroutine_threadsafe(consumer_started.wait(), self._loop)
114
+
115
+ loop_thread.add_shutdown_call(create_call(self.stop))
116
+ atexit.register(self.stop)
117
+ self._started = True
118
+
119
+ async def _consume_events(self, consumer_started: asyncio.Event):
120
+ async with get_events_subscriber(
121
+ filter=EventFilter(
122
+ event=EventNameFilter(
123
+ name=[
124
+ f"prefect.flow-run.{state.name.title()}"
125
+ for state in TERMINAL_STATES
126
+ ],
127
+ )
128
+ )
129
+ ) as subscriber:
130
+ consumer_started.set()
131
+ async for event in subscriber:
132
+ try:
133
+ self.logger.debug(
134
+ f"Received event: {event.resource['prefect.resource.id']}"
135
+ )
136
+ flow_run_id = uuid.UUID(
137
+ event.resource["prefect.resource.id"].replace(
138
+ "prefect.flow-run.", ""
139
+ )
140
+ )
141
+
142
+ with self._observed_completed_flow_runs_lock:
143
+ # Cache the flow run ID for a short period of time to avoid
144
+ # unnecessary waits
145
+ self._observed_completed_flow_runs[flow_run_id] = True
146
+ with self._completion_events_lock:
147
+ # Set the event for the flow run ID if it is in the cache
148
+ # so the waiter can wake up the waiting coroutine
149
+ if flow_run_id in self._completion_events:
150
+ self._completion_events[flow_run_id].set()
151
+ if flow_run_id in self._completion_callbacks:
152
+ self._completion_callbacks[flow_run_id]()
153
+ except Exception as exc:
154
+ self.logger.error(f"Error processing event: {exc}")
155
+
156
+ def stop(self) -> None:
157
+ """
158
+ Stop the FlowRunWaiter service.
159
+ """
160
+ self.logger.debug("Stopping FlowRunWaiter")
161
+ if self._consumer_task:
162
+ self._consumer_task.cancel()
163
+ self._consumer_task = None
164
+ self.__class__._instance = None
165
+ self._started = False
166
+
167
+ @classmethod
168
+ async def wait_for_flow_run(
169
+ cls, flow_run_id: uuid.UUID, timeout: float | None = None
170
+ ) -> None:
171
+ """
172
+ Wait for a flow run to finish.
173
+
174
+ Note this relies on a websocket connection to receive events from the server
175
+ and will not work with an ephemeral server.
176
+
177
+ Args:
178
+ flow_run_id: The ID of the flow run to wait for.
179
+ timeout: The maximum time to wait for the flow run to
180
+ finish. Defaults to None.
181
+ """
182
+ instance = cls.instance()
183
+ with instance._observed_completed_flow_runs_lock:
184
+ if flow_run_id in instance._observed_completed_flow_runs:
185
+ return
186
+
187
+ # Need to create event in loop thread to ensure it can be set
188
+ # from the loop thread
189
+ finished_event = await from_async.wait_for_call_in_loop_thread(
190
+ create_call(asyncio.Event)
191
+ )
192
+ with instance._completion_events_lock:
193
+ # Cache the event for the flow run ID so the consumer can set it
194
+ # when the event is received
195
+ instance._completion_events[flow_run_id] = finished_event
196
+
197
+ try:
198
+ # Now check one more time whether the flow run arrived before we start to
199
+ # wait on it, in case it came in while we were setting up the event above.
200
+ with instance._observed_completed_flow_runs_lock:
201
+ if flow_run_id in instance._observed_completed_flow_runs:
202
+ return
203
+
204
+ with anyio.move_on_after(delay=timeout):
205
+ await from_async.wait_for_call_in_loop_thread(
206
+ create_call(finished_event.wait)
207
+ )
208
+ finally:
209
+ with instance._completion_events_lock:
210
+ # Remove the event from the cache after it has been waited on
211
+ instance._completion_events.pop(flow_run_id, None)
212
+
213
+ @classmethod
214
+ def add_done_callback(
215
+ cls, flow_run_id: uuid.UUID, callback: Callable[[], None]
216
+ ) -> None:
217
+ """
218
+ Add a callback to be called when a flow run finishes.
219
+
220
+ Args:
221
+ flow_run_id: The ID of the flow run to wait for.
222
+ callback: The callback to call when the flow run finishes.
223
+ """
224
+ instance = cls.instance()
225
+ with instance._observed_completed_flow_runs_lock:
226
+ if flow_run_id in instance._observed_completed_flow_runs:
227
+ callback()
228
+ return
229
+
230
+ with instance._completion_events_lock:
231
+ # Cache the event for the flow run ID so the consumer can set it
232
+ # when the event is received
233
+ instance._completion_callbacks[flow_run_id] = callback
234
+
235
+ @classmethod
236
+ def instance(cls) -> Self:
237
+ """
238
+ Get the singleton instance of FlowRunWaiter.
239
+ """
240
+ with cls._instance_lock:
241
+ if cls._instance is None:
242
+ cls._instance = cls._new_instance()
243
+ return cls._instance
244
+
245
+ @classmethod
246
+ def _new_instance(cls):
247
+ instance = cls()
248
+
249
+ if threading.get_ident() == get_global_loop().thread.ident:
250
+ instance.start()
251
+ else:
252
+ from_sync.call_soon_in_loop_thread(create_call(instance.start)).result()
253
+
254
+ return instance
@@ -81,6 +81,7 @@ from prefect.client.orchestration._blocks_types.client import (
81
81
 
82
82
  import prefect
83
83
  import prefect.exceptions
84
+ from prefect.logging.loggers import get_run_logger
84
85
  import prefect.settings
85
86
  import prefect.states
86
87
  from prefect.client.constants import SERVER_API_VERSION
@@ -1182,8 +1183,17 @@ class PrefectClient(
1182
1183
  if api_version.major != client_version.major:
1183
1184
  raise RuntimeError(
1184
1185
  f"Found incompatible versions: client: {client_version}, server: {api_version}. "
1185
- f"Major versions must match."
1186
+ "Major versions must match."
1186
1187
  )
1188
+ if api_version < client_version:
1189
+ warning_message = (
1190
+ "Your Prefect server is running an older version of Prefect than your client which may result in unexpected behavior. "
1191
+ f"Please upgrade your Prefect server from version {api_version} to version {client_version} or higher."
1192
+ )
1193
+ try:
1194
+ get_run_logger().warning(warning_message)
1195
+ except prefect.context.MissingContextError:
1196
+ self.logger.warning(warning_message)
1187
1197
 
1188
1198
  async def __aenter__(self) -> Self:
1189
1199
  """
@@ -1523,8 +1533,17 @@ class SyncPrefectClient(
1523
1533
  if api_version.major != client_version.major:
1524
1534
  raise RuntimeError(
1525
1535
  f"Found incompatible versions: client: {client_version}, server: {api_version}. "
1526
- f"Major versions must match."
1536
+ "Major versions must match."
1527
1537
  )
1538
+ if api_version < client_version:
1539
+ warning_message = (
1540
+ "Your Prefect server is running an older version of Prefect than your client which may result in unexpected behavior. "
1541
+ f"Please upgrade your Prefect server from version {api_version} to version {client_version} or higher."
1542
+ )
1543
+ try:
1544
+ get_run_logger().warning(warning_message)
1545
+ except prefect.context.MissingContextError:
1546
+ self.logger.warning(warning_message)
1528
1547
 
1529
1548
  def set_task_run_name(self, task_run_id: UUID, name: str) -> httpx.Response:
1530
1549
  task_run_data = TaskRunUpdate(name=name)
@@ -5,6 +5,7 @@ from typing import Any, Generic, Optional, TypeVar
5
5
 
6
6
  import orjson
7
7
  import websockets
8
+ import websockets.asyncio.client
8
9
  import websockets.exceptions
9
10
  from starlette.status import WS_1008_POLICY_VIOLATION
10
11
  from typing_extensions import Self
@@ -45,7 +46,7 @@ class Subscription(Generic[S]):
45
46
  return self
46
47
 
47
48
  @property
48
- def websocket(self) -> websockets.WebSocketClientProtocol:
49
+ def websocket(self) -> websockets.asyncio.client.ClientConnection:
49
50
  if not self._websocket:
50
51
  raise RuntimeError("Subscription is not connected")
51
52
  return self._websocket
@@ -27,12 +27,12 @@ from prometheus_client import Counter
27
27
  from python_socks.async_.asyncio import Proxy
28
28
  from typing_extensions import Self
29
29
  from websockets import Subprotocol
30
+ from websockets.asyncio.client import ClientConnection, connect
30
31
  from websockets.exceptions import (
31
32
  ConnectionClosed,
32
33
  ConnectionClosedError,
33
34
  ConnectionClosedOK,
34
35
  )
35
- from websockets.legacy.client import Connect, WebSocketClientProtocol
36
36
 
37
37
  from prefect.events import Event
38
38
  from prefect.logging import get_logger
@@ -91,7 +91,7 @@ def events_out_socket_from_api_url(url: str) -> str:
91
91
  return http_to_ws(url) + "/events/out"
92
92
 
93
93
 
94
- class WebsocketProxyConnect(Connect):
94
+ class WebsocketProxyConnect(connect):
95
95
  def __init__(self: Self, uri: str, **kwargs: Any):
96
96
  # super() is intentionally deferred to the _proxy_connect method
97
97
  # to allow for the socket to be established first
@@ -130,7 +130,7 @@ class WebsocketProxyConnect(Connect):
130
130
  ctx.verify_mode = ssl.CERT_NONE
131
131
  self._kwargs.setdefault("ssl", ctx)
132
132
 
133
- async def _proxy_connect(self: Self) -> WebSocketClientProtocol:
133
+ async def _proxy_connect(self: Self) -> ClientConnection:
134
134
  if self._proxy:
135
135
  sock = await self._proxy.connect(
136
136
  dest_host=self._host,
@@ -142,7 +142,7 @@ class WebsocketProxyConnect(Connect):
142
142
  proto = await self.__await_impl__()
143
143
  return proto
144
144
 
145
- def __await__(self: Self) -> Generator[Any, None, WebSocketClientProtocol]:
145
+ def __await__(self: Self) -> Generator[Any, None, ClientConnection]:
146
146
  return self._proxy_connect().__await__()
147
147
 
148
148
 
@@ -311,7 +311,7 @@ def _get_api_url_and_key(
311
311
  class PrefectEventsClient(EventsClient):
312
312
  """A Prefect Events client that streams events to a Prefect server"""
313
313
 
314
- _websocket: Optional[WebSocketClientProtocol]
314
+ _websocket: Optional[ClientConnection]
315
315
  _unconfirmed_events: List[Event]
316
316
 
317
317
  def __init__(
@@ -403,19 +403,11 @@ class PrefectEventsClient(EventsClient):
403
403
  await self.emit(event)
404
404
  logger.debug("Finished resending unconfirmed events.")
405
405
 
406
- async def _checkpoint(self, event: Event) -> None:
406
+ async def _checkpoint(self) -> None:
407
407
  assert self._websocket
408
408
 
409
- self._unconfirmed_events.append(event)
410
-
411
409
  unconfirmed_count = len(self._unconfirmed_events)
412
410
 
413
- logger.debug(
414
- "Added event id=%s to unconfirmed events list. "
415
- "There are now %s unconfirmed events.",
416
- event.id,
417
- unconfirmed_count,
418
- )
419
411
  if unconfirmed_count < self._checkpoint_every:
420
412
  return
421
413
 
@@ -433,6 +425,16 @@ class PrefectEventsClient(EventsClient):
433
425
 
434
426
  async def _emit(self, event: Event) -> None:
435
427
  self._log_debug("Emitting event id=%s.", event.id)
428
+
429
+ self._unconfirmed_events.append(event)
430
+
431
+ logger.debug(
432
+ "Added event id=%s to unconfirmed events list. "
433
+ "There are now %s unconfirmed events.",
434
+ event.id,
435
+ len(self._unconfirmed_events),
436
+ )
437
+
436
438
  for i in range(self._reconnection_attempts + 1):
437
439
  self._log_debug("Emit reconnection attempt %s.", i)
438
440
  try:
@@ -450,7 +452,7 @@ class PrefectEventsClient(EventsClient):
450
452
  self._log_debug("Sending event id=%s.", event.id)
451
453
  await self._websocket.send(event.model_dump_json())
452
454
  self._log_debug("Checkpointing event id=%s.", event.id)
453
- await self._checkpoint(event)
455
+ await self._checkpoint()
454
456
 
455
457
  return
456
458
  except ConnectionClosed:
@@ -537,7 +539,7 @@ class PrefectCloudEventsClient(PrefectEventsClient):
537
539
  )
538
540
  self._connect = websocket_connect(
539
541
  self._events_socket_url,
540
- extra_headers={"Authorization": f"bearer {api_key}"},
542
+ additional_headers={"Authorization": f"bearer {api_key}"},
541
543
  )
542
544
 
543
545
 
@@ -562,7 +564,7 @@ class PrefectEventSubscriber:
562
564
 
563
565
  """
564
566
 
565
- _websocket: Optional[WebSocketClientProtocol]
567
+ _websocket: Optional[ClientConnection]
566
568
  _filter: "EventFilter"
567
569
  _seen_events: MutableMapping[UUID, bool]
568
570
 
@@ -84,7 +84,7 @@ class Trigger(PrefectBaseModel, abc.ABC, extra="ignore"): # type: ignore[call-a
84
84
  getattr(self, "name", None)
85
85
  or f"Automation for deployment {self._deployment_id}"
86
86
  ),
87
- description="",
87
+ description=getattr(self, "description", ""),
88
88
  enabled=getattr(self, "enabled", True),
89
89
  trigger=trigger,
90
90
  actions=self.actions(),