prefect-client 2.20.4__py3-none-any.whl → 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. prefect/__init__.py +74 -110
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/compatibility/migration.py +166 -0
  5. prefect/_internal/concurrency/__init__.py +2 -2
  6. prefect/_internal/concurrency/api.py +1 -35
  7. prefect/_internal/concurrency/calls.py +0 -6
  8. prefect/_internal/concurrency/cancellation.py +0 -3
  9. prefect/_internal/concurrency/event_loop.py +0 -20
  10. prefect/_internal/concurrency/inspection.py +3 -3
  11. prefect/_internal/concurrency/primitives.py +1 -0
  12. prefect/_internal/concurrency/services.py +23 -0
  13. prefect/_internal/concurrency/threads.py +35 -0
  14. prefect/_internal/concurrency/waiters.py +0 -28
  15. prefect/_internal/integrations.py +7 -0
  16. prefect/_internal/pydantic/__init__.py +0 -45
  17. prefect/_internal/pydantic/annotations/pendulum.py +2 -2
  18. prefect/_internal/pydantic/v1_schema.py +21 -22
  19. prefect/_internal/pydantic/v2_schema.py +0 -2
  20. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  21. prefect/_internal/pytz.py +1 -1
  22. prefect/_internal/retries.py +61 -0
  23. prefect/_internal/schemas/bases.py +45 -177
  24. prefect/_internal/schemas/fields.py +1 -43
  25. prefect/_internal/schemas/validators.py +47 -233
  26. prefect/agent.py +3 -695
  27. prefect/artifacts.py +173 -14
  28. prefect/automations.py +39 -4
  29. prefect/blocks/abstract.py +1 -1
  30. prefect/blocks/core.py +405 -153
  31. prefect/blocks/fields.py +2 -57
  32. prefect/blocks/notifications.py +43 -28
  33. prefect/blocks/redis.py +168 -0
  34. prefect/blocks/system.py +67 -20
  35. prefect/blocks/webhook.py +2 -9
  36. prefect/cache_policies.py +239 -0
  37. prefect/client/__init__.py +4 -0
  38. prefect/client/base.py +33 -27
  39. prefect/client/cloud.py +65 -20
  40. prefect/client/collections.py +1 -1
  41. prefect/client/orchestration.py +650 -442
  42. prefect/client/schemas/actions.py +115 -100
  43. prefect/client/schemas/filters.py +46 -52
  44. prefect/client/schemas/objects.py +228 -178
  45. prefect/client/schemas/responses.py +18 -36
  46. prefect/client/schemas/schedules.py +55 -36
  47. prefect/client/schemas/sorting.py +2 -0
  48. prefect/client/subscriptions.py +8 -7
  49. prefect/client/types/flexible_schedule_list.py +11 -0
  50. prefect/client/utilities.py +9 -6
  51. prefect/concurrency/asyncio.py +60 -11
  52. prefect/concurrency/context.py +24 -0
  53. prefect/concurrency/events.py +2 -2
  54. prefect/concurrency/services.py +46 -16
  55. prefect/concurrency/sync.py +51 -7
  56. prefect/concurrency/v1/asyncio.py +143 -0
  57. prefect/concurrency/v1/context.py +27 -0
  58. prefect/concurrency/v1/events.py +61 -0
  59. prefect/concurrency/v1/services.py +116 -0
  60. prefect/concurrency/v1/sync.py +92 -0
  61. prefect/context.py +246 -149
  62. prefect/deployments/__init__.py +33 -18
  63. prefect/deployments/base.py +10 -15
  64. prefect/deployments/deployments.py +2 -1048
  65. prefect/deployments/flow_runs.py +178 -0
  66. prefect/deployments/runner.py +72 -173
  67. prefect/deployments/schedules.py +31 -25
  68. prefect/deployments/steps/__init__.py +0 -1
  69. prefect/deployments/steps/core.py +7 -0
  70. prefect/deployments/steps/pull.py +15 -21
  71. prefect/deployments/steps/utility.py +2 -1
  72. prefect/docker/__init__.py +20 -0
  73. prefect/docker/docker_image.py +82 -0
  74. prefect/engine.py +15 -2475
  75. prefect/events/actions.py +17 -23
  76. prefect/events/cli/automations.py +20 -7
  77. prefect/events/clients.py +142 -80
  78. prefect/events/filters.py +14 -18
  79. prefect/events/related.py +74 -75
  80. prefect/events/schemas/__init__.py +0 -5
  81. prefect/events/schemas/automations.py +55 -46
  82. prefect/events/schemas/deployment_triggers.py +7 -197
  83. prefect/events/schemas/events.py +46 -65
  84. prefect/events/schemas/labelling.py +10 -14
  85. prefect/events/utilities.py +4 -5
  86. prefect/events/worker.py +23 -8
  87. prefect/exceptions.py +15 -0
  88. prefect/filesystems.py +30 -529
  89. prefect/flow_engine.py +827 -0
  90. prefect/flow_runs.py +379 -7
  91. prefect/flows.py +470 -360
  92. prefect/futures.py +382 -331
  93. prefect/infrastructure/__init__.py +5 -26
  94. prefect/infrastructure/base.py +3 -320
  95. prefect/infrastructure/provisioners/__init__.py +5 -3
  96. prefect/infrastructure/provisioners/cloud_run.py +13 -8
  97. prefect/infrastructure/provisioners/container_instance.py +14 -9
  98. prefect/infrastructure/provisioners/ecs.py +10 -8
  99. prefect/infrastructure/provisioners/modal.py +8 -5
  100. prefect/input/__init__.py +4 -0
  101. prefect/input/actions.py +2 -4
  102. prefect/input/run_input.py +9 -9
  103. prefect/logging/formatters.py +2 -4
  104. prefect/logging/handlers.py +9 -14
  105. prefect/logging/loggers.py +5 -5
  106. prefect/main.py +72 -0
  107. prefect/plugins.py +2 -64
  108. prefect/profiles.toml +16 -2
  109. prefect/records/__init__.py +1 -0
  110. prefect/records/base.py +223 -0
  111. prefect/records/filesystem.py +207 -0
  112. prefect/records/memory.py +178 -0
  113. prefect/records/result_store.py +64 -0
  114. prefect/results.py +577 -504
  115. prefect/runner/runner.py +117 -47
  116. prefect/runner/server.py +32 -34
  117. prefect/runner/storage.py +3 -12
  118. prefect/runner/submit.py +2 -10
  119. prefect/runner/utils.py +2 -2
  120. prefect/runtime/__init__.py +1 -0
  121. prefect/runtime/deployment.py +1 -0
  122. prefect/runtime/flow_run.py +40 -5
  123. prefect/runtime/task_run.py +1 -0
  124. prefect/serializers.py +28 -39
  125. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  126. prefect/settings.py +209 -332
  127. prefect/states.py +160 -63
  128. prefect/task_engine.py +1478 -57
  129. prefect/task_runners.py +383 -287
  130. prefect/task_runs.py +240 -0
  131. prefect/task_worker.py +463 -0
  132. prefect/tasks.py +684 -374
  133. prefect/transactions.py +410 -0
  134. prefect/types/__init__.py +72 -86
  135. prefect/types/entrypoint.py +13 -0
  136. prefect/utilities/annotations.py +4 -3
  137. prefect/utilities/asyncutils.py +227 -148
  138. prefect/utilities/callables.py +137 -45
  139. prefect/utilities/collections.py +134 -86
  140. prefect/utilities/dispatch.py +27 -14
  141. prefect/utilities/dockerutils.py +11 -4
  142. prefect/utilities/engine.py +186 -32
  143. prefect/utilities/filesystem.py +4 -5
  144. prefect/utilities/importtools.py +26 -27
  145. prefect/utilities/pydantic.py +128 -38
  146. prefect/utilities/schema_tools/hydration.py +18 -1
  147. prefect/utilities/schema_tools/validation.py +30 -0
  148. prefect/utilities/services.py +35 -9
  149. prefect/utilities/templating.py +12 -2
  150. prefect/utilities/timeout.py +20 -5
  151. prefect/utilities/urls.py +195 -0
  152. prefect/utilities/visualization.py +1 -0
  153. prefect/variables.py +78 -59
  154. prefect/workers/__init__.py +0 -1
  155. prefect/workers/base.py +237 -244
  156. prefect/workers/block.py +5 -226
  157. prefect/workers/cloud.py +6 -0
  158. prefect/workers/process.py +265 -12
  159. prefect/workers/server.py +29 -11
  160. {prefect_client-2.20.4.dist-info → prefect_client-3.0.0.dist-info}/METADATA +28 -24
  161. prefect_client-3.0.0.dist-info/RECORD +201 -0
  162. {prefect_client-2.20.4.dist-info → prefect_client-3.0.0.dist-info}/WHEEL +1 -1
  163. prefect/_internal/pydantic/_base_model.py +0 -51
  164. prefect/_internal/pydantic/_compat.py +0 -82
  165. prefect/_internal/pydantic/_flags.py +0 -20
  166. prefect/_internal/pydantic/_types.py +0 -8
  167. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  168. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  169. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  170. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  171. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  172. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  173. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  174. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  175. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  176. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  177. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  178. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  179. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  180. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  181. prefect/_vendor/fastapi/__init__.py +0 -25
  182. prefect/_vendor/fastapi/applications.py +0 -946
  183. prefect/_vendor/fastapi/background.py +0 -3
  184. prefect/_vendor/fastapi/concurrency.py +0 -44
  185. prefect/_vendor/fastapi/datastructures.py +0 -58
  186. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  187. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  188. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  189. prefect/_vendor/fastapi/encoders.py +0 -177
  190. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  191. prefect/_vendor/fastapi/exceptions.py +0 -46
  192. prefect/_vendor/fastapi/logger.py +0 -3
  193. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  194. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  195. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  196. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  197. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  198. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  199. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  200. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  201. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  202. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  203. prefect/_vendor/fastapi/openapi/models.py +0 -480
  204. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  205. prefect/_vendor/fastapi/param_functions.py +0 -340
  206. prefect/_vendor/fastapi/params.py +0 -453
  207. prefect/_vendor/fastapi/py.typed +0 -0
  208. prefect/_vendor/fastapi/requests.py +0 -4
  209. prefect/_vendor/fastapi/responses.py +0 -40
  210. prefect/_vendor/fastapi/routing.py +0 -1331
  211. prefect/_vendor/fastapi/security/__init__.py +0 -15
  212. prefect/_vendor/fastapi/security/api_key.py +0 -98
  213. prefect/_vendor/fastapi/security/base.py +0 -6
  214. prefect/_vendor/fastapi/security/http.py +0 -172
  215. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  216. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  217. prefect/_vendor/fastapi/security/utils.py +0 -10
  218. prefect/_vendor/fastapi/staticfiles.py +0 -1
  219. prefect/_vendor/fastapi/templating.py +0 -3
  220. prefect/_vendor/fastapi/testclient.py +0 -1
  221. prefect/_vendor/fastapi/types.py +0 -3
  222. prefect/_vendor/fastapi/utils.py +0 -235
  223. prefect/_vendor/fastapi/websockets.py +0 -7
  224. prefect/_vendor/starlette/__init__.py +0 -1
  225. prefect/_vendor/starlette/_compat.py +0 -28
  226. prefect/_vendor/starlette/_exception_handler.py +0 -80
  227. prefect/_vendor/starlette/_utils.py +0 -88
  228. prefect/_vendor/starlette/applications.py +0 -261
  229. prefect/_vendor/starlette/authentication.py +0 -159
  230. prefect/_vendor/starlette/background.py +0 -43
  231. prefect/_vendor/starlette/concurrency.py +0 -59
  232. prefect/_vendor/starlette/config.py +0 -151
  233. prefect/_vendor/starlette/convertors.py +0 -87
  234. prefect/_vendor/starlette/datastructures.py +0 -707
  235. prefect/_vendor/starlette/endpoints.py +0 -130
  236. prefect/_vendor/starlette/exceptions.py +0 -60
  237. prefect/_vendor/starlette/formparsers.py +0 -276
  238. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  239. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  240. prefect/_vendor/starlette/middleware/base.py +0 -220
  241. prefect/_vendor/starlette/middleware/cors.py +0 -176
  242. prefect/_vendor/starlette/middleware/errors.py +0 -265
  243. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  244. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  245. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  246. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  247. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  248. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  249. prefect/_vendor/starlette/py.typed +0 -0
  250. prefect/_vendor/starlette/requests.py +0 -328
  251. prefect/_vendor/starlette/responses.py +0 -347
  252. prefect/_vendor/starlette/routing.py +0 -933
  253. prefect/_vendor/starlette/schemas.py +0 -154
  254. prefect/_vendor/starlette/staticfiles.py +0 -248
  255. prefect/_vendor/starlette/status.py +0 -199
  256. prefect/_vendor/starlette/templating.py +0 -231
  257. prefect/_vendor/starlette/testclient.py +0 -804
  258. prefect/_vendor/starlette/types.py +0 -30
  259. prefect/_vendor/starlette/websockets.py +0 -193
  260. prefect/blocks/kubernetes.py +0 -119
  261. prefect/deprecated/__init__.py +0 -0
  262. prefect/deprecated/data_documents.py +0 -350
  263. prefect/deprecated/packaging/__init__.py +0 -12
  264. prefect/deprecated/packaging/base.py +0 -96
  265. prefect/deprecated/packaging/docker.py +0 -146
  266. prefect/deprecated/packaging/file.py +0 -92
  267. prefect/deprecated/packaging/orion.py +0 -80
  268. prefect/deprecated/packaging/serializers.py +0 -171
  269. prefect/events/instrument.py +0 -135
  270. prefect/infrastructure/container.py +0 -824
  271. prefect/infrastructure/kubernetes.py +0 -920
  272. prefect/infrastructure/process.py +0 -289
  273. prefect/manifests.py +0 -20
  274. prefect/new_flow_engine.py +0 -449
  275. prefect/new_task_engine.py +0 -423
  276. prefect/pydantic/__init__.py +0 -76
  277. prefect/pydantic/main.py +0 -39
  278. prefect/software/__init__.py +0 -2
  279. prefect/software/base.py +0 -50
  280. prefect/software/conda.py +0 -199
  281. prefect/software/pip.py +0 -122
  282. prefect/software/python.py +0 -52
  283. prefect/task_server.py +0 -322
  284. prefect_client-2.20.4.dist-info/RECORD +0 -294
  285. /prefect/{_internal/pydantic/utilities → client/types}/__init__.py +0 -0
  286. /prefect/{_vendor → concurrency/v1}/__init__.py +0 -0
  287. {prefect_client-2.20.4.dist-info → prefect_client-3.0.0.dist-info}/LICENSE +0 -0
  288. {prefect_client-2.20.4.dist-info → prefect_client-3.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,195 @@
1
+ import inspect
2
+ import urllib.parse
3
+ from typing import Any, Literal, Optional, Union
4
+ from uuid import UUID
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from prefect import settings
9
+ from prefect.blocks.core import Block
10
+ from prefect.events.schemas.automations import Automation
11
+ from prefect.events.schemas.events import ReceivedEvent, Resource
12
+ from prefect.futures import PrefectFuture
13
+ from prefect.logging.loggers import get_logger
14
+ from prefect.variables import Variable
15
+
16
+ logger = get_logger("utilities.urls")
17
+
18
+ # The following objects are excluded from UI URL generation because we lack a
19
+ # directly-addressable URL:
20
+ # worker
21
+ # artifact
22
+ # variable
23
+ # saved-search
24
+ UI_URL_FORMATS = {
25
+ "flow": "flows/flow/{obj_id}",
26
+ "flow-run": "runs/flow-run/{obj_id}",
27
+ "task-run": "runs/task-run/{obj_id}",
28
+ "block": "blocks/block/{obj_id}",
29
+ "block-document": "blocks/block/{obj_id}",
30
+ "work-pool": "work-pools/work-pool/{obj_id}",
31
+ "work-queue": "work-queues/work-queue/{obj_id}",
32
+ "concurrency-limit": "concurrency-limits/concurrency-limit/{obj_id}",
33
+ "deployment": "deployments/deployment/{obj_id}",
34
+ "automation": "automations/automation/{obj_id}",
35
+ "received-event": "events/event/{occurred}/{obj_id}",
36
+ }
37
+
38
+ # The following objects are excluded from API URL generation because we lack a
39
+ # directly-addressable URL:
40
+ # worker
41
+ # artifact
42
+ # saved-search
43
+ # received-event
44
+ API_URL_FORMATS = {
45
+ "flow": "flows/{obj_id}",
46
+ "flow-run": "flow_runs/{obj_id}",
47
+ "task-run": "task_runs/{obj_id}",
48
+ "variable": "variables/name/{obj_id}",
49
+ "block": "blocks/{obj_id}",
50
+ "work-pool": "work_pools/{obj_id}",
51
+ "work-queue": "work_queues/{obj_id}",
52
+ "concurrency-limit": "concurrency_limits/{obj_id}",
53
+ "deployment": "deployments/{obj_id}",
54
+ "automation": "automations/{obj_id}",
55
+ }
56
+
57
+ URLType = Literal["ui", "api"]
58
+ RUN_TYPES = {"flow-run", "task-run"}
59
+
60
+
61
+ def convert_class_to_name(obj: Any) -> str:
62
+ """
63
+ Convert CamelCase class name to dash-separated lowercase name
64
+ """
65
+ cls = obj if inspect.isclass(obj) else obj.__class__
66
+ name = cls.__name__
67
+ return "".join(["-" + i.lower() if i.isupper() else i for i in name]).lstrip("-")
68
+
69
+
70
+ def url_for(
71
+ obj: Union[
72
+ PrefectFuture,
73
+ Block,
74
+ Variable,
75
+ Automation,
76
+ Resource,
77
+ ReceivedEvent,
78
+ BaseModel,
79
+ str,
80
+ ],
81
+ obj_id: Optional[Union[str, UUID]] = None,
82
+ url_type: URLType = "ui",
83
+ default_base_url: Optional[str] = None,
84
+ ) -> Optional[str]:
85
+ """
86
+ Returns the URL for a Prefect object.
87
+
88
+ Pass in a supported object directly or provide an object name and ID.
89
+
90
+ Args:
91
+ obj (Union[PrefectFuture, Block, Variable, Automation, Resource, ReceivedEvent, BaseModel, str]):
92
+ A Prefect object to get the URL for, or its URL name and ID.
93
+ obj_id (Union[str, UUID], optional):
94
+ The UUID of the object.
95
+ url_type (Literal["ui", "api"], optional):
96
+ Whether to return the URL for the UI (default) or API.
97
+ default_base_url (str, optional):
98
+ The default base URL to use if no URL is configured.
99
+
100
+ Returns:
101
+ Optional[str]: The URL for the given object or None if the object is not supported.
102
+
103
+ Examples:
104
+ url_for(my_flow_run)
105
+ url_for(obj=my_flow_run)
106
+ url_for("flow-run", obj_id="123e4567-e89b-12d3-a456-426614174000")
107
+ """
108
+ if isinstance(obj, PrefectFuture):
109
+ name = "task-run"
110
+ elif isinstance(obj, Block):
111
+ name = "block"
112
+ elif isinstance(obj, Automation):
113
+ name = "automation"
114
+ elif isinstance(obj, ReceivedEvent):
115
+ name = "received-event"
116
+ elif isinstance(obj, Resource):
117
+ if obj.id.startswith("prefect."):
118
+ name = obj.id.split(".")[1]
119
+ else:
120
+ logger.debug(f"No URL known for resource with ID: {obj.id}")
121
+ return None
122
+ elif isinstance(obj, str):
123
+ name = obj
124
+ else:
125
+ name = convert_class_to_name(obj)
126
+
127
+ # Can't do an isinstance check here because the client build
128
+ # doesn't have access to that server schema.
129
+ if name == "work-queue-with-status":
130
+ name = "work-queue"
131
+
132
+ if url_type != "ui" and url_type != "api":
133
+ raise ValueError(f"Invalid URL type: {url_type}. Use 'ui' or 'api'.")
134
+
135
+ if url_type == "ui" and name not in UI_URL_FORMATS:
136
+ logger.debug("No UI URL known for this object: %s", name)
137
+ return None
138
+ elif url_type == "api" and name not in API_URL_FORMATS:
139
+ logger.debug("No API URL known for this object: %s", name)
140
+ return None
141
+
142
+ if isinstance(obj, str) and not obj_id:
143
+ raise ValueError(
144
+ "If passing an object name, you must also provide an object ID."
145
+ )
146
+
147
+ base_url = (
148
+ settings.PREFECT_UI_URL.value()
149
+ if url_type == "ui"
150
+ else settings.PREFECT_API_URL.value()
151
+ )
152
+ base_url = base_url or default_base_url
153
+
154
+ if not base_url:
155
+ logger.debug(
156
+ f"No URL found for the Prefect {'UI' if url_type == 'ui' else 'API'}, "
157
+ f"and no default base path provided."
158
+ )
159
+ return None
160
+
161
+ if not obj_id:
162
+ # We treat PrefectFuture as if it was the underlying task run,
163
+ # so we need to check the object type here instead of name.
164
+ if isinstance(obj, PrefectFuture):
165
+ obj_id = getattr(obj, "task_run_id", None)
166
+ elif name == "block":
167
+ # Blocks are client-side objects whose API representation is a
168
+ # BlockDocument.
169
+ obj_id = obj._block_document_id
170
+ elif name in ("variable", "work-pool"):
171
+ obj_id = obj.name
172
+ elif isinstance(obj, Resource):
173
+ obj_id = obj.id.rpartition(".")[2]
174
+ else:
175
+ obj_id = getattr(obj, "id", None)
176
+ if not obj_id:
177
+ logger.debug(
178
+ "An ID is required to build a URL, but object did not have one: %s", obj
179
+ )
180
+ return ""
181
+
182
+ url_format = (
183
+ UI_URL_FORMATS.get(name) if url_type == "ui" else API_URL_FORMATS.get(name)
184
+ )
185
+
186
+ if isinstance(obj, ReceivedEvent):
187
+ url = url_format.format(
188
+ occurred=obj.occurred.strftime("%Y-%m-%d"), obj_id=obj_id
189
+ )
190
+ else:
191
+ url = url_format.format(obj_id=obj_id)
192
+
193
+ if not base_url.endswith("/"):
194
+ base_url += "/"
195
+ return urllib.parse.urljoin(base_url, url)
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Utilities for working with Flow.visualize()
3
3
  """
4
+
4
5
  from functools import partial
5
6
  from typing import Any, List, Optional
6
7
 
prefect/variables.py CHANGED
@@ -1,9 +1,11 @@
1
1
  from typing import List, Optional
2
2
 
3
- from prefect._internal.compatibility.deprecated import deprecated_callable
3
+ from prefect._internal.compatibility.migration import getattr_migration
4
4
  from prefect.client.schemas.actions import VariableCreate as VariableRequest
5
5
  from prefect.client.schemas.actions import VariableUpdate as VariableUpdateRequest
6
6
  from prefect.client.utilities import get_or_create_client
7
+ from prefect.exceptions import ObjectNotFound
8
+ from prefect.types import StrictVariableValue
7
9
  from prefect.utilities.asyncutils import sync_compatible
8
10
 
9
11
 
@@ -23,92 +25,109 @@ class Variable(VariableRequest):
23
25
  async def set(
24
26
  cls,
25
27
  name: str,
26
- value: str,
28
+ value: StrictVariableValue,
27
29
  tags: Optional[List[str]] = None,
28
30
  overwrite: bool = False,
29
- ) -> Optional[str]:
31
+ ) -> "Variable":
30
32
  """
31
- Sets a new variable. If one exists with the same name, user must pass `overwrite=True`
32
- ```
33
- from prefect.variables import Variable
33
+ Sets a new variable. If one exists with the same name, must pass `overwrite=True`
34
34
 
35
- @flow
36
- def my_flow():
37
- var = Variable.set(name="my_var",value="test_value", tags=["hi", "there"], overwrite=True)
38
- ```
39
- or
40
- ```
35
+ Returns the newly set variable object.
36
+
37
+ Args:
38
+ - name: The name of the variable to set.
39
+ - value: The value of the variable to set.
40
+ - tags: An optional list of strings to associate with the variable.
41
+ - overwrite: Whether to overwrite the variable if it already exists.
42
+
43
+ Example:
44
+ Set a new variable and overwrite it if it already exists.
45
+ ```
41
46
  from prefect.variables import Variable
42
47
 
43
48
  @flow
44
- async def my_flow():
45
- var = await Variable.set(name="my_var",value="test_value", tags=["hi", "there"], overwrite=True)
46
- ```
49
+ def my_flow():
50
+ Variable.set(name="my_var",value="test_value", tags=["hi", "there"], overwrite=True)
51
+ ```
47
52
  """
48
53
  client, _ = get_or_create_client()
49
- variable = await client.read_variable_by_name(name)
50
- var_dict = {"name": name, "value": value}
51
- var_dict["tags"] = tags or []
52
- if variable:
54
+ variable_exists = await client.read_variable_by_name(name)
55
+ var_dict = {"name": name, "value": value, "tags": tags or []}
56
+
57
+ if variable_exists:
53
58
  if not overwrite:
54
59
  raise ValueError(
55
- "You are attempting to save a variable with a name that is already in use. If you would like to overwrite the values that are saved, then call .set with `overwrite=True`."
60
+ f"Variable {name!r} already exists. Use `overwrite=True` to update it."
56
61
  )
57
- var = VariableUpdateRequest(**var_dict)
58
- await client.update_variable(variable=var)
62
+ await client.update_variable(variable=VariableUpdateRequest(**var_dict))
59
63
  variable = await client.read_variable_by_name(name)
60
64
  else:
61
- var = VariableRequest(**var_dict)
62
- variable = await client.create_variable(variable=var)
65
+ variable = await client.create_variable(
66
+ variable=VariableRequest(**var_dict)
67
+ )
63
68
 
64
- return variable if variable else None
69
+ return variable
65
70
 
66
71
  @classmethod
67
72
  @sync_compatible
68
- async def get(cls, name: str, default: Optional[str] = None) -> Optional[str]:
73
+ async def get(
74
+ cls,
75
+ name: str,
76
+ default: StrictVariableValue = None,
77
+ ) -> StrictVariableValue:
69
78
  """
70
- Get a variable by name. If doesn't exist return the default.
71
- ```
79
+ Get a variable's value by name.
80
+
81
+ If the variable does not exist, return the default value.
82
+
83
+ Args:
84
+ - name: The name of the variable value to get.
85
+ - default: The default value to return if the variable does not exist.
86
+
87
+ Example:
88
+ Get a variable's value by name.
89
+ ```python
90
+ from prefect import flow
72
91
  from prefect.variables import Variable
73
92
 
74
93
  @flow
75
94
  def my_flow():
76
95
  var = Variable.get("my_var")
77
- ```
78
- or
79
- ```
96
+ ```
97
+ """
98
+ client, _ = get_or_create_client()
99
+ variable = await client.read_variable_by_name(name)
100
+
101
+ return variable.value if variable else default
102
+
103
+ @classmethod
104
+ @sync_compatible
105
+ async def unset(cls, name: str) -> bool:
106
+ """
107
+ Unset a variable by name.
108
+
109
+ Args:
110
+ - name: The name of the variable to unset.
111
+
112
+ Returns `True` if the variable was deleted, `False` if the variable did not exist.
113
+
114
+ Example:
115
+ Unset a variable by name.
116
+ ```python
117
+ from prefect import flow
80
118
  from prefect.variables import Variable
81
119
 
82
120
  @flow
83
- async def my_flow():
84
- var = await Variable.get("my_var")
85
- ```
121
+ def my_flow():
122
+ Variable.unset("my_var")
123
+ ```
86
124
  """
87
125
  client, _ = get_or_create_client()
88
- variable = await client.read_variable_by_name(name)
89
- return variable if variable else default
126
+ try:
127
+ await client.delete_variable_by_name(name=name)
128
+ return True
129
+ except ObjectNotFound:
130
+ return False
90
131
 
91
132
 
92
- @deprecated_callable(start_date="Apr 2024")
93
- @sync_compatible
94
- async def get(name: str, default: Optional[str] = None) -> Optional[str]:
95
- """
96
- Get a variable by name. If doesn't exist return the default.
97
- ```
98
- from prefect import variables
99
-
100
- @flow
101
- def my_flow():
102
- var = variables.get("my_var")
103
- ```
104
- or
105
- ```
106
- from prefect import variables
107
-
108
- @flow
109
- async def my_flow():
110
- var = await variables.get("my_var")
111
- ```
112
- """
113
- variable = await Variable.get(name)
114
- return variable.value if variable else default
133
+ __getattr__ = getattr_migration(__name__)
@@ -1,2 +1 @@
1
1
  from .process import ProcessWorker
2
- from .block import BlockWorker