flyte 2.0.0b32__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 (204) hide show
  1. flyte/__init__.py +108 -0
  2. flyte/_bin/__init__.py +0 -0
  3. flyte/_bin/debug.py +38 -0
  4. flyte/_bin/runtime.py +195 -0
  5. flyte/_bin/serve.py +178 -0
  6. flyte/_build.py +26 -0
  7. flyte/_cache/__init__.py +12 -0
  8. flyte/_cache/cache.py +147 -0
  9. flyte/_cache/defaults.py +9 -0
  10. flyte/_cache/local_cache.py +216 -0
  11. flyte/_cache/policy_function_body.py +42 -0
  12. flyte/_code_bundle/__init__.py +8 -0
  13. flyte/_code_bundle/_ignore.py +121 -0
  14. flyte/_code_bundle/_packaging.py +218 -0
  15. flyte/_code_bundle/_utils.py +347 -0
  16. flyte/_code_bundle/bundle.py +266 -0
  17. flyte/_constants.py +1 -0
  18. flyte/_context.py +155 -0
  19. flyte/_custom_context.py +73 -0
  20. flyte/_debug/__init__.py +0 -0
  21. flyte/_debug/constants.py +38 -0
  22. flyte/_debug/utils.py +17 -0
  23. flyte/_debug/vscode.py +307 -0
  24. flyte/_deploy.py +408 -0
  25. flyte/_deployer.py +109 -0
  26. flyte/_doc.py +29 -0
  27. flyte/_docstring.py +32 -0
  28. flyte/_environment.py +122 -0
  29. flyte/_excepthook.py +37 -0
  30. flyte/_group.py +32 -0
  31. flyte/_hash.py +8 -0
  32. flyte/_image.py +1055 -0
  33. flyte/_initialize.py +628 -0
  34. flyte/_interface.py +119 -0
  35. flyte/_internal/__init__.py +3 -0
  36. flyte/_internal/controllers/__init__.py +129 -0
  37. flyte/_internal/controllers/_local_controller.py +239 -0
  38. flyte/_internal/controllers/_trace.py +48 -0
  39. flyte/_internal/controllers/remote/__init__.py +58 -0
  40. flyte/_internal/controllers/remote/_action.py +211 -0
  41. flyte/_internal/controllers/remote/_client.py +47 -0
  42. flyte/_internal/controllers/remote/_controller.py +583 -0
  43. flyte/_internal/controllers/remote/_core.py +465 -0
  44. flyte/_internal/controllers/remote/_informer.py +381 -0
  45. flyte/_internal/controllers/remote/_service_protocol.py +50 -0
  46. flyte/_internal/imagebuild/__init__.py +3 -0
  47. flyte/_internal/imagebuild/docker_builder.py +706 -0
  48. flyte/_internal/imagebuild/image_builder.py +277 -0
  49. flyte/_internal/imagebuild/remote_builder.py +386 -0
  50. flyte/_internal/imagebuild/utils.py +78 -0
  51. flyte/_internal/resolvers/__init__.py +0 -0
  52. flyte/_internal/resolvers/_task_module.py +21 -0
  53. flyte/_internal/resolvers/common.py +31 -0
  54. flyte/_internal/resolvers/default.py +28 -0
  55. flyte/_internal/runtime/__init__.py +0 -0
  56. flyte/_internal/runtime/convert.py +486 -0
  57. flyte/_internal/runtime/entrypoints.py +204 -0
  58. flyte/_internal/runtime/io.py +188 -0
  59. flyte/_internal/runtime/resources_serde.py +152 -0
  60. flyte/_internal/runtime/reuse.py +125 -0
  61. flyte/_internal/runtime/rusty.py +193 -0
  62. flyte/_internal/runtime/task_serde.py +362 -0
  63. flyte/_internal/runtime/taskrunner.py +209 -0
  64. flyte/_internal/runtime/trigger_serde.py +160 -0
  65. flyte/_internal/runtime/types_serde.py +54 -0
  66. flyte/_keyring/__init__.py +0 -0
  67. flyte/_keyring/file.py +115 -0
  68. flyte/_logging.py +300 -0
  69. flyte/_map.py +312 -0
  70. flyte/_module.py +72 -0
  71. flyte/_pod.py +30 -0
  72. flyte/_resources.py +473 -0
  73. flyte/_retry.py +32 -0
  74. flyte/_reusable_environment.py +102 -0
  75. flyte/_run.py +724 -0
  76. flyte/_secret.py +96 -0
  77. flyte/_task.py +550 -0
  78. flyte/_task_environment.py +316 -0
  79. flyte/_task_plugins.py +47 -0
  80. flyte/_timeout.py +47 -0
  81. flyte/_tools.py +27 -0
  82. flyte/_trace.py +119 -0
  83. flyte/_trigger.py +1000 -0
  84. flyte/_utils/__init__.py +30 -0
  85. flyte/_utils/asyn.py +121 -0
  86. flyte/_utils/async_cache.py +139 -0
  87. flyte/_utils/coro_management.py +27 -0
  88. flyte/_utils/docker_credentials.py +173 -0
  89. flyte/_utils/file_handling.py +72 -0
  90. flyte/_utils/helpers.py +134 -0
  91. flyte/_utils/lazy_module.py +54 -0
  92. flyte/_utils/module_loader.py +104 -0
  93. flyte/_utils/org_discovery.py +57 -0
  94. flyte/_utils/uv_script_parser.py +49 -0
  95. flyte/_version.py +34 -0
  96. flyte/app/__init__.py +22 -0
  97. flyte/app/_app_environment.py +157 -0
  98. flyte/app/_deploy.py +125 -0
  99. flyte/app/_input.py +160 -0
  100. flyte/app/_runtime/__init__.py +3 -0
  101. flyte/app/_runtime/app_serde.py +347 -0
  102. flyte/app/_types.py +101 -0
  103. flyte/app/extras/__init__.py +3 -0
  104. flyte/app/extras/_fastapi.py +151 -0
  105. flyte/cli/__init__.py +12 -0
  106. flyte/cli/_abort.py +28 -0
  107. flyte/cli/_build.py +114 -0
  108. flyte/cli/_common.py +468 -0
  109. flyte/cli/_create.py +371 -0
  110. flyte/cli/_delete.py +45 -0
  111. flyte/cli/_deploy.py +293 -0
  112. flyte/cli/_gen.py +176 -0
  113. flyte/cli/_get.py +370 -0
  114. flyte/cli/_option.py +33 -0
  115. flyte/cli/_params.py +554 -0
  116. flyte/cli/_plugins.py +209 -0
  117. flyte/cli/_run.py +597 -0
  118. flyte/cli/_serve.py +64 -0
  119. flyte/cli/_update.py +37 -0
  120. flyte/cli/_user.py +17 -0
  121. flyte/cli/main.py +221 -0
  122. flyte/config/__init__.py +3 -0
  123. flyte/config/_config.py +248 -0
  124. flyte/config/_internal.py +73 -0
  125. flyte/config/_reader.py +225 -0
  126. flyte/connectors/__init__.py +11 -0
  127. flyte/connectors/_connector.py +270 -0
  128. flyte/connectors/_server.py +197 -0
  129. flyte/connectors/utils.py +135 -0
  130. flyte/errors.py +243 -0
  131. flyte/extend.py +19 -0
  132. flyte/extras/__init__.py +5 -0
  133. flyte/extras/_container.py +286 -0
  134. flyte/git/__init__.py +3 -0
  135. flyte/git/_config.py +21 -0
  136. flyte/io/__init__.py +29 -0
  137. flyte/io/_dataframe/__init__.py +131 -0
  138. flyte/io/_dataframe/basic_dfs.py +223 -0
  139. flyte/io/_dataframe/dataframe.py +1026 -0
  140. flyte/io/_dir.py +910 -0
  141. flyte/io/_file.py +914 -0
  142. flyte/io/_hashing_io.py +342 -0
  143. flyte/models.py +479 -0
  144. flyte/py.typed +0 -0
  145. flyte/remote/__init__.py +35 -0
  146. flyte/remote/_action.py +738 -0
  147. flyte/remote/_app.py +57 -0
  148. flyte/remote/_client/__init__.py +0 -0
  149. flyte/remote/_client/_protocols.py +189 -0
  150. flyte/remote/_client/auth/__init__.py +12 -0
  151. flyte/remote/_client/auth/_auth_utils.py +14 -0
  152. flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
  153. flyte/remote/_client/auth/_authenticators/base.py +403 -0
  154. flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
  155. flyte/remote/_client/auth/_authenticators/device_code.py +117 -0
  156. flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
  157. flyte/remote/_client/auth/_authenticators/factory.py +200 -0
  158. flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
  159. flyte/remote/_client/auth/_channel.py +213 -0
  160. flyte/remote/_client/auth/_client_config.py +85 -0
  161. flyte/remote/_client/auth/_default_html.py +32 -0
  162. flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  163. flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
  164. flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
  165. flyte/remote/_client/auth/_keyring.py +152 -0
  166. flyte/remote/_client/auth/_token_client.py +260 -0
  167. flyte/remote/_client/auth/errors.py +16 -0
  168. flyte/remote/_client/controlplane.py +128 -0
  169. flyte/remote/_common.py +30 -0
  170. flyte/remote/_console.py +19 -0
  171. flyte/remote/_data.py +161 -0
  172. flyte/remote/_logs.py +185 -0
  173. flyte/remote/_project.py +88 -0
  174. flyte/remote/_run.py +386 -0
  175. flyte/remote/_secret.py +142 -0
  176. flyte/remote/_task.py +527 -0
  177. flyte/remote/_trigger.py +306 -0
  178. flyte/remote/_user.py +33 -0
  179. flyte/report/__init__.py +3 -0
  180. flyte/report/_report.py +182 -0
  181. flyte/report/_template.html +124 -0
  182. flyte/storage/__init__.py +36 -0
  183. flyte/storage/_config.py +237 -0
  184. flyte/storage/_parallel_reader.py +274 -0
  185. flyte/storage/_remote_fs.py +34 -0
  186. flyte/storage/_storage.py +456 -0
  187. flyte/storage/_utils.py +5 -0
  188. flyte/syncify/__init__.py +56 -0
  189. flyte/syncify/_api.py +375 -0
  190. flyte/types/__init__.py +52 -0
  191. flyte/types/_interface.py +40 -0
  192. flyte/types/_pickle.py +145 -0
  193. flyte/types/_renderer.py +162 -0
  194. flyte/types/_string_literals.py +119 -0
  195. flyte/types/_type_engine.py +2254 -0
  196. flyte/types/_utils.py +80 -0
  197. flyte-2.0.0b32.data/scripts/debug.py +38 -0
  198. flyte-2.0.0b32.data/scripts/runtime.py +195 -0
  199. flyte-2.0.0b32.dist-info/METADATA +351 -0
  200. flyte-2.0.0b32.dist-info/RECORD +204 -0
  201. flyte-2.0.0b32.dist-info/WHEEL +5 -0
  202. flyte-2.0.0b32.dist-info/entry_points.txt +7 -0
  203. flyte-2.0.0b32.dist-info/licenses/LICENSE +201 -0
  204. flyte-2.0.0b32.dist-info/top_level.txt +1 -0
flyte/cli/_run.py ADDED
@@ -0,0 +1,597 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import inspect
5
+ from dataclasses import dataclass, field, fields
6
+ from functools import lru_cache
7
+ from pathlib import Path
8
+ from types import ModuleType
9
+ from typing import Any, Dict, List, cast
10
+
11
+ import rich_click as click
12
+ from typing_extensions import get_args
13
+
14
+ from .._code_bundle._utils import CopyFiles
15
+ from .._task import TaskTemplate
16
+ from ..remote import Run
17
+ from . import _common as common
18
+ from ._common import CLIConfig, initialize_config
19
+ from ._params import to_click_option
20
+
21
+ RUN_REMOTE_CMD = "deployed-task"
22
+
23
+
24
+ @lru_cache()
25
+ def _initialize_config(ctx: click.Context, project: str, domain: str, root_dir: str | None = None):
26
+ obj: CLIConfig | None = ctx.obj
27
+ if obj is None:
28
+ import flyte.config
29
+
30
+ obj = CLIConfig(flyte.config.auto(), ctx)
31
+
32
+ obj.init(project, domain, root_dir)
33
+ return obj
34
+
35
+
36
+ @lru_cache()
37
+ def _list_tasks(
38
+ ctx: click.Context,
39
+ project: str,
40
+ domain: str,
41
+ by_task_name: str | None = None,
42
+ by_task_env: str | None = None,
43
+ ) -> list[str]:
44
+ import flyte.remote
45
+
46
+ common.initialize_config(ctx, project, domain)
47
+ return [task.name for task in flyte.remote.Task.listall(by_task_name=by_task_name, by_task_env=by_task_env)]
48
+
49
+
50
+ @dataclass
51
+ class RunArguments:
52
+ project: str = field(
53
+ default=cast(str, common.PROJECT_OPTION.default), metadata={"click.option": common.PROJECT_OPTION}
54
+ )
55
+ domain: str = field(
56
+ default=cast(str, common.DOMAIN_OPTION.default), metadata={"click.option": common.DOMAIN_OPTION}
57
+ )
58
+ local: bool = field(
59
+ default=False,
60
+ metadata={
61
+ "click.option": click.Option(
62
+ ["--local"],
63
+ is_flag=True,
64
+ help="Run the task locally",
65
+ )
66
+ },
67
+ )
68
+ copy_style: CopyFiles = field(
69
+ default="loaded_modules",
70
+ metadata={
71
+ "click.option": click.Option(
72
+ ["--copy-style"],
73
+ type=click.Choice(get_args(CopyFiles)),
74
+ default="loaded_modules",
75
+ help="Copy style to use when running the task",
76
+ )
77
+ },
78
+ )
79
+ root_dir: str | None = field(
80
+ default=None,
81
+ metadata={
82
+ "click.option": click.Option(
83
+ ["--root-dir"],
84
+ type=str,
85
+ help="Override the root source directory, helpful when working with monorepos.",
86
+ )
87
+ },
88
+ )
89
+ raw_data_path: str | None = field(
90
+ default=None,
91
+ metadata={
92
+ "click.option": click.Option(
93
+ ["--raw-data-path"],
94
+ type=str,
95
+ help="Override the output prefix used to store offloaded data types. e.g. s3://bucket/",
96
+ )
97
+ },
98
+ )
99
+ service_account: str | None = field(
100
+ default=None,
101
+ metadata={
102
+ "click.option": click.Option(
103
+ ["--service-account"],
104
+ type=str,
105
+ help="Kubernetes service account. If not provided, the configured default will be used",
106
+ )
107
+ },
108
+ )
109
+ name: str | None = field(
110
+ default=None,
111
+ metadata={
112
+ "click.option": click.Option(
113
+ ["--name"],
114
+ type=str,
115
+ help="Name of the run. If not provided, a random name will be generated.",
116
+ )
117
+ },
118
+ )
119
+ follow: bool = field(
120
+ default=False,
121
+ metadata={
122
+ "click.option": click.Option(
123
+ ["--follow", "-f"],
124
+ is_flag=True,
125
+ default=False,
126
+ help="Wait and watch logs for the parent action. If not provided, the CLI will exit after "
127
+ "successfully launching a remote execution with a link to the UI.",
128
+ )
129
+ },
130
+ )
131
+ image: List[str] = field(
132
+ default_factory=list,
133
+ metadata={
134
+ "click.option": click.Option(
135
+ ["--image"],
136
+ type=str,
137
+ multiple=True,
138
+ help="Image to be used in the run. Format: imagename=imageuri. Can be specified multiple times.",
139
+ )
140
+ },
141
+ )
142
+ no_sync_local_sys_paths: bool = field(
143
+ default=True,
144
+ metadata={
145
+ "click.option": click.Option(
146
+ ["--no-sync-local-sys-paths"],
147
+ is_flag=True,
148
+ flag_value=True,
149
+ default=False,
150
+ help="Disable synchronization of local sys.path entries under the root directory "
151
+ "to the remote container.",
152
+ )
153
+ },
154
+ )
155
+
156
+ @classmethod
157
+ def from_dict(cls, d: Dict[str, Any]) -> RunArguments:
158
+ modified = {k: v for k, v in d.items() if k in {f.name for f in fields(cls)}}
159
+ return cls(**modified)
160
+
161
+ @classmethod
162
+ def options(cls) -> List[click.Option]:
163
+ """
164
+ Return the set of base parameters added to run subcommand.
165
+ """
166
+ return [common.get_option_from_metadata(f.metadata) for f in fields(cls) if f.metadata]
167
+
168
+
169
+ class RunTaskCommand(click.RichCommand):
170
+ def __init__(self, obj_name: str, obj: Any, run_args: RunArguments, *args, **kwargs):
171
+ self.obj_name = obj_name
172
+ self.obj = cast(TaskTemplate, obj)
173
+ self.run_args = run_args
174
+ kwargs.pop("name", None)
175
+ super().__init__(obj_name, *args, **kwargs)
176
+
177
+ def invoke(self, ctx: click.Context):
178
+ obj: CLIConfig = initialize_config(
179
+ ctx,
180
+ self.run_args.project,
181
+ self.run_args.domain,
182
+ self.run_args.root_dir,
183
+ tuple(self.run_args.image) or None,
184
+ not self.run_args.no_sync_local_sys_paths,
185
+ )
186
+
187
+ async def _run():
188
+ import flyte
189
+
190
+ console = common.get_console()
191
+ r = await flyte.with_runcontext(
192
+ copy_style=self.run_args.copy_style,
193
+ mode="local" if self.run_args.local else "remote",
194
+ name=self.run_args.name,
195
+ raw_data_path=self.run_args.raw_data_path,
196
+ service_account=self.run_args.service_account,
197
+ log_format=obj.log_format,
198
+ ).run.aio(self.obj, **ctx.params)
199
+ if self.run_args.local:
200
+ console.print(
201
+ common.get_panel(
202
+ "Local Run",
203
+ f"[green]Completed Local Run, data stored in path: {r.url} [/green] \n"
204
+ f"➡️ Outputs: {r.outputs()}",
205
+ obj.output_format,
206
+ )
207
+ )
208
+ return
209
+ if isinstance(r, Run) and r.action is not None:
210
+ console.print(
211
+ common.get_panel(
212
+ "Run",
213
+ f"[green bold]Created Run: {r.name} [/green bold] "
214
+ f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n"
215
+ f"➡️ [blue bold][link={r.url}]{r.url}[/link][/blue bold]",
216
+ obj.output_format,
217
+ )
218
+ )
219
+ if self.run_args.follow:
220
+ console.print(
221
+ "[dim]Log streaming enabled, will wait for task to start running "
222
+ "and log stream to be available[/dim]"
223
+ )
224
+ await r.show_logs.aio(max_lines=30, show_ts=True, raw=False)
225
+
226
+ asyncio.run(_run())
227
+
228
+ def get_params(self, ctx: click.Context) -> List[click.Parameter]:
229
+ # Note this function may be called multiple times by click.
230
+ task = self.obj
231
+ from .._internal.runtime.types_serde import transform_native_to_typed_interface
232
+
233
+ interface = transform_native_to_typed_interface(task.native_interface)
234
+ if interface is None:
235
+ return super().get_params(ctx)
236
+ inputs_interface = task.native_interface.inputs
237
+
238
+ params: List[click.Parameter] = []
239
+ for name, var in interface.inputs.variables.items():
240
+ default_val = None
241
+ if inputs_interface[name][1] is not inspect._empty:
242
+ default_val = inputs_interface[name][1]
243
+ params.append(to_click_option(name, var, inputs_interface[name][0], default_val))
244
+
245
+ self.params = params
246
+ return super().get_params(ctx)
247
+
248
+
249
+ class TaskPerFileGroup(common.ObjectsPerFileGroup):
250
+ """
251
+ Group that creates a command for each task in the current directory that is not __init__.py.
252
+ """
253
+
254
+ def __init__(self, filename: Path, run_args: RunArguments, *args, **kwargs):
255
+ if filename.is_absolute():
256
+ filename = filename.relative_to(Path.cwd())
257
+ super().__init__(*(filename, *args), **kwargs)
258
+ self.run_args = run_args
259
+
260
+ def _filter_objects(self, module: ModuleType) -> Dict[str, Any]:
261
+ return {k: v for k, v in module.__dict__.items() if isinstance(v, TaskTemplate)}
262
+
263
+ def list_commands(self, ctx):
264
+ common.initialize_config(
265
+ ctx,
266
+ self.run_args.project,
267
+ self.run_args.domain,
268
+ self.run_args.root_dir,
269
+ sync_local_sys_paths=not self.run_args.no_sync_local_sys_paths,
270
+ )
271
+ return super().list_commands(ctx)
272
+
273
+ def get_command(self, ctx, obj_name):
274
+ common.initialize_config(
275
+ ctx,
276
+ self.run_args.project,
277
+ self.run_args.domain,
278
+ self.run_args.root_dir,
279
+ sync_local_sys_paths=not self.run_args.no_sync_local_sys_paths,
280
+ )
281
+ return super().get_command(ctx, obj_name)
282
+
283
+ def _get_command_for_obj(self, ctx: click.Context, obj_name: str, obj: Any) -> click.Command:
284
+ obj = cast(TaskTemplate, obj)
285
+ return RunTaskCommand(
286
+ obj_name=obj_name,
287
+ obj=obj,
288
+ help=obj.docs.__help__str__() if obj.docs else None,
289
+ run_args=self.run_args,
290
+ )
291
+
292
+
293
+ class RunReferenceTaskCommand(click.RichCommand):
294
+ def __init__(self, task_name: str, run_args: RunArguments, version: str | None, *args, **kwargs):
295
+ self.task_name = task_name
296
+ self.run_args = run_args
297
+ self.version = version
298
+
299
+ super().__init__(*args, **kwargs)
300
+
301
+ def invoke(self, ctx: click.Context):
302
+ obj: CLIConfig = common.initialize_config(
303
+ ctx,
304
+ self.run_args.project,
305
+ self.run_args.domain,
306
+ self.run_args.root_dir,
307
+ tuple(self.run_args.image) or None,
308
+ not self.run_args.no_sync_local_sys_paths,
309
+ )
310
+
311
+ async def _run():
312
+ import flyte.remote
313
+
314
+ task = flyte.remote.Task.get(self.task_name, version=self.version, auto_version="latest")
315
+ console = common.get_console()
316
+
317
+ r = await flyte.with_runcontext(
318
+ copy_style=self.run_args.copy_style,
319
+ mode="local" if self.run_args.local else "remote",
320
+ name=self.run_args.name,
321
+ ).run.aio(task, **ctx.params)
322
+ if isinstance(r, Run) and r.action is not None:
323
+ console.print(
324
+ common.get_panel(
325
+ "Run",
326
+ f"[green bold]Created Run: {r.name} [/green bold] "
327
+ f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n"
328
+ f"➡️ [blue bold][link={r.url}]{r.url}[/link][/blue bold]",
329
+ obj.output_format,
330
+ )
331
+ )
332
+ if self.run_args.follow:
333
+ console.print(
334
+ "[dim]Log streaming enabled, will wait for task to start running "
335
+ "and log stream to be available[/dim]"
336
+ )
337
+ await r.show_logs.aio(max_lines=30, show_ts=True, raw=False)
338
+
339
+ asyncio.run(_run())
340
+
341
+ def get_params(self, ctx: click.Context) -> List[click.Parameter]:
342
+ # Note this function may be called multiple times by click.
343
+ import flyte.remote
344
+ from flyte._internal.runtime.types_serde import transform_native_to_typed_interface
345
+
346
+ common.initialize_config(
347
+ ctx,
348
+ self.run_args.project,
349
+ self.run_args.domain,
350
+ sync_local_sys_paths=not self.run_args.no_sync_local_sys_paths,
351
+ )
352
+
353
+ task = flyte.remote.Task.get(self.task_name, auto_version="latest")
354
+ task_details = task.fetch()
355
+
356
+ interface = transform_native_to_typed_interface(task_details.interface)
357
+ if interface is None:
358
+ return super().get_params(ctx)
359
+ inputs_interface = task_details.interface.inputs
360
+
361
+ params: List[click.Parameter] = []
362
+ for name, var in interface.inputs.variables.items():
363
+ default_val = None
364
+ if inputs_interface[name][1] is not inspect._empty:
365
+ default_val = inputs_interface[name][1]
366
+ params.append(to_click_option(name, var, inputs_interface[name][0], default_val))
367
+
368
+ self.params = params
369
+ return super().get_params(ctx)
370
+
371
+
372
+ class ReferenceEnvGroup(common.GroupBase):
373
+ def __init__(self, name: str, *args, run_args, env: str, **kwargs):
374
+ super().__init__(*args, **kwargs)
375
+ self.name = name
376
+ self.env = env
377
+ self.run_args = run_args
378
+
379
+ def list_commands(self, ctx):
380
+ return _list_tasks(ctx, self.run_args.project, self.run_args.domain, by_task_env=self.env)
381
+
382
+ def get_command(self, ctx, name):
383
+ return RunReferenceTaskCommand(
384
+ task_name=name,
385
+ run_args=self.run_args,
386
+ name=name,
387
+ version=None,
388
+ help=f"Run deployed task '{name}' from the Flyte backend",
389
+ )
390
+
391
+
392
+ class ReferenceTaskGroup(common.GroupBase):
393
+ """
394
+ Group that creates a command for each reference task in the current directory that is not __init__.py.
395
+ """
396
+
397
+ def __init__(self, name: str, *args, run_args, tasks: list[str] | None = None, **kwargs):
398
+ super().__init__(*args, **kwargs)
399
+ self.name = name
400
+ self.run_args = run_args
401
+
402
+ def list_commands(self, ctx):
403
+ # list envs of all reference tasks
404
+ envs = []
405
+ for task in _list_tasks(ctx, self.run_args.project, self.run_args.domain):
406
+ env = task.split(".")[0]
407
+ if env not in envs:
408
+ envs.append(env)
409
+ return envs
410
+
411
+ @staticmethod
412
+ def _parse_task_name(task_name: str) -> tuple[str, str | None, str | None]:
413
+ import re
414
+
415
+ pattern = r"^([^.:]+)(?:\.([^:]+))?(?::(.+))?$"
416
+ match = re.match(pattern, task_name)
417
+ if not match:
418
+ raise click.BadParameter(f"Invalid task name format: {task_name}")
419
+ return match.group(1), match.group(2), match.group(3)
420
+
421
+ def _env_is_task(self, ctx: click.Context, env: str) -> bool:
422
+ # check if the env name is the full task name, since sometimes task
423
+ # names don't have an environment prefix
424
+ tasks = [*_list_tasks(ctx, self.run_args.project, self.run_args.domain, by_task_name=env)]
425
+ return len(tasks) > 0
426
+
427
+ def get_command(self, ctx, name):
428
+ env, task, version = self._parse_task_name(name)
429
+ match env, task, version:
430
+ case env, None, None:
431
+ if self._env_is_task(ctx, env):
432
+ # this handles cases where task names do not have a environment prefix
433
+ task_name = env
434
+ return RunReferenceTaskCommand(
435
+ task_name=task_name,
436
+ run_args=self.run_args,
437
+ name=task_name,
438
+ version=None,
439
+ help=f"Run reference task `{task_name}` from the Flyte backend",
440
+ )
441
+ else:
442
+ return ReferenceEnvGroup(
443
+ name=name,
444
+ run_args=self.run_args,
445
+ env=env,
446
+ help=f"Run reference tasks in the `{env}` environment from the Flyte backend",
447
+ )
448
+ case env, task, None:
449
+ task_name = f"{env}.{task}"
450
+ return RunReferenceTaskCommand(
451
+ task_name=task_name,
452
+ run_args=self.run_args,
453
+ name=task_name,
454
+ version=None,
455
+ help=f"Run reference task '{task_name}' from the Flyte backend",
456
+ )
457
+ case env, task, version:
458
+ task_name = f"{env}.{task}"
459
+ return RunReferenceTaskCommand(
460
+ task_name=task_name,
461
+ run_args=self.run_args,
462
+ version=version,
463
+ name=f"{task_name}:{version}",
464
+ help=f"Run reference task '{task_name}' from the Flyte backend",
465
+ )
466
+ case _:
467
+ raise click.BadParameter(f"Invalid task name format: {task_name}")
468
+
469
+
470
+ class TaskFiles(common.FileGroup):
471
+ """
472
+ Group that creates a command for each file in the current directory that is not __init__.py.
473
+ """
474
+
475
+ common_options_enabled = False
476
+
477
+ def __init__(
478
+ self,
479
+ *args,
480
+ directory: Path | None = None,
481
+ **kwargs,
482
+ ):
483
+ if "params" not in kwargs:
484
+ kwargs["params"] = []
485
+ kwargs["params"].extend(RunArguments.options())
486
+ super().__init__(*args, directory=directory, **kwargs)
487
+
488
+ def list_commands(self, ctx):
489
+ v = [
490
+ RUN_REMOTE_CMD,
491
+ *super().list_commands(ctx),
492
+ ]
493
+ return v
494
+
495
+ def get_command(self, ctx, cmd_name):
496
+ run_args = RunArguments.from_dict(ctx.params)
497
+ if cmd_name == RUN_REMOTE_CMD:
498
+ return ReferenceTaskGroup(
499
+ name=cmd_name,
500
+ run_args=run_args,
501
+ help="Run reference task from the Flyte backend",
502
+ )
503
+
504
+ fp = Path(cmd_name)
505
+ if not fp.exists():
506
+ raise click.BadParameter(f"File {cmd_name} does not exist")
507
+ if fp.is_dir():
508
+ return TaskFiles(
509
+ directory=fp,
510
+ help=f"Run `*.py` file inside the {fp} directory",
511
+ )
512
+ return TaskPerFileGroup(
513
+ filename=fp,
514
+ run_args=run_args,
515
+ name=cmd_name,
516
+ help=f"Run functions decorated with `env.task` in {cmd_name}",
517
+ )
518
+
519
+
520
+ run = TaskFiles(
521
+ name="run",
522
+ help=f"""
523
+ Run a task from a python file or deployed task.
524
+
525
+ To run a remote task that already exists in Flyte, use the {RUN_REMOTE_CMD} command:
526
+
527
+ Example usage:
528
+
529
+ ```bash
530
+ flyte run --project my-project --domain development hello.py my_task --arg1 value1 --arg2 value2
531
+ ```
532
+
533
+ Arguments to the run command are provided right after the `run` command and before the file name.
534
+ For example, the command above specifies the project and domain.
535
+
536
+ To run a task locally, use the `--local` flag. This will run the task in the local environment instead of the remote
537
+ Flyte environment:
538
+
539
+ ```bash
540
+ flyte run --local hello.py my_task --arg1 value1 --arg2 value2
541
+ ```
542
+
543
+ You can provide image mappings with `--image` flag. This allows you to specify
544
+ the image URI for the task environment during CLI execution without changing
545
+ the code. Any images defined with `Image.from_ref_name("name")` will resolve to the
546
+ corresponding URIs you specify here.
547
+
548
+ ```bash
549
+ flyte run hello.py my_task --image my_image=ghcr.io/myorg/my-image:v1.0
550
+ ```
551
+
552
+ If the image name is not provided, it is regarded as a default image and will
553
+ be used when no image is specified in TaskEnvironment:
554
+
555
+ ```bash
556
+ flyte run hello.py my_task --image ghcr.io/myorg/default-image:latest
557
+ ```
558
+
559
+ You can specify multiple image arguments:
560
+
561
+ ```bash
562
+ flyte run hello.py my_task --image ghcr.io/org/default:latest --image gpu=ghcr.io/org/gpu:v2.0
563
+ ```
564
+
565
+ To run tasks that you've already deployed to Flyte, use the {RUN_REMOTE_CMD} command:
566
+
567
+ ```bash
568
+ flyte run {RUN_REMOTE_CMD} my_env.my_task --arg1 value1 --arg2 value2
569
+ ```
570
+
571
+ To run a specific version of a deployed task, use the `env.task:version` syntax:
572
+
573
+ ```bash
574
+ flyte run {RUN_REMOTE_CMD} my_env.my_task:xyz123 --arg1 value1 --arg2 value2
575
+ ```
576
+
577
+ You can specify the `--config` flag to point to a specific Flyte cluster:
578
+
579
+ ```bash
580
+ flyte run --config my-config.yaml {RUN_REMOTE_CMD} ...
581
+ ```
582
+
583
+ You can discover what deployed tasks are available by running:
584
+
585
+ ```bash
586
+ flyte run {RUN_REMOTE_CMD}
587
+ ```
588
+
589
+ Other arguments to the run command are listed below.
590
+
591
+ Arguments for the task itself are provided after the task name and can be retrieved using `--help`. For example:
592
+
593
+ ```bash
594
+ flyte run hello.py my_task --help
595
+ ```
596
+ """,
597
+ )
flyte/cli/_serve.py ADDED
@@ -0,0 +1,64 @@
1
+ from typing import List
2
+
3
+ import click
4
+
5
+
6
+ @click.group("serve")
7
+ @click.pass_context
8
+ def serve(_: click.Context):
9
+ """
10
+ Start the specific service. For example:
11
+
12
+ ```bash
13
+ flyte serve connector
14
+ ```
15
+ """
16
+
17
+
18
+ @serve.command()
19
+ @click.option(
20
+ "--port",
21
+ default="8000",
22
+ is_flag=False,
23
+ type=int,
24
+ help="Grpc port for the connector service",
25
+ )
26
+ @click.option(
27
+ "--prometheus_port",
28
+ default="9090",
29
+ is_flag=False,
30
+ type=int,
31
+ help="Prometheus port for the connector service",
32
+ )
33
+ @click.option(
34
+ "--worker",
35
+ default="10",
36
+ is_flag=False,
37
+ type=int,
38
+ help="Number of workers for the grpc server",
39
+ )
40
+ @click.option(
41
+ "--timeout",
42
+ default=None,
43
+ is_flag=False,
44
+ type=int,
45
+ help="It will wait for the specified number of seconds before shutting down grpc server. It should only be used "
46
+ "for testing.",
47
+ )
48
+ @click.option(
49
+ "--modules",
50
+ required=False,
51
+ multiple=True,
52
+ type=str,
53
+ help="List of additional files or module that defines the connector",
54
+ )
55
+ @click.pass_context
56
+ def connector(
57
+ _: click.Context, port: int, prometheus_port: int, worker: int, timeout: int | None, modules: List[str] | None
58
+ ):
59
+ """
60
+ Start a grpc server for the connector service.
61
+ """
62
+ from flyte.connectors import ConnectorService
63
+
64
+ ConnectorService.run(port, prometheus_port, worker, timeout, modules)
flyte/cli/_update.py ADDED
@@ -0,0 +1,37 @@
1
+ import rich_click as click
2
+
3
+ import flyte.remote as remote
4
+
5
+ from . import _common as common
6
+
7
+
8
+ @click.group(name="update")
9
+ def update():
10
+ """
11
+ Update various flyte entities.
12
+ """
13
+
14
+
15
+ @update.command("trigger", cls=common.CommandBase)
16
+ @click.argument("name", type=str)
17
+ @click.argument("task_name", type=str)
18
+ @click.option("--activate/--deactivate", required=True, help="Activate or deactivate the trigger.")
19
+ @click.pass_obj
20
+ def trigger(cfg: common.CLIConfig, name: str, task_name: str, activate: bool, project: str | None, domain: str | None):
21
+ """
22
+ Update a trigger.
23
+
24
+ \b
25
+ Example usage:
26
+
27
+ ```bash
28
+ flyte update trigger <trigger_name> <task_name> --activate | --deactivate
29
+ [--project <project_name> --domain <domain_name>]
30
+ ```
31
+ """
32
+ cfg.init(project, domain)
33
+ console = common.get_console()
34
+ to_state = "active" if activate else "deactivate"
35
+ with console.status(f"Updating trigger {name} for task {task_name} to {to_state}..."):
36
+ remote.Trigger.update(name, task_name, activate)
37
+ console.print(f"Trigger updated and is set to [fuchsia]{to_state}[/fuchsia]")