flyte 2.0.0b1__py3-none-any.whl → 2.0.0b3__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/_internal/controllers/__init__.py +3 -1
- flyte/_internal/controllers/_local_controller.py +3 -1
- flyte/_internal/controllers/remote/_controller.py +26 -13
- flyte/_internal/runtime/io.py +48 -9
- flyte/_protos/workflow/queue_service_pb2.py +22 -24
- flyte/_task.py +8 -2
- flyte/_task_environment.py +26 -4
- flyte/_version.py +2 -2
- flyte/errors.py +10 -0
- flyte/extras/_container.py +17 -6
- flyte/models.py +3 -0
- flyte/remote/_task.py +3 -1
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/METADATA +57 -85
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/RECORD +19 -23
- flyte/migrate/__init__.py +0 -1
- flyte/migrate/dynamic.py +0 -13
- flyte/migrate/task.py +0 -99
- flyte/migrate/workflow.py +0 -13
- {flyte-2.0.0b1.data → flyte-2.0.0b3.data}/scripts/runtime.py +0 -0
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/WHEEL +0 -0
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/entry_points.txt +0 -0
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/licenses/LICENSE +0 -0
- {flyte-2.0.0b1.dist-info → flyte-2.0.0b3.dist-info}/top_level.txt +0 -0
|
@@ -41,7 +41,9 @@ class Controller(Protocol):
|
|
|
41
41
|
"""
|
|
42
42
|
...
|
|
43
43
|
|
|
44
|
-
async def submit_task_ref(
|
|
44
|
+
async def submit_task_ref(
|
|
45
|
+
self, _task: task_definition_pb2.TaskDetails, max_inline_io_bytes: int, *args, **kwargs
|
|
46
|
+
) -> Any:
|
|
45
47
|
"""
|
|
46
48
|
Submit a task reference to the controller asynchronously and wait for the result. This is async and will block
|
|
47
49
|
the current coroutine until the result is available.
|
|
@@ -192,5 +192,7 @@ class LocalController:
|
|
|
192
192
|
assert info.start_time
|
|
193
193
|
assert info.end_time
|
|
194
194
|
|
|
195
|
-
async def submit_task_ref(
|
|
195
|
+
async def submit_task_ref(
|
|
196
|
+
self, _task: task_definition_pb2.TaskDetails, max_inline_io_bytes: int, *args, **kwargs
|
|
197
|
+
) -> Any:
|
|
196
198
|
raise flyte.errors.ReferenceTaskError("Reference tasks cannot be executed locally, only remotely.")
|
|
@@ -7,7 +7,7 @@ import threading
|
|
|
7
7
|
from collections import defaultdict
|
|
8
8
|
from collections.abc import Callable
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Any,
|
|
10
|
+
from typing import Any, Awaitable, DefaultDict, Tuple, TypeVar
|
|
11
11
|
|
|
12
12
|
import flyte
|
|
13
13
|
import flyte.errors
|
|
@@ -27,22 +27,30 @@ from flyte._protos.common import identifier_pb2
|
|
|
27
27
|
from flyte._protos.workflow import run_definition_pb2, task_definition_pb2
|
|
28
28
|
from flyte._task import TaskTemplate
|
|
29
29
|
from flyte._utils.helpers import _selector_policy
|
|
30
|
-
from flyte.models import ActionID, NativeInterface, SerializationContext
|
|
30
|
+
from flyte.models import MAX_INLINE_IO_BYTES, ActionID, NativeInterface, SerializationContext
|
|
31
31
|
|
|
32
32
|
R = TypeVar("R")
|
|
33
33
|
|
|
34
|
+
MAX_TRACE_BYTES = MAX_INLINE_IO_BYTES
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
|
|
37
|
+
async def upload_inputs_with_retry(serialized_inputs: bytes, inputs_uri: str, max_bytes: int) -> None:
|
|
36
38
|
"""
|
|
37
39
|
Upload inputs to the specified URI with error handling.
|
|
38
40
|
|
|
39
41
|
Args:
|
|
40
42
|
serialized_inputs: The serialized inputs to upload
|
|
41
43
|
inputs_uri: The destination URI
|
|
44
|
+
max_bytes: Maximum number of bytes to read from the input stream
|
|
42
45
|
|
|
43
46
|
Raises:
|
|
44
47
|
RuntimeSystemError: If the upload fails
|
|
45
48
|
"""
|
|
49
|
+
if len(serialized_inputs) > max_bytes:
|
|
50
|
+
raise flyte.errors.InlineIOMaxBytesBreached(
|
|
51
|
+
f"Inputs exceed max_bytes limit of {max_bytes / 1024 / 1024} MB,"
|
|
52
|
+
f" actual size: {len(serialized_inputs) / 1024 / 1024} MB"
|
|
53
|
+
)
|
|
46
54
|
try:
|
|
47
55
|
# TODO Add retry decorator to this
|
|
48
56
|
await storage.put_stream(serialized_inputs, to_path=inputs_uri)
|
|
@@ -80,19 +88,20 @@ async def handle_action_failure(action: Action, task_name: str) -> Exception:
|
|
|
80
88
|
return exc
|
|
81
89
|
|
|
82
90
|
|
|
83
|
-
async def load_and_convert_outputs(iface: NativeInterface, realized_outputs_uri: str) -> Any:
|
|
91
|
+
async def load_and_convert_outputs(iface: NativeInterface, realized_outputs_uri: str, max_bytes: int) -> Any:
|
|
84
92
|
"""
|
|
85
93
|
Load outputs from the given URI and convert them to native format.
|
|
86
94
|
|
|
87
95
|
Args:
|
|
88
96
|
iface: The Native interface
|
|
89
97
|
realized_outputs_uri: The URI where outputs are stored
|
|
98
|
+
max_bytes: Maximum number of bytes to read from the output file
|
|
90
99
|
|
|
91
100
|
Returns:
|
|
92
101
|
The converted native outputs
|
|
93
102
|
"""
|
|
94
103
|
outputs_file_path = io.outputs_path(realized_outputs_uri)
|
|
95
|
-
outputs = await io.load_outputs(outputs_file_path)
|
|
104
|
+
outputs = await io.load_outputs(outputs_file_path, max_bytes=max_bytes)
|
|
96
105
|
return await convert.convert_outputs_to_native(iface, outputs)
|
|
97
106
|
|
|
98
107
|
|
|
@@ -191,7 +200,7 @@ class RemoteController(Controller):
|
|
|
191
200
|
|
|
192
201
|
serialized_inputs = inputs.proto_inputs.SerializeToString(deterministic=True)
|
|
193
202
|
inputs_uri = io.inputs_path(sub_action_output_path)
|
|
194
|
-
await upload_inputs_with_retry(serialized_inputs, inputs_uri)
|
|
203
|
+
await upload_inputs_with_retry(serialized_inputs, inputs_uri, max_bytes=_task.max_inline_io_bytes)
|
|
195
204
|
|
|
196
205
|
md = task_spec.task_template.metadata
|
|
197
206
|
ignored_input_vars = []
|
|
@@ -254,7 +263,9 @@ class RemoteController(Controller):
|
|
|
254
263
|
"RuntimeError",
|
|
255
264
|
f"Task {n.action_id.name} did not return an output path, but the task has outputs defined.",
|
|
256
265
|
)
|
|
257
|
-
return await load_and_convert_outputs(
|
|
266
|
+
return await load_and_convert_outputs(
|
|
267
|
+
_task.native_interface, n.realized_outputs_uri, max_bytes=_task.max_inline_io_bytes
|
|
268
|
+
)
|
|
258
269
|
return None
|
|
259
270
|
|
|
260
271
|
async def submit(self, _task: TaskTemplate, *args, **kwargs) -> Any:
|
|
@@ -357,7 +368,7 @@ class RemoteController(Controller):
|
|
|
357
368
|
)
|
|
358
369
|
|
|
359
370
|
inputs_uri = io.inputs_path(sub_action_output_path)
|
|
360
|
-
await upload_inputs_with_retry(serialized_inputs, inputs_uri)
|
|
371
|
+
await upload_inputs_with_retry(serialized_inputs, inputs_uri, max_bytes=MAX_TRACE_BYTES)
|
|
361
372
|
# Clear to free memory
|
|
362
373
|
serialized_inputs = None # type: ignore
|
|
363
374
|
|
|
@@ -388,7 +399,7 @@ class RemoteController(Controller):
|
|
|
388
399
|
logger.warning(f"Action {prev_action.action_id.name} failed, but no error was found, re-running trace!")
|
|
389
400
|
elif prev_action.realized_outputs_uri is not None:
|
|
390
401
|
outputs_file_path = io.outputs_path(prev_action.realized_outputs_uri)
|
|
391
|
-
o = await io.load_outputs(outputs_file_path)
|
|
402
|
+
o = await io.load_outputs(outputs_file_path, max_bytes=MAX_TRACE_BYTES)
|
|
392
403
|
outputs = await convert.convert_outputs_to_native(_interface, o)
|
|
393
404
|
return (
|
|
394
405
|
TraceInfo(func_name, sub_action_id, _interface, inputs_uri, output=outputs),
|
|
@@ -421,7 +432,7 @@ class RemoteController(Controller):
|
|
|
421
432
|
f"Uploading outputs for {info.name} Outputs file path: {outputs_file_path}",
|
|
422
433
|
flush=True,
|
|
423
434
|
)
|
|
424
|
-
await io.upload_outputs(outputs, sub_run_output_path)
|
|
435
|
+
await io.upload_outputs(outputs, sub_run_output_path, max_bytes=MAX_TRACE_BYTES)
|
|
425
436
|
elif info.error:
|
|
426
437
|
err = convert.convert_from_native_to_error(info.error)
|
|
427
438
|
await io.upload_error(err.err, sub_run_output_path)
|
|
@@ -461,7 +472,9 @@ class RemoteController(Controller):
|
|
|
461
472
|
# If the action is cancelled, we need to cancel the action on the server as well
|
|
462
473
|
raise
|
|
463
474
|
|
|
464
|
-
async def submit_task_ref(
|
|
475
|
+
async def submit_task_ref(
|
|
476
|
+
self, _task: task_definition_pb2.TaskDetails, max_inline_io_bytes: int, *args, **kwargs
|
|
477
|
+
) -> Any:
|
|
465
478
|
ctx = internal_ctx()
|
|
466
479
|
tctx = ctx.data.task_context
|
|
467
480
|
if tctx is None:
|
|
@@ -482,7 +495,7 @@ class RemoteController(Controller):
|
|
|
482
495
|
|
|
483
496
|
serialized_inputs = inputs.proto_inputs.SerializeToString(deterministic=True)
|
|
484
497
|
inputs_uri = io.inputs_path(sub_action_output_path)
|
|
485
|
-
await upload_inputs_with_retry(serialized_inputs, inputs_uri)
|
|
498
|
+
await upload_inputs_with_retry(serialized_inputs, inputs_uri, max_inline_io_bytes)
|
|
486
499
|
# cache key - task name, task signature, inputs, cache version
|
|
487
500
|
cache_key = None
|
|
488
501
|
md = _task.spec.task_template.metadata
|
|
@@ -545,5 +558,5 @@ class RemoteController(Controller):
|
|
|
545
558
|
"RuntimeError",
|
|
546
559
|
f"Task {n.action_id.name} did not return an output path, but the task has outputs defined.",
|
|
547
560
|
)
|
|
548
|
-
return await load_and_convert_outputs(native_interface, n.realized_outputs_uri)
|
|
561
|
+
return await load_and_convert_outputs(native_interface, n.realized_outputs_uri, max_inline_io_bytes)
|
|
549
562
|
return None
|
flyte/_internal/runtime/io.py
CHANGED
|
@@ -5,14 +5,11 @@ It uses the storage module to handle the actual uploading and downloading of fil
|
|
|
5
5
|
TODO: Convert to use streaming apis
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import logging
|
|
9
|
-
|
|
10
8
|
from flyteidl.core import errors_pb2, execution_pb2
|
|
11
9
|
|
|
12
10
|
import flyte.storage as storage
|
|
13
11
|
from flyte._protos.workflow import run_definition_pb2
|
|
14
12
|
|
|
15
|
-
from ..._logging import log
|
|
16
13
|
from .convert import Inputs, Outputs, _clean_error_code
|
|
17
14
|
|
|
18
15
|
# ------------------------------- CONSTANTS ------------------------------- #
|
|
@@ -55,11 +52,19 @@ async def upload_inputs(inputs: Inputs, input_path: str):
|
|
|
55
52
|
await storage.put_stream(data_iterable=inputs.proto_inputs.SerializeToString(), to_path=input_path)
|
|
56
53
|
|
|
57
54
|
|
|
58
|
-
async def upload_outputs(outputs: Outputs, output_path: str):
|
|
55
|
+
async def upload_outputs(outputs: Outputs, output_path: str, max_bytes: int = -1):
|
|
59
56
|
"""
|
|
60
57
|
:param outputs: Outputs
|
|
61
58
|
:param output_path: The path to upload the output file.
|
|
59
|
+
:param max_bytes: Maximum number of bytes to write to the output file. Default is -1, which means no limit.
|
|
62
60
|
"""
|
|
61
|
+
if max_bytes != -1 and outputs.proto_outputs.ByteSize() > max_bytes:
|
|
62
|
+
import flyte.errors
|
|
63
|
+
|
|
64
|
+
raise flyte.errors.InlineIOMaxBytesBreached(
|
|
65
|
+
f"Output file at {output_path} exceeds max_bytes limit of {max_bytes},"
|
|
66
|
+
f" size: {outputs.proto_outputs.ByteSize()}"
|
|
67
|
+
)
|
|
63
68
|
output_uri = outputs_path(output_path)
|
|
64
69
|
await storage.put_stream(data_iterable=outputs.proto_outputs.SerializeToString(), to_path=output_uri)
|
|
65
70
|
|
|
@@ -85,25 +90,59 @@ async def upload_error(err: execution_pb2.ExecutionError, output_prefix: str):
|
|
|
85
90
|
|
|
86
91
|
|
|
87
92
|
# ------------------------------- DOWNLOAD Methods ------------------------------- #
|
|
88
|
-
|
|
89
|
-
async def load_inputs(path: str) -> Inputs:
|
|
93
|
+
async def load_inputs(path: str, max_bytes: int = -1) -> Inputs:
|
|
90
94
|
"""
|
|
91
95
|
:param path: Input file to be downloaded
|
|
96
|
+
:param max_bytes: Maximum number of bytes to read from the input file. Default is -1, which means no limit.
|
|
92
97
|
:return: Inputs object
|
|
93
98
|
"""
|
|
94
99
|
lm = run_definition_pb2.Inputs()
|
|
95
|
-
|
|
100
|
+
|
|
101
|
+
if max_bytes == -1:
|
|
102
|
+
proto_str = b"".join([c async for c in storage.get_stream(path=path)])
|
|
103
|
+
else:
|
|
104
|
+
proto_bytes = []
|
|
105
|
+
total_bytes = 0
|
|
106
|
+
async for chunk in storage.get_stream(path=path):
|
|
107
|
+
if total_bytes + len(chunk) > max_bytes:
|
|
108
|
+
import flyte.errors
|
|
109
|
+
|
|
110
|
+
raise flyte.errors.InlineIOMaxBytesBreached(
|
|
111
|
+
f"Input file at {path} exceeds max_bytes limit of {max_bytes}"
|
|
112
|
+
)
|
|
113
|
+
proto_bytes.append(chunk)
|
|
114
|
+
total_bytes += len(chunk)
|
|
115
|
+
proto_str = b"".join(proto_bytes)
|
|
116
|
+
|
|
96
117
|
lm.ParseFromString(proto_str)
|
|
97
118
|
return Inputs(proto_inputs=lm)
|
|
98
119
|
|
|
99
120
|
|
|
100
|
-
async def load_outputs(path: str) -> Outputs:
|
|
121
|
+
async def load_outputs(path: str, max_bytes: int = -1) -> Outputs:
|
|
101
122
|
"""
|
|
102
123
|
:param path: output file to be loaded
|
|
124
|
+
:param max_bytes: Maximum number of bytes to read from the output file.
|
|
125
|
+
If -1, reads the entire file.
|
|
103
126
|
:return: Outputs object
|
|
104
127
|
"""
|
|
105
128
|
lm = run_definition_pb2.Outputs()
|
|
106
|
-
|
|
129
|
+
|
|
130
|
+
if max_bytes == -1:
|
|
131
|
+
proto_str = b"".join([c async for c in storage.get_stream(path=path)])
|
|
132
|
+
else:
|
|
133
|
+
proto_bytes = []
|
|
134
|
+
total_bytes = 0
|
|
135
|
+
async for chunk in storage.get_stream(path=path):
|
|
136
|
+
if total_bytes + len(chunk) > max_bytes:
|
|
137
|
+
import flyte.errors
|
|
138
|
+
|
|
139
|
+
raise flyte.errors.InlineIOMaxBytesBreached(
|
|
140
|
+
f"Output file at {path} exceeds max_bytes limit of {max_bytes}"
|
|
141
|
+
)
|
|
142
|
+
proto_bytes.append(chunk)
|
|
143
|
+
total_bytes += len(chunk)
|
|
144
|
+
proto_str = b"".join(proto_bytes)
|
|
145
|
+
|
|
107
146
|
lm.ParseFromString(proto_str)
|
|
108
147
|
return Outputs(proto_outputs=lm)
|
|
109
148
|
|
|
@@ -20,7 +20,7 @@ from flyte._protos.workflow import run_definition_pb2 as workflow_dot_run__defin
|
|
|
20
20
|
from flyte._protos.workflow import task_definition_pb2 as workflow_dot_task__definition__pb2
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cworkflow/queue_service.proto\x12\x11\x63loudidl.workflow\x1a\x17\x63ommon/identifier.proto\x1a\x19\x66lyteidl/core/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x17validate/validate.proto\x1a\x1dworkflow/run_definition.proto\x1a\x1eworkflow/task_definition.proto\"\x7f\n\x10WorkerIdentifier\x12+\n\x0corganization\x18\x01 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x0corganization\x12!\n\x07\x63luster\x18\x02 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x07\x63luster\x12\x1b\n\x04name\x18\x03 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x04name\"\xbf\x04\n\x14\x45nqueueActionRequest\x12H\n\taction_id\x18\x01 \x01(\x0b\x32!.cloudidl.common.ActionIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x08\x61\x63tionId\x12\x31\n\x12parent_action_name\x18\x02 \x01(\tH\x01R\x10parentActionName\x88\x01\x01\x12\x35\n\x08run_spec\x18\x03 \x01(\x0b\x32\x1a.cloudidl.workflow.RunSpecR\x07runSpec\x12$\n\tinput_uri\x18\x06 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x08inputUri\x12/\n\x0frun_output_base\x18\x07 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\rrunOutputBase\x12\x14\n\x05group\x18\x08 \x01(\tR\x05group\x12\x18\n\x07subject\x18\t \x01(\tR\x07subject\x12=\n\x04task\x18\n \x01(\x0b\x32\x1d.cloudidl.workflow.TaskActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x04task\x12@\n\x05trace\x18\x0b \x01(\x0b\x32\x1e.cloudidl.workflow.TraceActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x05trace\x12L\n\tcondition\x18\x0c \x01(\x0b\x32\".cloudidl.workflow.ConditionActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\tconditionB\x06\n\x04specB\x15\n\x13_parent_action_name\"\xb5\x01\n\nTaskAction\x12\x31\n\x02id\x18\x01 \x01(\x0b\x32!.cloudidl.workflow.TaskIdentifierR\x02id\x12\x39\n\x04spec\x18\x02 \x01(\x0b\x32\x1b.cloudidl.workflow.TaskSpecB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x04spec\x12\x39\n\tcache_key\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.StringValueR\x08\x63\x61\x63heKey\"\
|
|
23
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cworkflow/queue_service.proto\x12\x11\x63loudidl.workflow\x1a\x17\x63ommon/identifier.proto\x1a\x19\x66lyteidl/core/types.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x17validate/validate.proto\x1a\x1dworkflow/run_definition.proto\x1a\x1eworkflow/task_definition.proto\"\x7f\n\x10WorkerIdentifier\x12+\n\x0corganization\x18\x01 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x0corganization\x12!\n\x07\x63luster\x18\x02 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x07\x63luster\x12\x1b\n\x04name\x18\x03 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x04name\"\xbf\x04\n\x14\x45nqueueActionRequest\x12H\n\taction_id\x18\x01 \x01(\x0b\x32!.cloudidl.common.ActionIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x08\x61\x63tionId\x12\x31\n\x12parent_action_name\x18\x02 \x01(\tH\x01R\x10parentActionName\x88\x01\x01\x12\x35\n\x08run_spec\x18\x03 \x01(\x0b\x32\x1a.cloudidl.workflow.RunSpecR\x07runSpec\x12$\n\tinput_uri\x18\x06 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x08inputUri\x12/\n\x0frun_output_base\x18\x07 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\rrunOutputBase\x12\x14\n\x05group\x18\x08 \x01(\tR\x05group\x12\x18\n\x07subject\x18\t \x01(\tR\x07subject\x12=\n\x04task\x18\n \x01(\x0b\x32\x1d.cloudidl.workflow.TaskActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x04task\x12@\n\x05trace\x18\x0b \x01(\x0b\x32\x1e.cloudidl.workflow.TraceActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x05trace\x12L\n\tcondition\x18\x0c \x01(\x0b\x32\".cloudidl.workflow.ConditionActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\tconditionB\x06\n\x04specB\x15\n\x13_parent_action_name\"\xb5\x01\n\nTaskAction\x12\x31\n\x02id\x18\x01 \x01(\x0b\x32!.cloudidl.workflow.TaskIdentifierR\x02id\x12\x39\n\x04spec\x18\x02 \x01(\x0b\x32\x1b.cloudidl.workflow.TaskSpecB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x04spec\x12\x39\n\tcache_key\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.StringValueR\x08\x63\x61\x63heKey\"\xce\x02\n\x0bTraceAction\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x04name\x12.\n\x05phase\x18\x02 \x01(\x0e\x32\x18.cloudidl.workflow.PhaseR\x05phase\x12\x39\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12:\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\x07\x65ndTime\x88\x01\x01\x12=\n\x07outputs\x18\x05 \x01(\x0b\x32#.cloudidl.workflow.OutputReferencesR\x07outputs\x12/\n\x04spec\x18\x06 \x01(\x0b\x32\x1b.cloudidl.workflow.TaskSpecR\x04specB\x0b\n\t_end_time\"\x8a\x02\n\x0f\x43onditionAction\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x04name\x12 \n\x06run_id\x18\x02 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01H\x00R\x05runId\x12&\n\taction_id\x18\x03 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01H\x00R\x08\x61\x63tionId\x12\x18\n\x06global\x18\x04 \x01(\x08H\x00R\x06global\x12.\n\x04type\x18\x06 \x01(\x0b\x32\x1a.flyteidl.core.LiteralTypeR\x04type\x12\x16\n\x06prompt\x18\x07 \x01(\tR\x06prompt\x12 \n\x0b\x64\x65scription\x18\x08 \x01(\tR\x0b\x64\x65scriptionB\x0c\n\x05scope\x12\x03\xf8\x42\x01\"\x17\n\x15\x45nqueueActionResponse\"X\n\x15\x41\x62ortQueuedRunRequest\x12?\n\x06run_id\x18\x01 \x01(\x0b\x32\x1e.cloudidl.common.RunIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x05runId\"\x18\n\x16\x41\x62ortQueuedRunResponse\"\x80\x03\n\x10HeartbeatRequest\x12J\n\tworker_id\x18\x01 \x01(\x0b\x32#.cloudidl.workflow.WorkerIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x08workerId\x12M\n\x11\x61\x63tive_action_ids\x18\x02 \x03(\x0b\x32!.cloudidl.common.ActionIdentifierR\x0f\x61\x63tiveActionIds\x12Q\n\x13terminal_action_ids\x18\x03 \x03(\x0b\x32!.cloudidl.common.ActionIdentifierR\x11terminalActionIds\x12O\n\x12\x61\x62orted_action_ids\x18\x04 \x03(\x0b\x32!.cloudidl.common.ActionIdentifierR\x10\x61\x62ortedActionIds\x12-\n\x12\x61vailable_capacity\x18\x05 \x01(\x05R\x11\x61vailableCapacity\"\xe2\x01\n\x11HeartbeatResponse\x12\x37\n\nnew_leases\x18\x01 \x03(\x0b\x32\x18.cloudidl.workflow.LeaseR\tnewLeases\x12?\n\x0e\x61\x62orted_leases\x18\x02 \x03(\x0b\x32\x18.cloudidl.workflow.LeaseR\rabortedLeases\x12S\n\x14\x66inalized_action_ids\x18\x03 \x03(\x0b\x32!.cloudidl.common.ActionIdentifierR\x12\x66inalizedActionIds\"a\n\x13StreamLeasesRequest\x12J\n\tworker_id\x18\x01 \x01(\x0b\x32#.cloudidl.workflow.WorkerIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x08workerId\"H\n\x14StreamLeasesResponse\x12\x30\n\x06leases\x18\x01 \x03(\x0b\x32\x18.cloudidl.workflow.LeaseR\x06leases\"\xc9\x04\n\x05Lease\x12H\n\taction_id\x18\x01 \x01(\x0b\x32!.cloudidl.common.ActionIdentifierB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01R\x08\x61\x63tionId\x12\x31\n\x12parent_action_name\x18\x02 \x01(\tH\x01R\x10parentActionName\x88\x01\x01\x12\x35\n\x08run_spec\x18\x03 \x01(\x0b\x32\x1a.cloudidl.workflow.RunSpecR\x07runSpec\x12$\n\tinput_uri\x18\x04 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\x08inputUri\x12/\n\x0frun_output_base\x18\x05 \x01(\tB\x07\xfa\x42\x04r\x02\x10\x01R\rrunOutputBase\x12=\n\x04task\x18\x06 \x01(\x0b\x32\x1d.cloudidl.workflow.TaskActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x04task\x12L\n\tcondition\x18\x07 \x01(\x0b\x32\".cloudidl.workflow.ConditionActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\tcondition\x12@\n\x05trace\x18\n \x01(\x0b\x32\x1e.cloudidl.workflow.TraceActionB\x08\xfa\x42\x05\x8a\x01\x02\x10\x01H\x00R\x05trace\x12\x14\n\x05group\x18\x08 \x01(\tR\x05group\x12\x18\n\x07subject\x18\t \x01(\tR\x07subject\x12\x12\n\x04host\x18\x0b \x01(\tR\x04hostB\x0b\n\x04spec\x12\x03\xf8\x42\x01\x42\x15\n\x13_parent_action_name2\xa0\x03\n\x0cQueueService\x12\x64\n\rEnqueueAction\x12\'.cloudidl.workflow.EnqueueActionRequest\x1a(.cloudidl.workflow.EnqueueActionResponse\"\x00\x12g\n\x0e\x41\x62ortQueuedRun\x12(.cloudidl.workflow.AbortQueuedRunRequest\x1a).cloudidl.workflow.AbortQueuedRunResponse\"\x00\x12\\\n\tHeartbeat\x12#.cloudidl.workflow.HeartbeatRequest\x1a$.cloudidl.workflow.HeartbeatResponse\"\x00(\x01\x30\x01\x12\x63\n\x0cStreamLeases\x12&.cloudidl.workflow.StreamLeasesRequest\x1a\'.cloudidl.workflow.StreamLeasesResponse\"\x00\x30\x01\x42\xbe\x01\n\x15\x63om.cloudidl.workflowB\x11QueueServiceProtoH\x02P\x01Z+github.com/unionai/cloud/gen/pb-go/workflow\xa2\x02\x03\x43WX\xaa\x02\x11\x43loudidl.Workflow\xca\x02\x11\x43loudidl\\Workflow\xe2\x02\x1d\x43loudidl\\Workflow\\GPBMetadata\xea\x02\x12\x43loudidl::Workflowb\x06proto3')
|
|
24
24
|
|
|
25
25
|
_globals = globals()
|
|
26
26
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -50,8 +50,6 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
50
50
|
_TASKACTION.fields_by_name['spec']._serialized_options = b'\372B\005\212\001\002\020\001'
|
|
51
51
|
_TRACEACTION.fields_by_name['name']._options = None
|
|
52
52
|
_TRACEACTION.fields_by_name['name']._serialized_options = b'\372B\004r\002\020\001'
|
|
53
|
-
_TRACEACTION.fields_by_name['spec']._options = None
|
|
54
|
-
_TRACEACTION.fields_by_name['spec']._serialized_options = b'\372B\005\212\001\002\020\001'
|
|
55
53
|
_CONDITIONACTION.oneofs_by_name['scope']._options = None
|
|
56
54
|
_CONDITIONACTION.oneofs_by_name['scope']._serialized_options = b'\370B\001'
|
|
57
55
|
_CONDITIONACTION.fields_by_name['name']._options = None
|
|
@@ -87,25 +85,25 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
87
85
|
_globals['_TASKACTION']._serialized_start=964
|
|
88
86
|
_globals['_TASKACTION']._serialized_end=1145
|
|
89
87
|
_globals['_TRACEACTION']._serialized_start=1148
|
|
90
|
-
_globals['_TRACEACTION']._serialized_end=
|
|
91
|
-
_globals['_CONDITIONACTION']._serialized_start=
|
|
92
|
-
_globals['_CONDITIONACTION']._serialized_end=
|
|
93
|
-
_globals['_ENQUEUEACTIONRESPONSE']._serialized_start=
|
|
94
|
-
_globals['_ENQUEUEACTIONRESPONSE']._serialized_end=
|
|
95
|
-
_globals['_ABORTQUEUEDRUNREQUEST']._serialized_start=
|
|
96
|
-
_globals['_ABORTQUEUEDRUNREQUEST']._serialized_end=
|
|
97
|
-
_globals['_ABORTQUEUEDRUNRESPONSE']._serialized_start=
|
|
98
|
-
_globals['_ABORTQUEUEDRUNRESPONSE']._serialized_end=
|
|
99
|
-
_globals['_HEARTBEATREQUEST']._serialized_start=
|
|
100
|
-
_globals['_HEARTBEATREQUEST']._serialized_end=
|
|
101
|
-
_globals['_HEARTBEATRESPONSE']._serialized_start=
|
|
102
|
-
_globals['_HEARTBEATRESPONSE']._serialized_end=
|
|
103
|
-
_globals['_STREAMLEASESREQUEST']._serialized_start=
|
|
104
|
-
_globals['_STREAMLEASESREQUEST']._serialized_end=
|
|
105
|
-
_globals['_STREAMLEASESRESPONSE']._serialized_start=
|
|
106
|
-
_globals['_STREAMLEASESRESPONSE']._serialized_end=
|
|
107
|
-
_globals['_LEASE']._serialized_start=
|
|
108
|
-
_globals['_LEASE']._serialized_end=
|
|
109
|
-
_globals['_QUEUESERVICE']._serialized_start=
|
|
110
|
-
_globals['_QUEUESERVICE']._serialized_end=
|
|
88
|
+
_globals['_TRACEACTION']._serialized_end=1482
|
|
89
|
+
_globals['_CONDITIONACTION']._serialized_start=1485
|
|
90
|
+
_globals['_CONDITIONACTION']._serialized_end=1751
|
|
91
|
+
_globals['_ENQUEUEACTIONRESPONSE']._serialized_start=1753
|
|
92
|
+
_globals['_ENQUEUEACTIONRESPONSE']._serialized_end=1776
|
|
93
|
+
_globals['_ABORTQUEUEDRUNREQUEST']._serialized_start=1778
|
|
94
|
+
_globals['_ABORTQUEUEDRUNREQUEST']._serialized_end=1866
|
|
95
|
+
_globals['_ABORTQUEUEDRUNRESPONSE']._serialized_start=1868
|
|
96
|
+
_globals['_ABORTQUEUEDRUNRESPONSE']._serialized_end=1892
|
|
97
|
+
_globals['_HEARTBEATREQUEST']._serialized_start=1895
|
|
98
|
+
_globals['_HEARTBEATREQUEST']._serialized_end=2279
|
|
99
|
+
_globals['_HEARTBEATRESPONSE']._serialized_start=2282
|
|
100
|
+
_globals['_HEARTBEATRESPONSE']._serialized_end=2508
|
|
101
|
+
_globals['_STREAMLEASESREQUEST']._serialized_start=2510
|
|
102
|
+
_globals['_STREAMLEASESREQUEST']._serialized_end=2607
|
|
103
|
+
_globals['_STREAMLEASESRESPONSE']._serialized_start=2609
|
|
104
|
+
_globals['_STREAMLEASESRESPONSE']._serialized_end=2681
|
|
105
|
+
_globals['_LEASE']._serialized_start=2684
|
|
106
|
+
_globals['_LEASE']._serialized_end=3269
|
|
107
|
+
_globals['_QUEUESERVICE']._serialized_start=3272
|
|
108
|
+
_globals['_QUEUESERVICE']._serialized_end=3688
|
|
111
109
|
# @@protoc_insertion_point(module_scope)
|
flyte/_task.py
CHANGED
|
@@ -33,7 +33,7 @@ from ._retry import RetryStrategy
|
|
|
33
33
|
from ._reusable_environment import ReusePolicy
|
|
34
34
|
from ._secret import SecretRequest
|
|
35
35
|
from ._timeout import TimeoutType
|
|
36
|
-
from .models import NativeInterface, SerializationContext
|
|
36
|
+
from .models import MAX_INLINE_IO_BYTES, NativeInterface, SerializationContext
|
|
37
37
|
|
|
38
38
|
if TYPE_CHECKING:
|
|
39
39
|
from flyteidl.core.tasks_pb2 import DataLoadingConfig
|
|
@@ -79,6 +79,8 @@ class TaskTemplate(Generic[P, R]):
|
|
|
79
79
|
:param env: Optional The environment variables to set for the task.
|
|
80
80
|
:param secrets: Optional The secrets that will be injected into the task at runtime.
|
|
81
81
|
:param timeout: Optional The timeout for the task.
|
|
82
|
+
:param max_inline_io_bytes: Maximum allowed size (in bytes) for all inputs and outputs passed directly to the task
|
|
83
|
+
(e.g., primitives, strings, dicts). Does not apply to files, directories, or dataframes.
|
|
82
84
|
"""
|
|
83
85
|
|
|
84
86
|
name: str
|
|
@@ -100,8 +102,8 @@ class TaskTemplate(Generic[P, R]):
|
|
|
100
102
|
report: bool = False
|
|
101
103
|
|
|
102
104
|
parent_env: Optional[weakref.ReferenceType[TaskEnvironment]] = None
|
|
103
|
-
local: bool = field(default=False, init=False)
|
|
104
105
|
ref: bool = field(default=False, init=False, repr=False, compare=False)
|
|
106
|
+
max_inline_io_bytes: int = MAX_INLINE_IO_BYTES
|
|
105
107
|
|
|
106
108
|
# Only used in python 3.10 and 3.11, where we cannot use markcoroutinefunction
|
|
107
109
|
_call_as_synchronous: bool = False
|
|
@@ -315,6 +317,7 @@ class TaskTemplate(Generic[P, R]):
|
|
|
315
317
|
reusable: Union[ReusePolicy, Literal["off"], None] = None,
|
|
316
318
|
env: Optional[Dict[str, str]] = None,
|
|
317
319
|
secrets: Optional[SecretRequest] = None,
|
|
320
|
+
max_inline_io_bytes: int | None = None,
|
|
318
321
|
**kwargs: Any,
|
|
319
322
|
) -> TaskTemplate:
|
|
320
323
|
"""
|
|
@@ -324,6 +327,8 @@ class TaskTemplate(Generic[P, R]):
|
|
|
324
327
|
cache = cache or self.cache
|
|
325
328
|
retries = retries or self.retries
|
|
326
329
|
timeout = timeout or self.timeout
|
|
330
|
+
max_inline_io_bytes = max_inline_io_bytes or self.max_inline_io_bytes
|
|
331
|
+
|
|
327
332
|
reusable = reusable or self.reusable
|
|
328
333
|
if reusable == "off":
|
|
329
334
|
reusable = None
|
|
@@ -371,6 +376,7 @@ class TaskTemplate(Generic[P, R]):
|
|
|
371
376
|
reusable=cast(Optional[ReusePolicy], reusable),
|
|
372
377
|
env=env,
|
|
373
378
|
secrets=secrets,
|
|
379
|
+
max_inline_io_bytes=max_inline_io_bytes,
|
|
374
380
|
)
|
|
375
381
|
|
|
376
382
|
|
flyte/_task_environment.py
CHANGED
|
@@ -27,7 +27,7 @@ from ._retry import RetryStrategy
|
|
|
27
27
|
from ._reusable_environment import ReusePolicy
|
|
28
28
|
from ._secret import SecretRequest
|
|
29
29
|
from ._task import AsyncFunctionTaskTemplate, TaskTemplate
|
|
30
|
-
from .models import NativeInterface
|
|
30
|
+
from .models import MAX_INLINE_IO_BYTES, NativeInterface
|
|
31
31
|
|
|
32
32
|
if TYPE_CHECKING:
|
|
33
33
|
from kubernetes.client import V1PodTemplate
|
|
@@ -55,8 +55,9 @@ class TaskEnvironment(Environment):
|
|
|
55
55
|
:param resources: Resources to allocate for the environment.
|
|
56
56
|
:param env: Environment variables to set for the environment.
|
|
57
57
|
:param secrets: Secrets to inject into the environment.
|
|
58
|
-
:param depends_on: Environment dependencies to hint, so when you deploy the environment,
|
|
59
|
-
also deployed. This is useful when you have a set of environments
|
|
58
|
+
:param depends_on: Environment dependencies to hint, so when you deploy the environment,
|
|
59
|
+
the dependencies are also deployed. This is useful when you have a set of environments
|
|
60
|
+
that depend on each other.
|
|
60
61
|
:param cache: Cache policy for the environment.
|
|
61
62
|
:param reusable: Reuse policy for the environment, if set, a python process may be reused for multiple tasks.
|
|
62
63
|
"""
|
|
@@ -86,8 +87,18 @@ class TaskEnvironment(Environment):
|
|
|
86
87
|
) -> TaskEnvironment:
|
|
87
88
|
"""
|
|
88
89
|
Clone the TaskEnvironment with new parameters.
|
|
89
|
-
besides the base environment parameters, you can override, kwargs like `cache`, `reusable`, etc.
|
|
90
90
|
|
|
91
|
+
Besides the base environment parameters, you can override kwargs like `cache`, `reusable`, etc.
|
|
92
|
+
|
|
93
|
+
:param name: The name of the environment.
|
|
94
|
+
:param image: The image to use for the environment.
|
|
95
|
+
:param resources: The resources to allocate for the environment.
|
|
96
|
+
:param env: The environment variables to set for the environment.
|
|
97
|
+
:param secrets: The secrets to inject into the environment.
|
|
98
|
+
:param depends_on: The environment dependencies to hint, so when you deploy the environment,
|
|
99
|
+
the dependencies are also deployed. This is useful when you have a set of environments
|
|
100
|
+
that depend on each other.
|
|
101
|
+
:param kwargs: Additional parameters to override the environment (e.g., cache, reusable, plugin_config).
|
|
91
102
|
"""
|
|
92
103
|
cache = kwargs.pop("cache", None)
|
|
93
104
|
reusable = None
|
|
@@ -130,9 +141,13 @@ class TaskEnvironment(Environment):
|
|
|
130
141
|
secrets: Optional[SecretRequest] = None,
|
|
131
142
|
pod_template: Optional[Union[str, "V1PodTemplate"]] = None,
|
|
132
143
|
report: bool = False,
|
|
144
|
+
max_inline_io_bytes: int = MAX_INLINE_IO_BYTES,
|
|
133
145
|
) -> Union[AsyncFunctionTaskTemplate, Callable[P, R]]:
|
|
134
146
|
"""
|
|
147
|
+
Decorate a function to be a task.
|
|
148
|
+
|
|
135
149
|
:param _func: Optional The function to decorate. If not provided, the decorator will return a callable that
|
|
150
|
+
accepts a function to be decorated.
|
|
136
151
|
:param name: Optional A friendly name for the task (defaults to the function name)
|
|
137
152
|
:param cache: Optional The cache policy for the task, defaults to auto, which will cache the results of the
|
|
138
153
|
task.
|
|
@@ -143,6 +158,8 @@ class TaskEnvironment(Environment):
|
|
|
143
158
|
:param pod_template: Optional The pod template for the task, if not provided the default pod template will be
|
|
144
159
|
used.
|
|
145
160
|
:param report: Optional Whether to generate the html report for the task, defaults to False.
|
|
161
|
+
:param max_inline_io_bytes: Maximum allowed size (in bytes) for all inputs and outputs passed directly to the
|
|
162
|
+
task (e.g., primitives, strings, dicts). Does not apply to files, directories, or dataframes.
|
|
146
163
|
"""
|
|
147
164
|
from ._task import P, R
|
|
148
165
|
|
|
@@ -194,6 +211,7 @@ class TaskEnvironment(Environment):
|
|
|
194
211
|
report=report,
|
|
195
212
|
friendly_name=friendly_name,
|
|
196
213
|
plugin_config=self.plugin_config,
|
|
214
|
+
max_inline_io_bytes=max_inline_io_bytes,
|
|
197
215
|
)
|
|
198
216
|
self._tasks[task_name] = tmpl
|
|
199
217
|
return tmpl
|
|
@@ -212,6 +230,10 @@ class TaskEnvironment(Environment):
|
|
|
212
230
|
def add_task(self, task: TaskTemplate) -> TaskTemplate:
|
|
213
231
|
"""
|
|
214
232
|
Add a task to the environment.
|
|
233
|
+
|
|
234
|
+
Useful when you want to add a task to an environment that is not defined using the `task` decorator.
|
|
235
|
+
|
|
236
|
+
:param task: The TaskTemplate to add to this environment.
|
|
215
237
|
"""
|
|
216
238
|
if task.name in self._tasks:
|
|
217
239
|
raise ValueError(f"Task {task.name} already exists in the environment. Task names should be unique.")
|
flyte/_version.py
CHANGED
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '2.0.
|
|
21
|
-
__version_tuple__ = version_tuple = (2, 0, 0, '
|
|
20
|
+
__version__ = version = '2.0.0b3'
|
|
21
|
+
__version_tuple__ = version_tuple = (2, 0, 0, 'b3')
|
flyte/errors.py
CHANGED
|
@@ -179,3 +179,13 @@ class ImageBuildError(RuntimeUserError):
|
|
|
179
179
|
|
|
180
180
|
def __init__(self, message: str):
|
|
181
181
|
super().__init__("ImageBuildError", message, "user")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class InlineIOMaxBytesBreached(RuntimeUserError):
|
|
185
|
+
"""
|
|
186
|
+
This error is raised when the inline IO max bytes limit is breached.
|
|
187
|
+
This can be adjusted per task by setting max_inline_io_bytes in the task definition.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
def __init__(self, message: str):
|
|
191
|
+
super().__init__("InlineIOMaxBytesBreached", message, "user")
|
flyte/extras/_container.py
CHANGED
|
@@ -7,6 +7,7 @@ from flyteidl.core import tasks_pb2
|
|
|
7
7
|
from flyte import Image, storage
|
|
8
8
|
from flyte._logging import logger
|
|
9
9
|
from flyte._task import TaskTemplate
|
|
10
|
+
from flyte.io import Dir, File
|
|
10
11
|
from flyte.models import NativeInterface, SerializationContext
|
|
11
12
|
|
|
12
13
|
|
|
@@ -191,7 +192,9 @@ class ContainerTask(TaskTemplate):
|
|
|
191
192
|
microseconds=microseconds,
|
|
192
193
|
)
|
|
193
194
|
|
|
194
|
-
def _convert_output_val_to_correct_type(
|
|
195
|
+
async def _convert_output_val_to_correct_type(
|
|
196
|
+
self, output_path: pathlib.Path, output_val: Any, output_type: Type
|
|
197
|
+
) -> Any:
|
|
195
198
|
import datetime
|
|
196
199
|
|
|
197
200
|
if issubclass(output_type, bool):
|
|
@@ -200,17 +203,25 @@ class ContainerTask(TaskTemplate):
|
|
|
200
203
|
return datetime.datetime.fromisoformat(output_val)
|
|
201
204
|
elif issubclass(output_type, datetime.timedelta):
|
|
202
205
|
return self._string_to_timedelta(output_val)
|
|
206
|
+
elif issubclass(output_type, File):
|
|
207
|
+
return await File.from_local(output_path)
|
|
208
|
+
elif issubclass(output_type, Dir):
|
|
209
|
+
return await Dir.from_local(output_path)
|
|
203
210
|
else:
|
|
204
211
|
return output_type(output_val)
|
|
205
212
|
|
|
206
|
-
def _get_output(self, output_directory: pathlib.Path) -> Tuple[Any]:
|
|
213
|
+
async def _get_output(self, output_directory: pathlib.Path) -> Tuple[Any]:
|
|
207
214
|
output_items = []
|
|
208
215
|
if self._outputs:
|
|
209
216
|
for k, output_type in self._outputs.items():
|
|
210
217
|
output_path = output_directory / k
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
218
|
+
if os.path.isfile(output_path):
|
|
219
|
+
with output_path.open("r") as f:
|
|
220
|
+
output_val = f.read()
|
|
221
|
+
else:
|
|
222
|
+
output_val = None
|
|
223
|
+
parsed = await self._convert_output_val_to_correct_type(output_path, output_val, output_type)
|
|
224
|
+
output_items.append(parsed)
|
|
214
225
|
# return a tuple so that each element is treated as a separate output.
|
|
215
226
|
# this allows flyte to map the user-defined output types (dict) to individual values.
|
|
216
227
|
# if we returned a list instead, it would be treated as a single output.
|
|
@@ -249,7 +260,7 @@ class ContainerTask(TaskTemplate):
|
|
|
249
260
|
|
|
250
261
|
container.wait()
|
|
251
262
|
|
|
252
|
-
output = self._get_output(output_directory)
|
|
263
|
+
output = await self._get_output(output_directory)
|
|
253
264
|
return output
|
|
254
265
|
|
|
255
266
|
def data_loading_config(self, sctx: SerializationContext) -> tasks_pb2.DataLoadingConfig:
|
flyte/models.py
CHANGED
flyte/remote/_task.py
CHANGED
|
@@ -81,6 +81,7 @@ AutoVersioning = Literal["latest", "current"]
|
|
|
81
81
|
@dataclass
|
|
82
82
|
class TaskDetails:
|
|
83
83
|
pb2: task_definition_pb2.TaskDetails
|
|
84
|
+
max_inline_io_bytes: int = 10 * 1024 * 1024 # 10 MB
|
|
84
85
|
|
|
85
86
|
@classmethod
|
|
86
87
|
def get(
|
|
@@ -252,7 +253,7 @@ class TaskDetails:
|
|
|
252
253
|
|
|
253
254
|
controller = get_controller()
|
|
254
255
|
if controller:
|
|
255
|
-
return await controller.submit_task_ref(self.pb2, *args, **kwargs)
|
|
256
|
+
return await controller.submit_task_ref(self.pb2, self.max_inline_io_bytes, *args, **kwargs)
|
|
256
257
|
raise flyte.errors
|
|
257
258
|
|
|
258
259
|
def override(
|
|
@@ -267,6 +268,7 @@ class TaskDetails:
|
|
|
267
268
|
reusable: Union[flyte.ReusePolicy, Literal["auto"], None] = None,
|
|
268
269
|
env: Optional[Dict[str, str]] = None,
|
|
269
270
|
secrets: Optional[flyte.SecretRequest] = None,
|
|
271
|
+
max_inline_io_bytes: int | None = None,
|
|
270
272
|
**kwargs: Any,
|
|
271
273
|
) -> TaskDetails:
|
|
272
274
|
raise NotImplementedError
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flyte
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b3
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Author-email: Ketan Umare <kumare3@users.noreply.github.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -8,7 +8,7 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Requires-Dist: aiofiles>=24.1.0
|
|
10
10
|
Requires-Dist: click>=8.2.1
|
|
11
|
-
Requires-Dist: flyteidl
|
|
11
|
+
Requires-Dist: flyteidl>=1.15.4b0
|
|
12
12
|
Requires-Dist: cloudpickle>=3.1.1
|
|
13
13
|
Requires-Dist: fsspec>=2025.3.0
|
|
14
14
|
Requires-Dist: grpcio>=1.71.0
|
|
@@ -36,6 +36,14 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
> ⚡ **Pure Python workflows** • 🔄 **Async-first parallelism** • 🛠️ **Zero DSL constraints** • 📊 **Sub-task observability**
|
|
38
38
|
|
|
39
|
+
## 🌍 Ecosystem & Resources
|
|
40
|
+
|
|
41
|
+
- **📖 Documentation**: [Docs Link](https://www.union.ai/docs/v2/flyte/user-guide/)
|
|
42
|
+
- **▶️ Getting Started**: [Docs Link](https://www.union.ai/docs/v2/flyte/user-guide/getting-started/)
|
|
43
|
+
- **💬 Community**: [Slack](https://slack.flyte.org/) | [GitHub Discussions](https://github.com/flyteorg/flyte/discussions)
|
|
44
|
+
- **🎓 Examples**: [GitHub Examples](https://github.com/flyteorg/flyte-sdk/tree/main/examples)
|
|
45
|
+
- **🐛 Issues**: [Bug Reports](https://github.com/flyteorg/flyte/issues)
|
|
46
|
+
|
|
39
47
|
## What is Flyte 2?
|
|
40
48
|
|
|
41
49
|
Flyte 2 represents a fundamental shift from constrained domain-specific languages to **pure Python workflows**. Write data pipelines, ML training jobs, and distributed compute exactly like you write Python—because it *is* Python.
|
|
@@ -65,21 +73,11 @@ if __name__ == "__main__":
|
|
|
65
73
|
|
|
66
74
|
## 🌟 Why Flyte 2?
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- ❌ Custom `map()` functions and workflow-specific parallel constructs
|
|
74
|
-
- ✅ **Native `asyncio`**: `await asyncio.gather()` for distributed parallel execution
|
|
75
|
-
|
|
76
|
-
### **True Container Reusability**
|
|
77
|
-
- ❌ Cold container starts for every task
|
|
78
|
-
- ✅ **Millisecond scheduling** with warm, reusable container pools
|
|
79
|
-
|
|
80
|
-
### **Fine-Grained Observability**
|
|
81
|
-
- ❌ Task-level logging only
|
|
82
|
-
- ✅ **Function-level tracing** with `@flyte.trace` for sub-task checkpoints
|
|
76
|
+
| Feature Highlight | Flyte 1 | Flyte 2 |
|
|
77
|
+
|-| ------- | ------- |
|
|
78
|
+
| **No More Workflow DSL** | ❌ `@workflow` decorators with Python subset limitations | ✅ **Pure Python**: loops, conditionals, error handling, dynamic structures |
|
|
79
|
+
| **Async-First Parallelism** | ❌ Custom `map()` functions and workflow-specific parallel constructs | ✅ **Native `asyncio`**: `await asyncio.gather()` for distributed parallel execution |
|
|
80
|
+
| **Fine-Grained Observability** | ❌ Task-level logging only | ✅ **Function-level tracing** with `@flyte.trace` for sub-task checkpoints |
|
|
83
81
|
|
|
84
82
|
## 🚀 Quick Start
|
|
85
83
|
|
|
@@ -102,13 +100,13 @@ uv pip install --prerelease=allow flyte
|
|
|
102
100
|
# hello.py
|
|
103
101
|
# /// script
|
|
104
102
|
# requires-python = ">=3.10"
|
|
105
|
-
# dependencies = ["flyte>=
|
|
103
|
+
# dependencies = ["flyte>=2.0.0b0"]
|
|
106
104
|
# ///
|
|
107
105
|
|
|
108
106
|
import flyte
|
|
109
107
|
|
|
110
108
|
env = flyte.TaskEnvironment(
|
|
111
|
-
name="hello_world",
|
|
109
|
+
name="hello_world",
|
|
112
110
|
resources=flyte.Resources(memory="250Mi")
|
|
113
111
|
)
|
|
114
112
|
|
|
@@ -116,7 +114,7 @@ env = flyte.TaskEnvironment(
|
|
|
116
114
|
def calculate(x: int) -> int:
|
|
117
115
|
return x * 2 + 5
|
|
118
116
|
|
|
119
|
-
@env.task
|
|
117
|
+
@env.task
|
|
120
118
|
async def main(numbers: list[int]) -> float:
|
|
121
119
|
# Parallel execution across distributed containers
|
|
122
120
|
results = await asyncio.gather(*[
|
|
@@ -156,7 +154,7 @@ def train_model(data: flyte.File) -> flyte.File:
|
|
|
156
154
|
# Runs in configured container with GPU access
|
|
157
155
|
pass
|
|
158
156
|
|
|
159
|
-
@env.task
|
|
157
|
+
@env.task
|
|
160
158
|
def evaluate_model(model: flyte.File, test_data: flyte.File) -> dict:
|
|
161
159
|
# Same container configuration, different instance
|
|
162
160
|
pass
|
|
@@ -168,7 +166,7 @@ def evaluate_model(model: flyte.File, test_data: flyte.File) -> dict:
|
|
|
168
166
|
@env.task
|
|
169
167
|
async def dynamic_pipeline(config: dict) -> list[str]:
|
|
170
168
|
results = []
|
|
171
|
-
|
|
169
|
+
|
|
172
170
|
# ✅ Use any Python construct
|
|
173
171
|
for dataset in config["datasets"]:
|
|
174
172
|
try:
|
|
@@ -182,7 +180,7 @@ async def dynamic_pipeline(config: dict) -> list[str]:
|
|
|
182
180
|
# ✅ Custom error recovery
|
|
183
181
|
result = await handle_error(dataset, e)
|
|
184
182
|
results.append(result)
|
|
185
|
-
|
|
183
|
+
|
|
186
184
|
return results
|
|
187
185
|
```
|
|
188
186
|
|
|
@@ -191,18 +189,18 @@ async def dynamic_pipeline(config: dict) -> list[str]:
|
|
|
191
189
|
```python
|
|
192
190
|
@env.task
|
|
193
191
|
async def parallel_training(hyperparams: list[dict]) -> dict:
|
|
194
|
-
# Each model trains on separate infrastructure
|
|
192
|
+
# Each model trains on separate infrastructure
|
|
195
193
|
models = await asyncio.gather(*[
|
|
196
194
|
train_model.aio(params) for params in hyperparams
|
|
197
195
|
])
|
|
198
|
-
|
|
196
|
+
|
|
199
197
|
# Evaluate all models in parallel
|
|
200
198
|
evaluations = await asyncio.gather(*[
|
|
201
|
-
evaluate_model.aio(model) for model in models
|
|
199
|
+
evaluate_model.aio(model) for model in models
|
|
202
200
|
])
|
|
203
|
-
|
|
201
|
+
|
|
204
202
|
# Find best model
|
|
205
|
-
best_idx = max(range(len(evaluations)),
|
|
203
|
+
best_idx = max(range(len(evaluations)),
|
|
206
204
|
key=lambda i: evaluations[i]["accuracy"])
|
|
207
205
|
return {"best_model": models[best_idx], "accuracy": evaluations[best_idx]}
|
|
208
206
|
```
|
|
@@ -223,7 +221,7 @@ async def main_task(inputs: list[str]) -> list[str]:
|
|
|
223
221
|
results = []
|
|
224
222
|
for inp in inputs:
|
|
225
223
|
# If task fails here, it resumes from the last successful trace
|
|
226
|
-
result = await expensive_computation(inp)
|
|
224
|
+
result = await expensive_computation(inp)
|
|
227
225
|
results.append(result)
|
|
228
226
|
return results
|
|
229
227
|
```
|
|
@@ -241,31 +239,11 @@ spark_task = flyte.remote.Task.get("spark_env.process_data", auto_version="lates
|
|
|
241
239
|
async def orchestrator(raw_data: flyte.File) -> flyte.File:
|
|
242
240
|
# Execute Spark job on big data cluster
|
|
243
241
|
processed = await spark_task(raw_data)
|
|
244
|
-
|
|
245
|
-
# Execute PyTorch training on GPU cluster
|
|
246
|
-
model = await torch_task(processed)
|
|
247
|
-
|
|
248
|
-
return model
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### **High-Performance Container Reuse**
|
|
252
242
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
name="high_throughput",
|
|
256
|
-
reusable=flyte.ReusePolicy(
|
|
257
|
-
replicas=10, # Keep 10 warm containers
|
|
258
|
-
idle_ttl=600, # 10-minute idle timeout
|
|
259
|
-
),
|
|
260
|
-
resources=flyte.Resources(cpu=2, memory="4Gi")
|
|
261
|
-
)
|
|
243
|
+
# Execute PyTorch training on GPU cluster
|
|
244
|
+
model = await torch_task(processed)
|
|
262
245
|
|
|
263
|
-
|
|
264
|
-
@env.task
|
|
265
|
-
async def process_thousands(items: list[str]) -> list[str]:
|
|
266
|
-
return await asyncio.gather(*[
|
|
267
|
-
process_item.aio(item) for item in items
|
|
268
|
-
])
|
|
246
|
+
return model
|
|
269
247
|
```
|
|
270
248
|
|
|
271
249
|
## 📊 Native Jupyter Integration
|
|
@@ -296,7 +274,7 @@ endpoint: https://my-flyte-instance.com
|
|
|
296
274
|
project: ml-team
|
|
297
275
|
domain: production
|
|
298
276
|
image:
|
|
299
|
-
builder:
|
|
277
|
+
builder: local
|
|
300
278
|
registry: ghcr.io/my-org
|
|
301
279
|
auth:
|
|
302
280
|
type: oauth2
|
|
@@ -308,14 +286,14 @@ auth:
|
|
|
308
286
|
# Deploy tasks to remote cluster
|
|
309
287
|
flyte deploy my_workflow.py
|
|
310
288
|
|
|
311
|
-
# Run deployed workflow
|
|
289
|
+
# Run deployed workflow
|
|
312
290
|
flyte run my_workflow --input-file params.json
|
|
313
291
|
|
|
314
292
|
# Monitor execution
|
|
315
293
|
flyte logs <execution-id>
|
|
316
294
|
```
|
|
317
295
|
|
|
318
|
-
##
|
|
296
|
+
## Migration from Flyte 1
|
|
319
297
|
|
|
320
298
|
| Flyte 1 | Flyte 2 |
|
|
321
299
|
|---------|---------|
|
|
@@ -326,46 +304,40 @@ flyte logs <execution-id>
|
|
|
326
304
|
| `LaunchPlan` schedules | `@env.task(on_schedule=...)` |
|
|
327
305
|
| Workflow failure handlers | Python `try/except` |
|
|
328
306
|
|
|
329
|
-
### Example Migration
|
|
330
|
-
|
|
331
|
-
```python
|
|
332
|
-
# Flyte 1
|
|
333
|
-
@flytekit.workflow
|
|
334
|
-
def old_workflow(data: list[str]) -> list[str]:
|
|
335
|
-
return [process_item(item=item) for item in data]
|
|
336
|
-
|
|
337
|
-
# Flyte 2
|
|
338
|
-
@env.task
|
|
339
|
-
async def new_workflow(data: list[str]) -> list[str]:
|
|
340
|
-
return await asyncio.gather(*[
|
|
341
|
-
process_item.aio(item) for item in data
|
|
342
|
-
])
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
## 🌍 Ecosystem & Resources
|
|
346
|
-
|
|
347
|
-
- **📖 Documentation**: [flyte.org/docs](https://flyte.org/docs)
|
|
348
|
-
- **💬 Community**: [Slack](https://flyte.org/slack) | [GitHub Discussions](https://github.com/flyteorg/flyte/discussions)
|
|
349
|
-
- **🎓 Examples**: [GitHub Examples](https://github.com/flyteorg/flytesnacks)
|
|
350
|
-
- **🐛 Issues**: [Bug Reports](https://github.com/flyteorg/flyte/issues)
|
|
351
|
-
|
|
352
307
|
## 🤝 Contributing
|
|
353
308
|
|
|
354
309
|
We welcome contributions! Whether it's:
|
|
355
310
|
|
|
356
311
|
- 🐛 **Bug fixes**
|
|
357
|
-
- ✨ **New features**
|
|
312
|
+
- ✨ **New features**
|
|
358
313
|
- 📚 **Documentation improvements**
|
|
359
314
|
- 🧪 **Testing enhancements**
|
|
360
315
|
|
|
361
|
-
|
|
316
|
+
### Setup & Iteration Cycle
|
|
317
|
+
To get started, make sure you start from a new virtual environment and install this package in editable mode with any of the supported Python versions, from 3.10 to 3.13.
|
|
362
318
|
|
|
363
|
-
|
|
319
|
+
```bash
|
|
320
|
+
uv venv --python 3.13
|
|
321
|
+
uv pip install -e .
|
|
322
|
+
```
|
|
364
323
|
|
|
365
|
-
|
|
324
|
+
Besides from picking up local code changes, installing the package in editable mode
|
|
325
|
+
also changes the definition of the default `Image()` object to use a locally
|
|
326
|
+
build wheel. You will need to build said wheel by yourself though, with the `make dist` target.
|
|
366
327
|
|
|
367
|
-
|
|
328
|
+
```bash
|
|
329
|
+
make dist
|
|
330
|
+
python maint_tools/build_default_image.py
|
|
331
|
+
```
|
|
332
|
+
You'll need to have a local docker daemon running for this. The build script does nothing
|
|
333
|
+
more than invoke the local image builder, which will create a buildx builder named `flytex` if not present. Note that only members of the `Flyte Maintainers` group has
|
|
334
|
+
access to push to the default registry. If you don't have access, please make sure to
|
|
335
|
+
specify the registry and name to the build script.
|
|
368
336
|
|
|
369
|
-
|
|
337
|
+
```bash
|
|
338
|
+
python maint_tools/build_default_image.py --registry ghcr.io/my-org --name my-flyte-image
|
|
339
|
+
```
|
|
370
340
|
|
|
371
|
-
|
|
341
|
+
## 📄 License
|
|
342
|
+
|
|
343
|
+
Flyte 2 is licensed under the [Apache 2.0 License](LICENSE).
|
|
@@ -19,16 +19,16 @@ flyte/_retry.py,sha256=rfLv0MvWxzPByKESTglEmjPsytEAKiIvvmzlJxXwsfE,941
|
|
|
19
19
|
flyte/_reusable_environment.py,sha256=f8Y1GilUwGcXH4n2Fckrnx0SrZmhk3nCfoe-TqUKivI,3740
|
|
20
20
|
flyte/_run.py,sha256=HkTD3rHL34pAwvn1WPN6OXYmk-GWX0txLdRH1OIMvEA,24338
|
|
21
21
|
flyte/_secret.py,sha256=ogXmCNfYYIphV6p-2iiWmwr2cNUES5Cq01PPjY6uQNA,3217
|
|
22
|
-
flyte/_task.py,sha256=
|
|
23
|
-
flyte/_task_environment.py,sha256=
|
|
22
|
+
flyte/_task.py,sha256=rYR7SVGihfBp7UYrhdmqhHp0ngl2K7Za8IJfhv1K2oc,19402
|
|
23
|
+
flyte/_task_environment.py,sha256=Zpfr8gjwXg5KuCfIbT4s3l2mtJCFqDxXwv6ZStHWBuc,9840
|
|
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=
|
|
29
|
-
flyte/errors.py,sha256=
|
|
28
|
+
flyte/_version.py,sha256=fn05QckBHXt6TeCLv-zTOz1tLPEdQLSISwMKmzhR-ks,519
|
|
29
|
+
flyte/errors.py,sha256=MsVZxq6oeIOXe6AVWpxqA3ZiyxCGM0A6UqnYuvmSUCU,5514
|
|
30
30
|
flyte/extend.py,sha256=GB4ZedGzKa30vYWRVPOdxEeK62xnUVFY4z2tD6H9eEw,376
|
|
31
|
-
flyte/models.py,sha256=
|
|
31
|
+
flyte/models.py,sha256=AJZXL8eRmZ2RHEvjL6VSdpTmgF5S1Ekh_tAKRn0b6mM,15321
|
|
32
32
|
flyte/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
flyte/_bin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
flyte/_bin/runtime.py,sha256=2jTy3ccvrJ__Xrfdo2t0Fxhsojc5o2zIxDHt98RE_eU,6475
|
|
@@ -42,13 +42,13 @@ flyte/_code_bundle/_packaging.py,sha256=5QUuea6kg9s-ebBg7gFAHaxOMchxR5MhTQ8KohWs
|
|
|
42
42
|
flyte/_code_bundle/_utils.py,sha256=qlAVmik9rLasfd1oNrCxhL870w5ntk5ZlNGeaKSKaAU,12028
|
|
43
43
|
flyte/_code_bundle/bundle.py,sha256=nUAwYTVAE3Z9dfgkBtsqCoKJImjSl4AicG36yweWHLc,8797
|
|
44
44
|
flyte/_internal/__init__.py,sha256=vjXgGzAAjy609YFkAy9_RVPuUlslsHSJBXCLNTVnqOY,136
|
|
45
|
-
flyte/_internal/controllers/__init__.py,sha256=
|
|
46
|
-
flyte/_internal/controllers/_local_controller.py,sha256=
|
|
45
|
+
flyte/_internal/controllers/__init__.py,sha256=TVAc4ydsldcIFmN3PW9-IX5UkKeD8oOmuIukIgEae9M,4341
|
|
46
|
+
flyte/_internal/controllers/_local_controller.py,sha256=__-eEira0k18DsBu1LBXeEjhFGFcp1Uai9K0YEBbwKM,7300
|
|
47
47
|
flyte/_internal/controllers/_trace.py,sha256=ywFg_M2nGrCKYLbh4iVdsVlRtPT1K2S-XZMvDJU8AKU,1499
|
|
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=
|
|
51
|
+
flyte/_internal/controllers/remote/_controller.py,sha256=80e7Sbvg0SKFvF5wln_8RlSkwaYmT1QUFYUao9BwvUA,24508
|
|
52
52
|
flyte/_internal/controllers/remote/_core.py,sha256=49l1X3YFyX-QYeSlvkOWdyEU2xc1Fr7I8qHvC3nQ6MA,19069
|
|
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
|
|
@@ -63,7 +63,7 @@ flyte/_internal/resolvers/default.py,sha256=nX4DHUYod1nRvEsl_vSgutQVEdExu2xL8pRk
|
|
|
63
63
|
flyte/_internal/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
64
|
flyte/_internal/runtime/convert.py,sha256=yK5Fy25-CVSqTtWF8BuBel2jwlVoh8R5F4UhIMYpgmg,16086
|
|
65
65
|
flyte/_internal/runtime/entrypoints.py,sha256=9Ng-aQ45M-_MMWeOe9uGmgx69qO9b0xaMRiu542ZI9g,6581
|
|
66
|
-
flyte/_internal/runtime/io.py,sha256=
|
|
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
69
|
flyte/_internal/runtime/rusty.py,sha256=puMaa6aLaoR4Tl5xxZulC4AzY58nmGg-5ok4ydHHjdM,6145
|
|
@@ -124,7 +124,7 @@ flyte/_protos/workflow/environment_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDC
|
|
|
124
124
|
flyte/_protos/workflow/node_execution_service_pb2.py,sha256=IOLg3tNikY7n00kLOVsC69yyXc5Ttnx-_-xUuc0q05Q,1654
|
|
125
125
|
flyte/_protos/workflow/node_execution_service_pb2.pyi,sha256=C7VVuw_bnxp68qemD3SLoGIL-Hmno6qkIoq3l6W2qb8,135
|
|
126
126
|
flyte/_protos/workflow/node_execution_service_pb2_grpc.py,sha256=2JJDS3Aww3FFDW-qYdTaxC75gRpsgnn4an6LPZmF9uA,947
|
|
127
|
-
flyte/_protos/workflow/queue_service_pb2.py,sha256=
|
|
127
|
+
flyte/_protos/workflow/queue_service_pb2.py,sha256=idHNrsnJglPVxoviySSkVqfSTf3H1lAGIBXNVZACYBA,13374
|
|
128
128
|
flyte/_protos/workflow/queue_service_pb2.pyi,sha256=lZ9rO0KpuyGadl5GqQ8JgffZcDlzfSeyNmsZ3du9Gqg,9499
|
|
129
129
|
flyte/_protos/workflow/queue_service_pb2_grpc.py,sha256=6KK87jYXrmK0jacf4AKhHp21QU9JFJPOiEBjbDRkBm0,7839
|
|
130
130
|
flyte/_protos/workflow/run_definition_pb2.py,sha256=sdyl7xgl6tTqkKNXrWcrhvV4KOZPqoMa9vjEmwVyfZc,16193
|
|
@@ -172,17 +172,13 @@ flyte/config/_internal.py,sha256=LMcAtDjvTjf5bGlsJVxPuLxQQ82mLd00xK5-JlYGCi8,298
|
|
|
172
172
|
flyte/config/_reader.py,sha256=coidKV5CVODEnqDnsHZ9-VMC0UGXanXhAZE1SmYRhxI,7021
|
|
173
173
|
flyte/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
174
174
|
flyte/extras/__init__.py,sha256=FhB0uK7H1Yo5De9vOuF7UGnezTKncj3u2Wo5uQdWN0g,74
|
|
175
|
-
flyte/extras/_container.py,sha256=
|
|
175
|
+
flyte/extras/_container.py,sha256=xfbxaGrx2JyQyrvQx1UWTzho2ion8_xujPW5V4uDEIs,11818
|
|
176
176
|
flyte/io/__init__.py,sha256=qF8jq_IKuocuGU0LAvoy_uxjMs4G-vXjDA9Prba0JGU,538
|
|
177
177
|
flyte/io/_dir.py,sha256=rih9CY1YjNX05bcAu5LG62Xoyij5GXAlv7jLyVF0je8,15310
|
|
178
178
|
flyte/io/_file.py,sha256=kp5700SKPy5htmMhm4hE2ybb99Ykny1b0Kwm3huCWXs,15572
|
|
179
179
|
flyte/io/_dataframe/__init__.py,sha256=SDgNw45uf7m3cHhbUCOA3V3-5A2zSKgPcsWriRLwd74,4283
|
|
180
180
|
flyte/io/_dataframe/basic_dfs.py,sha256=weQ8EfzdU-LcKi8Eebq1AiATVS1fGdfcbqtCDOrVLos,7728
|
|
181
181
|
flyte/io/_dataframe/dataframe.py,sha256=uecLLjaAuLyYta2d4Tkk-DjxuHkzZjFUBbvMapPM7R8,51554
|
|
182
|
-
flyte/migrate/__init__.py,sha256=I1I0JoESM6s_kILMUcuP972Zks1DeTc5CiU2zjKxTeU,64
|
|
183
|
-
flyte/migrate/dynamic.py,sha256=igL6lMgKKH-g3CwF48SGi-F5YWdE9p8iXlMi4LJGnxc,296
|
|
184
|
-
flyte/migrate/task.py,sha256=V1-bKQuz0aPYG9jzHpjdujPJSGTQRH4Yda3ZPmwkVxA,3714
|
|
185
|
-
flyte/migrate/workflow.py,sha256=AbPchkUZXUAAGlrdy43M23fdpo9tsVaXcMLVSh7z9pU,328
|
|
186
182
|
flyte/remote/__init__.py,sha256=y9eke9JzEJkygk8eKZjSj44fJGlyepuW4i-j6lbCAPY,617
|
|
187
183
|
flyte/remote/_action.py,sha256=5DN6rEb4WhsdDEZsYPFFOUyn2yjSMefVojkMF7DE7XM,23839
|
|
188
184
|
flyte/remote/_console.py,sha256=avmELJPx8nQMAVPrHlh6jEIRPjrMwFpdZjJsWOOa9rE,660
|
|
@@ -191,7 +187,7 @@ flyte/remote/_logs.py,sha256=aDG18-uPVb2J3PxmqmAY1C0Z4Iv1P1agg-iF4nSQR4U,6709
|
|
|
191
187
|
flyte/remote/_project.py,sha256=CFNTGpgXU3X599tkJ_oxijs9zPzzCWOB6mAWn6WeDEU,2828
|
|
192
188
|
flyte/remote/_run.py,sha256=fpr_YcGZIv6K7Jt1if3-HHHVB2TVt_8AWcZ55rN_fgk,9750
|
|
193
189
|
flyte/remote/_secret.py,sha256=l5xeMS83uMcWWeSSTRsSZUNhS0N--1Dze09C-thSOQs,4341
|
|
194
|
-
flyte/remote/_task.py,sha256=
|
|
190
|
+
flyte/remote/_task.py,sha256=xHfWChnC-L7Hdp2IB9qDnbNyaOgM2TWOlnkmevoc2dA,15314
|
|
195
191
|
flyte/remote/_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
196
192
|
flyte/remote/_client/_protocols.py,sha256=JyBWHs5WsVOxEDUyG9X7wPLDzzzjkoaNhJlU-X4YlN0,5599
|
|
197
193
|
flyte/remote/_client/controlplane.py,sha256=FsOfj4rO4MIMnYrpAT53F8q588VVf5t4sDuwoPuc840,3102
|
|
@@ -230,10 +226,10 @@ flyte/types/_renderer.py,sha256=ygcCo5l60lHufyQISFddZfWwLlQ8kJAKxUT_XnR_6dY,4818
|
|
|
230
226
|
flyte/types/_string_literals.py,sha256=NlG1xV8RSA-sZ-n-IFQCAsdB6jXJOAKkHWtnopxVVDk,4231
|
|
231
227
|
flyte/types/_type_engine.py,sha256=Tas_OXYddOi0nDuORjqan2SkJ96wKD8937I2l1bo8vk,97916
|
|
232
228
|
flyte/types/_utils.py,sha256=pbts9E1_2LTdLygAY0UYTLYJ8AsN3BZyviSXvrtcutc,2626
|
|
233
|
-
flyte-2.0.
|
|
234
|
-
flyte-2.0.
|
|
235
|
-
flyte-2.0.
|
|
236
|
-
flyte-2.0.
|
|
237
|
-
flyte-2.0.
|
|
238
|
-
flyte-2.0.
|
|
239
|
-
flyte-2.0.
|
|
229
|
+
flyte-2.0.0b3.data/scripts/runtime.py,sha256=2jTy3ccvrJ__Xrfdo2t0Fxhsojc5o2zIxDHt98RE_eU,6475
|
|
230
|
+
flyte-2.0.0b3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
231
|
+
flyte-2.0.0b3.dist-info/METADATA,sha256=DxTr4d_6Ohm1VRSqhqILMy_McBGsKB4ykk274bne-fM,9955
|
|
232
|
+
flyte-2.0.0b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
233
|
+
flyte-2.0.0b3.dist-info/entry_points.txt,sha256=MIq2z5dBurdCJfpXfMKzgBv7sJOakKRYxr8G0cMiTrg,75
|
|
234
|
+
flyte-2.0.0b3.dist-info/top_level.txt,sha256=7dkyFbikvA12LEZEqawx8oDG1CMod6hTliPj7iWzgYo,6
|
|
235
|
+
flyte-2.0.0b3.dist-info/RECORD,,
|
flyte/migrate/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from flyte.migrate import dynamic, task, workflow # noqa: F401
|
flyte/migrate/dynamic.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from typing import Callable, Union
|
|
2
|
-
|
|
3
|
-
import flytekit
|
|
4
|
-
|
|
5
|
-
import flyte.migrate
|
|
6
|
-
from flyte._task import AsyncFunctionTaskTemplate, P, R
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def dynamic_shim(**kwargs) -> Union[AsyncFunctionTaskTemplate, Callable[P, R]]:
|
|
10
|
-
return flyte.migrate.task.task_shim(**kwargs)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
flytekit.dynamic = dynamic_shim
|
flyte/migrate/task.py
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
from typing import Callable, Dict, Iterable, List, Literal, Optional, Tuple, Union
|
|
3
|
-
|
|
4
|
-
import flytekit
|
|
5
|
-
from flytekit.core import launch_plan, workflow
|
|
6
|
-
from flytekit.core.base_task import T, TaskResolverMixin
|
|
7
|
-
from flytekit.core.python_function_task import PythonFunctionTask
|
|
8
|
-
from flytekit.core.task import FuncOut
|
|
9
|
-
from flytekit.deck import DeckField
|
|
10
|
-
from flytekit.extras.accelerators import BaseAccelerator
|
|
11
|
-
|
|
12
|
-
import flyte
|
|
13
|
-
from flyte import Image, Resources, TaskEnvironment
|
|
14
|
-
from flyte._doc import Documentation
|
|
15
|
-
from flyte._task import AsyncFunctionTaskTemplate, P, R
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def task_shim(
|
|
19
|
-
_task_function: Optional[Callable[P, FuncOut]] = None,
|
|
20
|
-
task_config: Optional[T] = None,
|
|
21
|
-
cache: Union[bool, flytekit.Cache] = False,
|
|
22
|
-
retries: int = 0,
|
|
23
|
-
interruptible: Optional[bool] = None,
|
|
24
|
-
deprecated: str = "",
|
|
25
|
-
timeout: Union[datetime.timedelta, int] = 0,
|
|
26
|
-
container_image: Optional[Union[str, flytekit.ImageSpec]] = None,
|
|
27
|
-
environment: Optional[Dict[str, str]] = None,
|
|
28
|
-
requests: Optional[flytekit.Resources] = None,
|
|
29
|
-
limits: Optional[flytekit.Resources] = None,
|
|
30
|
-
secret_requests: Optional[List[flytekit.Secret]] = None,
|
|
31
|
-
execution_mode: PythonFunctionTask.ExecutionBehavior = PythonFunctionTask.ExecutionBehavior.DEFAULT,
|
|
32
|
-
node_dependency_hints: Optional[
|
|
33
|
-
Iterable[
|
|
34
|
-
Union[
|
|
35
|
-
flytekit.PythonFunctionTask,
|
|
36
|
-
launch_plan.LaunchPlan,
|
|
37
|
-
workflow.WorkflowBase,
|
|
38
|
-
]
|
|
39
|
-
]
|
|
40
|
-
] = None,
|
|
41
|
-
task_resolver: Optional[TaskResolverMixin] = None,
|
|
42
|
-
docs: Optional[flytekit.Documentation] = None,
|
|
43
|
-
disable_deck: Optional[bool] = None,
|
|
44
|
-
enable_deck: Optional[bool] = None,
|
|
45
|
-
deck_fields: Optional[Tuple[DeckField, ...]] = (
|
|
46
|
-
DeckField.SOURCE_CODE,
|
|
47
|
-
DeckField.DEPENDENCIES,
|
|
48
|
-
DeckField.TIMELINE,
|
|
49
|
-
DeckField.INPUT,
|
|
50
|
-
DeckField.OUTPUT,
|
|
51
|
-
),
|
|
52
|
-
pod_template: Optional[flytekit.PodTemplate] = None,
|
|
53
|
-
pod_template_name: Optional[str] = None,
|
|
54
|
-
accelerator: Optional[BaseAccelerator] = None,
|
|
55
|
-
pickle_untyped: bool = False,
|
|
56
|
-
shared_memory: Optional[Union[Literal[True], str]] = None,
|
|
57
|
-
resources: Optional[Resources] = None,
|
|
58
|
-
labels: Optional[dict[str, str]] = None,
|
|
59
|
-
annotations: Optional[dict[str, str]] = None,
|
|
60
|
-
**kwargs,
|
|
61
|
-
) -> Union[AsyncFunctionTaskTemplate, Callable[P, R]]:
|
|
62
|
-
plugin_config = task_config
|
|
63
|
-
pod_template = (
|
|
64
|
-
flyte.PodTemplate(
|
|
65
|
-
pod_spec=pod_template.pod_spec,
|
|
66
|
-
primary_container_name=pod_template.primary_container_name,
|
|
67
|
-
labels=pod_template.labels,
|
|
68
|
-
annotations=pod_template.annotations,
|
|
69
|
-
)
|
|
70
|
-
if pod_template
|
|
71
|
-
else None
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
if isinstance(container_image, flytekit.ImageSpec):
|
|
75
|
-
image = Image.from_debian_base()
|
|
76
|
-
if container_image.apt_packages:
|
|
77
|
-
image = image.with_apt_packages(*container_image.apt_packages)
|
|
78
|
-
pip_packages = ["flytekit"]
|
|
79
|
-
if container_image.packages:
|
|
80
|
-
pip_packages.extend(container_image.packages)
|
|
81
|
-
image = image.with_pip_packages(*pip_packages)
|
|
82
|
-
elif isinstance(container_image, str):
|
|
83
|
-
image = Image.from_base(container_image).with_pip_packages("flyte")
|
|
84
|
-
else:
|
|
85
|
-
image = Image.from_debian_base().with_pip_packages("flytekit")
|
|
86
|
-
|
|
87
|
-
docs = Documentation(description=docs.short_description) if docs else None
|
|
88
|
-
|
|
89
|
-
env = TaskEnvironment(
|
|
90
|
-
name="flytekit",
|
|
91
|
-
resources=Resources(cpu=0.8, memory="800Mi"),
|
|
92
|
-
image=image,
|
|
93
|
-
cache="enabled" if cache else "disable",
|
|
94
|
-
plugin_config=plugin_config,
|
|
95
|
-
)
|
|
96
|
-
return env.task(retries=retries, pod_template=pod_template_name or pod_template, docs=docs)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
flytekit.task = task_shim
|
flyte/migrate/workflow.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import flytekit
|
|
2
|
-
|
|
3
|
-
from flyte import Image, Resources, TaskEnvironment
|
|
4
|
-
|
|
5
|
-
env = TaskEnvironment(
|
|
6
|
-
name="flytekit",
|
|
7
|
-
resources=Resources(cpu=0.8, memory="800Mi"),
|
|
8
|
-
image=Image.from_debian_base().with_apt_packages("vim").with_pip_packages("flytekit", "pandas"),
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
# TODO: Build subtask's image
|
|
12
|
-
|
|
13
|
-
flytekit.workflow = env.task
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|