flyte 0.0.1b0__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.

Potentially problematic release.


This version of flyte might be problematic. Click here for more details.

Files changed (390) hide show
  1. flyte/__init__.py +62 -0
  2. flyte/_api_commons.py +3 -0
  3. flyte/_bin/__init__.py +0 -0
  4. flyte/_bin/runtime.py +126 -0
  5. flyte/_build.py +25 -0
  6. flyte/_cache/__init__.py +12 -0
  7. flyte/_cache/cache.py +146 -0
  8. flyte/_cache/defaults.py +9 -0
  9. flyte/_cache/policy_function_body.py +42 -0
  10. flyte/_cli/__init__.py +0 -0
  11. flyte/_cli/_common.py +287 -0
  12. flyte/_cli/_create.py +42 -0
  13. flyte/_cli/_delete.py +23 -0
  14. flyte/_cli/_deploy.py +140 -0
  15. flyte/_cli/_get.py +235 -0
  16. flyte/_cli/_run.py +152 -0
  17. flyte/_cli/main.py +72 -0
  18. flyte/_code_bundle/__init__.py +8 -0
  19. flyte/_code_bundle/_ignore.py +113 -0
  20. flyte/_code_bundle/_packaging.py +187 -0
  21. flyte/_code_bundle/_utils.py +339 -0
  22. flyte/_code_bundle/bundle.py +178 -0
  23. flyte/_context.py +146 -0
  24. flyte/_datastructures.py +342 -0
  25. flyte/_deploy.py +202 -0
  26. flyte/_doc.py +29 -0
  27. flyte/_docstring.py +32 -0
  28. flyte/_environment.py +43 -0
  29. flyte/_group.py +31 -0
  30. flyte/_hash.py +23 -0
  31. flyte/_image.py +760 -0
  32. flyte/_initialize.py +634 -0
  33. flyte/_interface.py +84 -0
  34. flyte/_internal/__init__.py +3 -0
  35. flyte/_internal/controllers/__init__.py +115 -0
  36. flyte/_internal/controllers/_local_controller.py +118 -0
  37. flyte/_internal/controllers/_trace.py +40 -0
  38. flyte/_internal/controllers/pbhash.py +39 -0
  39. flyte/_internal/controllers/remote/__init__.py +40 -0
  40. flyte/_internal/controllers/remote/_action.py +141 -0
  41. flyte/_internal/controllers/remote/_client.py +43 -0
  42. flyte/_internal/controllers/remote/_controller.py +361 -0
  43. flyte/_internal/controllers/remote/_core.py +402 -0
  44. flyte/_internal/controllers/remote/_informer.py +361 -0
  45. flyte/_internal/controllers/remote/_service_protocol.py +50 -0
  46. flyte/_internal/imagebuild/__init__.py +11 -0
  47. flyte/_internal/imagebuild/docker_builder.py +416 -0
  48. flyte/_internal/imagebuild/image_builder.py +241 -0
  49. flyte/_internal/imagebuild/remote_builder.py +0 -0
  50. flyte/_internal/resolvers/__init__.py +0 -0
  51. flyte/_internal/resolvers/_task_module.py +54 -0
  52. flyte/_internal/resolvers/common.py +31 -0
  53. flyte/_internal/resolvers/default.py +28 -0
  54. flyte/_internal/runtime/__init__.py +0 -0
  55. flyte/_internal/runtime/convert.py +199 -0
  56. flyte/_internal/runtime/entrypoints.py +135 -0
  57. flyte/_internal/runtime/io.py +136 -0
  58. flyte/_internal/runtime/resources_serde.py +138 -0
  59. flyte/_internal/runtime/task_serde.py +210 -0
  60. flyte/_internal/runtime/taskrunner.py +190 -0
  61. flyte/_internal/runtime/types_serde.py +54 -0
  62. flyte/_logging.py +124 -0
  63. flyte/_protos/__init__.py +0 -0
  64. flyte/_protos/common/authorization_pb2.py +66 -0
  65. flyte/_protos/common/authorization_pb2.pyi +108 -0
  66. flyte/_protos/common/authorization_pb2_grpc.py +4 -0
  67. flyte/_protos/common/identifier_pb2.py +71 -0
  68. flyte/_protos/common/identifier_pb2.pyi +82 -0
  69. flyte/_protos/common/identifier_pb2_grpc.py +4 -0
  70. flyte/_protos/common/identity_pb2.py +48 -0
  71. flyte/_protos/common/identity_pb2.pyi +72 -0
  72. flyte/_protos/common/identity_pb2_grpc.py +4 -0
  73. flyte/_protos/common/list_pb2.py +36 -0
  74. flyte/_protos/common/list_pb2.pyi +69 -0
  75. flyte/_protos/common/list_pb2_grpc.py +4 -0
  76. flyte/_protos/common/policy_pb2.py +37 -0
  77. flyte/_protos/common/policy_pb2.pyi +27 -0
  78. flyte/_protos/common/policy_pb2_grpc.py +4 -0
  79. flyte/_protos/common/role_pb2.py +37 -0
  80. flyte/_protos/common/role_pb2.pyi +53 -0
  81. flyte/_protos/common/role_pb2_grpc.py +4 -0
  82. flyte/_protos/common/runtime_version_pb2.py +28 -0
  83. flyte/_protos/common/runtime_version_pb2.pyi +24 -0
  84. flyte/_protos/common/runtime_version_pb2_grpc.py +4 -0
  85. flyte/_protos/logs/dataplane/payload_pb2.py +96 -0
  86. flyte/_protos/logs/dataplane/payload_pb2.pyi +168 -0
  87. flyte/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
  88. flyte/_protos/secret/definition_pb2.py +49 -0
  89. flyte/_protos/secret/definition_pb2.pyi +93 -0
  90. flyte/_protos/secret/definition_pb2_grpc.py +4 -0
  91. flyte/_protos/secret/payload_pb2.py +62 -0
  92. flyte/_protos/secret/payload_pb2.pyi +94 -0
  93. flyte/_protos/secret/payload_pb2_grpc.py +4 -0
  94. flyte/_protos/secret/secret_pb2.py +38 -0
  95. flyte/_protos/secret/secret_pb2.pyi +6 -0
  96. flyte/_protos/secret/secret_pb2_grpc.py +198 -0
  97. flyte/_protos/secret/secret_pb2_grpc_grpc.py +198 -0
  98. flyte/_protos/validate/validate/validate_pb2.py +76 -0
  99. flyte/_protos/workflow/node_execution_service_pb2.py +26 -0
  100. flyte/_protos/workflow/node_execution_service_pb2.pyi +4 -0
  101. flyte/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
  102. flyte/_protos/workflow/queue_service_pb2.py +106 -0
  103. flyte/_protos/workflow/queue_service_pb2.pyi +141 -0
  104. flyte/_protos/workflow/queue_service_pb2_grpc.py +172 -0
  105. flyte/_protos/workflow/run_definition_pb2.py +128 -0
  106. flyte/_protos/workflow/run_definition_pb2.pyi +310 -0
  107. flyte/_protos/workflow/run_definition_pb2_grpc.py +4 -0
  108. flyte/_protos/workflow/run_logs_service_pb2.py +41 -0
  109. flyte/_protos/workflow/run_logs_service_pb2.pyi +28 -0
  110. flyte/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
  111. flyte/_protos/workflow/run_service_pb2.py +133 -0
  112. flyte/_protos/workflow/run_service_pb2.pyi +175 -0
  113. flyte/_protos/workflow/run_service_pb2_grpc.py +412 -0
  114. flyte/_protos/workflow/state_service_pb2.py +58 -0
  115. flyte/_protos/workflow/state_service_pb2.pyi +71 -0
  116. flyte/_protos/workflow/state_service_pb2_grpc.py +138 -0
  117. flyte/_protos/workflow/task_definition_pb2.py +72 -0
  118. flyte/_protos/workflow/task_definition_pb2.pyi +65 -0
  119. flyte/_protos/workflow/task_definition_pb2_grpc.py +4 -0
  120. flyte/_protos/workflow/task_service_pb2.py +44 -0
  121. flyte/_protos/workflow/task_service_pb2.pyi +31 -0
  122. flyte/_protos/workflow/task_service_pb2_grpc.py +104 -0
  123. flyte/_resources.py +226 -0
  124. flyte/_retry.py +32 -0
  125. flyte/_reusable_environment.py +25 -0
  126. flyte/_run.py +411 -0
  127. flyte/_secret.py +61 -0
  128. flyte/_task.py +367 -0
  129. flyte/_task_environment.py +200 -0
  130. flyte/_timeout.py +47 -0
  131. flyte/_tools.py +27 -0
  132. flyte/_trace.py +128 -0
  133. flyte/_utils/__init__.py +20 -0
  134. flyte/_utils/asyn.py +119 -0
  135. flyte/_utils/coro_management.py +25 -0
  136. flyte/_utils/file_handling.py +72 -0
  137. flyte/_utils/helpers.py +108 -0
  138. flyte/_utils/lazy_module.py +54 -0
  139. flyte/_utils/uv_script_parser.py +49 -0
  140. flyte/_version.py +21 -0
  141. flyte/connectors/__init__.py +0 -0
  142. flyte/errors.py +143 -0
  143. flyte/extras/__init__.py +5 -0
  144. flyte/extras/_container.py +273 -0
  145. flyte/io/__init__.py +11 -0
  146. flyte/io/_dataframe.py +0 -0
  147. flyte/io/_dir.py +448 -0
  148. flyte/io/_file.py +468 -0
  149. flyte/io/pickle/__init__.py +0 -0
  150. flyte/io/pickle/transformer.py +117 -0
  151. flyte/io/structured_dataset/__init__.py +129 -0
  152. flyte/io/structured_dataset/basic_dfs.py +219 -0
  153. flyte/io/structured_dataset/structured_dataset.py +1061 -0
  154. flyte/py.typed +0 -0
  155. flyte/remote/__init__.py +25 -0
  156. flyte/remote/_client/__init__.py +0 -0
  157. flyte/remote/_client/_protocols.py +131 -0
  158. flyte/remote/_client/auth/__init__.py +12 -0
  159. flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
  160. flyte/remote/_client/auth/_authenticators/base.py +397 -0
  161. flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
  162. flyte/remote/_client/auth/_authenticators/device_code.py +118 -0
  163. flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
  164. flyte/remote/_client/auth/_authenticators/factory.py +200 -0
  165. flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
  166. flyte/remote/_client/auth/_channel.py +184 -0
  167. flyte/remote/_client/auth/_client_config.py +83 -0
  168. flyte/remote/_client/auth/_default_html.py +32 -0
  169. flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  170. flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
  171. flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
  172. flyte/remote/_client/auth/_keyring.py +143 -0
  173. flyte/remote/_client/auth/_token_client.py +260 -0
  174. flyte/remote/_client/auth/errors.py +16 -0
  175. flyte/remote/_client/controlplane.py +95 -0
  176. flyte/remote/_console.py +18 -0
  177. flyte/remote/_data.py +155 -0
  178. flyte/remote/_logs.py +116 -0
  179. flyte/remote/_project.py +86 -0
  180. flyte/remote/_run.py +873 -0
  181. flyte/remote/_secret.py +132 -0
  182. flyte/remote/_task.py +227 -0
  183. flyte/report/__init__.py +3 -0
  184. flyte/report/_report.py +178 -0
  185. flyte/report/_template.html +124 -0
  186. flyte/storage/__init__.py +24 -0
  187. flyte/storage/_remote_fs.py +34 -0
  188. flyte/storage/_storage.py +251 -0
  189. flyte/storage/_utils.py +5 -0
  190. flyte/types/__init__.py +13 -0
  191. flyte/types/_interface.py +25 -0
  192. flyte/types/_renderer.py +162 -0
  193. flyte/types/_string_literals.py +120 -0
  194. flyte/types/_type_engine.py +2210 -0
  195. flyte/types/_utils.py +80 -0
  196. flyte-0.0.1b0.dist-info/METADATA +179 -0
  197. flyte-0.0.1b0.dist-info/RECORD +390 -0
  198. flyte-0.0.1b0.dist-info/WHEEL +5 -0
  199. flyte-0.0.1b0.dist-info/entry_points.txt +3 -0
  200. flyte-0.0.1b0.dist-info/top_level.txt +1 -0
  201. union/__init__.py +54 -0
  202. union/_api_commons.py +3 -0
  203. union/_bin/__init__.py +0 -0
  204. union/_bin/runtime.py +113 -0
  205. union/_build.py +25 -0
  206. union/_cache/__init__.py +12 -0
  207. union/_cache/cache.py +141 -0
  208. union/_cache/defaults.py +9 -0
  209. union/_cache/policy_function_body.py +42 -0
  210. union/_cli/__init__.py +0 -0
  211. union/_cli/_common.py +263 -0
  212. union/_cli/_create.py +40 -0
  213. union/_cli/_delete.py +23 -0
  214. union/_cli/_deploy.py +120 -0
  215. union/_cli/_get.py +162 -0
  216. union/_cli/_params.py +579 -0
  217. union/_cli/_run.py +150 -0
  218. union/_cli/main.py +72 -0
  219. union/_code_bundle/__init__.py +8 -0
  220. union/_code_bundle/_ignore.py +113 -0
  221. union/_code_bundle/_packaging.py +187 -0
  222. union/_code_bundle/_utils.py +342 -0
  223. union/_code_bundle/bundle.py +176 -0
  224. union/_context.py +146 -0
  225. union/_datastructures.py +295 -0
  226. union/_deploy.py +185 -0
  227. union/_doc.py +29 -0
  228. union/_docstring.py +26 -0
  229. union/_environment.py +43 -0
  230. union/_group.py +31 -0
  231. union/_hash.py +23 -0
  232. union/_image.py +760 -0
  233. union/_initialize.py +585 -0
  234. union/_interface.py +84 -0
  235. union/_internal/__init__.py +3 -0
  236. union/_internal/controllers/__init__.py +77 -0
  237. union/_internal/controllers/_local_controller.py +77 -0
  238. union/_internal/controllers/pbhash.py +39 -0
  239. union/_internal/controllers/remote/__init__.py +40 -0
  240. union/_internal/controllers/remote/_action.py +131 -0
  241. union/_internal/controllers/remote/_client.py +43 -0
  242. union/_internal/controllers/remote/_controller.py +169 -0
  243. union/_internal/controllers/remote/_core.py +341 -0
  244. union/_internal/controllers/remote/_informer.py +260 -0
  245. union/_internal/controllers/remote/_service_protocol.py +44 -0
  246. union/_internal/imagebuild/__init__.py +11 -0
  247. union/_internal/imagebuild/docker_builder.py +416 -0
  248. union/_internal/imagebuild/image_builder.py +243 -0
  249. union/_internal/imagebuild/remote_builder.py +0 -0
  250. union/_internal/resolvers/__init__.py +0 -0
  251. union/_internal/resolvers/_task_module.py +31 -0
  252. union/_internal/resolvers/common.py +24 -0
  253. union/_internal/resolvers/default.py +27 -0
  254. union/_internal/runtime/__init__.py +0 -0
  255. union/_internal/runtime/convert.py +163 -0
  256. union/_internal/runtime/entrypoints.py +121 -0
  257. union/_internal/runtime/io.py +136 -0
  258. union/_internal/runtime/resources_serde.py +134 -0
  259. union/_internal/runtime/task_serde.py +202 -0
  260. union/_internal/runtime/taskrunner.py +179 -0
  261. union/_internal/runtime/types_serde.py +53 -0
  262. union/_logging.py +124 -0
  263. union/_protos/__init__.py +0 -0
  264. union/_protos/common/authorization_pb2.py +66 -0
  265. union/_protos/common/authorization_pb2.pyi +106 -0
  266. union/_protos/common/authorization_pb2_grpc.py +4 -0
  267. union/_protos/common/identifier_pb2.py +71 -0
  268. union/_protos/common/identifier_pb2.pyi +82 -0
  269. union/_protos/common/identifier_pb2_grpc.py +4 -0
  270. union/_protos/common/identity_pb2.py +48 -0
  271. union/_protos/common/identity_pb2.pyi +72 -0
  272. union/_protos/common/identity_pb2_grpc.py +4 -0
  273. union/_protos/common/list_pb2.py +36 -0
  274. union/_protos/common/list_pb2.pyi +69 -0
  275. union/_protos/common/list_pb2_grpc.py +4 -0
  276. union/_protos/common/policy_pb2.py +37 -0
  277. union/_protos/common/policy_pb2.pyi +27 -0
  278. union/_protos/common/policy_pb2_grpc.py +4 -0
  279. union/_protos/common/role_pb2.py +37 -0
  280. union/_protos/common/role_pb2.pyi +51 -0
  281. union/_protos/common/role_pb2_grpc.py +4 -0
  282. union/_protos/common/runtime_version_pb2.py +28 -0
  283. union/_protos/common/runtime_version_pb2.pyi +24 -0
  284. union/_protos/common/runtime_version_pb2_grpc.py +4 -0
  285. union/_protos/logs/dataplane/payload_pb2.py +96 -0
  286. union/_protos/logs/dataplane/payload_pb2.pyi +168 -0
  287. union/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
  288. union/_protos/secret/definition_pb2.py +49 -0
  289. union/_protos/secret/definition_pb2.pyi +93 -0
  290. union/_protos/secret/definition_pb2_grpc.py +4 -0
  291. union/_protos/secret/payload_pb2.py +62 -0
  292. union/_protos/secret/payload_pb2.pyi +94 -0
  293. union/_protos/secret/payload_pb2_grpc.py +4 -0
  294. union/_protos/secret/secret_pb2.py +38 -0
  295. union/_protos/secret/secret_pb2.pyi +6 -0
  296. union/_protos/secret/secret_pb2_grpc.py +198 -0
  297. union/_protos/validate/validate/validate_pb2.py +76 -0
  298. union/_protos/workflow/node_execution_service_pb2.py +26 -0
  299. union/_protos/workflow/node_execution_service_pb2.pyi +4 -0
  300. union/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
  301. union/_protos/workflow/queue_service_pb2.py +75 -0
  302. union/_protos/workflow/queue_service_pb2.pyi +103 -0
  303. union/_protos/workflow/queue_service_pb2_grpc.py +172 -0
  304. union/_protos/workflow/run_definition_pb2.py +100 -0
  305. union/_protos/workflow/run_definition_pb2.pyi +256 -0
  306. union/_protos/workflow/run_definition_pb2_grpc.py +4 -0
  307. union/_protos/workflow/run_logs_service_pb2.py +41 -0
  308. union/_protos/workflow/run_logs_service_pb2.pyi +28 -0
  309. union/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
  310. union/_protos/workflow/run_service_pb2.py +133 -0
  311. union/_protos/workflow/run_service_pb2.pyi +173 -0
  312. union/_protos/workflow/run_service_pb2_grpc.py +412 -0
  313. union/_protos/workflow/state_service_pb2.py +58 -0
  314. union/_protos/workflow/state_service_pb2.pyi +69 -0
  315. union/_protos/workflow/state_service_pb2_grpc.py +138 -0
  316. union/_protos/workflow/task_definition_pb2.py +72 -0
  317. union/_protos/workflow/task_definition_pb2.pyi +65 -0
  318. union/_protos/workflow/task_definition_pb2_grpc.py +4 -0
  319. union/_protos/workflow/task_service_pb2.py +44 -0
  320. union/_protos/workflow/task_service_pb2.pyi +31 -0
  321. union/_protos/workflow/task_service_pb2_grpc.py +104 -0
  322. union/_resources.py +226 -0
  323. union/_retry.py +32 -0
  324. union/_reusable_environment.py +25 -0
  325. union/_run.py +374 -0
  326. union/_secret.py +61 -0
  327. union/_task.py +354 -0
  328. union/_task_environment.py +186 -0
  329. union/_timeout.py +47 -0
  330. union/_tools.py +27 -0
  331. union/_utils/__init__.py +11 -0
  332. union/_utils/asyn.py +119 -0
  333. union/_utils/file_handling.py +71 -0
  334. union/_utils/helpers.py +46 -0
  335. union/_utils/lazy_module.py +54 -0
  336. union/_utils/uv_script_parser.py +49 -0
  337. union/_version.py +21 -0
  338. union/connectors/__init__.py +0 -0
  339. union/errors.py +128 -0
  340. union/extras/__init__.py +5 -0
  341. union/extras/_container.py +263 -0
  342. union/io/__init__.py +11 -0
  343. union/io/_dataframe.py +0 -0
  344. union/io/_dir.py +425 -0
  345. union/io/_file.py +418 -0
  346. union/io/pickle/__init__.py +0 -0
  347. union/io/pickle/transformer.py +117 -0
  348. union/io/structured_dataset/__init__.py +122 -0
  349. union/io/structured_dataset/basic_dfs.py +219 -0
  350. union/io/structured_dataset/structured_dataset.py +1057 -0
  351. union/py.typed +0 -0
  352. union/remote/__init__.py +23 -0
  353. union/remote/_client/__init__.py +0 -0
  354. union/remote/_client/_protocols.py +129 -0
  355. union/remote/_client/auth/__init__.py +12 -0
  356. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  357. union/remote/_client/auth/_authenticators/base.py +391 -0
  358. union/remote/_client/auth/_authenticators/client_credentials.py +73 -0
  359. union/remote/_client/auth/_authenticators/device_code.py +120 -0
  360. union/remote/_client/auth/_authenticators/external_command.py +77 -0
  361. union/remote/_client/auth/_authenticators/factory.py +200 -0
  362. union/remote/_client/auth/_authenticators/pkce.py +515 -0
  363. union/remote/_client/auth/_channel.py +184 -0
  364. union/remote/_client/auth/_client_config.py +83 -0
  365. union/remote/_client/auth/_default_html.py +32 -0
  366. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  367. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +204 -0
  368. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +144 -0
  369. union/remote/_client/auth/_keyring.py +154 -0
  370. union/remote/_client/auth/_token_client.py +258 -0
  371. union/remote/_client/auth/errors.py +16 -0
  372. union/remote/_client/controlplane.py +86 -0
  373. union/remote/_data.py +149 -0
  374. union/remote/_logs.py +74 -0
  375. union/remote/_project.py +86 -0
  376. union/remote/_run.py +820 -0
  377. union/remote/_secret.py +132 -0
  378. union/remote/_task.py +193 -0
  379. union/report/__init__.py +3 -0
  380. union/report/_report.py +178 -0
  381. union/report/_template.html +124 -0
  382. union/storage/__init__.py +24 -0
  383. union/storage/_remote_fs.py +34 -0
  384. union/storage/_storage.py +247 -0
  385. union/storage/_utils.py +5 -0
  386. union/types/__init__.py +11 -0
  387. union/types/_renderer.py +162 -0
  388. union/types/_string_literals.py +120 -0
  389. union/types/_type_engine.py +2131 -0
  390. union/types/_utils.py +80 -0
flyte/_secret.py ADDED
@@ -0,0 +1,61 @@
1
+ import pathlib
2
+ import re
3
+ from dataclasses import dataclass
4
+ from typing import List, Optional, Union
5
+
6
+
7
+ @dataclass
8
+ class Secret:
9
+ """
10
+ Secrets are used to inject sensitive information into tasks. Secrets can be mounted as environment variables or
11
+ files. The secret key is the name of the secret in the secret store. The group is optional and maybe used with some
12
+ secret stores to organize secrets. The secret_mount is used to specify how the secret should be mounted. If the
13
+ secret_mount is set to "env" the secret will be mounted as an environment variable. If the secret_mount is set to
14
+ "file" the secret will be mounted as a file. The as_env_var is an optional parameter that can be used to specify the
15
+ name of the environment variable that the secret should be mounted as.
16
+
17
+ Example:
18
+ ```python
19
+ @task(secrets="MY_SECRET")
20
+ async def my_task():
21
+ os.environ["MY_SECRET"] # This will be set to the value of the secret
22
+
23
+ @task(secrets=Secret("MY_SECRET", mount="/path/to/secret"))
24
+ async def my_task2():
25
+ async with open("/path/to/secret") as f:
26
+ secret_value = f.read()
27
+ ```
28
+
29
+ TODO: Add support for secret versioning (some stores) and secret groups (some stores) and mounting as files.
30
+
31
+ :param key: The name of the secret in the secret store.
32
+ :param group: The group of the secret in the secret store.
33
+ :param mount: Use this to specify the path where the secret should be mounted.
34
+ :param as_env_var: The name of the environment variable that the secret should be mounted as.
35
+ """
36
+
37
+ key: str
38
+ group: Optional[str] = None
39
+ mount: pathlib.Path | None = None
40
+ as_env_var: Optional[str] = None
41
+
42
+ def __post_init__(self):
43
+ if self.as_env_var is not None:
44
+ pattern = r"^[A-Z_][A-Z0-9_]*$"
45
+ if not re.match(pattern, self.as_env_var):
46
+ raise ValueError(f"Invalid environment variable name: {self.as_env_var}, must match {pattern}")
47
+
48
+
49
+ SecretRequest = Union[str, Secret, List[str | Secret]]
50
+
51
+
52
+ def secrets_from_request(secrets: SecretRequest) -> List[Secret]:
53
+ """
54
+ Converts a secret request into a list of secrets.
55
+ """
56
+ if isinstance(secrets, str):
57
+ return [Secret(key=secrets)]
58
+ elif isinstance(secrets, Secret):
59
+ return [secrets]
60
+ else:
61
+ return [Secret(key=s) if isinstance(s, str) else s for s in secrets]
flyte/_task.py ADDED
@@ -0,0 +1,367 @@
1
+ from __future__ import annotations
2
+
3
+ import weakref
4
+ from dataclasses import dataclass, field, replace
5
+ from functools import cached_property
6
+ from typing import (
7
+ TYPE_CHECKING,
8
+ Any,
9
+ Awaitable,
10
+ Callable,
11
+ Coroutine,
12
+ Dict,
13
+ Generic,
14
+ List,
15
+ Literal,
16
+ Optional,
17
+ ParamSpec,
18
+ TypeVar,
19
+ Union,
20
+ )
21
+
22
+ from flyteidl.core.tasks_pb2 import DataLoadingConfig
23
+
24
+ from flyte.errors import RuntimeSystemError, RuntimeUserError
25
+
26
+ from ._cache import Cache, CacheRequest
27
+ from ._context import internal_ctx
28
+ from ._datastructures import NativeInterface, SerializationContext
29
+ from ._doc import Documentation
30
+ from ._image import Image
31
+ from ._resources import Resources
32
+ from ._retry import RetryStrategy
33
+ from ._reusable_environment import ReusePolicy
34
+ from ._secret import SecretRequest
35
+ from ._timeout import TimeoutType
36
+
37
+ if TYPE_CHECKING:
38
+ from kubernetes.client import V1PodTemplate
39
+
40
+ from ._task_environment import TaskEnvironment
41
+
42
+ P = ParamSpec("P") # capture the function's parameters
43
+ R = TypeVar("R") # return type
44
+
45
+
46
+ @dataclass(kw_only=True)
47
+ class TaskTemplate(Generic[P, R]):
48
+ """
49
+ Task template is a template for a task that can be executed. It defines various parameters for the task, which
50
+ can be defined statically at the time of task definition or dynamically at the time of task invocation using
51
+ the override method.
52
+
53
+ Example usage:
54
+ ```python
55
+ @task(name="my_task", image="my_image", resources=Resources(cpu="1", memory="1Gi"))
56
+ def my_task():
57
+ pass
58
+ ```
59
+
60
+ :param name: Optional The name of the task (defaults to the function name)
61
+ :param task_type: Router type for the task, this is used to determine how the task will be executed.
62
+ This is usually set to match with th execution plugin.
63
+ :param image: Optional The image to use for the task, if set to "auto" will use the default image for the python
64
+ version with flyte installed
65
+ :param resources: Optional The resources to use for the task
66
+ :param cache: Optional The cache policy for the task, defaults to auto, which will cache the results of the task.
67
+ :param interruptable: Optional The interruptable policy for the task, defaults to False, which means the task
68
+ will not be scheduled on interruptable nodes. If set to True, the task will be scheduled on interruptable nodes,
69
+ and the code should handle interruptions and resumptions.
70
+ :param retries: Optional The number of retries for the task, defaults to 0, which means no retries.
71
+ :param reusable: Optional The reusability policy for the task, defaults to None, which means the task environment
72
+ will not be reused across task invocations.
73
+ :param docs: Optional The documentation for the task, if not provided the function docstring will be used.
74
+ :param env: Optional The environment variables to set for the task.
75
+ :param secrets: Optional The secrets that will be injected into the task at runtime.
76
+ :param timeout: Optional The timeout for the task.
77
+ """
78
+
79
+ name: str
80
+ interface: NativeInterface
81
+ task_type: str = "python"
82
+ task_type_version: int = 0
83
+ image: Union[str, Image, Literal["auto"]] = "auto"
84
+ resources: Optional[Resources] = None
85
+ cache: CacheRequest = "auto"
86
+ interruptable: bool = False
87
+ retries: Union[int, RetryStrategy] = 0
88
+ reusable: Union[ReusePolicy, Literal["auto"], None] = None
89
+ docs: Optional[Documentation] = None
90
+ env: Optional[Dict[str, str]] = None
91
+ secrets: Optional[SecretRequest] = None
92
+ timeout: Optional[TimeoutType] = None
93
+ primary_container_name: str = "primary"
94
+ pod_template: Optional[Union[str, V1PodTemplate]] = None
95
+ report: bool = False
96
+
97
+ parent_env: Optional[weakref.ReferenceType[TaskEnvironment]] = None
98
+ local: bool = field(default=False, init=False)
99
+ ref: bool = field(default=False, init=False, repr=False, compare=False)
100
+
101
+ def __post_init__(self):
102
+ # If pod_template is set to a pod, verify
103
+ if self.pod_template is not None and not isinstance(self.pod_template, str):
104
+ try:
105
+ from kubernetes.client import V1PodTemplate # noqa: F401
106
+ except ImportError as e:
107
+ raise ImportError(
108
+ "kubernetes is not installed, please install kubernetes package to use pod_template"
109
+ ) from e
110
+
111
+ # Auto set the image based on the image request
112
+ if self.image == "auto":
113
+ self.image = Image.auto()
114
+ elif isinstance(self.image, str):
115
+ self.image = Image.from_prebuilt(str(self.image))
116
+
117
+ # Auto set cache based on the cache request
118
+ if isinstance(self.cache, str):
119
+ match self.cache:
120
+ case "auto":
121
+ self.cache = Cache(behavior="auto")
122
+ case "override":
123
+ self.cache = Cache(behavior="override")
124
+ case "disable":
125
+ self.cache = Cache(behavior="disable")
126
+
127
+ # if retries is set to int, convert to RetryStrategy
128
+ if isinstance(self.retries, int):
129
+ self.retries = RetryStrategy(count=self.retries)
130
+
131
+ def __getstate__(self):
132
+ """
133
+ This method is called when the object is pickled. We need to remove the parent_env reference
134
+ to avoid circular references.
135
+ """
136
+ state = self.__dict__.copy()
137
+ state.pop("parent_env", None)
138
+ return state
139
+
140
+ def __setstate__(self, state):
141
+ """
142
+ This method is called when the object is unpickled. We need to set the parent_env reference
143
+ to the environment that created the task.
144
+ """
145
+ self.__dict__.update(state)
146
+ self.parent_env = None
147
+
148
+ async def pre(self, *args, **kwargs) -> Dict[str, Any]:
149
+ """
150
+ This is the preexecute function that will be
151
+ called before the task is executed
152
+ """
153
+ return {}
154
+
155
+ async def execute(self, *args, **kwargs) -> Any:
156
+ """
157
+ This is the pure python function that will be executed when the task is called.
158
+ """
159
+ raise NotImplementedError
160
+
161
+ async def post(self, return_vals: Any) -> Any:
162
+ """
163
+ This is the postexecute function that will be
164
+ called after the task is executed
165
+ """
166
+ return return_vals
167
+
168
+ # ---- Extension points ----
169
+ def config(self, sctx: SerializationContext) -> Dict[str, str]:
170
+ """
171
+ Returns additional configuration for the task. This is a set of key-value pairs that can be used to
172
+ configure the task execution environment at runtime. This is usually used by plugins.
173
+ """
174
+ return {}
175
+
176
+ def custom_config(self, sctx: SerializationContext) -> Dict[str, str]:
177
+ """
178
+ Returns additional configuration for the task. This is a set of key-value pairs that can be used to
179
+ configure the task execution environment at runtime. This is usually used by plugins.
180
+ """
181
+ return {}
182
+
183
+ def data_loading_config(self, sctx: SerializationContext) -> DataLoadingConfig:
184
+ """
185
+ This configuration allows executing raw containers in Flyte using the Flyte CoPilot system
186
+ Flyte CoPilot, eliminates the needs of sdk inside the container. Any inputs required by the users container
187
+ are side-loaded in the input_path
188
+ Any outputs generated by the user container - within output_path are automatically uploaded
189
+ """
190
+
191
+ def container_args(self, sctx: SerializationContext) -> List[str]:
192
+ """
193
+ Returns the container args for the task. This is a set of key-value pairs that can be used to
194
+ configure the task execution environment at runtime. This is usually used by plugins.
195
+ """
196
+ return []
197
+
198
+ def sql(self, sctx: SerializationContext) -> Optional[str]:
199
+ """
200
+ Returns the SQL for the task. This is a set of key-value pairs that can be used to
201
+ configure the task execution environment at runtime. This is usually used by plugins.
202
+ """
203
+ return None
204
+
205
+ # ---- Extension points ----
206
+
207
+ @property
208
+ def native_interface(self) -> NativeInterface:
209
+ return self.interface
210
+
211
+ async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Coroutine[Any, Any, R]:
212
+ """
213
+ This is the entrypoint for an async function task at runtime. It will be called during an execution.
214
+ Please do not override this method, if you simply want to modify the execution behavior, override the
215
+ execute method.
216
+
217
+ # TODO lets provide one hook to implement, _pre, _execute and _post. We do not want actual execute to
218
+ """
219
+ try:
220
+ ctx = internal_ctx()
221
+ if ctx.is_task_context():
222
+ # If we are in a task context, that implies we are executing a Run.
223
+ # In this scenario, we should submit the task to the controller.
224
+ # We will also check if we are not initialized, It is not expected to be not initialized
225
+ from ._internal.controllers import get_controller
226
+
227
+ controller = await get_controller()
228
+ if controller:
229
+ return await controller.submit(self, *args, **kwargs)
230
+ return await self.execute(*args, **kwargs)
231
+ except RuntimeSystemError:
232
+ raise
233
+ except RuntimeUserError:
234
+ raise
235
+ except Exception as e:
236
+ raise RuntimeUserError(type(e).__name__, str(e)) from e
237
+
238
+ def override(
239
+ self,
240
+ *,
241
+ local: Optional[bool] = None,
242
+ ref: Optional[bool] = None,
243
+ resources: Optional[Resources] = None,
244
+ cache: CacheRequest = "auto",
245
+ retries: Union[int, RetryStrategy] = 0,
246
+ timeout: Optional[TimeoutType] = None,
247
+ reusable: Union[ReusePolicy, Literal["auto"], None] = None,
248
+ env: Optional[Dict[str, str]] = None,
249
+ secrets: Optional[SecretRequest] = None,
250
+ **kwargs: Any,
251
+ ) -> TaskTemplate:
252
+ """
253
+ Override various parameters of the task template. This allows for dynamic configuration of the task
254
+ when it is called, such as changing the image, resources, cache policy, etc.
255
+ """
256
+ resources = resources or self.resources
257
+ cache = cache or self.cache
258
+ retries = retries or self.retries
259
+ timeout = timeout or self.timeout
260
+ reusable = reusable or self.reusable
261
+ env = env or self.env
262
+ secrets = secrets or self.secrets
263
+ local = local or self.local
264
+ ref = ref or self.ref
265
+ for k, v in kwargs.items():
266
+ if k == "name":
267
+ raise ValueError("Name cannot be overridden")
268
+ if k == "image":
269
+ raise ValueError("Image cannot be overridden")
270
+ if k == "docs":
271
+ raise ValueError("Docs cannot be overridden")
272
+ if k == "interface":
273
+ raise ValueError("Interface cannot be overridden")
274
+ return replace(
275
+ self,
276
+ resources=resources,
277
+ cache=cache,
278
+ retries=retries,
279
+ timeout=timeout,
280
+ reusable=reusable,
281
+ env=env,
282
+ secrets=secrets,
283
+ )
284
+
285
+
286
+ @dataclass(kw_only=True)
287
+ class AsyncFunctionTaskTemplate(TaskTemplate[P, R]):
288
+ """
289
+ A task template that wraps an asynchronous functions. This is automatically created when an asynchronous function
290
+ is decorated with the task decorator.
291
+ """
292
+
293
+ func: Callable[P, Awaitable[R]]
294
+
295
+ @cached_property
296
+ def native_interface(self) -> NativeInterface:
297
+ return NativeInterface.from_callable(self.func)
298
+
299
+ async def execute(self, *args: P.args, **kwargs: P.kwargs) -> R:
300
+ """
301
+ This is the execute method that will be called when the task is invoked. It will call the actual function.
302
+ # TODO We may need to keep this as the bare func execute, and need a pre and post execute some other func.
303
+ """
304
+ ctx = internal_ctx()
305
+ ctx_data = await self.pre(*args, **kwargs)
306
+ if ctx.data.task_context is not None:
307
+ tctx = ctx.data.task_context.replace(data=ctx_data)
308
+ with ctx.replace_task_context(tctx):
309
+ v = await self.func(*args, **kwargs)
310
+ await self.post(v)
311
+ else:
312
+ v = await self.func(*args, **kwargs)
313
+ await self.post(v)
314
+ return v
315
+
316
+ def container_args(self, serialize_context: SerializationContext) -> List[str]:
317
+ args = [
318
+ "a0",
319
+ "--inputs",
320
+ serialize_context.input_path,
321
+ "--outputs-path",
322
+ serialize_context.output_path,
323
+ "--version",
324
+ serialize_context.version, # pr: should this be serialize_context.version or code_bundle.version?
325
+ "--raw-data-path",
326
+ "{{.rawOutputDataPrefix}}",
327
+ "--checkpoint-path",
328
+ "{{.checkpointOutputPrefix}}",
329
+ "--prev-checkpoint",
330
+ "{{.prevCheckpointPrefix}}",
331
+ "--run-name",
332
+ "{{.runName}}",
333
+ "--name",
334
+ "{{.actionName}}",
335
+ ]
336
+ # Add on all the known images
337
+ if serialize_context.image_cache and serialize_context.image_cache.serialized_form:
338
+ args = [*args, "--image-cache", serialize_context.image_cache.serialized_form]
339
+ else:
340
+ if serialize_context.image_cache:
341
+ args = [*args, "--image-cache", serialize_context.image_cache.to_transport]
342
+
343
+ if serialize_context.code_bundle:
344
+ if serialize_context.code_bundle.tgz:
345
+ args = [*args, *["--tgz", f"{serialize_context.code_bundle.tgz}"]]
346
+ elif serialize_context.code_bundle.pkl:
347
+ args = [*args, *["--pkl", f"{serialize_context.code_bundle.pkl}"]]
348
+ args = [*args, *["--dest", f"{serialize_context.code_bundle.destination or '.'}"]]
349
+
350
+ if not serialize_context.code_bundle or not serialize_context.code_bundle.pkl:
351
+ # If we do not have a code bundle, or if we have one, but it is not a pkl, we need to add the resolver
352
+
353
+ from flyte._internal.resolvers.default import DefaultTaskResolver
354
+
355
+ _task_resolver = DefaultTaskResolver()
356
+ args = [
357
+ *args,
358
+ *[
359
+ "--resolver",
360
+ _task_resolver.import_path,
361
+ *_task_resolver.loader_args(task=self, root_dir=serialize_context.root_dir),
362
+ ],
363
+ ]
364
+
365
+ assert all(isinstance(item, str) for item in args), f"All args should be strings, non string item = {args}"
366
+
367
+ return args
@@ -0,0 +1,200 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import weakref
5
+ from dataclasses import dataclass, field, replace
6
+ from datetime import timedelta
7
+ from functools import wraps
8
+ from typing import TYPE_CHECKING, Awaitable, Callable, Dict, List, Literal, Optional, ParamSpec, TypeVar, Union, cast
9
+
10
+ import rich.repr
11
+
12
+ from ._cache import CacheRequest
13
+ from ._datastructures import NativeInterface
14
+ from ._doc import Documentation
15
+ from ._environment import Environment
16
+ from ._image import Image
17
+ from ._resources import Resources
18
+ from ._retry import RetryStrategy
19
+ from ._reusable_environment import ReusePolicy
20
+ from ._secret import SecretRequest
21
+ from ._task import AsyncFunctionTaskTemplate, TaskTemplate
22
+
23
+ if TYPE_CHECKING:
24
+ from kubernetes.client import V1PodTemplate
25
+
26
+ P = ParamSpec("P") # capture the function's parameters
27
+ R = TypeVar("R") # return type
28
+
29
+
30
+ @rich.repr.auto
31
+ @dataclass(init=True, repr=True)
32
+ class TaskEnvironment(Environment):
33
+ """
34
+ Environment class to define a new environment for a set of tasks.
35
+
36
+ Example usage:
37
+ ```python
38
+ env = flyte.TaskEnvironment(name="my_env", image="my_image", resources=Resources(cpu="1", memory="1Gi"))
39
+
40
+ @env.task
41
+ async def my_task():
42
+ pass
43
+ ```
44
+
45
+ :param name: Name of the environment
46
+ :param image: Docker image to use for the environment. If set to "auto", will use the default image.
47
+ :param resources: Resources to allocate for the environment.
48
+ :param env: Environment variables to set for the environment.
49
+ :param secrets: Secrets to inject into the environment.
50
+ :param env_dep_hints: Environment dependencies to hint, so when you deploy the environment, the dependencies are
51
+ also deployed. This is useful when you have a set of environments that depend on each other.
52
+ :param cache: Cache policy for the environment.
53
+ :param reusable: Reuse policy for the environment, if set, a python process may be reused for multiple tasks.
54
+ """
55
+
56
+ cache: Union[CacheRequest] = "auto"
57
+ reusable: Union[ReusePolicy, Literal["auto"], None] = None
58
+ # TODO Shall we make this union of string or env? This way we can lookup the env by module/file:name
59
+ # TODO also we could add list of files that are used by this environment
60
+
61
+ _tasks: Dict[str, TaskTemplate] = field(default_factory=dict, init=False)
62
+
63
+ def clone_with(
64
+ self,
65
+ name: str,
66
+ image: Optional[Union[str, Image, Literal["auto"]]] = None,
67
+ resources: Optional[Resources] = None,
68
+ cache: Union[CacheRequest, None] = None,
69
+ env: Optional[Dict[str, str]] = None,
70
+ reusable: Union[ReusePolicy, None] = None,
71
+ secrets: Optional[SecretRequest] = None,
72
+ env_dep_hints: Optional[List[Environment]] = None,
73
+ ) -> TaskEnvironment:
74
+ """
75
+ Clone the environment with new settings.
76
+ """
77
+ if image is None:
78
+ image = self.image
79
+ else:
80
+ image = "auto"
81
+ return replace(
82
+ self,
83
+ cache=cache if cache else "auto",
84
+ reusable=reusable,
85
+ name=name,
86
+ image=image,
87
+ resources=resources,
88
+ env=env,
89
+ secrets=secrets,
90
+ env_dep_hints=env_dep_hints if env_dep_hints else [],
91
+ )
92
+
93
+ def _task(
94
+ self,
95
+ _func=None,
96
+ *,
97
+ name: Optional[str] = None,
98
+ cache: Union[CacheRequest] | None = None,
99
+ retries: Union[int, RetryStrategy] = 0,
100
+ timeout: Union[timedelta, int] = 0,
101
+ docs: Optional[Documentation] = None,
102
+ secrets: Optional[SecretRequest] = None,
103
+ pod_template: Optional[Union[str, "V1PodTemplate"]] = None,
104
+ report: bool = False,
105
+ ) -> Union[AsyncFunctionTaskTemplate, Callable[P, R]]:
106
+ """
107
+ :param name: Optional The name of the task (defaults to the function name)
108
+ :param cache: Optional The cache policy for the task, defaults to auto, which will cache the results of the
109
+ task.
110
+ :param retries: Optional The number of retries for the task, defaults to 0, which means no retries.
111
+ :param docs: Optional The documentation for the task, if not provided the function docstring will be used.
112
+ :param secrets: Optional The secrets that will be injected into the task at runtime.
113
+ :param timeout: Optional The timeout for the task.
114
+ :param pod_template: Optional The pod template for the task, if not provided the default pod template will be
115
+ used.
116
+ :param report: Optional Whether to generate the html report for the task, defaults to False.
117
+ """
118
+ if self.reusable is not None:
119
+ if pod_template is not None:
120
+ raise ValueError("Cannot set pod_template when environment is reusable.")
121
+
122
+ def decorator(func: Callable[P, Awaitable[R]]) -> AsyncFunctionTaskTemplate[P, R]:
123
+ task_name = name or func.__name__
124
+ task_name = self.name + "." + task_name
125
+ if len(task_name) > 30:
126
+ # delete this if we can remove the restriction that task names must be <= 30 characters
127
+ task_name = task_name[-30:]
128
+
129
+ @wraps(func)
130
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
131
+ return await func(*args, **kwargs)
132
+
133
+ if not asyncio.iscoroutinefunction(func):
134
+ raise TypeError(
135
+ f"Function {func.__name__} is not a coroutine function. Use @env.task decorator for async tasks."
136
+ f"You can simply mark your function as async def {func.__name__} to make it a coroutine function, "
137
+ f"it is ok to write sync code in async functions, but not the other way around."
138
+ )
139
+ tmpl = AsyncFunctionTaskTemplate(
140
+ func=wrapper,
141
+ name=task_name,
142
+ image=self.image,
143
+ resources=self.resources,
144
+ cache=cache or self.cache,
145
+ retries=retries,
146
+ timeout=timeout,
147
+ reusable=self.reusable,
148
+ docs=docs,
149
+ env=self.env,
150
+ secrets=secrets or self.secrets,
151
+ pod_template=pod_template or self.pod_template,
152
+ parent_env=weakref.ref(self),
153
+ interface=NativeInterface.from_callable(func),
154
+ report=report,
155
+ )
156
+ self._tasks[task_name] = tmpl
157
+ return tmpl
158
+
159
+ if _func is None:
160
+ return cast(AsyncFunctionTaskTemplate, decorator)
161
+ return cast(AsyncFunctionTaskTemplate, decorator(_func))
162
+
163
+ @property
164
+ def task(self) -> Callable:
165
+ """
166
+ Decorator to create a new task with the environment settings.
167
+ The task will be executed in its own container with the specified image, resources, and environment variables,
168
+ unless reusePolicy is set, in which case the same container will be reused for all tasks with the same
169
+ environment settings.
170
+
171
+ :param name: Optional The name of the task (defaults to the function name)
172
+ :param cache: Optional The cache policy for the task, defaults to auto, which will cache the results of the
173
+ task.
174
+ :param retries: Optional The number of retries for the task, defaults to 0, which means no retries.
175
+ :param docs: Optional The documentation for the task, if not provided the function docstring will be used.
176
+ :param secrets: Optional The secrets that will be injected into the task at runtime.
177
+ :param timeout: Optional The timeout for the task.
178
+ :param pod_template: Optional The pod template for the task, if not provided the default pod template will be
179
+ used.
180
+ :param report: Optional Whether to generate the html report for the task, defaults to False.
181
+
182
+ :return: New Task instance or Task decorator
183
+ """
184
+ return self._task
185
+
186
+ @property
187
+ def tasks(self) -> Dict[str, TaskTemplate]:
188
+ """
189
+ Get all tasks defined in the environment.
190
+ """
191
+ return self._tasks
192
+
193
+ def add_task(self, task: TaskTemplate) -> TaskTemplate:
194
+ """
195
+ Add a task to the environment.
196
+ """
197
+ if task.name in self._tasks:
198
+ raise ValueError(f"Task {task.name} already exists in the environment. Task names should be unique.")
199
+ self._tasks[task.name] = task
200
+ return task
flyte/_timeout.py ADDED
@@ -0,0 +1,47 @@
1
+ from dataclasses import dataclass
2
+ from datetime import timedelta
3
+
4
+
5
+ @dataclass
6
+ class Timeout:
7
+ """
8
+ Timeout class to define a timeout for a task.
9
+ The task timeout can be set to a maximum runtime and a maximum queued time.
10
+ Maximum runtime is the maximum time the task can run for (in one attempt).
11
+ Maximum queued time is the maximum time the task can stay in the queue before it starts executing.
12
+
13
+ Example usage:
14
+ ```python
15
+ timeout = Timeout(max_runtime=timedelta(minutes=5), max_queued_time=timedelta(minutes=10))
16
+ @env.task(timeout=timeout)
17
+ async def my_task():
18
+ pass
19
+ ```
20
+ :param max_runtime: timedelta or int - Maximum runtime for the task. If specified int, it will be converted to
21
+ timedelta as seconds.
22
+ :param max_queued_time: optional, timedelta or int - Maximum queued time for the task. If specified int,
23
+ it will be converted to timedelta as seconds. Defaults to None.
24
+
25
+ """
26
+
27
+ max_runtime: timedelta | int
28
+ max_queued_time: timedelta | int | None = None
29
+
30
+
31
+ TimeoutType = Timeout | int | timedelta
32
+
33
+
34
+ def timeout_from_request(timeout: TimeoutType) -> Timeout:
35
+ """
36
+ Converts a timeout request into a Timeout object.
37
+ """
38
+ if isinstance(timeout, Timeout):
39
+ return timeout
40
+ else:
41
+ if isinstance(timeout, int):
42
+ timeout = timedelta(seconds=timeout)
43
+ elif isinstance(timeout, timedelta):
44
+ pass
45
+ else:
46
+ raise ValueError("Timeout must be an instance of Timeout, int, or timedelta.")
47
+ return Timeout(max_runtime=timeout)