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/_tools.py ADDED
@@ -0,0 +1,27 @@
1
+ import os
2
+
3
+
4
+ def ipython_check() -> bool:
5
+ """
6
+ Check if interface is launching from iPython (not colab)
7
+ :return is_ipython (bool): True or False
8
+ """
9
+ is_ipython = False
10
+ try: # Check if running interactively using ipython.
11
+ from IPython import get_ipython
12
+
13
+ if get_ipython() is not None:
14
+ is_ipython = True
15
+ except (ImportError, NameError):
16
+ pass
17
+ return is_ipython
18
+
19
+
20
+ def is_in_cluster() -> bool:
21
+ """
22
+ Check if the task is running in a cluster
23
+ :return is_in_cluster (bool): True or False
24
+ """
25
+ if os.getenv("_UN_CLS"):
26
+ return True
27
+ return False
flyte/_trace.py ADDED
@@ -0,0 +1,128 @@
1
+ import functools
2
+ import inspect
3
+ import time
4
+ from datetime import timedelta
5
+ from typing import Any, AsyncGenerator, AsyncIterator, Awaitable, Callable, TypeGuard, TypeVar, Union, cast
6
+
7
+ from flyte._datastructures import NativeInterface
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ def trace(func: Callable[..., T]) -> Callable[..., T]:
13
+ """
14
+ A decorator that traces function execution with timing information.
15
+ Works with regular functions, async functions, and async generators/iterators.
16
+ """
17
+ func_name = func.__name__
18
+
19
+ @functools.wraps(func)
20
+ def wrapper_sync(*args: Any, **kwargs: Any) -> Any:
21
+ raise NotImplementedError
22
+
23
+ @functools.wraps(func)
24
+ async def wrapper_async(*args: Any, **kwargs: Any) -> Any:
25
+ from flyte._context import internal_ctx
26
+
27
+ ctx = internal_ctx()
28
+ if ctx.is_task_context():
29
+ # If we are in a task context, that implies we are executing a Run.
30
+ # In this scenario, we should submit the task to the controller.
31
+ # We will also check if we are not initialized, It is not expected to be not initialized
32
+ from ._internal.controllers import get_controller
33
+
34
+ controller = await get_controller()
35
+ iface = NativeInterface.from_callable(func)
36
+ info, ok = await controller.get_action_outputs(iface, func_name, *args, **kwargs)
37
+ if ok:
38
+ if info.output:
39
+ return info.output
40
+ elif info.error:
41
+ raise info.error
42
+ start_time = time.time()
43
+ try:
44
+ # Cast to Awaitable to satisfy mypy
45
+ coroutine_result = cast(Awaitable[Any], func(*args, **kwargs))
46
+ results = await coroutine_result
47
+ duration = time.time() - start_time
48
+ info.add_outputs(results, timedelta(seconds=duration))
49
+ await controller.record_trace(info)
50
+ return results
51
+ except Exception as e:
52
+ # If there is an error, we need to record it
53
+ duration = time.time() - start_time
54
+ info.add_error(e, timedelta(seconds=duration))
55
+ await controller.record_trace(info)
56
+ raise e
57
+ else:
58
+ # If we are not in a task context, we can just call the function normally
59
+ # Cast to Awaitable to satisfy mypy
60
+ coroutine_result = cast(Awaitable[Any], func(*args, **kwargs))
61
+ return await coroutine_result
62
+
63
+ def is_async_iterable(obj: Any) -> TypeGuard[Union[AsyncGenerator, AsyncIterator]]:
64
+ return hasattr(obj, "__aiter__")
65
+
66
+ @functools.wraps(func)
67
+ async def wrapper_async_iterator(*args: Any, **kwargs: Any) -> AsyncIterator[Any]:
68
+ from flyte._context import internal_ctx
69
+
70
+ ctx = internal_ctx()
71
+ if ctx.is_task_context():
72
+ # If we are in a task context, that implies we are executing a Run.
73
+ # In this scenario, we should submit the task to the controller.
74
+ # We will also check if we are not initialized, It is not expected to be not initialized
75
+ from ._internal.controllers import get_controller
76
+
77
+ controller = await get_controller()
78
+ iface = NativeInterface.from_callable(func)
79
+ info, ok = await controller.get_action_outputs(iface, func_name, *args, **kwargs)
80
+ if ok:
81
+ if info.output:
82
+ for item in info.output:
83
+ yield item
84
+ elif info.error:
85
+ raise info.error
86
+ start_time = time.time()
87
+ try:
88
+ items = []
89
+ result = func(*args, **kwargs)
90
+ # TODO ideally we should use streaming into the type-engine so that it stream uploads large blocks
91
+ if inspect.isasyncgen(result):
92
+ # If it's directly an async generator
93
+ async_iter = result
94
+ async for item in async_iter:
95
+ items.append(item)
96
+ yield item
97
+ elif is_async_iterable(result):
98
+ # If it's an async iterable (has __aiter__)
99
+ async for item in result:
100
+ items.append(item)
101
+ yield item
102
+ duration = time.time() - start_time
103
+ info.add_outputs(items, timedelta(seconds=duration))
104
+ await controller.record_trace(info)
105
+ return
106
+ except Exception as e:
107
+ end_time = time.time()
108
+ duration = end_time - start_time
109
+ info.add_error(e, timedelta(seconds=duration))
110
+ await controller.record_trace(info)
111
+ raise e
112
+ else:
113
+ result = func(*args, **kwargs)
114
+ if is_async_iterable(result):
115
+ async for item in result:
116
+ yield item
117
+
118
+ # Choose the appropriate wrapper based on the function type
119
+ if inspect.iscoroutinefunction(func):
120
+ # This handles async functions that return normal values
121
+ print(f"Coroutine function {func.__name__}")
122
+ return cast(Callable[..., T], wrapper_async)
123
+ elif inspect.isasyncgenfunction(func):
124
+ print(f"Async generator function {func.__name__}")
125
+ return cast(Callable[..., T], wrapper_async_iterator)
126
+ else:
127
+ # For regular sync functions
128
+ return cast(Callable[..., T], wrapper_sync)
@@ -0,0 +1,20 @@
1
+ """
2
+ Internal utility functions.
3
+
4
+ Except for logging, modules in this package should not depend on any other part of the repo.
5
+ """
6
+
7
+ from .coro_management import run_coros
8
+ from .file_handling import filehash_update, update_hasher_for_source
9
+ from .helpers import get_cwd_editable_install
10
+ from .lazy_module import lazy_module
11
+ from .uv_script_parser import parse_uv_script_file
12
+
13
+ __all__ = [
14
+ "filehash_update",
15
+ "get_cwd_editable_install",
16
+ "lazy_module",
17
+ "parse_uv_script_file",
18
+ "run_coros",
19
+ "update_hasher_for_source",
20
+ ]
flyte/_utils/asyn.py ADDED
@@ -0,0 +1,119 @@
1
+ """Manages an async event loop on another thread. Developers should only require to call
2
+ sync to use the managed loop:
3
+
4
+ from flytekit.tools.asyn import run_sync
5
+
6
+ async def async_add(a: int, b: int) -> int:
7
+ return a + b
8
+
9
+ result = run_sync(async_add, a=10, b=12)
10
+ """
11
+
12
+ import asyncio
13
+ import atexit
14
+ import functools
15
+ import os
16
+ import threading
17
+ from contextlib import contextmanager
18
+ from typing import Any, Awaitable, Callable, TypeVar
19
+
20
+ from typing_extensions import ParamSpec
21
+
22
+ from flyte._logging import logger
23
+
24
+ T = TypeVar("T")
25
+
26
+ P = ParamSpec("P")
27
+
28
+
29
+ @contextmanager
30
+ def _selector_policy():
31
+ original_policy = asyncio.get_event_loop_policy()
32
+ try:
33
+ if os.name == "nt" and hasattr(asyncio, "WindowsSelectorEventLoopPolicy"):
34
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
35
+
36
+ yield
37
+ finally:
38
+ asyncio.set_event_loop_policy(original_policy)
39
+
40
+
41
+ class _TaskRunner:
42
+ """A task runner that runs an asyncio event loop on a background thread."""
43
+
44
+ def __init__(self) -> None:
45
+ self.__loop: asyncio.AbstractEventLoop | None = None
46
+ self.__runner_thread: threading.Thread | None = None
47
+ self.__lock = threading.Lock()
48
+ atexit.register(self._close)
49
+
50
+ def _close(self) -> None:
51
+ if self.__loop:
52
+ self.__loop.stop()
53
+
54
+ def _execute(self) -> None:
55
+ loop = self.__loop
56
+ assert loop is not None
57
+ try:
58
+ loop.run_forever()
59
+ finally:
60
+ loop.close()
61
+
62
+ def get_exc_handler(self):
63
+ def exc_handler(loop, context):
64
+ logger.error(
65
+ f"Taskrunner for {self.__runner_thread.name if self.__runner_thread else 'no thread'} caught"
66
+ f" exception in {loop}: {context}"
67
+ )
68
+
69
+ return exc_handler
70
+
71
+ def run(self, coro: Any) -> Any:
72
+ """Synchronously run a coroutine on a background thread."""
73
+ name = f"{threading.current_thread().name} : loop-runner"
74
+ with self.__lock:
75
+ if self.__loop is None:
76
+ with _selector_policy():
77
+ self.__loop = asyncio.new_event_loop()
78
+
79
+ exc_handler = self.get_exc_handler()
80
+ self.__loop.set_exception_handler(exc_handler)
81
+ self.__runner_thread = threading.Thread(target=self._execute, daemon=True, name=name)
82
+ self.__runner_thread.start()
83
+ fut = asyncio.run_coroutine_threadsafe(coro, self.__loop)
84
+
85
+ res = fut.result(None)
86
+
87
+ return res
88
+
89
+
90
+ class _AsyncLoopManager:
91
+ def __init__(self):
92
+ self._runner_map: dict[str, _TaskRunner] = {}
93
+
94
+ def run_sync(self, coro_func: Callable[..., Awaitable[T]], *args, **kwargs) -> T:
95
+ """
96
+ This should be called from synchronous functions to run an async function.
97
+ """
98
+ name = threading.current_thread().name + f"PID:{os.getpid()}"
99
+ coro = coro_func(*args, **kwargs)
100
+ if name not in self._runner_map:
101
+ if len(self._runner_map) > 500:
102
+ logger.warning(
103
+ "More than 500 event loop runners created!!! This could be a case of runaway recursion..."
104
+ )
105
+ self._runner_map[name] = _TaskRunner()
106
+ return self._runner_map[name].run(coro)
107
+
108
+ def synced(self, coro_func: Callable[P, Awaitable[T]]) -> Callable[P, T]:
109
+ """Make loop run coroutine until it returns. Runs in other thread"""
110
+
111
+ @functools.wraps(coro_func)
112
+ def wrapped(*args: Any, **kwargs: Any) -> T:
113
+ return self.run_sync(coro_func, *args, **kwargs)
114
+
115
+ return wrapped
116
+
117
+
118
+ loop_manager = _AsyncLoopManager()
119
+ run_sync = loop_manager.run_sync
@@ -0,0 +1,25 @@
1
+ import asyncio
2
+ import typing
3
+
4
+
5
+ async def run_coros(*coros: typing.Coroutine, return_when: str = asyncio.FIRST_COMPLETED):
6
+ """
7
+ Run a list of coroutines concurrently and wait for the first one to finish or exit.
8
+ When the first one finishes, cancel all other tasks.
9
+
10
+ :param coros:
11
+ :param return_when:
12
+ :return:
13
+ """
14
+ tasks: typing.List[asyncio.Task[typing.Never]] = [asyncio.create_task(c) for c in coros]
15
+ done, pending = await asyncio.wait(tasks, return_when=return_when)
16
+
17
+ for t in pending: # type: asyncio.Task
18
+ t.cancel() # Cancel all tasks that didn't finish first
19
+
20
+ for t in done:
21
+ err = t.exception()
22
+ if err:
23
+ raise err
24
+ else:
25
+ print(f"Task result: {t.result()}")
@@ -0,0 +1,72 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import os
5
+ import pathlib
6
+ import stat
7
+ import typing
8
+ from pathlib import Path
9
+ from typing import List, Optional, Union
10
+
11
+ from flyte._logging import logger
12
+
13
+
14
+ def filehash_update(path: pathlib.Path, hasher: hashlib._Hash) -> None:
15
+ blocksize = 65536
16
+ with open(path, "rb") as f:
17
+ bytes = f.read(blocksize)
18
+ while bytes:
19
+ hasher.update(bytes)
20
+ bytes = f.read(blocksize)
21
+
22
+
23
+ def _pathhash_update(path: Union[os.PathLike, str], hasher: hashlib._Hash) -> None:
24
+ path_list = str(path).split(os.sep)
25
+ hasher.update("".join(path_list).encode("utf-8"))
26
+
27
+
28
+ def update_hasher_for_source(
29
+ source: Union[os.PathLike, List[os.PathLike]], hasher: hashlib._Hash, filter: Optional[typing.Callable] = None
30
+ ):
31
+ """
32
+ Walks the entirety of the source dir to compute a deterministic md5 hex digest of the dir contents.
33
+ :param os.PathLike source:
34
+ :param callable filter:
35
+ :return Text:
36
+ """
37
+
38
+ def compute_digest_for_file(path: os.PathLike, rel_path: os.PathLike) -> None:
39
+ # Only consider files that exist (e.g. disregard symlinks that point to non-existent files)
40
+ if not os.path.exists(path):
41
+ logger.info(f"Skipping non-existent file {path}")
42
+ return
43
+
44
+ # Skip socket files
45
+ if stat.S_ISSOCK(os.stat(path).st_mode):
46
+ logger.info(f"Skip socket file {path}")
47
+ return
48
+
49
+ if filter:
50
+ if filter(rel_path):
51
+ return
52
+
53
+ filehash_update(Path(path), hasher)
54
+ _pathhash_update(rel_path, hasher)
55
+
56
+ def compute_digest_for_dir(source: os.PathLike):
57
+ for root, _, files in os.walk(str(source), topdown=True):
58
+ files.sort()
59
+
60
+ for fname in files:
61
+ abspath = os.path.join(root, fname)
62
+ relpath = os.path.relpath(abspath, source)
63
+ compute_digest_for_file(Path(abspath), Path(relpath))
64
+
65
+ if isinstance(source, list):
66
+ for src in source:
67
+ if os.path.isdir(src):
68
+ compute_digest_for_dir(src)
69
+ else:
70
+ compute_digest_for_file(src, os.path.basename(src))
71
+ else:
72
+ compute_digest_for_dir(source)
@@ -0,0 +1,108 @@
1
+ import os
2
+ import string
3
+ import typing
4
+ from pathlib import Path
5
+
6
+
7
+ def load_proto_from_file(pb2_type, path):
8
+ with open(path, "rb") as reader:
9
+ out = pb2_type()
10
+ out.ParseFromString(reader.read())
11
+ return out
12
+
13
+
14
+ def write_proto_to_file(proto, path):
15
+ Path(os.path.dirname(path)).mkdir(parents=True, exist_ok=True)
16
+ with open(path, "wb") as writer:
17
+ writer.write(proto.SerializeToString())
18
+
19
+
20
+ def str2bool(value: typing.Optional[str]) -> bool:
21
+ """
22
+ Convert a string to a boolean. This is useful for parsing environment variables.
23
+ :param value: The string to convert to a boolean
24
+ :return: the boolean value
25
+ """
26
+ if value is None:
27
+ return False
28
+ return value.lower() in ("true", "t", "1")
29
+
30
+
31
+ BASE36_ALPHABET = string.digits + string.ascii_lowercase # 0-9 + a-z (36 characters)
32
+
33
+
34
+ def base36_encode(byte_data: bytes) -> str:
35
+ """
36
+ This function expects to encode bytes coming from an hd5 hash function into a base36 encoded string.
37
+ md5 shas are limited to 128 bits, so the maximum byte value should easily fit into a 30 character long string.
38
+ If the input is too large howeer
39
+ """
40
+ # Convert bytes to a big integer
41
+ num = int.from_bytes(byte_data, byteorder="big")
42
+
43
+ # Convert integer to base36 string
44
+ if num == 0:
45
+ return BASE36_ALPHABET[0]
46
+
47
+ base36 = []
48
+ while num:
49
+ num, rem = divmod(num, 36)
50
+ base36.append(BASE36_ALPHABET[rem])
51
+ return "".join(reversed(base36))
52
+
53
+
54
+ # does not work at all in the setuptools case. see old flytekit editable installs
55
+ def get_cwd_editable_install() -> typing.Optional[Path]:
56
+ """
57
+ This helper function is incomplete since it hasn't been tested with all the package managers out there,
58
+ but the intention is that it returns the source folder for an editable install if the current working directory
59
+ is inside the editable install project - if the code is inside an src/ folder, and the cwd is a level above,
60
+ it should still work, returning the src/ folder. If cwd is the src/ folder, this should return the same.
61
+
62
+ The idea is that the return path will be used to determine the relative path for imported modules when building
63
+ the code bundle.
64
+
65
+ :return:
66
+ """
67
+ import site
68
+
69
+ from flyte._logging import logger
70
+
71
+ egg_links = [Path(p) for p in Path(site.getsitepackages()[0]).glob("*.egg-link")]
72
+ pth_files = [Path(p) for p in Path(site.getsitepackages()[0]).glob("*.pth")]
73
+
74
+ if not egg_links and not pth_files:
75
+ logger.debug("No editable installs found.")
76
+ return None
77
+
78
+ editable_installs = []
79
+ egg_links.extend(pth_files)
80
+ for file in egg_links:
81
+ with open(file, "r") as f:
82
+ line = f.readline()
83
+ if line:
84
+ # Check if the first line is a directory
85
+ p = Path(line)
86
+ if p.is_dir():
87
+ editable_installs.append(p)
88
+ logger.debug(f"Editable installs: {editable_installs}")
89
+
90
+ # check to see if the current working directory is in any of the editable installs
91
+ # including if the current folder is the root folder, one level up from the src and contains
92
+ # the pyproject.toml file.
93
+ # Two scenarios to consider
94
+ # - if cwd is nested inside the editable install folder.
95
+ # - if the cwd is exactly one level above the editable install folder.
96
+ cwd = Path.cwd()
97
+ for install in editable_installs:
98
+ # child.is_relative_to(parent) is True if child is inside parent
99
+ if cwd.is_relative_to(install):
100
+ return install
101
+ else:
102
+ # check if the cwd is one level above the install folder
103
+ if install.parent == cwd:
104
+ # check if the install folder contains a pyproject.toml file
105
+ if (cwd / "pyproject.toml").exists() or (cwd / "setup.py").exists():
106
+ return install # note we want the install folder, not the parent
107
+
108
+ return None
@@ -0,0 +1,54 @@
1
+ import importlib.util
2
+ import sys
3
+ import types
4
+
5
+
6
+ class _LazyModule(types.ModuleType):
7
+ """
8
+ `lazy_module` returns an instance of this class if the module is not found in the python environment.
9
+ """
10
+
11
+ def __init__(self, module_name: str):
12
+ super().__init__(module_name)
13
+ self._module_name = module_name
14
+
15
+ def __getattribute__(self, attr):
16
+ raise ImportError(f"Module {object.__getattribute__(self, '_module_name')} is not yet installed.")
17
+
18
+
19
+ def is_imported(module_name):
20
+ """
21
+ This function is used to check if a module has been imported by the regular import.
22
+ Return false if module is lazy imported and not used yet.
23
+ """
24
+ return (
25
+ module_name in sys.modules
26
+ and object.__getattribute__(lazy_module(module_name), "__class__").__name__ != "_LazyModule"
27
+ )
28
+
29
+
30
+ def lazy_module(fullname):
31
+ """
32
+ This function is used to lazily import modules. It is used in the following way:
33
+ .. code-block:: python
34
+ from flytekit.lazy_import import lazy_module
35
+ sklearn = lazy_module("sklearn")
36
+ sklearn.svm.SVC()
37
+ :param Text fullname: The full name of the module to import
38
+ """
39
+ if fullname in sys.modules:
40
+ return sys.modules[fullname]
41
+ # https://docs.python.org/3/library/importlib.html#implementing-lazy-imports
42
+ spec = importlib.util.find_spec(fullname)
43
+ if spec is None or spec.loader is None:
44
+ # Return a lazy module if the module is not found in the python environment,
45
+ # so that we can raise a proper error when the user tries to access an attribute in the module.
46
+ # The reason to do this is because importlib.util.LazyLoader still requires
47
+ # the module to be installed even if you don't use it.
48
+ return _LazyModule(fullname)
49
+ loader = importlib.util.LazyLoader(spec.loader)
50
+ spec.loader = loader
51
+ module = importlib.util.module_from_spec(spec)
52
+ sys.modules[fullname] = module
53
+ loader.exec_module(module)
54
+ return module
@@ -0,0 +1,49 @@
1
+ import pathlib
2
+ import re
3
+ from dataclasses import dataclass, field
4
+ from typing import Dict, List, Optional
5
+
6
+ import toml
7
+
8
+
9
+ @dataclass
10
+ class ToolUVConfig:
11
+ exclude_newer: Optional[str] = None
12
+
13
+
14
+ @dataclass
15
+ class UVScriptMetadata:
16
+ requires_python: Optional[str] = None
17
+ dependencies: List[str] = field(default_factory=list)
18
+ tool: Optional[Dict[str, ToolUVConfig]] = None
19
+
20
+
21
+ def _extract_uv_metadata_block(text: str) -> str | None:
22
+ pattern = re.compile(r"# /// script\s*(.*?)# ///", re.DOTALL)
23
+ match = pattern.search(text)
24
+ if not match:
25
+ return None
26
+ lines = [line.lstrip("# ").rstrip() for line in match.group(1).splitlines()]
27
+ return "\n".join(lines)
28
+
29
+
30
+ def parse_uv_script_file(path: pathlib.Path) -> UVScriptMetadata:
31
+ if not path.exists() or not path.is_file():
32
+ raise FileNotFoundError(f"File not found: {path}")
33
+
34
+ text = path.read_text(encoding="utf-8")
35
+ raw_header = _extract_uv_metadata_block(text)
36
+ if raw_header is None:
37
+ raise ValueError("No uv metadata block found")
38
+
39
+ try:
40
+ data = toml.loads(raw_header)
41
+ except toml.TomlDecodeError as e:
42
+ raise ValueError(f"Invalid TOML in metadata block: {e}")
43
+
44
+ tool_data = data.get("tool", {}).get("uv", {})
45
+ return UVScriptMetadata(
46
+ requires_python=data.get("requires-python"),
47
+ dependencies=data.get("dependencies", []),
48
+ tool={"uv": ToolUVConfig(exclude_newer=tool_data.get("exclude-newer"))} if tool_data else None,
49
+ )
flyte/_version.py ADDED
@@ -0,0 +1,21 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
6
+ TYPE_CHECKING = False
7
+ if TYPE_CHECKING:
8
+ from typing import Tuple
9
+ from typing import Union
10
+
11
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
12
+ else:
13
+ VERSION_TUPLE = object
14
+
15
+ version: str
16
+ __version__: str
17
+ __version_tuple__: VERSION_TUPLE
18
+ version_tuple: VERSION_TUPLE
19
+
20
+ __version__ = version = '0.0.1b0'
21
+ __version_tuple__ = version_tuple = (0, 0, 1, 'b0')
File without changes