flyte 2.0.0b6__py3-none-any.whl → 2.0.0b7__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.

flyte/_bin/runtime.py CHANGED
@@ -26,7 +26,6 @@ DOMAIN_NAME = "FLYTE_INTERNAL_TASK_DOMAIN"
26
26
  ORG_NAME = "_U_ORG_NAME"
27
27
  ENDPOINT_OVERRIDE = "_U_EP_OVERRIDE"
28
28
  RUN_OUTPUT_BASE_DIR = "_U_RUN_BASE"
29
- ENABLE_REF_TASKS = "_REF_TASKS" # This is a temporary flag to enable reference tasks in the runtime.
30
29
 
31
30
  # TODO: Remove this after proper auth is implemented
32
31
  _UNION_EAGER_API_KEY_ENV_VAR = "_UNION_EAGER_API_KEY"
@@ -87,6 +86,7 @@ def main(
87
86
 
88
87
  import flyte
89
88
  import flyte._utils as utils
89
+ import flyte.errors
90
90
  from flyte._initialize import init
91
91
  from flyte._internal.controllers import create_controller
92
92
  from flyte._internal.imagebuild.image_builder import ImageCache
@@ -123,22 +123,7 @@ def main(
123
123
  logger.debug(f"Using controller endpoint: {ep} with kwargs: {controller_kwargs}")
124
124
 
125
125
  bundle = CodeBundle(tgz=tgz, pkl=pkl, destination=dest, computed_version=version)
126
- enable_ref_tasks = os.getenv(ENABLE_REF_TASKS, "false").lower() in ("true", "1", "yes")
127
- # We init regular client here so that reference tasks can work
128
- # Current reference tasks will not work with remote controller, because we create 2 different
129
- # channels on different threads and this is not supported by grpcio or the auth system. It ends up leading
130
- # File "src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi", line 147,
131
- # in grpc._cython.cygrpc.PollerCompletionQueue._handle_events
132
- # BlockingIOError: [Errno 11] Resource temporarily unavailable
133
- # TODO solution is to use a single channel for both controller and reference tasks, but this requires a refactor
134
- if enable_ref_tasks:
135
- logger.warning(
136
- "Reference tasks are enabled. This will initialize client and you will see a BlockIOError. "
137
- "This is harmless, but a nuisance. We are working on a fix."
138
- )
139
- init(org=org, project=project, domain=domain, **controller_kwargs)
140
- else:
141
- init()
126
+ init(org=org, project=project, domain=domain, **controller_kwargs)
142
127
  # Controller is created with the same kwargs as init, so that it can be used to run tasks
143
128
  controller = create_controller(ct="remote", **controller_kwargs)
144
129
 
@@ -164,6 +149,8 @@ def main(
164
149
 
165
150
  # Run both coroutines concurrently and wait for first to finish and cancel the other
166
151
  async def _run_and_stop():
152
+ loop = asyncio.get_event_loop()
153
+ loop.set_exception_handler(flyte.errors.silence_grpc_polling_error)
167
154
  await utils.run_coros(controller_failure, task_coroutine)
168
155
  await controller.stop()
169
156
 
flyte/_cache/cache.py CHANGED
@@ -21,7 +21,7 @@ from flyte.models import CodeBundle
21
21
  P = ParamSpec("P")
22
22
  FuncOut = TypeVar("FuncOut")
23
23
 
24
- CacheBehavior = Literal["auto", "override", "disable", "enabled"]
24
+ CacheBehavior = Literal["auto", "override", "disable"]
25
25
 
26
26
 
27
27
  @dataclass
flyte/_deploy.py CHANGED
@@ -5,7 +5,6 @@ import typing
5
5
  from dataclasses import dataclass
6
6
  from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
7
7
 
8
- import grpc.aio
9
8
  import rich.repr
10
9
 
11
10
  import flyte.errors
@@ -86,6 +85,8 @@ async def _deploy_task(
86
85
  Deploy the given task.
87
86
  """
88
87
  ensure_client()
88
+ import grpc.aio
89
+
89
90
  from ._internal.runtime.convert import convert_upload_default_inputs
90
91
  from ._internal.runtime.task_serde import translate_task_to_wire
91
92
  from ._protos.workflow import task_definition_pb2, task_service_pb2
@@ -253,6 +253,21 @@ class RemoteController(Controller):
253
253
  await self.cancel_action(action)
254
254
  raise
255
255
 
256
+ # If the action is aborted, we should abort the controller as well
257
+ if n.phase == run_definition_pb2.PHASE_ABORTED:
258
+ logger.warning(f"Action {n.action_id.name} was aborted, aborting current Action{current_action_id.name}")
259
+ raise flyte.errors.RunAbortedError(
260
+ f"Action {n.action_id.name} was aborted, aborting current Action {current_action_id.name}"
261
+ )
262
+
263
+ if n.phase == run_definition_pb2.PHASE_TIMED_OUT:
264
+ logger.warning(
265
+ f"Action {n.action_id.name} timed out, raising timeout exception Action {current_action_id.name}"
266
+ )
267
+ raise flyte.errors.TaskTimeoutError(
268
+ f"Action {n.action_id.name} timed out, raising exception in current Action {current_action_id.name}"
269
+ )
270
+
256
271
  if n.has_error() or n.phase == run_definition_pb2.PHASE_FAILED:
257
272
  exc = await handle_action_failure(action, _task.name)
258
273
  raise exc
@@ -16,7 +16,6 @@ from flyte._protos.workflow import (
16
16
  queue_service_pb2,
17
17
  task_definition_pb2,
18
18
  )
19
- from flyte.errors import RuntimeSystemError
20
19
 
21
20
  from ._action import Action
22
21
  from ._informer import InformerCache
@@ -125,7 +124,7 @@ class Controller:
125
124
  async def watch_for_errors(self):
126
125
  """Watch for errors in the background thread"""
127
126
  await self._run_coroutine_in_controller_thread(self._bg_watch_for_errors())
128
- raise RuntimeSystemError(
127
+ raise flyte.errors.RuntimeSystemError(
129
128
  code="InformerWatchFailure",
130
129
  message=f"Controller thread failed with exception: {self._get_exception()}",
131
130
  )
@@ -164,7 +163,7 @@ class Controller:
164
163
  raise TimeoutError("Controller thread failed to start in time")
165
164
 
166
165
  if self._get_exception():
167
- raise RuntimeSystemError(
166
+ raise flyte.errors.RuntimeSystemError(
168
167
  type(self._get_exception()).__name__,
169
168
  f"Controller thread startup failed: {self._get_exception()}",
170
169
  )
@@ -212,6 +211,7 @@ class Controller:
212
211
  # Create a new event loop for this thread
213
212
  self._loop = asyncio.new_event_loop()
214
213
  asyncio.set_event_loop(self._loop)
214
+ self._loop.set_exception_handler(flyte.errors.silence_grpc_polling_error)
215
215
  logger.debug(f"Controller thread started with new event loop: {threading.current_thread().name}")
216
216
 
217
217
  # Create an event to signal the errors were observed in the thread's loop
@@ -1,4 +1,6 @@
1
+ import asyncio
1
2
  import sys
3
+ import time
2
4
  from typing import Any, List, Tuple
3
5
 
4
6
  from flyte._context import contextual_run
@@ -75,19 +77,23 @@ async def create_controller(
75
77
  :return:
76
78
  """
77
79
  logger.info(f"[rusty] Creating controller with endpoint {endpoint}")
80
+ import flyte.errors
78
81
  from flyte._initialize import init
79
82
 
80
- # TODO Currently refrence tasks are not supported in Rusty.
83
+ loop = asyncio.get_event_loop()
84
+ loop.set_exception_handler(flyte.errors.silence_grpc_polling_error)
85
+
86
+ # TODO Currently reference tasks are not supported in Rusty.
81
87
  await init.aio()
82
88
  controller_kwargs: dict[str, Any] = {"insecure": insecure}
83
89
  if api_key:
84
- logger.info("Using api key from environment")
90
+ logger.info("[rusty] Using api key from environment")
85
91
  controller_kwargs["api_key"] = api_key
86
92
  else:
87
93
  controller_kwargs["endpoint"] = endpoint
88
94
  if "localhost" in endpoint or "docker" in endpoint:
89
95
  controller_kwargs["insecure"] = True
90
- logger.debug(f"Using controller endpoint: {endpoint} with kwargs: {controller_kwargs}")
96
+ logger.debug(f"[rusty] Using controller endpoint: {endpoint} with kwargs: {controller_kwargs}")
91
97
 
92
98
  return _create_controller(ct="remote", **controller_kwargs)
93
99
 
@@ -130,22 +136,39 @@ async def run_task(
130
136
  :param input_path: Optional input path for the task.
131
137
  :return: The loaded task template.
132
138
  """
133
- logger.info(f"[rusty] Running task {task.name}")
134
- await contextual_run(
135
- extract_download_run_upload,
136
- task,
137
- action=ActionID(name=name, org=org, project=project, domain=domain, run_name=run_name),
138
- version=version,
139
- controller=controller,
140
- raw_data_path=RawDataPath(path=raw_data_path),
141
- output_path=output_path,
142
- run_base_dir=run_base_dir,
143
- checkpoints=Checkpoints(prev_checkpoint_path=prev_checkpoint, checkpoint_path=checkpoint_path),
144
- code_bundle=code_bundle,
145
- input_path=input_path,
146
- image_cache=ImageCache.from_transport(image_cache) if image_cache else None,
139
+ start_time = time.time()
140
+ action_id = f"{org}/{project}/{domain}/{run_name}/{name}"
141
+
142
+ logger.info(
143
+ f"[rusty] Running task '{task.name}' (action: {action_id})"
144
+ f" at {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(start_time))}"
147
145
  )
148
- logger.info(f"[rusty] Finished task {task.name}")
146
+
147
+ try:
148
+ await contextual_run(
149
+ extract_download_run_upload,
150
+ task,
151
+ action=ActionID(name=name, org=org, project=project, domain=domain, run_name=run_name),
152
+ version=version,
153
+ controller=controller,
154
+ raw_data_path=RawDataPath(path=raw_data_path),
155
+ output_path=output_path,
156
+ run_base_dir=run_base_dir,
157
+ checkpoints=Checkpoints(prev_checkpoint_path=prev_checkpoint, checkpoint_path=checkpoint_path),
158
+ code_bundle=code_bundle,
159
+ input_path=input_path,
160
+ image_cache=ImageCache.from_transport(image_cache) if image_cache else None,
161
+ )
162
+ except Exception as e:
163
+ logger.error(f"[rusty] Task failed: {e!s}")
164
+ raise
165
+ finally:
166
+ end_time = time.time()
167
+ duration = end_time - start_time
168
+ logger.info(
169
+ f"[rusty] TASK_EXECUTION_END: Task '{task.name}' (action: {action_id})"
170
+ f" done after {duration:.2f}s at {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(end_time))}"
171
+ )
149
172
 
150
173
 
151
174
  async def ping(name: str) -> str:
flyte/_run.py CHANGED
@@ -18,7 +18,6 @@ from flyte._initialize import (
18
18
  requires_storage,
19
19
  )
20
20
  from flyte._logging import logger
21
- from flyte._protos.common import identifier_pb2
22
21
  from flyte._task import P, R, TaskTemplate
23
22
  from flyte._tools import ipython_check
24
23
  from flyte.errors import InitializationError
@@ -411,6 +410,7 @@ class _Runner:
411
410
  async def _run_local(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) -> Run:
412
411
  from flyte._internal.controllers import create_controller
413
412
  from flyte._internal.controllers._local_controller import LocalController
413
+ from flyte._protos.common import identifier_pb2
414
414
  from flyte.remote import Run
415
415
  from flyte.report import Report
416
416
 
@@ -62,7 +62,7 @@ class TaskEnvironment(Environment):
62
62
  :param reusable: Reuse policy for the environment, if set, a python process may be reused for multiple tasks.
63
63
  """
64
64
 
65
- cache: Union[CacheRequest] = "disable"
65
+ cache: CacheRequest = "disable"
66
66
  reusable: ReusePolicy | None = None
67
67
  plugin_config: Optional[Any] = None
68
68
  # TODO Shall we make this union of string or env? This way we can lookup the env by module/file:name
@@ -134,7 +134,7 @@ class TaskEnvironment(Environment):
134
134
  _func=None,
135
135
  *,
136
136
  name: Optional[str] = None,
137
- cache: Union[CacheRequest] | None = None,
137
+ cache: CacheRequest | None = None,
138
138
  retries: Union[int, RetryStrategy] = 0,
139
139
  timeout: Union[timedelta, int] = 0,
140
140
  docs: Optional[Documentation] = None,
flyte/_version.py CHANGED
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '2.0.0b6'
21
- __version_tuple__ = version_tuple = (2, 0, 0, 'b6')
31
+ __version__ = version = '2.0.0b7'
32
+ __version_tuple__ = version_tuple = (2, 0, 0, 'b7')
33
+
34
+ __commit_id__ = commit_id = 'g5cfd1e5ec'
flyte/cli/_build.py CHANGED
@@ -54,7 +54,7 @@ class BuildEnvCommand(click.Command):
54
54
  with console.status("Building...", spinner="dots"):
55
55
  image_cache = flyte.build_images(self.obj)
56
56
 
57
- console.print(common.get_table("Images", image_cache.repr(), simple=obj.simple))
57
+ console.print(common.format("Images", image_cache.repr(), obj.output_format))
58
58
 
59
59
 
60
60
  class EnvPerFileGroup(common.ObjectsPerFileGroup):
flyte/cli/_common.py CHANGED
@@ -8,19 +8,22 @@ from abc import abstractmethod
8
8
  from dataclasses import dataclass, replace
9
9
  from pathlib import Path
10
10
  from types import MappingProxyType, ModuleType
11
- from typing import Any, Dict, Iterable, List, Optional
11
+ from typing import Any, Dict, Iterable, List, Literal, Optional
12
12
 
13
13
  import rich.box
14
14
  import rich.repr
15
15
  import rich_click as click
16
16
  from rich.console import Console
17
17
  from rich.panel import Panel
18
+ from rich.pretty import pretty_repr
18
19
  from rich.table import Table
19
20
  from rich.traceback import Traceback
20
21
 
21
22
  import flyte.errors
22
23
  from flyte.config import Config
23
24
 
25
+ OutputFormat = Literal["table", "json", "table-simple"]
26
+
24
27
  PREFERRED_BORDER_COLOR = "dim cyan"
25
28
  PREFERRED_ACCENT_COLOR = "bold #FFD700"
26
29
  HEADER_STYLE = f"{PREFERRED_ACCENT_COLOR} on black"
@@ -99,8 +102,8 @@ class CLIConfig:
99
102
  endpoint: str | None = None
100
103
  insecure: bool = False
101
104
  org: str | None = None
102
- simple: bool = False
103
105
  auth_type: str | None = None
106
+ output_format: OutputFormat = "table"
104
107
 
105
108
  def replace(self, **kwargs) -> CLIConfig:
106
109
  """
@@ -327,20 +330,7 @@ class FileGroup(GroupBase):
327
330
  raise NotImplementedError
328
331
 
329
332
 
330
- def get_table(title: str, vals: Iterable[Any], simple: bool = False) -> Table:
331
- """
332
- Get a table from a list of values.
333
- """
334
- if simple:
335
- table = Table(title, box=None)
336
- else:
337
- table = Table(
338
- title=title,
339
- box=rich.box.SQUARE_DOUBLE_HEAD,
340
- header_style=HEADER_STYLE,
341
- show_header=True,
342
- border_style=PREFERRED_BORDER_COLOR,
343
- )
333
+ def _table_format(table: Table, vals: Iterable[Any]) -> Table:
344
334
  headers = None
345
335
  has_rich_repr = False
346
336
  for p in vals:
@@ -357,11 +347,37 @@ def get_table(title: str, vals: Iterable[Any], simple: bool = False) -> Table:
357
347
  return table
358
348
 
359
349
 
360
- def get_panel(title: str, renderable: Any, simple: bool = False) -> Panel:
350
+ def format(title: str, vals: Iterable[Any], of: OutputFormat = "table") -> Table | Any:
351
+ """
352
+ Get a table from a list of values.
353
+ """
354
+
355
+ match of:
356
+ case "table-simple":
357
+ return _table_format(Table(title, box=None), vals)
358
+ case "table":
359
+ return _table_format(
360
+ Table(
361
+ title=title,
362
+ box=rich.box.SQUARE_DOUBLE_HEAD,
363
+ header_style=HEADER_STYLE,
364
+ show_header=True,
365
+ border_style=PREFERRED_BORDER_COLOR,
366
+ ),
367
+ vals,
368
+ )
369
+ case "json":
370
+ if not vals:
371
+ return pretty_repr([])
372
+ return pretty_repr([v.to_dict() for v in vals])
373
+ raise click.ClickException("Unknown output format. Supported formats are: table, table-simple, json.")
374
+
375
+
376
+ def get_panel(title: str, renderable: Any, of: OutputFormat = "table") -> Panel:
361
377
  """
362
378
  Get a panel from a list of values.
363
379
  """
364
- if simple:
380
+ if of in ["table-simple", "json"]:
365
381
  return renderable
366
382
  return Panel.fit(
367
383
  renderable,
flyte/cli/_create.py CHANGED
@@ -4,6 +4,7 @@ from typing import Any, Dict, get_args
4
4
  import rich_click as click
5
5
 
6
6
  import flyte.cli._common as common
7
+ from flyte.cli._option import MutuallyExclusiveOption
7
8
  from flyte.remote import SecretTypes
8
9
 
9
10
 
@@ -16,8 +17,21 @@ def create():
16
17
 
17
18
  @create.command(cls=common.CommandBase)
18
19
  @click.argument("name", type=str, required=True)
19
- @click.argument("value", type=str, required=False)
20
- @click.option("--from-file", type=click.Path(exists=True), help="Path to the file with the binary secret.")
20
+ @click.option(
21
+ "--value",
22
+ help="Secret value",
23
+ prompt="Enter secret value",
24
+ hide_input=True,
25
+ cls=MutuallyExclusiveOption,
26
+ mutually_exclusive=["from_file"],
27
+ )
28
+ @click.option(
29
+ "--from-file",
30
+ type=click.Path(exists=True),
31
+ help="Path to the file with the binary secret.",
32
+ cls=MutuallyExclusiveOption,
33
+ mutually_exclusive=["value"],
34
+ )
21
35
  @click.option(
22
36
  "--type", type=click.Choice(get_args(SecretTypes)), default="regular", help="Type of the secret.", show_default=True
23
37
  )
@@ -38,6 +52,14 @@ def secret(
38
52
  $ flyte create secret my_secret --value my_value
39
53
  ```
40
54
 
55
+ If you don't provide a `--value` flag, you will be prompted to enter the
56
+ secret value in the terminal.
57
+
58
+ ```bash
59
+ $ flyte create secret my_secret
60
+ Enter secret value:
61
+ ```
62
+
41
63
  If `--from-file` is specified, the value will be read from the file instead of being provided directly:
42
64
 
43
65
  ```bash
flyte/cli/_deploy.py CHANGED
@@ -109,8 +109,8 @@ class DeployEnvCommand(click.Command):
109
109
  version=self.deploy_args.version,
110
110
  )
111
111
 
112
- console.print(common.get_table("Environments", deployment[0].env_repr(), simple=obj.simple))
113
- console.print(common.get_table("Tasks", deployment[0].task_repr(), simple=obj.simple))
112
+ console.print(common.format("Environments", deployment[0].env_repr(), obj.output_format))
113
+ console.print(common.format("Tasks", deployment[0].task_repr(), obj.output_format))
114
114
 
115
115
 
116
116
  class DeployEnvRecursiveCommand(click.Command):
@@ -139,7 +139,7 @@ class DeployEnvRecursiveCommand(click.Command):
139
139
  if failed_paths:
140
140
  console.print(f"Loaded {len(loaded_modules)} modules with, but failed to load {len(failed_paths)} paths:")
141
141
  console.print(
142
- common.get_table("Modules", [[("Path", p), ("Err", e)] for p, e in failed_paths], simple=obj.simple)
142
+ common.format("Modules", [[("Path", p), ("Err", e)] for p, e in failed_paths], obj.output_format)
143
143
  )
144
144
  else:
145
145
  console.print(f"Loaded {len(loaded_modules)} modules")
@@ -149,9 +149,7 @@ class DeployEnvRecursiveCommand(click.Command):
149
149
  if not all_envs:
150
150
  console.print("No environments found to deploy")
151
151
  return
152
- console.print(
153
- common.get_table("Loaded Environments", [[("name", e.name)] for e in all_envs], simple=obj.simple)
154
- )
152
+ console.print(common.format("Loaded Environments", [[("name", e.name)] for e in all_envs], obj.output_format))
155
153
 
156
154
  if not self.deploy_args.ignore_load_errors and len(failed_paths) > 0:
157
155
  raise click.ClickException(
@@ -168,11 +166,9 @@ class DeployEnvRecursiveCommand(click.Command):
168
166
  )
169
167
 
170
168
  console.print(
171
- common.get_table("Environments", [env for d in deployments for env in d.env_repr()], simple=obj.simple)
172
- )
173
- console.print(
174
- common.get_table("Tasks", [task for d in deployments for task in d.task_repr()], simple=obj.simple)
169
+ common.format("Environments", [env for d in deployments for env in d.env_repr()], obj.output_format)
175
170
  )
171
+ console.print(common.format("Tasks", [task for d in deployments for task in d.task_repr()], obj.output_format))
176
172
 
177
173
 
178
174
  class EnvPerFileGroup(common.ObjectsPerFileGroup):
flyte/cli/_get.py CHANGED
@@ -48,13 +48,20 @@ def project(cfg: common.CLIConfig, name: str | None = None):
48
48
  if name:
49
49
  console.print(pretty_repr(Project.get(name)))
50
50
  else:
51
- console.print(common.get_table("Projects", Project.listall(), simple=cfg.simple))
51
+ console.print(common.format("Projects", Project.listall(), cfg.output_format))
52
52
 
53
53
 
54
54
  @get.command(cls=common.CommandBase)
55
55
  @click.argument("name", type=str, required=False)
56
+ @click.option("--limit", type=int, default=100, help="Limit the number of runs to fetch when listing.")
56
57
  @click.pass_obj
57
- def run(cfg: common.CLIConfig, name: str | None = None, project: str | None = None, domain: str | None = None):
58
+ def run(
59
+ cfg: common.CLIConfig,
60
+ name: str | None = None,
61
+ project: str | None = None,
62
+ domain: str | None = None,
63
+ limit: int = 100,
64
+ ):
58
65
  """
59
66
  Get a list of all runs, or details of a specific run by name.
60
67
 
@@ -71,13 +78,13 @@ def run(cfg: common.CLIConfig, name: str | None = None, project: str | None = No
71
78
  details = RunDetails.get(name=name)
72
79
  console.print(pretty_repr(details))
73
80
  else:
74
- console.print(common.get_table("Runs", Run.listall(), simple=cfg.simple))
81
+ console.print(common.format("Runs", Run.listall(limit=limit), cfg.output_format))
75
82
 
76
83
 
77
84
  @get.command(cls=common.CommandBase)
78
85
  @click.argument("name", type=str, required=False)
79
86
  @click.argument("version", type=str, required=False)
80
- @click.option("--limit", type=int, default=100, help="Limit the number of tasks to show.")
87
+ @click.option("--limit", type=int, default=100, help="Limit the number of tasks to fetch.")
81
88
  @click.pass_obj
82
89
  def task(
83
90
  cfg: common.CLIConfig,
@@ -105,9 +112,9 @@ def task(
105
112
  t = v.fetch()
106
113
  console.print(pretty_repr(t))
107
114
  else:
108
- console.print(common.get_table("Tasks", Task.listall(by_task_name=name, limit=limit), simple=cfg.simple))
115
+ console.print(common.format("Tasks", Task.listall(by_task_name=name, limit=limit), cfg.output_format))
109
116
  else:
110
- console.print(common.get_table("Tasks", Task.listall(limit=limit), simple=cfg.simple))
117
+ console.print(common.format("Tasks", Task.listall(limit=limit), cfg.output_format))
111
118
 
112
119
 
113
120
  @get.command(cls=common.CommandBase)
@@ -133,8 +140,8 @@ def action(
133
140
  else:
134
141
  # List all actions for the run
135
142
  console.print(
136
- common.get_table(
137
- f"Actions for {run_name}", flyte.remote._action.Action.listall(for_run_name=run_name), simple=cfg.simple
143
+ common.format(
144
+ f"Actions for {run_name}", flyte.remote._action.Action.listall(for_run_name=run_name), cfg.output_format
138
145
  )
139
146
  )
140
147
 
@@ -230,7 +237,7 @@ def secret(
230
237
  if name:
231
238
  console.print(pretty_repr(remote.Secret.get(name)))
232
239
  else:
233
- console.print(common.get_table("Secrets", remote.Secret.listall(), simple=cfg.simple))
240
+ console.print(common.format("Secrets", remote.Secret.listall(), cfg.output_format))
234
241
 
235
242
 
236
243
  @get.command(cls=common.CommandBase)
@@ -299,7 +306,7 @@ def io(
299
306
  common.get_panel(
300
307
  "Inputs & Outputs",
301
308
  f"[green bold]Inputs[/green bold]\n{inputs}\n\n[blue bold]Outputs[/blue bold]\n{outputs}",
302
- simple=cfg.simple,
309
+ cfg.output_format,
303
310
  )
304
311
  )
305
312
 
flyte/cli/_option.py ADDED
@@ -0,0 +1,33 @@
1
+ from click import Option, UsageError
2
+
3
+
4
+ class MutuallyExclusiveMixin:
5
+ def __init__(self, *args, **kwargs):
6
+ self.mutually_exclusive = set(kwargs.pop("mutually_exclusive", []))
7
+ self.error_format = kwargs.pop(
8
+ "error_msg", "Illegal usage: options '{name}' and '{invalid}' are mutually exclusive"
9
+ )
10
+ super().__init__(*args, **kwargs)
11
+
12
+ def handle_parse_result(self, ctx, opts, args):
13
+ self_present = self.name in opts and opts[self.name] is not None
14
+ others_intersect = self.mutually_exclusive.intersection(opts)
15
+ others_present = others_intersect and any(opts[value] is not None for value in others_intersect)
16
+
17
+ if others_present:
18
+ if self_present:
19
+ raise UsageError(self.error_format.format(name=self.name, invalid=", ".join(self.mutually_exclusive)))
20
+ else:
21
+ self.prompt = None
22
+
23
+ return super().handle_parse_result(ctx, opts, args)
24
+
25
+
26
+ # See https://stackoverflow.com/a/37491504/499285 and https://stackoverflow.com/a/44349292/499285
27
+ class MutuallyExclusiveOption(MutuallyExclusiveMixin, Option):
28
+ def __init__(self, *args, **kwargs):
29
+ mutually_exclusive = kwargs.get("mutually_exclusive", [])
30
+ help = kwargs.get("help", "")
31
+ if mutually_exclusive:
32
+ kwargs["help"] = help + f" Mutually exclusive with {', '.join(mutually_exclusive)}."
33
+ super().__init__(*args, **kwargs)
flyte/cli/_run.py CHANGED
@@ -117,7 +117,7 @@ class RunTaskCommand(click.Command):
117
117
  f"[green bold]Created Run: {r.name} [/green bold] "
118
118
  f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n"
119
119
  f"➡️ [blue bold]{r.url}[/blue bold]",
120
- simple=obj.simple,
120
+ obj.output_format,
121
121
  )
122
122
  )
123
123
  if self.run_args.follow:
flyte/cli/main.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import rich_click as click
2
+ from typing_extensions import get_args
2
3
 
3
4
  from flyte._logging import initialize_logger, logger
4
5
 
@@ -107,10 +108,13 @@ def _verbosity_to_loglevel(verbosity: int) -> int | None:
107
108
  help="Path to the configuration file to use. If not specified, the default configuration file is used.",
108
109
  )
109
110
  @click.option(
110
- "--simple",
111
- is_flag=True,
112
- default=False,
113
- help="Use a simple output format for commands that support it. This is useful for copying, pasting, and scripting.",
111
+ "--output-format",
112
+ "-of",
113
+ type=click.Choice(get_args(common.OutputFormat), case_sensitive=False),
114
+ default="table",
115
+ help="Output format for commands that support it. Defaults to 'table'.",
116
+ show_default=True,
117
+ required=False,
114
118
  )
115
119
  @click.rich_config(help_config=help_config)
116
120
  @click.pass_context
@@ -121,8 +125,8 @@ def main(
121
125
  verbose: int,
122
126
  org: str | None,
123
127
  config_file: str | None,
124
- simple: bool = False,
125
128
  auth_type: str | None = None,
129
+ output_format: common.OutputFormat = "table",
126
130
  ):
127
131
  """
128
132
  The Flyte CLI is the command line interface for working with the Flyte SDK and backend.
@@ -176,8 +180,8 @@ def main(
176
180
  org=org,
177
181
  config=cfg,
178
182
  ctx=ctx,
179
- simple=simple,
180
183
  auth_type=auth_type,
184
+ output_format=output_format,
181
185
  )
182
186
 
183
187
 
flyte/errors.py CHANGED
@@ -10,6 +10,16 @@ from typing import Literal
10
10
  ErrorKind = Literal["system", "unknown", "user"]
11
11
 
12
12
 
13
+ def silence_grpc_polling_error(loop, context):
14
+ """
15
+ Suppress specific gRPC polling errors in the event loop.
16
+ """
17
+ exc = context.get("exception")
18
+ if isinstance(exc, BlockingIOError):
19
+ return # suppress
20
+ loop.default_exception_handler(context)
21
+
22
+
13
23
  class BaseRuntimeError(RuntimeError):
14
24
  """
15
25
  Base class for all Union runtime errors. These errors are raised when the underlying task execution fails, either
@@ -86,6 +96,9 @@ class TaskTimeoutError(RuntimeUserError):
86
96
  This error is raised when the underlying task execution runs for longer than the specified timeout.
87
97
  """
88
98
 
99
+ def __init__(self, message: str):
100
+ super().__init__("TaskTimeoutError", message, "user")
101
+
89
102
 
90
103
  class RetriesExhaustedError(RuntimeUserError):
91
104
  """
@@ -199,3 +212,12 @@ class InlineIOMaxBytesBreached(RuntimeUserError):
199
212
 
200
213
  def __init__(self, message: str):
201
214
  super().__init__("InlineIOMaxBytesBreached", message, "user")
215
+
216
+
217
+ class RunAbortedError(RuntimeUserError):
218
+ """
219
+ This error is raised when the run is aborted by the user.
220
+ """
221
+
222
+ def __init__(self, message: str):
223
+ super().__init__("RunAbortedError", message, "user")
flyte/remote/_action.py CHANGED
@@ -28,6 +28,7 @@ from flyte._initialize import ensure_client, get_client, get_common_config
28
28
  from flyte._protos.common import identifier_pb2, list_pb2
29
29
  from flyte._protos.workflow import run_definition_pb2, run_service_pb2
30
30
  from flyte._protos.workflow.run_service_pb2 import WatchActionDetailsResponse
31
+ from flyte.remote._common import ToJSONMixin
31
32
  from flyte.remote._logs import Logs
32
33
  from flyte.syncify import syncify
33
34
 
@@ -120,7 +121,7 @@ def _action_done_check(phase: run_definition_pb2.Phase) -> bool:
120
121
 
121
122
 
122
123
  @dataclass
123
- class Action:
124
+ class Action(ToJSONMixin):
124
125
  """
125
126
  A class representing an action. It is used to manage the run of a task and its state on the remote Union API.
126
127
  """
@@ -411,7 +412,7 @@ class Action:
411
412
 
412
413
 
413
414
  @dataclass
414
- class ActionDetails:
415
+ class ActionDetails(ToJSONMixin):
415
416
  """
416
417
  A class representing an action. It is used to manage the run of a task and its state on the remote Union API.
417
418
  """
@@ -692,7 +693,7 @@ class ActionDetails:
692
693
 
693
694
 
694
695
  @dataclass
695
- class ActionInputs(UserDict):
696
+ class ActionInputs(UserDict, ToJSONMixin):
696
697
  """
697
698
  A class representing the inputs of an action. It is used to manage the inputs of a task and its state on the
698
699
  remote Union API.
@@ -709,7 +710,7 @@ class ActionInputs(UserDict):
709
710
  return rich.pretty.pretty_repr(types.literal_string_repr(self.pb2))
710
711
 
711
712
 
712
- class ActionOutputs(tuple):
713
+ class ActionOutputs(tuple, ToJSONMixin):
713
714
  """
714
715
  A class representing the outputs of an action. It is used to manage the outputs of a task and its state on the
715
716
  remote Union API.
@@ -0,0 +1,30 @@
1
+ import json
2
+
3
+ from google.protobuf.json_format import MessageToDict, MessageToJson
4
+
5
+
6
+ class ToJSONMixin:
7
+ """
8
+ A mixin class that provides a method to convert an object to a JSON-serializable dictionary.
9
+ """
10
+
11
+ def to_dict(self) -> dict:
12
+ """
13
+ Convert the object to a JSON-serializable dictionary.
14
+
15
+ Returns:
16
+ dict: A dictionary representation of the object.
17
+ """
18
+ if hasattr(self, "pb2"):
19
+ return MessageToDict(self.pb2)
20
+ else:
21
+ return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
22
+
23
+ def to_json(self) -> str:
24
+ """
25
+ Convert the object to a JSON string.
26
+
27
+ Returns:
28
+ str: A JSON string representation of the object.
29
+ """
30
+ return MessageToJson(self.pb2) if hasattr(self, "pb2") else json.dumps(self.to_dict())
flyte/remote/_project.py CHANGED
@@ -9,15 +9,17 @@ from flyteidl.admin import common_pb2, project_pb2
9
9
  from flyte._initialize import ensure_client, get_client
10
10
  from flyte.syncify import syncify
11
11
 
12
+ from ._common import ToJSONMixin
13
+
12
14
 
13
15
  # TODO Add support for orgs again
14
16
  @dataclass
15
- class Project:
17
+ class Project(ToJSONMixin):
16
18
  """
17
19
  A class representing a project in the Union API.
18
20
  """
19
21
 
20
- _pb2: project_pb2.Project
22
+ pb2: project_pb2.Project
21
23
 
22
24
  @syncify
23
25
  @classmethod
@@ -76,11 +78,11 @@ class Project:
76
78
  break
77
79
 
78
80
  def __rich_repr__(self) -> rich.repr.Result:
79
- yield "name", self._pb2.name
80
- yield "id", self._pb2.id
81
- yield "description", self._pb2.description
82
- yield "state", project_pb2.Project.ProjectState.Name(self._pb2.state)
81
+ yield "name", self.pb2.name
82
+ yield "id", self.pb2.id
83
+ yield "description", self.pb2.description
84
+ yield "state", project_pb2.Project.ProjectState.Name(self.pb2.state)
83
85
  yield (
84
86
  "labels",
85
- ", ".join([f"{k}: {v}" for k, v in self._pb2.labels.values.items()]) if self._pb2.labels else None,
87
+ ", ".join([f"{k}: {v}" for k, v in self.pb2.labels.values.items()]) if self.pb2.labels else None,
86
88
  )
flyte/remote/_run.py CHANGED
@@ -13,11 +13,12 @@ from flyte.syncify import syncify
13
13
 
14
14
  from . import Action, ActionDetails, ActionInputs, ActionOutputs
15
15
  from ._action import _action_details_rich_repr, _action_rich_repr
16
+ from ._common import ToJSONMixin
16
17
  from ._console import get_run_url
17
18
 
18
19
 
19
20
  @dataclass
20
- class Run:
21
+ class Run(ToJSONMixin):
21
22
  """
22
23
  A class representing a run of a task. It is used to manage the run of a task and its state on the remote
23
24
  Union API.
@@ -41,12 +42,14 @@ class Run:
41
42
  cls,
42
43
  filters: str | None = None,
43
44
  sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
45
+ limit: int = 100,
44
46
  ) -> AsyncIterator[Run]:
45
47
  """
46
48
  Get all runs for the current project and domain.
47
49
 
48
50
  :param filters: The filters to apply to the project list.
49
51
  :param sort_by: The sorting criteria for the project list, in the format (field, order).
52
+ :param limit: The maximum number of runs to return.
50
53
  :return: An iterator of runs.
51
54
  """
52
55
  ensure_client()
@@ -57,9 +60,10 @@ class Run:
57
60
  direction=(list_pb2.Sort.ASCENDING if sort_by[1] == "asc" else list_pb2.Sort.DESCENDING),
58
61
  )
59
62
  cfg = get_common_config()
63
+ i = 0
60
64
  while True:
61
65
  req = list_pb2.ListRequest(
62
- limit=100,
66
+ limit=min(100, limit),
63
67
  token=token,
64
68
  sort_by=sort_pb2,
65
69
  )
@@ -76,6 +80,9 @@ class Run:
76
80
  )
77
81
  token = resp.token
78
82
  for r in resp.runs:
83
+ i += 1
84
+ if i > limit:
85
+ return
79
86
  yield cls(r)
80
87
  if not token:
81
88
  break
@@ -213,7 +220,7 @@ class Run:
213
220
 
214
221
 
215
222
  @dataclass
216
- class RunDetails:
223
+ class RunDetails(ToJSONMixin):
217
224
  """
218
225
  A class representing a run of a task. It is used to manage the run of a task and its state on the remote
219
226
  Union API.
flyte/remote/_secret.py CHANGED
@@ -7,13 +7,14 @@ import rich.repr
7
7
 
8
8
  from flyte._initialize import ensure_client, get_client, get_common_config
9
9
  from flyte._protos.secret import definition_pb2, payload_pb2
10
+ from flyte.remote._common import ToJSONMixin
10
11
  from flyte.syncify import syncify
11
12
 
12
13
  SecretTypes = Literal["regular", "image_pull"]
13
14
 
14
15
 
15
16
  @dataclass
16
- class Secret:
17
+ class Secret(ToJSONMixin):
17
18
  pb2: definition_pb2.Secret
18
19
 
19
20
  @syncify
flyte/remote/_task.py CHANGED
@@ -10,6 +10,7 @@ from google.protobuf import timestamp
10
10
 
11
11
  import flyte
12
12
  import flyte.errors
13
+ from flyte._cache.cache import CacheBehavior
13
14
  from flyte._context import internal_ctx
14
15
  from flyte._initialize import ensure_client, get_client, get_common_config
15
16
  from flyte._logging import logger
@@ -18,6 +19,8 @@ from flyte._protos.workflow import task_definition_pb2, task_service_pb2
18
19
  from flyte.models import NativeInterface
19
20
  from flyte.syncify import syncify
20
21
 
22
+ from ._common import ToJSONMixin
23
+
21
24
 
22
25
  def _repr_task_metadata(metadata: task_definition_pb2.TaskMetadata) -> rich.repr.Result:
23
26
  """
@@ -79,7 +82,7 @@ AutoVersioning = Literal["latest", "current"]
79
82
 
80
83
 
81
84
  @dataclass
82
- class TaskDetails:
85
+ class TaskDetails(ToJSONMixin):
83
86
  pb2: task_definition_pb2.TaskDetails
84
87
  max_inline_io_bytes: int = 10 * 1024 * 1024 # 10 MB
85
88
 
@@ -201,11 +204,20 @@ class TaskDetails:
201
204
  """
202
205
  The cache policy of the task.
203
206
  """
207
+ metadata = self.pb2.spec.task_template.metadata
208
+ behavior: CacheBehavior
209
+ if not metadata.discoverable:
210
+ behavior = "disable"
211
+ elif metadata.discovery_version:
212
+ behavior = "override"
213
+ else:
214
+ behavior = "auto"
215
+
204
216
  return flyte.Cache(
205
- behavior="enabled" if self.pb2.spec.task_template.metadata.discoverable else "disable",
206
- version_override=self.pb2.spec.task_template.metadata.discovery_version,
207
- serialize=self.pb2.spec.task_template.metadata.cache_serializable,
208
- ignored_inputs=tuple(self.pb2.spec.task_template.metadata.cache_ignore_input_vars),
217
+ behavior=behavior,
218
+ version_override=metadata.discovery_version if metadata.discovery_version else None,
219
+ serialize=metadata.cache_serializable,
220
+ ignored_inputs=tuple(metadata.cache_ignore_input_vars),
209
221
  )
210
222
 
211
223
  @property
@@ -294,7 +306,7 @@ class TaskDetails:
294
306
 
295
307
 
296
308
  @dataclass
297
- class Task:
309
+ class Task(ToJSONMixin):
298
310
  pb2: task_definition_pb2.Task
299
311
 
300
312
  def __init__(self, pb2: task_definition_pb2.Task):
flyte/syncify/_api.py CHANGED
@@ -64,6 +64,10 @@ class _BackgroundLoop:
64
64
  atexit.register(self.stop)
65
65
 
66
66
  def _run(self):
67
+ import flyte.errors
68
+
69
+ # Set the exception handler to silence specific gRPC polling errors
70
+ self.loop.set_exception_handler(flyte.errors.silence_grpc_polling_error)
67
71
  asyncio.set_event_loop(self.loop)
68
72
  self.loop.run_forever()
69
73
 
@@ -26,7 +26,6 @@ DOMAIN_NAME = "FLYTE_INTERNAL_TASK_DOMAIN"
26
26
  ORG_NAME = "_U_ORG_NAME"
27
27
  ENDPOINT_OVERRIDE = "_U_EP_OVERRIDE"
28
28
  RUN_OUTPUT_BASE_DIR = "_U_RUN_BASE"
29
- ENABLE_REF_TASKS = "_REF_TASKS" # This is a temporary flag to enable reference tasks in the runtime.
30
29
 
31
30
  # TODO: Remove this after proper auth is implemented
32
31
  _UNION_EAGER_API_KEY_ENV_VAR = "_UNION_EAGER_API_KEY"
@@ -87,6 +86,7 @@ def main(
87
86
 
88
87
  import flyte
89
88
  import flyte._utils as utils
89
+ import flyte.errors
90
90
  from flyte._initialize import init
91
91
  from flyte._internal.controllers import create_controller
92
92
  from flyte._internal.imagebuild.image_builder import ImageCache
@@ -123,22 +123,7 @@ def main(
123
123
  logger.debug(f"Using controller endpoint: {ep} with kwargs: {controller_kwargs}")
124
124
 
125
125
  bundle = CodeBundle(tgz=tgz, pkl=pkl, destination=dest, computed_version=version)
126
- enable_ref_tasks = os.getenv(ENABLE_REF_TASKS, "false").lower() in ("true", "1", "yes")
127
- # We init regular client here so that reference tasks can work
128
- # Current reference tasks will not work with remote controller, because we create 2 different
129
- # channels on different threads and this is not supported by grpcio or the auth system. It ends up leading
130
- # File "src/python/grpcio/grpc/_cython/_cygrpc/aio/completion_queue.pyx.pxi", line 147,
131
- # in grpc._cython.cygrpc.PollerCompletionQueue._handle_events
132
- # BlockingIOError: [Errno 11] Resource temporarily unavailable
133
- # TODO solution is to use a single channel for both controller and reference tasks, but this requires a refactor
134
- if enable_ref_tasks:
135
- logger.warning(
136
- "Reference tasks are enabled. This will initialize client and you will see a BlockIOError. "
137
- "This is harmless, but a nuisance. We are working on a fix."
138
- )
139
- init(org=org, project=project, domain=domain, **controller_kwargs)
140
- else:
141
- init()
126
+ init(org=org, project=project, domain=domain, **controller_kwargs)
142
127
  # Controller is created with the same kwargs as init, so that it can be used to run tasks
143
128
  controller = create_controller(ct="remote", **controller_kwargs)
144
129
 
@@ -164,6 +149,8 @@ def main(
164
149
 
165
150
  # Run both coroutines concurrently and wait for first to finish and cancel the other
166
151
  async def _run_and_stop():
152
+ loop = asyncio.get_event_loop()
153
+ loop.set_exception_handler(flyte.errors.silence_grpc_polling_error)
167
154
  await utils.run_coros(controller_failure, task_coroutine)
168
155
  await controller.stop()
169
156
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyte
3
- Version: 2.0.0b6
3
+ Version: 2.0.0b7
4
4
  Summary: Add your description here
5
5
  Author-email: Ketan Umare <kumare3@users.noreply.github.com>
6
6
  Requires-Python: >=3.10
@@ -1,7 +1,7 @@
1
1
  flyte/__init__.py,sha256=jWSynBJyJ0WuSjE8HID2MT386ZNlRzx7LzCHW1y_XNw,1468
2
2
  flyte/_build.py,sha256=MkgfLAPeL56YeVrGRNZUCZgbwzlEzVP3wLbl5Qru4yk,578
3
3
  flyte/_context.py,sha256=K0-TCt-_pHOoE5Xni87_8uIe2vCBOhfNQEtjGT4Hu4k,5239
4
- flyte/_deploy.py,sha256=v4QYa7L9AeFxZh1Ya5Wn8OSPBA3YAX5favQStdD-x-s,10536
4
+ flyte/_deploy.py,sha256=6FTL7m3unDG-1V-5hTF2pRnql-6e9pRRyCM9o3xiHWQ,10541
5
5
  flyte/_doc.py,sha256=_OPCf3t_git6UT7kSJISFaWO9cfNzJhhoe6JjVdyCJo,706
6
6
  flyte/_docstring.py,sha256=SsG0Ab_YMAwy2ABJlEo3eBKlyC3kwPdnDJ1FIms-ZBQ,1127
7
7
  flyte/_environment.py,sha256=6ks0lkvGt4oSqM5EFPFlhWC3eoUghxUvCn0wstcAD2E,3713
@@ -17,23 +17,23 @@ flyte/_pod.py,sha256=--72b0c6IkOEbBwZPLmgl-ll-j7ECfG-kh75LzBnNN8,1068
17
17
  flyte/_resources.py,sha256=L2JuvQDlMo1JLJeUmJPRwtWbunhR2xJEhFgQW5yc72c,9690
18
18
  flyte/_retry.py,sha256=rfLv0MvWxzPByKESTglEmjPsytEAKiIvvmzlJxXwsfE,941
19
19
  flyte/_reusable_environment.py,sha256=f8Y1GilUwGcXH4n2Fckrnx0SrZmhk3nCfoe-TqUKivI,3740
20
- flyte/_run.py,sha256=SSD35ICaYaqt7Ep4SNAi7BLESIullo68g0g4x_dfrW4,25654
20
+ flyte/_run.py,sha256=7wT3JyCqZKzM5ZDtM_Xk_KpeafpxGdLA85Adx1Nv3Q8,25662
21
21
  flyte/_secret.py,sha256=89VIihdXI03irHb217GMfipt7jzXBafm17YYmyv6gHo,3245
22
22
  flyte/_task.py,sha256=FUqGDtDmhOVPdv-UVko4h0oecoAcc3JZKu8S__cwUpY,19805
23
- flyte/_task_environment.py,sha256=Zpfr8gjwXg5KuCfIbT4s3l2mtJCFqDxXwv6ZStHWBuc,9840
23
+ flyte/_task_environment.py,sha256=hblOR-B_Cc6ibpFkedZSyN6V9vi0_vZ0132YKN5D4EM,9826
24
24
  flyte/_task_plugins.py,sha256=9MH3nFPOH_e8_92BT4sFk4oyAnj6GJFvaPYWaraX7yE,1037
25
25
  flyte/_timeout.py,sha256=zx5sFcbYmjJAJbZWSGzzX-BpC9HC7Jfs35T7vVhKwkk,1571
26
26
  flyte/_tools.py,sha256=tWb0sx3t3mm4jbaQVjCTc9y39oR_Ibo3z_KHToP3Lto,966
27
27
  flyte/_trace.py,sha256=SSE1nzUgmVTS2xFNtchEOjEjlRavMOIInasXzY8i9lU,4911
28
- flyte/_version.py,sha256=c1--_MDUEVzy0HOAoU4GvWafX-tUEg8fSks16cbT7nQ,519
29
- flyte/errors.py,sha256=DKKw0LVywBNuiWR9WMkODxd_dwWRn-NtyN1TMs6HHd0,5800
28
+ flyte/_version.py,sha256=1YvgXBLYYXUpymS5IKos1Ax9Mkky98AhIJ8qBmjaQ0w,720
29
+ flyte/errors.py,sha256=z28rhbNmJF5Ie7quQWtoSL4K5p_tC3QjZDIZTupNQFw,6395
30
30
  flyte/extend.py,sha256=GB4ZedGzKa30vYWRVPOdxEeK62xnUVFY4z2tD6H9eEw,376
31
31
  flyte/models.py,sha256=2TgfrkPPgcnnk1P_MO5SEmOYAUbsMKl3gxIDwhW2yEU,15674
32
32
  flyte/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  flyte/_bin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- flyte/_bin/runtime.py,sha256=2jTy3ccvrJ__Xrfdo2t0Fxhsojc5o2zIxDHt98RE_eU,6475
34
+ flyte/_bin/runtime.py,sha256=8U_tIhdF8phBLDFr0U1xv92OKK5RquiaTJFv8v_fIgQ,5537
35
35
  flyte/_cache/__init__.py,sha256=zhdO5UuHQRdzn8GHmSN40nrxfAmI4ihDRuHZM11U84Y,305
36
- flyte/_cache/cache.py,sha256=ErhWzzJdEjTIuEF4f-r6IBgko-3Al9iUs1Eq4O42TUE,5021
36
+ flyte/_cache/cache.py,sha256=-oS5q6QpkxPqZ8gWkn8uVNgzx3JFuXaWLV-h0KVKW9c,5010
37
37
  flyte/_cache/defaults.py,sha256=gzJZW0QJPUfd2OPnGpv3tzIfwPtgFjAKoie3NP1P97U,217
38
38
  flyte/_cache/policy_function_body.py,sha256=_AcyN6XKRXq16yV5lWuRJYCIVUlmyPvvWuYRxfU-Ldo,1507
39
39
  flyte/_code_bundle/__init__.py,sha256=G7DJTQ0UN_ETvdh55pYcWsTrZJKXEcyQl9iQQNQOBXQ,328
@@ -48,8 +48,8 @@ flyte/_internal/controllers/_trace.py,sha256=ywFg_M2nGrCKYLbh4iVdsVlRtPT1K2S-XZM
48
48
  flyte/_internal/controllers/remote/__init__.py,sha256=9_azH1eHLqY6VULpDugXi7Kf1kK1ODqEnsQ_3wM6IqU,1919
49
49
  flyte/_internal/controllers/remote/_action.py,sha256=ENV1thRXllSpi2s4idL-vCVcmXQNS17hmP2lMDKzNdo,7397
50
50
  flyte/_internal/controllers/remote/_client.py,sha256=HPbzbfaWZVv5wpOvKNtFXR6COiZDwd1cUJQqi60A7oU,1421
51
- flyte/_internal/controllers/remote/_controller.py,sha256=tnHHWYd2nc16_1Slm8lShrbQdrfHjyNiSiByFk3A1mg,24988
52
- flyte/_internal/controllers/remote/_core.py,sha256=PhqI_qwKieH0abOzXYzUZt3v166DxX9HkZPqLWXqH6w,18975
51
+ flyte/_internal/controllers/remote/_controller.py,sha256=ZH2w_HzNCN0GbRISpIdI7wbtc7o28j7aeOUhhZzLpS0,25802
52
+ flyte/_internal/controllers/remote/_core.py,sha256=R-gm0tFzsdvyCbrPs0zikXCnzyaTeCQ9qz6iE05nBls,19043
53
53
  flyte/_internal/controllers/remote/_informer.py,sha256=w4p29_dzS_ns762eNBljvnbJLgCm36d1Ogo2ZkgV1yg,14418
54
54
  flyte/_internal/controllers/remote/_service_protocol.py,sha256=B9qbIg6DiGeac-iSccLmX_AL2xUgX4ezNUOiAbSy4V0,1357
55
55
  flyte/_internal/imagebuild/__init__.py,sha256=dwXdJ1jMhw9RF8itF7jkPLanvX1yCviSns7hE5eoIts,102
@@ -66,7 +66,7 @@ flyte/_internal/runtime/entrypoints.py,sha256=9Ng-aQ45M-_MMWeOe9uGmgx69qO9b0xaMR
66
66
  flyte/_internal/runtime/io.py,sha256=ysL7hMpfVumvsEYWOM-_VPa8MXn5_X_CZorKbOThyv4,5935
67
67
  flyte/_internal/runtime/resources_serde.py,sha256=TObMVsSjVcQhcY8-nY81pbvrz7TP-adDD5xV-LqAaxM,4813
68
68
  flyte/_internal/runtime/reuse.py,sha256=WEuBfC9tBezxaIXeUQDgnJfnRHiUmPK0S25nTOFle4E,4676
69
- flyte/_internal/runtime/rusty.py,sha256=puMaa6aLaoR4Tl5xxZulC4AzY58nmGg-5ok4ydHHjdM,6145
69
+ flyte/_internal/runtime/rusty.py,sha256=e2uSg9-Hooa65-BIuqXhIrEq86RHteFFs3W7dDuM3uo,6946
70
70
  flyte/_internal/runtime/task_serde.py,sha256=n7cGuD3yPjtZ5gJOwQ-7sNfDaLdTghdT3o4xPv7aVfU,14108
71
71
  flyte/_internal/runtime/taskrunner.py,sha256=rHWS4t5qgZnzGdGrs0_O0sSs_PVGoE1CNPDb-fTwwmo,7332
72
72
  flyte/_internal/runtime/types_serde.py,sha256=EjRh9Yypx9-20XXQprtNgp766LeQVRoYWtY6XPGMZQg,1813
@@ -157,16 +157,17 @@ flyte/_utils/org_discovery.py,sha256=C7aJa0LfnWBkDtSU9M7bE60zp27qEhJC58piqOErZ94
157
157
  flyte/_utils/uv_script_parser.py,sha256=PxqD8lSMi6xv0uDd1s8LKB2IPZr4ttZJCUweqlyMTKk,1483
158
158
  flyte/cli/__init__.py,sha256=aeCcumeP9xD_5aCmaRYUPCe2QRJSGCaxcUbTZ3co768,341
159
159
  flyte/cli/_abort.py,sha256=Ty-63Gtd2PUn6lCuL5AaasfBoPu7TDSU5EQKVbkF4qw,661
160
- flyte/cli/_build.py,sha256=SBgybTVWOZ22VBHFL8CVFB_oo34lF9wvlwNirYFFyk0,3543
161
- flyte/cli/_common.py,sha256=SLY3M7ganzLCf2MaybJFRkk677IoZrkZKjIR5Qoc0cE,12542
162
- flyte/cli/_create.py,sha256=Rv_Ox_OA9TqdSI6zaTzLp9vwiqOanOk-Oasnbgx1Q3M,5081
160
+ flyte/cli/_build.py,sha256=gX8fqYAMoArn8kfR__5GtWc9dJahV9bPkSljOCg5zvI,3540
161
+ flyte/cli/_common.py,sha256=vKgf4UaY3NrwIV2_rjBqwu_rskhh4Dl4g9dJOqVTNss,13201
162
+ flyte/cli/_create.py,sha256=tXDhZAdsxvpQ4ngO4U-PhyYwzQ3Hi2AJrNtZ3eqJptQ,5541
163
163
  flyte/cli/_delete.py,sha256=VTmXv09PBjkdtyl23mbSjIQQlN7Y1AI_bO0GkHP-f9E,546
164
- flyte/cli/_deploy.py,sha256=h-laMIbqNskxPzqtBNxIhgamjt2MxGoNongi9_nTQbo,8939
164
+ flyte/cli/_deploy.py,sha256=sDbO8gobXR4O0Vlp3RKEH-kBSr25BiXJIoHVwau9Occ,8877
165
165
  flyte/cli/_gen.py,sha256=ni3E65_wSBc9x5NNbq1REuxfZCJz-ioLMVQnZIgwyYg,5745
166
- flyte/cli/_get.py,sha256=fvoJaBmZuD4sDs33dMo94dvBJVk3MaWPJe24e3cG0Ps,10200
166
+ flyte/cli/_get.py,sha256=cnvK5gh_HpISyfXMfn-srqlhyt2xnxZL3ZsGu7ETx9E,10339
167
+ flyte/cli/_option.py,sha256=oC1Gs0u0UrOC1SsrFo-iCuAkqQvI1wJWCdjYXA9rW4Q,1445
167
168
  flyte/cli/_params.py,sha256=8Gj8UYGHwu-SUXGWCTRX5QsVf19NiajhaUMMae6FF9o,19466
168
- flyte/cli/_run.py,sha256=x1BRMK4M0kUboZVOKNuufi8B0cFjsOE7b36zbHT40Cc,7764
169
- flyte/cli/main.py,sha256=9sLH-xaGdF9HamUQrTxmGTGNScdCtBfNmyYyPHiW3vU,5180
169
+ flyte/cli/_run.py,sha256=z8sZUa03Tx1TFBCwGBrdwq2sQaDr1VTAlMH5miZaEdY,7764
170
+ flyte/cli/main.py,sha256=t5Ivjipd6bVHIGjRBGwkeP577j59ASq9c1wgoNf3h2c,5334
170
171
  flyte/config/__init__.py,sha256=MiwEYK5Iv7MRR22z61nzbsbvZ9Q6MdmAU_g9If1Pmb8,144
171
172
  flyte/config/_config.py,sha256=WElU--Kw4MM9zx1v-rLD8qYu2T5Zk0-1QbTpkEc27bc,10779
172
173
  flyte/config/_internal.py,sha256=LMcAtDjvTjf5bGlsJVxPuLxQQ82mLd00xK5-JlYGCi8,2989
@@ -181,14 +182,15 @@ flyte/io/_dataframe/__init__.py,sha256=SDgNw45uf7m3cHhbUCOA3V3-5A2zSKgPcsWriRLwd
181
182
  flyte/io/_dataframe/basic_dfs.py,sha256=weQ8EfzdU-LcKi8Eebq1AiATVS1fGdfcbqtCDOrVLos,7728
182
183
  flyte/io/_dataframe/dataframe.py,sha256=uecLLjaAuLyYta2d4Tkk-DjxuHkzZjFUBbvMapPM7R8,51554
183
184
  flyte/remote/__init__.py,sha256=y9eke9JzEJkygk8eKZjSj44fJGlyepuW4i-j6lbCAPY,617
184
- flyte/remote/_action.py,sha256=5DN6rEb4WhsdDEZsYPFFOUyn2yjSMefVojkMF7DE7XM,23839
185
+ flyte/remote/_action.py,sha256=9Skj2Loroh2ZGarxNHUdljxKgwqR03Qx_ohxaMa4hYA,23936
186
+ flyte/remote/_common.py,sha256=2XLLxWL1NjwfdPQUhOfYn3zMrg-yGNfi6NYIaqHutUA,862
185
187
  flyte/remote/_console.py,sha256=avmELJPx8nQMAVPrHlh6jEIRPjrMwFpdZjJsWOOa9rE,660
186
188
  flyte/remote/_data.py,sha256=zYXXlqEvPdsC44Gm7rP_hQjRgVe3EFfhZNEWKF0p4MQ,6163
187
189
  flyte/remote/_logs.py,sha256=aDG18-uPVb2J3PxmqmAY1C0Z4Iv1P1agg-iF4nSQR4U,6709
188
- flyte/remote/_project.py,sha256=CFNTGpgXU3X599tkJ_oxijs9zPzzCWOB6mAWn6WeDEU,2828
189
- flyte/remote/_run.py,sha256=fpr_YcGZIv6K7Jt1if3-HHHVB2TVt_8AWcZ55rN_fgk,9750
190
- flyte/remote/_secret.py,sha256=l5xeMS83uMcWWeSSTRsSZUNhS0N--1Dze09C-thSOQs,4341
191
- flyte/remote/_task.py,sha256=xHfWChnC-L7Hdp2IB9qDnbNyaOgM2TWOlnkmevoc2dA,15314
190
+ flyte/remote/_project.py,sha256=IbkxKRAvZunKLIwpmcreA4O-0GxWC0KPC62WSYvsK34,2868
191
+ flyte/remote/_run.py,sha256=1QGmXJvUhmuw08zMkT2Eo9ISoaB8AF12eH5G7BBEDGs,10001
192
+ flyte/remote/_secret.py,sha256=CF9WiZKeMJaUNeIawVPf8XHk9OjFt2wc0m7S9ZOdGbE,4399
193
+ flyte/remote/_task.py,sha256=JQbZ8FriV-y_zBer9_H6gJM2AcngY7C_aV-67eJI9WU,15585
192
194
  flyte/remote/_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
193
195
  flyte/remote/_client/_protocols.py,sha256=JyBWHs5WsVOxEDUyG9X7wPLDzzzjkoaNhJlU-X4YlN0,5599
194
196
  flyte/remote/_client/controlplane.py,sha256=FsOfj4rO4MIMnYrpAT53F8q588VVf5t4sDuwoPuc840,3102
@@ -219,7 +221,7 @@ flyte/storage/_remote_fs.py,sha256=kM_iszbccjVD5VtVdgfkl1FHS8NPnY__JOo_CPQUE4c,1
219
221
  flyte/storage/_storage.py,sha256=AQ_ubpYwJjRdEYV-qU4ttXDZuuT28t6-S5eFQD5D9sQ,10175
220
222
  flyte/storage/_utils.py,sha256=8oLCM-7D7JyJhzUi1_Q1NFx8GBUPRfou0T_5tPBmPbE,309
221
223
  flyte/syncify/__init__.py,sha256=WgTk-v-SntULnI55CsVy71cxGJ9Q6pxpTrhbPFuouJ0,1974
222
- flyte/syncify/_api.py,sha256=fh7Dlh0cZGELnWDh5lFmxVu-_cqlfsu9XLwkiuDRseE,14672
224
+ flyte/syncify/_api.py,sha256=k4LQB8odJb5Fx2dabL340g0Tq1bKfSG_ZHsV5qRodE0,14858
223
225
  flyte/types/__init__.py,sha256=9310PRtVrwJePwEPeoUO0HPyIkgaja7-Dar_QlE_MUI,1745
224
226
  flyte/types/_interface.py,sha256=5y9EC5r897xz03Hh0ltF8QVGKMfMfAznws-hKSEO4Go,1677
225
227
  flyte/types/_pickle.py,sha256=PjdR66OTDMZ3OYq6GvM_Ua0cIo5t2XQaIjmpJ9xo4Ys,4050
@@ -227,10 +229,10 @@ flyte/types/_renderer.py,sha256=ygcCo5l60lHufyQISFddZfWwLlQ8kJAKxUT_XnR_6dY,4818
227
229
  flyte/types/_string_literals.py,sha256=NlG1xV8RSA-sZ-n-IFQCAsdB6jXJOAKkHWtnopxVVDk,4231
228
230
  flyte/types/_type_engine.py,sha256=Tas_OXYddOi0nDuORjqan2SkJ96wKD8937I2l1bo8vk,97916
229
231
  flyte/types/_utils.py,sha256=pbts9E1_2LTdLygAY0UYTLYJ8AsN3BZyviSXvrtcutc,2626
230
- flyte-2.0.0b6.data/scripts/runtime.py,sha256=2jTy3ccvrJ__Xrfdo2t0Fxhsojc5o2zIxDHt98RE_eU,6475
231
- flyte-2.0.0b6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
232
- flyte-2.0.0b6.dist-info/METADATA,sha256=AfK1udiYYhGWg2MmKRBZGsVOe7Ff3QrPdMozeqv3feY,10004
233
- flyte-2.0.0b6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
234
- flyte-2.0.0b6.dist-info/entry_points.txt,sha256=MIq2z5dBurdCJfpXfMKzgBv7sJOakKRYxr8G0cMiTrg,75
235
- flyte-2.0.0b6.dist-info/top_level.txt,sha256=7dkyFbikvA12LEZEqawx8oDG1CMod6hTliPj7iWzgYo,6
236
- flyte-2.0.0b6.dist-info/RECORD,,
232
+ flyte-2.0.0b7.data/scripts/runtime.py,sha256=8U_tIhdF8phBLDFr0U1xv92OKK5RquiaTJFv8v_fIgQ,5537
233
+ flyte-2.0.0b7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
234
+ flyte-2.0.0b7.dist-info/METADATA,sha256=Rkv8GGIoqC6GIkYpy8mpFHoug7XBU5wldwr4YnUfDk4,10004
235
+ flyte-2.0.0b7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
236
+ flyte-2.0.0b7.dist-info/entry_points.txt,sha256=MIq2z5dBurdCJfpXfMKzgBv7sJOakKRYxr8G0cMiTrg,75
237
+ flyte-2.0.0b7.dist-info/top_level.txt,sha256=7dkyFbikvA12LEZEqawx8oDG1CMod6hTliPj7iWzgYo,6
238
+ flyte-2.0.0b7.dist-info/RECORD,,