flyte 0.0.1b3__py3-none-any.whl → 0.2.0a0__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 (319) hide show
  1. flyte/__init__.py +20 -4
  2. flyte/_bin/runtime.py +33 -7
  3. flyte/_build.py +3 -2
  4. flyte/_cache/cache.py +1 -2
  5. flyte/_code_bundle/_packaging.py +1 -1
  6. flyte/_code_bundle/_utils.py +0 -16
  7. flyte/_code_bundle/bundle.py +43 -12
  8. flyte/_context.py +8 -2
  9. flyte/_deploy.py +56 -15
  10. flyte/_environment.py +45 -4
  11. flyte/_excepthook.py +37 -0
  12. flyte/_group.py +2 -1
  13. flyte/_image.py +8 -4
  14. flyte/_initialize.py +112 -254
  15. flyte/_interface.py +3 -3
  16. flyte/_internal/controllers/__init__.py +19 -6
  17. flyte/_internal/controllers/_local_controller.py +83 -8
  18. flyte/_internal/controllers/_trace.py +2 -1
  19. flyte/_internal/controllers/remote/__init__.py +27 -7
  20. flyte/_internal/controllers/remote/_action.py +7 -2
  21. flyte/_internal/controllers/remote/_client.py +5 -1
  22. flyte/_internal/controllers/remote/_controller.py +159 -26
  23. flyte/_internal/controllers/remote/_core.py +13 -5
  24. flyte/_internal/controllers/remote/_informer.py +4 -4
  25. flyte/_internal/controllers/remote/_service_protocol.py +6 -6
  26. flyte/_internal/imagebuild/docker_builder.py +12 -1
  27. flyte/_internal/imagebuild/image_builder.py +16 -11
  28. flyte/_internal/runtime/convert.py +164 -21
  29. flyte/_internal/runtime/entrypoints.py +1 -1
  30. flyte/_internal/runtime/io.py +3 -3
  31. flyte/_internal/runtime/task_serde.py +140 -20
  32. flyte/_internal/runtime/taskrunner.py +4 -3
  33. flyte/_internal/runtime/types_serde.py +1 -1
  34. flyte/_logging.py +12 -1
  35. flyte/_map.py +215 -0
  36. flyte/_pod.py +19 -0
  37. flyte/_protos/common/list_pb2.py +3 -3
  38. flyte/_protos/common/list_pb2.pyi +2 -0
  39. flyte/_protos/logs/dataplane/payload_pb2.py +28 -24
  40. flyte/_protos/logs/dataplane/payload_pb2.pyi +11 -2
  41. flyte/_protos/workflow/common_pb2.py +27 -0
  42. flyte/_protos/workflow/common_pb2.pyi +14 -0
  43. flyte/_protos/workflow/environment_pb2.py +29 -0
  44. flyte/_protos/workflow/environment_pb2.pyi +12 -0
  45. flyte/_protos/workflow/queue_service_pb2.py +40 -41
  46. flyte/_protos/workflow/queue_service_pb2.pyi +35 -30
  47. flyte/_protos/workflow/queue_service_pb2_grpc.py +15 -15
  48. flyte/_protos/workflow/run_definition_pb2.py +61 -61
  49. flyte/_protos/workflow/run_definition_pb2.pyi +8 -4
  50. flyte/_protos/workflow/run_service_pb2.py +20 -24
  51. flyte/_protos/workflow/run_service_pb2.pyi +2 -6
  52. flyte/_protos/workflow/state_service_pb2.py +36 -28
  53. flyte/_protos/workflow/state_service_pb2.pyi +19 -15
  54. flyte/_protos/workflow/state_service_pb2_grpc.py +28 -28
  55. flyte/_protos/workflow/task_definition_pb2.py +29 -22
  56. flyte/_protos/workflow/task_definition_pb2.pyi +21 -5
  57. flyte/_protos/workflow/task_service_pb2.py +27 -11
  58. flyte/_protos/workflow/task_service_pb2.pyi +29 -1
  59. flyte/_protos/workflow/task_service_pb2_grpc.py +34 -0
  60. flyte/_run.py +166 -95
  61. flyte/_task.py +110 -28
  62. flyte/_task_environment.py +55 -72
  63. flyte/_trace.py +6 -14
  64. flyte/_utils/__init__.py +6 -0
  65. flyte/_utils/async_cache.py +139 -0
  66. flyte/_utils/coro_management.py +0 -2
  67. flyte/_utils/helpers.py +45 -19
  68. flyte/_utils/org_discovery.py +57 -0
  69. flyte/_version.py +2 -2
  70. flyte/cli/__init__.py +3 -0
  71. flyte/cli/_abort.py +28 -0
  72. flyte/{_cli → cli}/_common.py +73 -23
  73. flyte/cli/_create.py +145 -0
  74. flyte/{_cli → cli}/_delete.py +4 -4
  75. flyte/{_cli → cli}/_deploy.py +26 -14
  76. flyte/cli/_gen.py +163 -0
  77. flyte/{_cli → cli}/_get.py +98 -23
  78. {union/_cli → flyte/cli}/_params.py +106 -147
  79. flyte/{_cli → cli}/_run.py +99 -20
  80. flyte/cli/main.py +166 -0
  81. flyte/config/__init__.py +3 -0
  82. flyte/config/_config.py +216 -0
  83. flyte/config/_internal.py +64 -0
  84. flyte/config/_reader.py +207 -0
  85. flyte/errors.py +29 -0
  86. flyte/extras/_container.py +33 -43
  87. flyte/io/__init__.py +17 -1
  88. flyte/io/_dir.py +2 -2
  89. flyte/io/_file.py +3 -4
  90. flyte/io/{structured_dataset → _structured_dataset}/basic_dfs.py +1 -1
  91. flyte/io/{structured_dataset → _structured_dataset}/structured_dataset.py +1 -1
  92. flyte/{_datastructures.py → models.py} +56 -7
  93. flyte/remote/__init__.py +2 -1
  94. flyte/remote/_client/_protocols.py +2 -0
  95. flyte/remote/_client/auth/_auth_utils.py +14 -0
  96. flyte/remote/_client/auth/_channel.py +34 -3
  97. flyte/remote/_client/auth/_token_client.py +3 -3
  98. flyte/remote/_client/controlplane.py +13 -13
  99. flyte/remote/_console.py +1 -1
  100. flyte/remote/_data.py +10 -6
  101. flyte/remote/_logs.py +89 -29
  102. flyte/remote/_project.py +8 -9
  103. flyte/remote/_run.py +228 -131
  104. flyte/remote/_secret.py +12 -12
  105. flyte/remote/_task.py +179 -15
  106. flyte/report/_report.py +4 -4
  107. flyte/storage/__init__.py +5 -0
  108. flyte/storage/_config.py +233 -0
  109. flyte/storage/_storage.py +23 -3
  110. flyte/syncify/__init__.py +56 -0
  111. flyte/syncify/_api.py +371 -0
  112. flyte/types/__init__.py +23 -0
  113. flyte/types/_interface.py +22 -7
  114. flyte/{io/pickle/transformer.py → types/_pickle.py} +2 -1
  115. flyte/types/_type_engine.py +95 -18
  116. flyte-0.2.0a0.dist-info/METADATA +249 -0
  117. flyte-0.2.0a0.dist-info/RECORD +218 -0
  118. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/entry_points.txt +1 -1
  119. flyte/_api_commons.py +0 -3
  120. flyte/_cli/__init__.py +0 -0
  121. flyte/_cli/_create.py +0 -42
  122. flyte/_cli/main.py +0 -72
  123. flyte/_internal/controllers/pbhash.py +0 -39
  124. flyte/io/_dataframe.py +0 -0
  125. flyte/io/pickle/__init__.py +0 -0
  126. flyte-0.0.1b3.dist-info/METADATA +0 -179
  127. flyte-0.0.1b3.dist-info/RECORD +0 -390
  128. union/__init__.py +0 -54
  129. union/_api_commons.py +0 -3
  130. union/_bin/__init__.py +0 -0
  131. union/_bin/runtime.py +0 -113
  132. union/_build.py +0 -25
  133. union/_cache/__init__.py +0 -12
  134. union/_cache/cache.py +0 -141
  135. union/_cache/defaults.py +0 -9
  136. union/_cache/policy_function_body.py +0 -42
  137. union/_cli/__init__.py +0 -0
  138. union/_cli/_common.py +0 -263
  139. union/_cli/_create.py +0 -40
  140. union/_cli/_delete.py +0 -23
  141. union/_cli/_deploy.py +0 -120
  142. union/_cli/_get.py +0 -162
  143. union/_cli/_run.py +0 -150
  144. union/_cli/main.py +0 -72
  145. union/_code_bundle/__init__.py +0 -8
  146. union/_code_bundle/_ignore.py +0 -113
  147. union/_code_bundle/_packaging.py +0 -187
  148. union/_code_bundle/_utils.py +0 -342
  149. union/_code_bundle/bundle.py +0 -176
  150. union/_context.py +0 -146
  151. union/_datastructures.py +0 -295
  152. union/_deploy.py +0 -185
  153. union/_doc.py +0 -29
  154. union/_docstring.py +0 -26
  155. union/_environment.py +0 -43
  156. union/_group.py +0 -31
  157. union/_hash.py +0 -23
  158. union/_image.py +0 -760
  159. union/_initialize.py +0 -585
  160. union/_interface.py +0 -84
  161. union/_internal/__init__.py +0 -3
  162. union/_internal/controllers/__init__.py +0 -77
  163. union/_internal/controllers/_local_controller.py +0 -77
  164. union/_internal/controllers/pbhash.py +0 -39
  165. union/_internal/controllers/remote/__init__.py +0 -40
  166. union/_internal/controllers/remote/_action.py +0 -131
  167. union/_internal/controllers/remote/_client.py +0 -43
  168. union/_internal/controllers/remote/_controller.py +0 -169
  169. union/_internal/controllers/remote/_core.py +0 -341
  170. union/_internal/controllers/remote/_informer.py +0 -260
  171. union/_internal/controllers/remote/_service_protocol.py +0 -44
  172. union/_internal/imagebuild/__init__.py +0 -11
  173. union/_internal/imagebuild/docker_builder.py +0 -416
  174. union/_internal/imagebuild/image_builder.py +0 -243
  175. union/_internal/imagebuild/remote_builder.py +0 -0
  176. union/_internal/resolvers/__init__.py +0 -0
  177. union/_internal/resolvers/_task_module.py +0 -31
  178. union/_internal/resolvers/common.py +0 -24
  179. union/_internal/resolvers/default.py +0 -27
  180. union/_internal/runtime/__init__.py +0 -0
  181. union/_internal/runtime/convert.py +0 -163
  182. union/_internal/runtime/entrypoints.py +0 -121
  183. union/_internal/runtime/io.py +0 -136
  184. union/_internal/runtime/resources_serde.py +0 -134
  185. union/_internal/runtime/task_serde.py +0 -202
  186. union/_internal/runtime/taskrunner.py +0 -179
  187. union/_internal/runtime/types_serde.py +0 -53
  188. union/_logging.py +0 -124
  189. union/_protos/__init__.py +0 -0
  190. union/_protos/common/authorization_pb2.py +0 -66
  191. union/_protos/common/authorization_pb2.pyi +0 -106
  192. union/_protos/common/identifier_pb2.py +0 -71
  193. union/_protos/common/identifier_pb2.pyi +0 -82
  194. union/_protos/common/identity_pb2.py +0 -48
  195. union/_protos/common/identity_pb2.pyi +0 -72
  196. union/_protos/common/identity_pb2_grpc.py +0 -4
  197. union/_protos/common/list_pb2.py +0 -36
  198. union/_protos/common/list_pb2.pyi +0 -69
  199. union/_protos/common/list_pb2_grpc.py +0 -4
  200. union/_protos/common/policy_pb2.py +0 -37
  201. union/_protos/common/policy_pb2.pyi +0 -27
  202. union/_protos/common/policy_pb2_grpc.py +0 -4
  203. union/_protos/common/role_pb2.py +0 -37
  204. union/_protos/common/role_pb2.pyi +0 -51
  205. union/_protos/common/role_pb2_grpc.py +0 -4
  206. union/_protos/common/runtime_version_pb2.py +0 -28
  207. union/_protos/common/runtime_version_pb2.pyi +0 -24
  208. union/_protos/common/runtime_version_pb2_grpc.py +0 -4
  209. union/_protos/logs/dataplane/payload_pb2.py +0 -96
  210. union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  211. union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  212. union/_protos/secret/definition_pb2.py +0 -49
  213. union/_protos/secret/definition_pb2.pyi +0 -93
  214. union/_protos/secret/definition_pb2_grpc.py +0 -4
  215. union/_protos/secret/payload_pb2.py +0 -62
  216. union/_protos/secret/payload_pb2.pyi +0 -94
  217. union/_protos/secret/payload_pb2_grpc.py +0 -4
  218. union/_protos/secret/secret_pb2.py +0 -38
  219. union/_protos/secret/secret_pb2.pyi +0 -6
  220. union/_protos/secret/secret_pb2_grpc.py +0 -198
  221. union/_protos/validate/validate/validate_pb2.py +0 -76
  222. union/_protos/workflow/node_execution_service_pb2.py +0 -26
  223. union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  224. union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  225. union/_protos/workflow/queue_service_pb2.py +0 -75
  226. union/_protos/workflow/queue_service_pb2.pyi +0 -103
  227. union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  228. union/_protos/workflow/run_definition_pb2.py +0 -100
  229. union/_protos/workflow/run_definition_pb2.pyi +0 -256
  230. union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  231. union/_protos/workflow/run_logs_service_pb2.py +0 -41
  232. union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  233. union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  234. union/_protos/workflow/run_service_pb2.py +0 -133
  235. union/_protos/workflow/run_service_pb2.pyi +0 -173
  236. union/_protos/workflow/run_service_pb2_grpc.py +0 -412
  237. union/_protos/workflow/state_service_pb2.py +0 -58
  238. union/_protos/workflow/state_service_pb2.pyi +0 -69
  239. union/_protos/workflow/state_service_pb2_grpc.py +0 -138
  240. union/_protos/workflow/task_definition_pb2.py +0 -72
  241. union/_protos/workflow/task_definition_pb2.pyi +0 -65
  242. union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  243. union/_protos/workflow/task_service_pb2.py +0 -44
  244. union/_protos/workflow/task_service_pb2.pyi +0 -31
  245. union/_protos/workflow/task_service_pb2_grpc.py +0 -104
  246. union/_resources.py +0 -226
  247. union/_retry.py +0 -32
  248. union/_reusable_environment.py +0 -25
  249. union/_run.py +0 -374
  250. union/_secret.py +0 -61
  251. union/_task.py +0 -354
  252. union/_task_environment.py +0 -186
  253. union/_timeout.py +0 -47
  254. union/_tools.py +0 -27
  255. union/_utils/__init__.py +0 -11
  256. union/_utils/asyn.py +0 -119
  257. union/_utils/file_handling.py +0 -71
  258. union/_utils/helpers.py +0 -46
  259. union/_utils/lazy_module.py +0 -54
  260. union/_utils/uv_script_parser.py +0 -49
  261. union/_version.py +0 -21
  262. union/connectors/__init__.py +0 -0
  263. union/errors.py +0 -128
  264. union/extras/__init__.py +0 -5
  265. union/extras/_container.py +0 -263
  266. union/io/__init__.py +0 -11
  267. union/io/_dataframe.py +0 -0
  268. union/io/_dir.py +0 -425
  269. union/io/_file.py +0 -418
  270. union/io/pickle/__init__.py +0 -0
  271. union/io/pickle/transformer.py +0 -117
  272. union/io/structured_dataset/__init__.py +0 -122
  273. union/io/structured_dataset/basic_dfs.py +0 -219
  274. union/io/structured_dataset/structured_dataset.py +0 -1057
  275. union/py.typed +0 -0
  276. union/remote/__init__.py +0 -23
  277. union/remote/_client/__init__.py +0 -0
  278. union/remote/_client/_protocols.py +0 -129
  279. union/remote/_client/auth/__init__.py +0 -12
  280. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  281. union/remote/_client/auth/_authenticators/base.py +0 -391
  282. union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
  283. union/remote/_client/auth/_authenticators/device_code.py +0 -120
  284. union/remote/_client/auth/_authenticators/external_command.py +0 -77
  285. union/remote/_client/auth/_authenticators/factory.py +0 -200
  286. union/remote/_client/auth/_authenticators/pkce.py +0 -515
  287. union/remote/_client/auth/_channel.py +0 -184
  288. union/remote/_client/auth/_client_config.py +0 -83
  289. union/remote/_client/auth/_default_html.py +0 -32
  290. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  291. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
  292. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
  293. union/remote/_client/auth/_keyring.py +0 -154
  294. union/remote/_client/auth/_token_client.py +0 -258
  295. union/remote/_client/auth/errors.py +0 -16
  296. union/remote/_client/controlplane.py +0 -86
  297. union/remote/_data.py +0 -149
  298. union/remote/_logs.py +0 -74
  299. union/remote/_project.py +0 -86
  300. union/remote/_run.py +0 -820
  301. union/remote/_secret.py +0 -132
  302. union/remote/_task.py +0 -193
  303. union/report/__init__.py +0 -3
  304. union/report/_report.py +0 -178
  305. union/report/_template.html +0 -124
  306. union/storage/__init__.py +0 -24
  307. union/storage/_remote_fs.py +0 -34
  308. union/storage/_storage.py +0 -247
  309. union/storage/_utils.py +0 -5
  310. union/types/__init__.py +0 -11
  311. union/types/_renderer.py +0 -162
  312. union/types/_string_literals.py +0 -120
  313. union/types/_type_engine.py +0 -2131
  314. union/types/_utils.py +0 -80
  315. /union/_protos/common/authorization_pb2_grpc.py → /flyte/_protos/workflow/common_pb2_grpc.py +0 -0
  316. /union/_protos/common/identifier_pb2_grpc.py → /flyte/_protos/workflow/environment_pb2_grpc.py +0 -0
  317. /flyte/io/{structured_dataset → _structured_dataset}/__init__.py +0 -0
  318. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/WHEEL +0 -0
  319. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/top_level.txt +0 -0
union/_cli/_get.py DELETED
@@ -1,162 +0,0 @@
1
- import asyncio
2
-
3
- import rich_click as click
4
- from rich.console import Console
5
-
6
- from . import _common as common
7
-
8
-
9
- @click.group(name="get")
10
- def get():
11
- """
12
- Get the value of a task or environment.
13
- """
14
-
15
-
16
- @get.command()
17
- @click.argument("name", type=str, required=False)
18
- @click.pass_obj
19
- def project(cfg: common.CLIConfig, name: str | None = None):
20
- """
21
- Get the current project.
22
- """
23
- from union.remote import Project
24
-
25
- print(cfg)
26
- cfg.init()
27
-
28
- console = Console()
29
- if name:
30
- console.print(Project.get(name))
31
- else:
32
- console.print(common.get_table("Projects", Project.listall()))
33
-
34
-
35
- @get.command(cls=common.CommandBase)
36
- @click.argument("name", type=str, required=False)
37
- @click.pass_obj
38
- def run(cfg: common.CLIConfig, name: str | None = None, project: str | None = None, domain: str | None = None):
39
- """
40
- Get the current run.
41
- """
42
- from union.remote import Run, RunDetails
43
-
44
- cfg.init(project=project, domain=domain)
45
-
46
- console = Console()
47
- if name:
48
- details = RunDetails.get(name=name)
49
- console.print(details)
50
- else:
51
- console.print(common.get_table("Runs", Run.listall()))
52
-
53
-
54
- @get.command(cls=common.CommandBase)
55
- @click.argument("name", type=str, required=False)
56
- @click.argument("version", type=str, required=False)
57
- @click.pass_obj
58
- def task(
59
- cfg: common.CLIConfig,
60
- name: str | None = None,
61
- version: str | None = None,
62
- project: str | None = None,
63
- domain: str | None = None,
64
- ):
65
- """
66
- Get the current task.
67
- """
68
- from union.remote import Task
69
-
70
- cfg.init(project=project, domain=domain)
71
-
72
- console = Console()
73
- if name:
74
- v = Task.get(name=name, version=version)
75
- if v is None:
76
- raise click.BadParameter(f"Task {name} not found.")
77
- t = v.fetch()
78
- console.print(t)
79
- else:
80
- raise click.BadParameter("Task listing is not supported yet, please provide a name.")
81
- # console.print(common.get_table("Tasks", Task.listall()))
82
-
83
-
84
- @get.command(cls=common.CommandBase)
85
- @click.argument("run_name", type=str, required=True)
86
- @click.argument("action_name", type=str, required=False)
87
- @click.pass_obj
88
- def action(
89
- cfg: common.CLIConfig,
90
- run_name: str,
91
- action_name: str | None = None,
92
- project: str | None = None,
93
- domain: str | None = None,
94
- ):
95
- """
96
- Get all actions for a run or details for a specific action.
97
- """
98
- import union.remote as remote
99
-
100
- cfg.init(project=project, domain=domain)
101
-
102
- console = Console()
103
- if action_name:
104
- console.print(remote.Action.get(run_name=run_name, name=action_name))
105
- else:
106
- # List all actions for the run
107
- console.print(common.get_table(f"Actions for {run_name}", remote.Action.listall(for_run_name=run_name)))
108
-
109
-
110
- @get.command(cls=common.CommandBase)
111
- @click.argument("run_name", type=str, required=False)
112
- @click.argument("action_name", type=str, required=False)
113
- @click.pass_obj
114
- def logs(
115
- cfg: common.CLIConfig,
116
- run_name: str,
117
- action_name: str | None = None,
118
- project: str | None = None,
119
- domain: str | None = None,
120
- ):
121
- """
122
- Get the current run.
123
- """
124
- import union.remote as remote
125
-
126
- cfg.init(project=project, domain=domain)
127
-
128
- async def _run_log_view(_obj):
129
- task = asyncio.create_task(_obj.show_logs())
130
- try:
131
- await task
132
- except KeyboardInterrupt:
133
- task.cancel()
134
-
135
- if action_name:
136
- obj = remote.Action.get(run_name=run_name, name=action_name)
137
- else:
138
- obj = remote.Run.get(run_name)
139
- asyncio.run(_run_log_view(obj))
140
-
141
-
142
- @get.command(cls=common.CommandBase)
143
- @click.argument("name", type=str, required=False)
144
- @click.pass_obj
145
- def secret(
146
- cfg: common.CLIConfig,
147
- name: str | None = None,
148
- project: str | None = None,
149
- domain: str | None = None,
150
- ):
151
- """
152
- Get the current secret.
153
- """
154
- import union.remote as remote
155
-
156
- cfg.init(project=project, domain=domain)
157
-
158
- console = Console()
159
- if name:
160
- console.print(remote.Secret.get(name))
161
- else:
162
- console.print(common.get_table("Secrets", remote.Secret.listall()))
union/_cli/_run.py DELETED
@@ -1,150 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from union._logging import logger
4
- from dataclasses import dataclass, fields
5
- from pathlib import Path
6
- from types import ModuleType
7
- from typing import Any, Dict, List, cast
8
-
9
- import click
10
-
11
- import union
12
-
13
- from .._code_bundle._utils import CopyFiles
14
- from .._initialize import initialize_in_cluster, S3
15
- from .._task import TaskTemplate
16
- from . import _common as common
17
- from ._common import CLIConfig
18
-
19
-
20
- @dataclass
21
- class RunArguments:
22
- project: str = common.make_click_option_field(common.PROJECT_OPTION)
23
- domain: str = common.make_click_option_field(common.DOMAIN_OPTION)
24
- local: bool = common.make_click_option_field(
25
- click.Option(
26
- ["--local"],
27
- is_flag=True,
28
- help="Run the task locally",
29
- )
30
- )
31
- hybrid: bool = common.make_click_option_field(
32
- click.Option(
33
- ["--hybrid"],
34
- is_flag=True,
35
- help="hybrid mode",
36
- )
37
- )
38
- copy_style: CopyFiles = common.make_click_option_field(
39
- click.Option(
40
- ["--copy-style"],
41
- type=click.Choice(["loaded_modules", "all_files", "none"]),
42
- default="loaded_modules",
43
- help="Copy style to use when running the task",
44
- )
45
- )
46
-
47
- @classmethod
48
- def from_dict(cls, d: Dict[str, Any]) -> RunArguments:
49
- return cls(**d)
50
-
51
- @classmethod
52
- def options(cls) -> List[click.Option]:
53
- """
54
- Return the set of base parameters added to run subcommand.
55
- """
56
- return [common.get_option_from_metadata(f.metadata) for f in fields(cls) if f.metadata]
57
-
58
-
59
- class RunTaskCommand(click.Command):
60
- def __init__(self, obj_name: str, obj: Any, run_args: RunArguments, *args, **kwargs):
61
- self.obj_name = obj_name
62
- self.obj = cast(TaskTemplate, obj)
63
- self.run_args = run_args
64
- super().__init__(name=obj_name, *args, **kwargs)
65
-
66
- def invoke(self, ctx):
67
- obj: CLIConfig = ctx.obj
68
- obj.init(self.run_args.project, self.run_args.domain)
69
-
70
- # todo: remove this when backend supports
71
- from union.storage import get_random_local_path
72
-
73
- run_name = "random-run-" + str(get_random_local_path())[-8:]
74
- if self.run_args.local:
75
- mode = "local"
76
- elif self.run_args.hybrid:
77
- mode = "hybrid"
78
- # TODO configure storage correctly for cluster
79
- initialize_in_cluster(storage=S3.auto())
80
- else:
81
- mode = "remote"
82
- logger.debug(f"Running {self.obj_name} in {mode} mode")
83
- r = union.with_runcontext(
84
- name=run_name,
85
- copy_style=self.run_args.copy_style,
86
- version=self.run_args.copy_style,
87
- mode=mode,
88
- ).run(self.obj)
89
- # click.secho(f"Created Run: {r.action.id}", fg="green")
90
-
91
-
92
- class TaskPerFileGroup(common.ObjectsPerFileGroup):
93
- """
94
- Group that creates a command for each task in the current directory that is not __init__.py.
95
- """
96
-
97
- def __init__(self, filename: Path, run_args: RunArguments, *args, **kwargs):
98
- super().__init__(*args, filename=filename, **kwargs)
99
- self.run_args = run_args
100
-
101
- def _filter_objects(self, module: ModuleType) -> Dict[str, Any]:
102
- return {k: v for k, v in module.__dict__.items() if isinstance(v, TaskTemplate)}
103
-
104
- def _get_command_for_obj(self, ctx: click.Context, obj_name: str, obj: Any) -> click.Command:
105
- obj = cast(TaskTemplate, obj)
106
- return RunTaskCommand(
107
- obj_name=obj_name,
108
- obj=obj,
109
- help=obj.docs.__help__str__() if obj.docs else None,
110
- run_args=self.run_args,
111
- )
112
-
113
-
114
- class TaskFiles(common.FileGroup):
115
- """
116
- Group that creates a command for each file in the current directory that is not __init__.py.
117
- """
118
-
119
- common_options_enabled = False
120
-
121
- def __init__(
122
- self,
123
- *args,
124
- directory: Path | None = None,
125
- **kwargs,
126
- ):
127
- if "params" not in kwargs:
128
- kwargs["params"] = []
129
- kwargs["params"].extend(RunArguments.options())
130
- super().__init__(*args, directory=directory, **kwargs)
131
-
132
- def get_command(self, ctx, filename):
133
- run_args = RunArguments.from_dict(ctx.params)
134
- fp = Path(filename)
135
- if not fp.exists():
136
- raise click.BadParameter(f"File {filename} does not exist")
137
- if fp.is_dir():
138
- return TaskFiles(directory=fp)
139
- return TaskPerFileGroup(
140
- filename=Path(filename),
141
- run_args=run_args,
142
- name=filename,
143
- help=f"Run, functions decorated `env.task` or instances of Tasks in {filename}",
144
- )
145
-
146
-
147
- run = TaskFiles(
148
- name="run",
149
- help="Run a task from a python file",
150
- )
union/_cli/main.py DELETED
@@ -1,72 +0,0 @@
1
- import rich_click as click
2
-
3
- from ._common import CLIConfig
4
- from ._create import create
5
- from ._deploy import deploy
6
- from ._get import get
7
- from ._run import run
8
-
9
-
10
- def _verbosity_to_loglevel(verbosity: int) -> int | None:
11
- """
12
- Converts a verbosity level from the CLI to a logging level.
13
-
14
- :param verbosity: verbosity level from the CLI
15
- :return: logging level
16
- """
17
- import logging
18
-
19
- match verbosity:
20
- case 0:
21
- return None
22
- case 1:
23
- return logging.WARNING
24
- case 2:
25
- return logging.INFO
26
- case _:
27
- return logging.DEBUG
28
-
29
-
30
- @click.group(cls=click.RichGroup)
31
- @click.option(
32
- "--endpoint",
33
- type=str,
34
- required=False,
35
- help="The endpoint to connect to, this will override any config and simply used pkce to connect.",
36
- )
37
- @click.option(
38
- "--insecure",
39
- is_flag=True,
40
- required=False,
41
- help="insecure",
42
- type=bool,
43
- default=False,
44
- )
45
- @click.option(
46
- "-v",
47
- "--verbose",
48
- required=False,
49
- help="Show verbose messages and exception traces",
50
- count=True,
51
- default=0,
52
- type=int,
53
- )
54
- @click.option(
55
- "--org-override",
56
- type=str,
57
- required=False,
58
- help="Override for org",
59
- )
60
- @click.pass_context
61
- def main(ctx: click.Context, endpoint: str | None, insecure: bool, verbose: int, org_override: str | None):
62
- """
63
- v2 cli. Root command, please use one of the subcommands.
64
- """
65
- log_level = _verbosity_to_loglevel(verbose)
66
- ctx.obj = CLIConfig(log_level=log_level, endpoint=endpoint, insecure=insecure, org_override=org_override)
67
-
68
-
69
- main.add_command(run)
70
- main.add_command(deploy)
71
- main.add_command(get) # type: ignore
72
- main.add_command(create) # type: ignore
@@ -1,8 +0,0 @@
1
- from ._ignore import GitIgnore, IgnoreGroup, StandardIgnore
2
- from ._utils import CopyFiles
3
- from .bundle import build_code_bundle, build_pkl_bundle, download_bundle
4
-
5
- __all__ = ["CopyFiles", "build_code_bundle", "build_pkl_bundle", "default_ignores", "download_bundle"]
6
-
7
-
8
- default_ignores = [GitIgnore, StandardIgnore, IgnoreGroup]
@@ -1,113 +0,0 @@
1
- import os
2
- import pathlib
3
- import subprocess
4
- import tarfile as _tarfile
5
- from abc import ABC, abstractmethod
6
- from fnmatch import fnmatch
7
- from pathlib import Path
8
- from shutil import which
9
- from typing import List, Optional, Type
10
-
11
- from union._logging import logger
12
-
13
-
14
- class Ignore(ABC):
15
- """Base for Ignores, implements core logic. Children have to implement _is_ignored"""
16
-
17
- def __init__(self, root: Path):
18
- self.root = root
19
-
20
- def is_ignored(self, path: pathlib.Path) -> bool:
21
- return self._is_ignored(path)
22
-
23
- def tar_filter(self, tarinfo: _tarfile.TarInfo) -> Optional[_tarfile.TarInfo]:
24
- if self.is_ignored(pathlib.Path(tarinfo.name)):
25
- return None
26
- return tarinfo
27
-
28
- @abstractmethod
29
- def _is_ignored(self, path: pathlib.Path) -> bool:
30
- pass
31
-
32
-
33
- class GitIgnore(Ignore):
34
- """Uses git cli (if available) to list all ignored files and compare with those."""
35
-
36
- def __init__(self, root: Path):
37
- super().__init__(root)
38
- self.has_git = which("git") is not None
39
- self.ignored_files = self._list_ignored_files()
40
- self.ignored_dirs = self._list_ignored_dirs()
41
-
42
- def _git_wrapper(self, extra_args: List[str]) -> set[str]:
43
- if self.has_git:
44
- out = subprocess.run(
45
- ["git", "ls-files", "-io", "--exclude-standard", *extra_args],
46
- cwd=self.root,
47
- capture_output=True,
48
- check=False,
49
- )
50
- if out.returncode == 0:
51
- return set(out.stdout.decode("utf-8").split("\n")[:-1])
52
- logger.info(f"Could not determine ignored paths due to:\n{out.stderr}\nNot applying any filters")
53
- return set()
54
- logger.info("No git executable found, not applying any filters")
55
- return set()
56
-
57
- def _list_ignored_files(self) -> set[str]:
58
- return self._git_wrapper([])
59
-
60
- def _list_ignored_dirs(self) -> set[str]:
61
- return self._git_wrapper(["--directory"])
62
-
63
- def _is_ignored(self, path: str) -> bool:
64
- if self.ignored_files:
65
- # git-ls-files uses POSIX paths
66
- if Path(path).as_posix() in self.ignored_files:
67
- return True
68
- # Ignore empty directories
69
- if os.path.isdir(os.path.join(self.root, path)) and self.ignored_dirs:
70
- return Path(path).as_posix() + "/" in self.ignored_dirs
71
- return False
72
-
73
-
74
- STANDARD_IGNORE_PATTERNS = ["*.pyc", ".cache", ".cache/*", "__pycache__", "**/__pycache__"]
75
-
76
-
77
- class StandardIgnore(Ignore):
78
- """Retains the standard ignore functionality that previously existed. Could in theory
79
- by fed with custom ignore patterns from cli."""
80
-
81
- def __init__(self, root: Path, patterns: Optional[List[str]] = None):
82
- super().__init__(root)
83
- self.patterns = patterns if patterns else STANDARD_IGNORE_PATTERNS
84
-
85
- def _is_ignored(self, path: pathlib.Path) -> bool:
86
- for pattern in self.patterns:
87
- if fnmatch(str(path), pattern):
88
- return True
89
- return False
90
-
91
-
92
- class IgnoreGroup(Ignore):
93
- """Groups multiple Ignores and checks a path against them. A file is ignored if any
94
- Ignore considers it ignored."""
95
-
96
- def __init__(self, root: Path, *ignores: Type[Ignore]):
97
- super().__init__(root)
98
- self.ignores = [ignore(root) for ignore in ignores]
99
-
100
- def _is_ignored(self, path: pathlib.Path) -> bool:
101
- for ignore in self.ignores:
102
- if ignore.is_ignored(path):
103
- return True
104
- return False
105
-
106
- def list_ignored(self) -> List[str]:
107
- ignored = []
108
- for dir, _, files in self.root.walk():
109
- for file in files:
110
- abs_path = dir / file
111
- if self.is_ignored(abs_path):
112
- ignored.append(str(abs_path.relative_to(self.root)))
113
- return ignored
@@ -1,187 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import gzip
4
- import hashlib
5
- import os
6
- import pathlib
7
- import posixpath
8
- import shutil
9
- import stat
10
- import subprocess
11
- import tarfile
12
- import time
13
- import typing
14
- from typing import List, Optional, Tuple, Union
15
-
16
- import click
17
- from rich import print as rich_print
18
- from rich.tree import Tree
19
-
20
- from union._logging import logger
21
-
22
- from ._ignore import Ignore, IgnoreGroup
23
- from ._utils import CopyFiles, _filehash_update, _pathhash_update, ls_files, tar_strip_file_attributes
24
-
25
- FAST_PREFIX = "fast"
26
- FAST_FILEENDING = ".tar.gz"
27
-
28
-
29
- def print_ls_tree(source: os.PathLike, ls: typing.List[str]):
30
- click.secho("Files to be copied for fast registration...", fg="bright_blue")
31
-
32
- tree_root = Tree(
33
- f":open_file_folder: [link file://{source}]{source} (detected source root)",
34
- guide_style="bold bright_blue",
35
- )
36
- trees = {pathlib.Path(source): tree_root}
37
-
38
- for f in ls:
39
- fpp = pathlib.Path(f)
40
- if fpp.parent not in trees:
41
- # add trees for all intermediate folders
42
- current = tree_root
43
- current_path = pathlib.Path(source)
44
- for subdir in fpp.parent.relative_to(source).parts:
45
- current_path = current_path / subdir
46
- if current_path not in trees:
47
- current = current.add(f"{subdir}", guide_style="bold bright_blue")
48
- trees[current_path] = current
49
- else:
50
- current = trees[current_path]
51
- trees[fpp.parent].add(f"{fpp.name}", guide_style="bold bright_blue")
52
- rich_print(tree_root)
53
-
54
-
55
- def _compress_tarball(source: pathlib.Path, output: pathlib.Path) -> None:
56
- """Compress code tarball using pigz if available, otherwise gzip"""
57
- if pigz := shutil.which("pigz"):
58
- with open(str(output), "wb") as gzipped:
59
- subprocess.run([pigz, "--no-time", "-c", str(source)], stdout=gzipped, check=True)
60
- else:
61
- start_time = time.time()
62
- with gzip.GzipFile(filename=str(output), mode="wb", mtime=0) as gzipped:
63
- with open(source, "rb") as source_file:
64
- gzipped.write(source_file.read())
65
-
66
- end_time = time.time()
67
- warning_time = 10
68
- if end_time - start_time > warning_time:
69
- click.secho(
70
- f"Code tarball compression took {end_time - start_time:.0f} seconds. "
71
- f"Consider installing `pigz` for faster compression.",
72
- fg="yellow",
73
- )
74
-
75
-
76
- def list_files_to_bundle(
77
- source: pathlib.Path,
78
- deref_symlinks: bool = False,
79
- *ignores: typing.Type[Ignore],
80
- copy_style: CopyFiles = "all",
81
- ) -> typing.Tuple[List[str], str]:
82
- """
83
- Takes a source directory and returns a list of all files to be included in the code bundle and a hexdigest of the
84
- included files.
85
- :param source: The source directory to package
86
- :param deref_symlinks: Whether to dereference symlinks or not
87
- :param ignores: A list of Ignore classes to use for ignoring files
88
- :param copy_style: The copy style to use for the tarball
89
- :return: A list of all files to be included in the code bundle and a hexdigest of the included files
90
- """
91
- ignore = IgnoreGroup(source, *ignores)
92
-
93
- ls, ls_digest = ls_files(source, copy_style, deref_symlinks, ignore)
94
- logger.debug(f"Hash digest: {ls_digest}")
95
- return ls, ls_digest
96
-
97
-
98
- def create_bundle(
99
- source: pathlib.Path, output_dir: pathlib.Path, ls: List[str], ls_digest: str, deref_symlinks: bool = False
100
- ) -> Tuple[pathlib.Path, float, float]:
101
- """
102
- Takes a source directory and packages everything not covered by common ignores into a tarball.
103
- The output_dir is the directory where the tarball and a compressed version of the tarball will be written.
104
- The output_dir can be a temporary directory.
105
-
106
- :param source: The source directory to package
107
- :param output_dir: The directory to write the tarball to
108
- :param deref_symlinks: Whether to dereference symlinks or not
109
- :param ls: The list of files to include in the tarball
110
- :param ls_digest: The hexdigest of the included files
111
- :return: The path to the tarball, the size of the tarball in MB, and the size of the compressed tarball in MB
112
- """
113
- # Compute where the archive should be written
114
- archive_fname = output_dir / f"{FAST_PREFIX}{ls_digest}{FAST_FILEENDING}"
115
- tar_path = output_dir / "tmp.tar"
116
- with tarfile.open(str(tar_path), "w", dereference=deref_symlinks) as tar:
117
- for ws_file in ls:
118
- rel_path = os.path.relpath(ws_file, start=source)
119
- tar.add(
120
- os.path.join(source, ws_file),
121
- recursive=False,
122
- arcname=rel_path,
123
- filter=lambda x: tar_strip_file_attributes(x),
124
- )
125
-
126
- size_mbs = tar_path.stat().st_size / 1024 / 1024
127
- _compress_tarball(tar_path, archive_fname)
128
- asize_mbs = archive_fname.stat().st_size / 1024 / 1024
129
-
130
- return archive_fname, size_mbs, asize_mbs
131
-
132
-
133
- def compute_digest(source: Union[os.PathLike, List[os.PathLike]], filter: Optional[callable] = None) -> str:
134
- """
135
- Walks the entirety of the source dir to compute a deterministic md5 hex digest of the dir contents.
136
- :param os.PathLike source:
137
- :param callable filter:
138
- :return Text:
139
- """
140
- hasher = hashlib.md5()
141
-
142
- def compute_digest_for_file(path: os.PathLike, rel_path: os.PathLike) -> None:
143
- # Only consider files that exist (e.g. disregard symlinks that point to non-existent files)
144
- if not os.path.exists(path):
145
- logger.info(f"Skipping non-existent file {path}")
146
- return
147
-
148
- # Skip socket files
149
- if stat.S_ISSOCK(os.stat(path).st_mode):
150
- logger.info(f"Skip socket file {path}")
151
- return
152
-
153
- if filter:
154
- if filter(rel_path):
155
- return
156
-
157
- _filehash_update(path, hasher)
158
- _pathhash_update(rel_path, hasher)
159
-
160
- def compute_digest_for_dir(source: os.PathLike) -> None:
161
- for root, _, files in os.walk(source, topdown=True):
162
- files.sort()
163
-
164
- for fname in files:
165
- abspath = os.path.join(root, fname)
166
- relpath = os.path.relpath(abspath, source)
167
- compute_digest_for_file(abspath, relpath)
168
-
169
- if isinstance(source, list):
170
- for src in source:
171
- if os.path.isdir(src):
172
- compute_digest_for_dir(src)
173
- else:
174
- compute_digest_for_file(src, os.path.basename(src))
175
- else:
176
- compute_digest_for_dir(source)
177
-
178
- return hasher.hexdigest()
179
-
180
-
181
- def get_additional_distribution_loc(remote_location: str, identifier: str) -> str:
182
- """
183
- :param Text remote_location:
184
- :param Text identifier:
185
- :return Text:
186
- """
187
- return posixpath.join(remote_location, "{}.{}".format(identifier, "tar.gz"))