flyte 2.0.0b21__py3-none-any.whl → 2.0.0b23__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 (92) hide show
  1. flyte/__init__.py +5 -0
  2. flyte/_bin/runtime.py +36 -6
  3. flyte/_cache/cache.py +4 -2
  4. flyte/_cache/local_cache.py +215 -0
  5. flyte/_code_bundle/bundle.py +1 -0
  6. flyte/_debug/constants.py +0 -1
  7. flyte/_debug/vscode.py +6 -1
  8. flyte/_deploy.py +204 -55
  9. flyte/_environment.py +5 -0
  10. flyte/_excepthook.py +1 -1
  11. flyte/_image.py +101 -68
  12. flyte/_initialize.py +30 -1
  13. flyte/_interface.py +3 -1
  14. flyte/_internal/controllers/_local_controller.py +64 -24
  15. flyte/_internal/controllers/remote/_action.py +4 -1
  16. flyte/_internal/controllers/remote/_controller.py +5 -2
  17. flyte/_internal/controllers/remote/_core.py +6 -3
  18. flyte/_internal/controllers/remote/_informer.py +1 -1
  19. flyte/_internal/imagebuild/docker_builder.py +95 -28
  20. flyte/_internal/imagebuild/image_builder.py +0 -5
  21. flyte/_internal/imagebuild/remote_builder.py +6 -1
  22. flyte/_internal/runtime/io.py +13 -1
  23. flyte/_internal/runtime/rusty.py +17 -2
  24. flyte/_internal/runtime/task_serde.py +15 -11
  25. flyte/_internal/runtime/taskrunner.py +1 -1
  26. flyte/_internal/runtime/trigger_serde.py +153 -0
  27. flyte/_keyring/file.py +2 -2
  28. flyte/_logging.py +1 -1
  29. flyte/_protos/common/identifier_pb2.py +19 -1
  30. flyte/_protos/common/identifier_pb2.pyi +22 -0
  31. flyte/_protos/workflow/common_pb2.py +14 -3
  32. flyte/_protos/workflow/common_pb2.pyi +49 -0
  33. flyte/_protos/workflow/queue_service_pb2.py +41 -35
  34. flyte/_protos/workflow/queue_service_pb2.pyi +26 -12
  35. flyte/_protos/workflow/queue_service_pb2_grpc.py +34 -0
  36. flyte/_protos/workflow/run_definition_pb2.py +38 -38
  37. flyte/_protos/workflow/run_definition_pb2.pyi +4 -2
  38. flyte/_protos/workflow/run_service_pb2.py +60 -50
  39. flyte/_protos/workflow/run_service_pb2.pyi +24 -6
  40. flyte/_protos/workflow/run_service_pb2_grpc.py +34 -0
  41. flyte/_protos/workflow/task_definition_pb2.py +15 -11
  42. flyte/_protos/workflow/task_definition_pb2.pyi +19 -2
  43. flyte/_protos/workflow/task_service_pb2.py +18 -17
  44. flyte/_protos/workflow/task_service_pb2.pyi +5 -2
  45. flyte/_protos/workflow/trigger_definition_pb2.py +66 -0
  46. flyte/_protos/workflow/trigger_definition_pb2.pyi +117 -0
  47. flyte/_protos/workflow/trigger_definition_pb2_grpc.py +4 -0
  48. flyte/_protos/workflow/trigger_service_pb2.py +96 -0
  49. flyte/_protos/workflow/trigger_service_pb2.pyi +110 -0
  50. flyte/_protos/workflow/trigger_service_pb2_grpc.py +281 -0
  51. flyte/_run.py +42 -15
  52. flyte/_task.py +35 -4
  53. flyte/_task_environment.py +61 -16
  54. flyte/_trigger.py +382 -0
  55. flyte/_version.py +3 -3
  56. flyte/cli/_abort.py +3 -3
  57. flyte/cli/_build.py +1 -3
  58. flyte/cli/_common.py +17 -4
  59. flyte/cli/_create.py +74 -0
  60. flyte/cli/_delete.py +23 -1
  61. flyte/cli/_deploy.py +16 -10
  62. flyte/cli/_get.py +75 -34
  63. flyte/cli/_params.py +4 -2
  64. flyte/cli/_run.py +25 -6
  65. flyte/cli/_update.py +36 -0
  66. flyte/cli/_user.py +17 -0
  67. flyte/cli/main.py +9 -1
  68. flyte/errors.py +9 -0
  69. flyte/io/_dir.py +513 -115
  70. flyte/io/_file.py +495 -135
  71. flyte/models.py +32 -0
  72. flyte/remote/__init__.py +6 -1
  73. flyte/remote/_action.py +9 -8
  74. flyte/remote/_client/_protocols.py +36 -2
  75. flyte/remote/_client/controlplane.py +19 -3
  76. flyte/remote/_run.py +42 -2
  77. flyte/remote/_task.py +14 -1
  78. flyte/remote/_trigger.py +308 -0
  79. flyte/remote/_user.py +33 -0
  80. flyte/storage/__init__.py +6 -1
  81. flyte/storage/_storage.py +119 -101
  82. flyte/types/_pickle.py +34 -7
  83. flyte/types/_type_engine.py +6 -0
  84. {flyte-2.0.0b21.data → flyte-2.0.0b23.data}/scripts/runtime.py +36 -6
  85. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/METADATA +3 -1
  86. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/RECORD +91 -79
  87. flyte/_protos/secret/secret_pb2_grpc_grpc.py +0 -198
  88. {flyte-2.0.0b21.data → flyte-2.0.0b23.data}/scripts/debug.py +0 -0
  89. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/WHEEL +0 -0
  90. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/entry_points.txt +0 -0
  91. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/licenses/LICENSE +0 -0
  92. {flyte-2.0.0b21.dist-info → flyte-2.0.0b23.dist-info}/top_level.txt +0 -0
flyte/_trigger.py ADDED
@@ -0,0 +1,382 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Any, Dict, Mapping, Union
6
+
7
+ import rich.repr
8
+
9
+
10
+ class _trigger_time:
11
+ """
12
+ This class represents the actual time of Trigger, which can be bound to any task input.
13
+ """
14
+
15
+
16
+ TriggerTime = _trigger_time()
17
+
18
+
19
+ @rich.repr.auto
20
+ @dataclass(frozen=True)
21
+ class Cron:
22
+ """
23
+ This class defines a Cron automation that can be associated with a Trigger in Flyte.
24
+ Example usage:
25
+ ```python
26
+ from flyte.trigger import Trigger, Cron
27
+ my_trigger = Trigger(
28
+ name="my_cron_trigger",
29
+ automation=Cron("0 * * * *"), # Runs every hour
30
+ description="A trigger that runs every hour",
31
+ )
32
+ ```
33
+ """
34
+
35
+ expression: str
36
+
37
+ def __str__(self):
38
+ return f"Cron Trigger: {self.expression}"
39
+
40
+
41
+ @rich.repr.auto
42
+ @dataclass(frozen=True)
43
+ class FixedRate:
44
+ """
45
+ This class defines a FixedRate automation that can be associated with a Trigger in Flyte.
46
+ Example usage:
47
+ ```python
48
+ from flyte.trigger import Trigger, FixedRate
49
+ my_trigger = Trigger(
50
+ name="my_fixed_rate_trigger",
51
+ automation=FixedRate(60), # Runs every hour
52
+ description="A trigger that runs every hour",
53
+ )
54
+ ```
55
+ """
56
+
57
+ interval_minutes: int
58
+ start_time: datetime | None = None
59
+
60
+ def __str__(self):
61
+ return f"FixedRate Trigger: every {self.interval_minutes} minutes"
62
+
63
+
64
+ @rich.repr.auto
65
+ @dataclass(frozen=True)
66
+ class Trigger:
67
+ """
68
+ This class defines specification of a Trigger, that can be associated with any Flyte V2 task.
69
+ The trigger then is deployed to the Flyte Platform.
70
+
71
+ Triggers can be used to run tasks on a schedule, in response to events, or based on other conditions.
72
+ The `Trigger` class encapsulates the metadata and configuration needed to define a trigger.
73
+
74
+ You can associate the same Trigger object with multiple tasks.
75
+
76
+ Example usage:
77
+ ```python
78
+ from flyte.trigger import Trigger
79
+ my_trigger = Trigger(
80
+ name="my_trigger",
81
+ description="A trigger that runs every hour",
82
+ )
83
+ ```
84
+
85
+ :param name: (str) The name of the trigger.
86
+ :param automation: (AutomationType) The automation type, currently only supports Cron.
87
+ :param description: (str) A description of the trigger, default is an empty string.
88
+ :param auto_activate: (bool) Whether the trigger should be automatically activated, default is True.
89
+ :param inputs: (Dict[str, Any]) Optional inputs for the trigger, default is None. If provided, will replace the
90
+ values for inputs to these defaults.
91
+ :param env_vars: (Dict[str, str]) Optional environment variables for the trigger, default is None. If provided, will
92
+ replace the environment variables set in the config of the task.
93
+ :param interruptible: (bool) Whether the trigger is interruptible, default is None. If provided,
94
+ it overrides whatever is set in the config of the task.
95
+ :param overwrite_cache: (bool) Whether to overwrite the cache, default is False.
96
+ :param queue: (str) Optional queue to run the trigger in, default is None.
97
+ :param labels: (Mapping[str, str]) Optional labels to attach to the trigger, default is None.
98
+ :param annotations: (Mapping[str, str]) Optional annotations to attach to the trigger, default is None.
99
+ """
100
+
101
+ name: str
102
+ automation: Union[Cron, FixedRate]
103
+ description: str = ""
104
+ auto_activate: bool = True
105
+ inputs: Dict[str, Any] | None = None
106
+ env_vars: Dict[str, str] | None = None
107
+ interruptible: bool | None = None
108
+ overwrite_cache: bool = False
109
+ queue: str | None = None
110
+ labels: Mapping[str, str] | None = None
111
+ annotations: Mapping[str, str] | None = None
112
+
113
+ def __post_init__(self):
114
+ if not self.name:
115
+ raise ValueError("Trigger name cannot be empty")
116
+ if self.automation is None:
117
+ raise ValueError("Automation cannot be None")
118
+
119
+ @classmethod
120
+ def daily(
121
+ cls,
122
+ trigger_time_input_key: str = "trigger_time",
123
+ *,
124
+ name: str = "daily",
125
+ description: str = "A trigger that runs daily at midnight",
126
+ auto_activate: bool = True,
127
+ inputs: Dict[str, Any] | None = None,
128
+ env_vars: Dict[str, str] | None = None,
129
+ interruptible: bool | None = None,
130
+ overwrite_cache: bool = False,
131
+ queue: str | None = None,
132
+ labels: Mapping[str, str] | None = None,
133
+ annotations: Mapping[str, str] | None = None,
134
+ ) -> Trigger:
135
+ """
136
+ Creates a Cron trigger that runs daily at midnight.
137
+
138
+ Args:
139
+ trigger_time_input_key (str): The input key for the trigger time, default is "trigger_time".
140
+ name (str): The name of the trigger, default is "daily".
141
+ description (str): A description of the trigger.
142
+ auto_activate (bool): Whether the trigger should be automatically activated.
143
+ inputs (Dict[str, Any] | None): Optional inputs for the trigger.
144
+ env_vars (Dict[str, str] | None): Optional environment variables.
145
+ interruptible (bool | None): Whether the trigger is interruptible.
146
+ overwrite_cache (bool): Whether to overwrite the cache.
147
+ queue (str | None): Optional queue to run the trigger in.
148
+ labels (Mapping[str, str] | None): Optional labels to attach to the trigger.
149
+ annotations (Mapping[str, str] | None): Optional annotations to attach to the trigger.
150
+
151
+ Returns:
152
+ Trigger: A trigger that runs daily at midnight.
153
+ """
154
+ final_inputs = {trigger_time_input_key: TriggerTime}
155
+ if inputs:
156
+ final_inputs.update(inputs)
157
+
158
+ return cls(
159
+ name=name,
160
+ automation=Cron("0 0 * * *"), # Cron expression for daily at midnight
161
+ description=description,
162
+ auto_activate=auto_activate,
163
+ inputs=final_inputs,
164
+ env_vars=env_vars,
165
+ interruptible=interruptible,
166
+ overwrite_cache=overwrite_cache,
167
+ queue=queue,
168
+ labels=labels,
169
+ annotations=annotations,
170
+ )
171
+
172
+ @classmethod
173
+ def hourly(
174
+ cls,
175
+ trigger_time_input_key: str = "trigger_time",
176
+ *,
177
+ name: str = "hourly",
178
+ description: str = "A trigger that runs every hour",
179
+ auto_activate: bool = True,
180
+ inputs: Dict[str, Any] | None = None,
181
+ env_vars: Dict[str, str] | None = None,
182
+ interruptible: bool | None = None,
183
+ overwrite_cache: bool = False,
184
+ queue: str | None = None,
185
+ labels: Mapping[str, str] | None = None,
186
+ annotations: Mapping[str, str] | None = None,
187
+ ) -> Trigger:
188
+ """
189
+ Creates a Cron trigger that runs every hour.
190
+
191
+ Args:
192
+ trigger_time_input_key (str): The input parameter for the trigger time, default is "trigger_time".
193
+ name (str): The name of the trigger, default is "hourly".
194
+ description (str): A description of the trigger.
195
+ auto_activate (bool): Whether the trigger should be automatically activated.
196
+ inputs (Dict[str, Any] | None): Optional inputs for the trigger.
197
+ env_vars (Dict[str, str] | None): Optional environment variables.
198
+ interruptible (bool | None): Whether the trigger is interruptible.
199
+ overwrite_cache (bool): Whether to overwrite the cache.
200
+ queue (str | None): Optional queue to run the trigger in.
201
+ labels (Mapping[str, str] | None): Optional labels to attach to the trigger.
202
+ annotations (Mapping[str, str] | None): Optional annotations to attach to the trigger.
203
+
204
+ Returns:
205
+ Trigger: A trigger that runs every hour, on the hour.
206
+ """
207
+ final_inputs = {trigger_time_input_key: TriggerTime}
208
+ if inputs:
209
+ final_inputs.update(inputs)
210
+
211
+ return cls(
212
+ name=name,
213
+ automation=Cron("0 * * * *"), # Cron expression for every hour
214
+ description=description,
215
+ auto_activate=auto_activate,
216
+ inputs=final_inputs,
217
+ env_vars=env_vars,
218
+ interruptible=interruptible,
219
+ overwrite_cache=overwrite_cache,
220
+ queue=queue,
221
+ labels=labels,
222
+ annotations=annotations,
223
+ )
224
+
225
+ @classmethod
226
+ def minutely(
227
+ cls,
228
+ trigger_time_input_key: str = "trigger_time",
229
+ *,
230
+ name: str = "minutely",
231
+ description: str = "A trigger that runs every minute",
232
+ auto_activate: bool = True,
233
+ inputs: Dict[str, Any] | None = None,
234
+ env_vars: Dict[str, str] | None = None,
235
+ interruptible: bool | None = None,
236
+ overwrite_cache: bool = False,
237
+ queue: str | None = None,
238
+ labels: Mapping[str, str] | None = None,
239
+ annotations: Mapping[str, str] | None = None,
240
+ ) -> Trigger:
241
+ """
242
+ Creates a Cron trigger that runs every minute.
243
+
244
+ Args:
245
+ trigger_time_input_key (str): The input parameter for the trigger time, default is "trigger_time".
246
+ name (str): The name of the trigger, default is "every_minute".
247
+ description (str): A description of the trigger.
248
+ auto_activate (bool): Whether the trigger should be automatically activated.
249
+ inputs (Dict[str, Any] | None): Optional inputs for the trigger.
250
+ env_vars (Dict[str, str] | None): Optional environment variables.
251
+ interruptible (bool | None): Whether the trigger is interruptible.
252
+ overwrite_cache (bool): Whether to overwrite the cache.
253
+ queue (str | None): Optional queue to run the trigger in.
254
+ labels (Mapping[str, str] | None): Optional labels to attach to the trigger.
255
+ annotations (Mapping[str, str] | None): Optional annotations to attach to the trigger.
256
+
257
+ Returns:
258
+ Trigger: A trigger that runs every minute.
259
+ """
260
+ final_inputs = {trigger_time_input_key: TriggerTime}
261
+ if inputs:
262
+ final_inputs.update(inputs)
263
+
264
+ return cls(
265
+ name=name,
266
+ automation=Cron("* * * * *"), # Cron expression for every minute
267
+ description=description,
268
+ auto_activate=auto_activate,
269
+ inputs=final_inputs,
270
+ env_vars=env_vars,
271
+ interruptible=interruptible,
272
+ overwrite_cache=overwrite_cache,
273
+ queue=queue,
274
+ labels=labels,
275
+ annotations=annotations,
276
+ )
277
+
278
+ @classmethod
279
+ def weekly(
280
+ cls,
281
+ trigger_time_input_key: str = "trigger_time",
282
+ *,
283
+ name: str = "weekly",
284
+ description: str = "A trigger that runs weekly on Sundays at midnight",
285
+ auto_activate: bool = True,
286
+ inputs: Dict[str, Any] | None = None,
287
+ env_vars: Dict[str, str] | None = None,
288
+ interruptible: bool | None = None,
289
+ overwrite_cache: bool = False,
290
+ queue: str | None = None,
291
+ labels: Mapping[str, str] | None = None,
292
+ annotations: Mapping[str, str] | None = None,
293
+ ) -> Trigger:
294
+ """
295
+ Creates a Cron trigger that runs weekly on Sundays at midnight.
296
+
297
+ Args:
298
+ trigger_time_input_key (str): The input parameter for the trigger time, default is "trigger_time".
299
+ name (str): The name of the trigger, default is "weekly".
300
+ description (str): A description of the trigger.
301
+ auto_activate (bool): Whether the trigger should be automatically activated.
302
+ inputs (Dict[str, Any] | None): Optional inputs for the trigger.
303
+ env_vars (Dict[str, str] | None): Optional environment variables.
304
+ interruptible (bool | None): Whether the trigger is interruptible.
305
+ overwrite_cache (bool): Whether to overwrite the cache.
306
+ queue (str | None): Optional queue to run the trigger in.
307
+ labels (Mapping[str, str] | None): Optional labels to attach to the trigger.
308
+ annotations (Mapping[str, str] | None): Optional annotations to attach to the trigger.
309
+
310
+ Returns:
311
+ Trigger: A trigger that runs weekly on Sundays at midnight.
312
+ """
313
+ final_inputs = {trigger_time_input_key: TriggerTime}
314
+ if inputs:
315
+ final_inputs.update(inputs)
316
+
317
+ return cls(
318
+ name=name,
319
+ automation=Cron("0 0 * * 0"), # Cron expression for every Sunday at midnight
320
+ description=description,
321
+ auto_activate=auto_activate,
322
+ inputs=final_inputs,
323
+ env_vars=env_vars,
324
+ interruptible=interruptible,
325
+ overwrite_cache=overwrite_cache,
326
+ queue=queue,
327
+ labels=labels,
328
+ annotations=annotations,
329
+ )
330
+
331
+ @classmethod
332
+ def monthly(
333
+ cls,
334
+ trigger_time_input_key: str = "trigger_time",
335
+ *,
336
+ name: str = "monthly",
337
+ description: str = "A trigger that runs monthly on the 1st at midnight",
338
+ auto_activate: bool = True,
339
+ inputs: Dict[str, Any] | None = None,
340
+ env_vars: Dict[str, str] | None = None,
341
+ interruptible: bool | None = None,
342
+ overwrite_cache: bool = False,
343
+ queue: str | None = None,
344
+ labels: Mapping[str, str] | None = None,
345
+ annotations: Mapping[str, str] | None = None,
346
+ ) -> Trigger:
347
+ """
348
+ Creates a Cron trigger that runs monthly on the 1st at midnight.
349
+
350
+ Args:
351
+ trigger_time_input_key (str): The input parameter for the trigger time, default is "trigger_time".
352
+ name (str): The name of the trigger, default is "monthly".
353
+ description (str): A description of the trigger.
354
+ auto_activate (bool): Whether the trigger should be automatically activated.
355
+ inputs (Dict[str, Any] | None): Optional inputs for the trigger.
356
+ env_vars (Dict[str, str] | None): Optional environment variables.
357
+ interruptible (bool | None): Whether the trigger is interruptible.
358
+ overwrite_cache (bool): Whether to overwrite the cache.
359
+ queue (str | None): Optional queue to run the trigger in.
360
+ labels (Mapping[str, str] | None): Optional labels to attach to the trigger.
361
+ annotations (Mapping[str, str] | None): Optional annotations to attach to the trigger.
362
+
363
+ Returns:
364
+ Trigger: A trigger that runs monthly on the 1st at midnight.
365
+ """
366
+ final_inputs = {trigger_time_input_key: TriggerTime}
367
+ if inputs:
368
+ final_inputs.update(inputs)
369
+
370
+ return cls(
371
+ name=name,
372
+ automation=Cron("0 0 1 * *"), # Cron expression for monthly on the 1st at midnight
373
+ description=description,
374
+ auto_activate=auto_activate,
375
+ inputs=final_inputs,
376
+ env_vars=env_vars,
377
+ interruptible=interruptible,
378
+ overwrite_cache=overwrite_cache,
379
+ queue=queue,
380
+ labels=labels,
381
+ annotations=annotations,
382
+ )
flyte/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2.0.0b21'
32
- __version_tuple__ = version_tuple = (2, 0, 0, 'b21')
31
+ __version__ = version = '2.0.0b23'
32
+ __version_tuple__ = version_tuple = (2, 0, 0, 'b23')
33
33
 
34
- __commit_id__ = commit_id = 'g7f82f6ddd'
34
+ __commit_id__ = commit_id = 'g52dc01de2'
flyte/cli/_abort.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import rich_click as click
2
- from rich.console import Console
3
2
 
4
3
  from flyte.cli import _common as common
5
4
 
@@ -23,6 +22,7 @@ def run(cfg: common.CLIConfig, run_name: str, project: str | None = None, domain
23
22
  cfg.init(project=project, domain=domain)
24
23
  r = Run.get(name=run_name)
25
24
  if r:
26
- console = Console()
27
- r.abort()
25
+ console = common.get_console()
26
+ with console.status(f"Aborting run '{run_name}'...", spinner="dots"):
27
+ r.abort()
28
28
  console.print(f"Run '{run_name}' has been aborted.")
flyte/cli/_build.py CHANGED
@@ -44,9 +44,7 @@ class BuildEnvCommand(click.Command):
44
44
  super().__init__(*args, **kwargs)
45
45
 
46
46
  def invoke(self, ctx: click.Context):
47
- from rich.console import Console
48
-
49
- console = Console()
47
+ console = common.get_console()
50
48
  console.print(f"Building Environment: {self.obj_name}")
51
49
  obj: CLIConfig = ctx.obj
52
50
  obj.init()
flyte/cli/_common.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import importlib.util
4
+ import json
4
5
  import logging
5
6
  import os
6
7
  import sys
@@ -22,7 +23,7 @@ from rich.traceback import Traceback
22
23
  import flyte.errors
23
24
  from flyte.config import Config
24
25
 
25
- OutputFormat = Literal["table", "json", "table-simple"]
26
+ OutputFormat = Literal["table", "json", "table-simple", "json-raw"]
26
27
 
27
28
  PREFERRED_BORDER_COLOR = "dim cyan"
28
29
  PREFERRED_ACCENT_COLOR = "bold #FFD700"
@@ -111,7 +112,7 @@ class CLIConfig:
111
112
  """
112
113
  return replace(self, **kwargs)
113
114
 
114
- def init(self, project: str | None = None, domain: str | None = None):
115
+ def init(self, project: str | None = None, domain: str | None = None, root_dir: str | None = None):
115
116
  from flyte.config._config import TaskConfig
116
117
 
117
118
  task_cfg = TaskConfig(
@@ -131,7 +132,7 @@ class CLIConfig:
131
132
 
132
133
  updated_config = self.config.with_params(platform_cfg, task_cfg)
133
134
 
134
- flyte.init_from_config(updated_config, log_level=self.log_level)
135
+ flyte.init_from_config(updated_config, log_level=self.log_level, root_dir=root_dir)
135
136
 
136
137
 
137
138
  class InvokeBaseMixin:
@@ -177,7 +178,7 @@ class InvokeBaseMixin:
177
178
  except Exception as e:
178
179
  if ctx.obj and ctx.obj.log_level and ctx.obj.log_level <= logging.DEBUG:
179
180
  # If the user has requested verbose output, print the full traceback
180
- console = Console()
181
+ console = get_console()
181
182
  console.print(Traceback.from_exception(type(e), e, e.__traceback__))
182
183
  exit(1)
183
184
  else:
@@ -381,6 +382,11 @@ def format(title: str, vals: Iterable[Any], of: OutputFormat = "table") -> Table
381
382
  if not vals:
382
383
  return pretty_repr([])
383
384
  return pretty_repr([v.to_dict() for v in vals])
385
+ case "json-raw":
386
+ if not vals:
387
+ return []
388
+ return json.dumps([v.to_dict() for v in vals])
389
+
384
390
  raise click.ClickException("Unknown output format. Supported formats are: table, table-simple, json.")
385
391
 
386
392
 
@@ -395,3 +401,10 @@ def get_panel(title: str, renderable: Any, of: OutputFormat = "table") -> Panel:
395
401
  title=f"[{PREFERRED_ACCENT_COLOR}]{title}[/{PREFERRED_ACCENT_COLOR}]",
396
402
  border_style=PREFERRED_BORDER_COLOR,
397
403
  )
404
+
405
+
406
+ def get_console() -> Console:
407
+ """
408
+ Get a console that is configured to use colors if the terminal supports it.
409
+ """
410
+ return Console(color_system="auto", force_terminal=True, width=120)
flyte/cli/_create.py CHANGED
@@ -3,6 +3,7 @@ from typing import Any, Dict, get_args
3
3
 
4
4
  import rich_click as click
5
5
 
6
+ import flyte
6
7
  import flyte.cli._common as common
7
8
  from flyte.cli._option import MutuallyExclusiveOption
8
9
  from flyte.remote import SecretTypes
@@ -194,3 +195,76 @@ def config(
194
195
  yaml.dump(d, f)
195
196
 
196
197
  click.echo(f"Config file written to {output_path}")
198
+
199
+
200
+ @create.command(cls=common.CommandBase)
201
+ @click.argument("task_name", type=str, required=True)
202
+ @click.argument("name", type=str, required=True)
203
+ @click.option(
204
+ "--schedule",
205
+ type=str,
206
+ required=True,
207
+ help="Cron schedule for the trigger. Defaults to every minute.",
208
+ show_default=True,
209
+ )
210
+ @click.option(
211
+ "--description",
212
+ type=str,
213
+ default="",
214
+ help="Description of the trigger.",
215
+ show_default=True,
216
+ )
217
+ @click.option(
218
+ "--auto-activate",
219
+ is_flag=True,
220
+ default=True,
221
+ help="Whether the trigger should not be automatically activated. Defaults to True.",
222
+ show_default=True,
223
+ )
224
+ @click.option(
225
+ "--trigger-time-var",
226
+ type=str,
227
+ default="trigger_time",
228
+ help="Variable name for the trigger time in the task inputs. Defaults to 'trigger_time'.",
229
+ show_default=True,
230
+ )
231
+ @click.pass_obj
232
+ def trigger(
233
+ cfg: common.CLIConfig,
234
+ task_name: str,
235
+ name: str,
236
+ schedule: str,
237
+ trigger_time_var: str = "trigger_time",
238
+ auto_activate: bool = True,
239
+ description: str = "",
240
+ project: str | None = None,
241
+ domain: str | None = None,
242
+ ):
243
+ """
244
+ Create a new trigger for a task. The task name and trigger name are required.
245
+
246
+ Example:
247
+
248
+ ```bash
249
+ $ flyte create trigger my_task my_trigger --schedule "0 0 * * *"
250
+ ```
251
+
252
+ This will create a trigger that runs every day at midnight.
253
+ """
254
+ from flyte.remote import Trigger
255
+
256
+ cfg.init(project, domain)
257
+ console = common.get_console()
258
+
259
+ trigger = flyte.Trigger(
260
+ name=name,
261
+ automation=flyte.Cron(schedule),
262
+ description=description,
263
+ auto_activate=auto_activate,
264
+ inputs={trigger_time_var: flyte.TriggerTime}, # Use the trigger time variable in inputs
265
+ env_vars=None,
266
+ interruptible=None,
267
+ )
268
+ with console.status("Creating trigger..."):
269
+ v = Trigger.create(trigger, task_name=task_name)
270
+ console.print(f"[bold green]Trigger {v.name} created successfully![/bold green]")
flyte/cli/_delete.py CHANGED
@@ -20,4 +20,26 @@ def secret(cfg: common.CLIConfig, name: str, project: str | None = None, domain:
20
20
  from flyte.remote import Secret
21
21
 
22
22
  cfg.init(project, domain)
23
- Secret.delete(name=name)
23
+ console = common.get_console()
24
+ with console.status(f"Deleting secret {name}..."):
25
+ Secret.delete(name=name)
26
+ console.print(f"Successfully deleted secret {name}.")
27
+
28
+
29
+ @delete.command(cls=common.CommandBase)
30
+ @click.argument("name", type=str, required=True)
31
+ @click.argument("task-name", type=str, required=True)
32
+ @click.pass_obj
33
+ def trigger(cfg: common.CLIConfig, name: str, task_name: str, project: str | None = None, domain: str | None = None):
34
+ """
35
+ Delete a trigger. The name of the trigger is required.
36
+ """
37
+ from flyte.remote import Trigger
38
+
39
+ cfg.init(project, domain)
40
+ console = common.get_console()
41
+
42
+ with console.status(f"Deleting trigger {name}..."):
43
+ Trigger.delete(name=name, task_name=task_name)
44
+
45
+ console.log(f"[green]Successfully deleted trigger {name}[/green]")
flyte/cli/_deploy.py CHANGED
@@ -7,8 +7,8 @@ from typing import Any, Dict, List, cast, get_args
7
7
  import rich_click as click
8
8
 
9
9
  import flyte
10
+ from flyte._code_bundle._utils import CopyFiles
10
11
 
11
- from .._code_bundle._utils import CopyFiles
12
12
  from . import _common as common
13
13
  from ._common import CLIConfig
14
14
 
@@ -43,6 +43,16 @@ class DeployArguments:
43
43
  )
44
44
  },
45
45
  )
46
+ root_dir: str | None = field(
47
+ default=None,
48
+ metadata={
49
+ "click.option": click.Option(
50
+ ["--root-dir"],
51
+ type=str,
52
+ help="Override the root source directory, helpful when working with monorepos.",
53
+ )
54
+ },
55
+ )
46
56
  recursive: bool = field(
47
57
  default=False,
48
58
  metadata={
@@ -94,12 +104,10 @@ class DeployEnvCommand(click.RichCommand):
94
104
  super().__init__(*args, **kwargs)
95
105
 
96
106
  def invoke(self, ctx: click.Context):
97
- from rich.console import Console
98
-
99
- console = Console()
107
+ console = common.get_console()
100
108
  console.print(f"Deploying root - environment: {self.env_name}")
101
109
  obj: CLIConfig = ctx.obj
102
- obj.init(self.deploy_args.project, self.deploy_args.domain)
110
+ obj.init(self.deploy_args.project, self.deploy_args.domain, root_dir=self.deploy_args.root_dir)
103
111
  with console.status("Deploying...", spinner="dots"):
104
112
  deployment = flyte.deploy(
105
113
  self.env,
@@ -109,7 +117,7 @@ class DeployEnvCommand(click.RichCommand):
109
117
  )
110
118
 
111
119
  console.print(common.format("Environments", deployment[0].env_repr(), obj.output_format))
112
- console.print(common.format("Tasks", deployment[0].task_repr(), obj.output_format))
120
+ console.print(common.format("Tasks", deployment[0].table_repr(), obj.output_format))
113
121
 
114
122
 
115
123
  class DeployEnvRecursiveCommand(click.Command):
@@ -125,13 +133,11 @@ class DeployEnvRecursiveCommand(click.Command):
125
133
  super().__init__(*args, **kwargs)
126
134
 
127
135
  def invoke(self, ctx: click.Context):
128
- from rich.console import Console
129
-
130
136
  from flyte._environment import list_loaded_environments
131
137
  from flyte._utils import load_python_modules
132
138
 
133
- console = Console()
134
139
  obj: CLIConfig = ctx.obj
140
+ console = common.get_console()
135
141
 
136
142
  # Load all python modules
137
143
  loaded_modules, failed_paths = load_python_modules(self.path, self.deploy_args.recursive)
@@ -167,7 +173,7 @@ class DeployEnvRecursiveCommand(click.Command):
167
173
  console.print(
168
174
  common.format("Environments", [env for d in deployments for env in d.env_repr()], obj.output_format)
169
175
  )
170
- console.print(common.format("Tasks", [task for d in deployments for task in d.task_repr()], obj.output_format))
176
+ console.print(common.format("Tasks", [task for d in deployments for task in d.table_repr()], obj.output_format))
171
177
 
172
178
 
173
179
  class EnvPerFileGroup(common.ObjectsPerFileGroup):