flyte 0.2.0b25__py3-none-any.whl → 0.2.0b27__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 +6 -1
- flyte/_image.py +16 -6
- flyte/_internal/controllers/_local_controller.py +4 -2
- flyte/_internal/runtime/convert.py +24 -2
- flyte/_run.py +32 -3
- flyte/_task_environment.py +6 -2
- flyte/_tools.py +13 -0
- flyte/_version.py +2 -2
- flyte/cli/_get.py +11 -8
- flyte/remote/__init__.py +2 -1
- flyte/remote/_action.py +698 -0
- flyte/remote/_logs.py +8 -0
- flyte/remote/_project.py +5 -4
- flyte/remote/_run.py +3 -658
- flyte/types/_type_engine.py +4 -1
- {flyte-0.2.0b25.data → flyte-0.2.0b27.data}/scripts/runtime.py +6 -1
- {flyte-0.2.0b25.dist-info → flyte-0.2.0b27.dist-info}/METADATA +1 -1
- {flyte-0.2.0b25.dist-info → flyte-0.2.0b27.dist-info}/RECORD +21 -20
- {flyte-0.2.0b25.dist-info → flyte-0.2.0b27.dist-info}/WHEEL +0 -0
- {flyte-0.2.0b25.dist-info → flyte-0.2.0b27.dist-info}/entry_points.txt +0 -0
- {flyte-0.2.0b25.dist-info → flyte-0.2.0b27.dist-info}/top_level.txt +0 -0
flyte/_bin/runtime.py
CHANGED
|
@@ -82,6 +82,9 @@ def main(
|
|
|
82
82
|
):
|
|
83
83
|
sys.path.insert(0, ".")
|
|
84
84
|
|
|
85
|
+
import faulthandler
|
|
86
|
+
import signal
|
|
87
|
+
|
|
85
88
|
import flyte
|
|
86
89
|
import flyte._utils as utils
|
|
87
90
|
from flyte._initialize import init
|
|
@@ -91,8 +94,10 @@ def main(
|
|
|
91
94
|
from flyte._logging import logger
|
|
92
95
|
from flyte.models import ActionID, Checkpoints, CodeBundle, RawDataPath
|
|
93
96
|
|
|
94
|
-
logger.info(
|
|
97
|
+
logger.info("Registering faulthandler for SIGUSR1")
|
|
98
|
+
faulthandler.register(signal.SIGUSR1)
|
|
95
99
|
|
|
100
|
+
logger.info(f"Initializing flyte runtime - version {flyte.__version__}")
|
|
96
101
|
assert org, "Org is required for now"
|
|
97
102
|
assert project, "Project is required"
|
|
98
103
|
assert domain, "Domain is required"
|
flyte/_image.py
CHANGED
|
@@ -355,7 +355,11 @@ class Image:
|
|
|
355
355
|
|
|
356
356
|
@classmethod
|
|
357
357
|
def _get_default_image_for(
|
|
358
|
-
cls,
|
|
358
|
+
cls,
|
|
359
|
+
python_version: Tuple[int, int],
|
|
360
|
+
flyte_version: Optional[str] = None,
|
|
361
|
+
install_flyte: bool = True,
|
|
362
|
+
platform: Optional[Tuple[Architecture, ...]] = None,
|
|
359
363
|
) -> Image:
|
|
360
364
|
# Would love a way to move this outside of this class (but still needs to be accessible via Image.auto())
|
|
361
365
|
# this default image definition may need to be updated once there is a released pypi version
|
|
@@ -377,7 +381,7 @@ class Image:
|
|
|
377
381
|
base_image=f"python:{python_version[0]}.{python_version[1]}-slim-bookworm",
|
|
378
382
|
registry=_BASE_REGISTRY,
|
|
379
383
|
name=_DEFAULT_IMAGE_NAME,
|
|
380
|
-
platform=("linux/amd64", "linux/arm64"),
|
|
384
|
+
platform=("linux/amd64", "linux/arm64") if platform is None else platform,
|
|
381
385
|
)
|
|
382
386
|
labels_and_user = _DockerLines(
|
|
383
387
|
(
|
|
@@ -430,6 +434,7 @@ class Image:
|
|
|
430
434
|
install_flyte: bool = True,
|
|
431
435
|
registry: Optional[str] = None,
|
|
432
436
|
name: Optional[str] = None,
|
|
437
|
+
platform: Optional[Tuple[Architecture, ...]] = None,
|
|
433
438
|
) -> Image:
|
|
434
439
|
"""
|
|
435
440
|
Use this method to start using the default base image, built from this library's base Dockerfile
|
|
@@ -440,6 +445,8 @@ class Image:
|
|
|
440
445
|
:param install_flyte: If True, will install the flyte library in the image
|
|
441
446
|
:param registry: Registry to use for the image
|
|
442
447
|
:param name: Name of the image if you want to override the default name
|
|
448
|
+
:param platform: Platform to use for the image, default is linux/amd64, use tuple for multiple values
|
|
449
|
+
Example: ("linux/amd64", "linux/arm64")
|
|
443
450
|
|
|
444
451
|
:return: Image
|
|
445
452
|
"""
|
|
@@ -447,7 +454,10 @@ class Image:
|
|
|
447
454
|
python_version = _detect_python_version()
|
|
448
455
|
|
|
449
456
|
base_image = cls._get_default_image_for(
|
|
450
|
-
python_version=python_version,
|
|
457
|
+
python_version=python_version,
|
|
458
|
+
flyte_version=flyte_version,
|
|
459
|
+
install_flyte=install_flyte,
|
|
460
|
+
platform=platform,
|
|
451
461
|
)
|
|
452
462
|
|
|
453
463
|
if registry and name:
|
|
@@ -481,7 +491,7 @@ class Image:
|
|
|
481
491
|
extra_index_urls: Union[str, List[str], Tuple[str, ...], None] = None,
|
|
482
492
|
pre: bool = False,
|
|
483
493
|
extra_args: Optional[str] = None,
|
|
484
|
-
|
|
494
|
+
platform: Optional[Tuple[Architecture, ...]] = None,
|
|
485
495
|
) -> Image:
|
|
486
496
|
"""
|
|
487
497
|
Use this method to create a new image with the specified uv script.
|
|
@@ -506,7 +516,7 @@ class Image:
|
|
|
506
516
|
:param python_version: Python version to use for the image, if not specified, will use the current Python
|
|
507
517
|
version
|
|
508
518
|
:param script: path to the uv script
|
|
509
|
-
:param
|
|
519
|
+
:param platform: architecture to use for the image, default is linux/amd64, use tuple for multiple values
|
|
510
520
|
:param python_version: Python version for the image, if not specified, will use the current Python version
|
|
511
521
|
:param index_url: index url to use for pip install, default is None
|
|
512
522
|
:param extra_index_urls: extra index urls to use for pip install, default is None
|
|
@@ -530,7 +540,7 @@ class Image:
|
|
|
530
540
|
raise ValueError("registry must be specified")
|
|
531
541
|
|
|
532
542
|
# todo: arch
|
|
533
|
-
img = cls.from_debian_base(registry=registry, name=name, python_version=python_version)
|
|
543
|
+
img = cls.from_debian_base(registry=registry, name=name, python_version=python_version, platform=platform)
|
|
534
544
|
|
|
535
545
|
# add ca-certificates to the image by default
|
|
536
546
|
img = img.with_apt_packages("ca-certificates")
|
|
@@ -106,10 +106,12 @@ class LocalController:
|
|
|
106
106
|
raise exc
|
|
107
107
|
else:
|
|
108
108
|
raise flyte.errors.RuntimeSystemError("BadError", "Unknown error")
|
|
109
|
-
if _task.native_interface.outputs
|
|
109
|
+
if _task.native_interface.outputs:
|
|
110
|
+
if out is None:
|
|
111
|
+
raise flyte.errors.RuntimeSystemError("BadOutput", "Task output not captured.")
|
|
110
112
|
result = await convert.convert_outputs_to_native(_task.native_interface, out)
|
|
111
113
|
return result
|
|
112
|
-
return
|
|
114
|
+
return None
|
|
113
115
|
|
|
114
116
|
def submit_sync(self, _task: TaskTemplate, *args, **kwargs) -> concurrent.futures.Future:
|
|
115
117
|
name = threading.current_thread().name + f"PID:{os.getpid()}"
|
|
@@ -120,13 +120,19 @@ async def convert_from_native_to_inputs(interface: NativeInterface, *args, **kwa
|
|
|
120
120
|
for input_name, (input_type, default_value) in interface.inputs.items():
|
|
121
121
|
if input_name in kwargs:
|
|
122
122
|
type_hints[input_name] = input_type
|
|
123
|
-
elif (
|
|
124
|
-
default_value is None and
|
|
123
|
+
elif (
|
|
124
|
+
(default_value is not None and default_value is not inspect.Signature.empty)
|
|
125
|
+
or (default_value is None and is_optional_type(input_type))
|
|
126
|
+
or input_type is None
|
|
125
127
|
):
|
|
126
128
|
if default_value == NativeInterface.has_default:
|
|
127
129
|
if interface._remote_defaults is None or input_name not in interface._remote_defaults:
|
|
128
130
|
raise ValueError(f"Input '{input_name}' has a default value but it is not set in the interface.")
|
|
129
131
|
already_converted_kwargs[input_name] = interface._remote_defaults[input_name]
|
|
132
|
+
elif input_type is None:
|
|
133
|
+
# If the type is None, we assume it's a placeholder for no type
|
|
134
|
+
kwargs[input_name] = None
|
|
135
|
+
type_hints[input_name] = NoneType
|
|
130
136
|
else:
|
|
131
137
|
kwargs[input_name] = default_value
|
|
132
138
|
type_hints[input_name] = input_type
|
|
@@ -150,6 +156,22 @@ async def convert_from_native_to_inputs(interface: NativeInterface, *args, **kwa
|
|
|
150
156
|
)
|
|
151
157
|
|
|
152
158
|
|
|
159
|
+
async def convert_from_inputs_to_native(native_interface: NativeInterface, inputs: Inputs) -> Dict[str, Any]:
|
|
160
|
+
"""
|
|
161
|
+
Converts the inputs from a run definition proto to a native Python dictionary.
|
|
162
|
+
:param native_interface: The native interface of the task.
|
|
163
|
+
:param inputs: The run definition inputs proto.
|
|
164
|
+
:return: A dictionary of input names to their native Python values.
|
|
165
|
+
"""
|
|
166
|
+
if not inputs or not inputs.proto_inputs or not inputs.proto_inputs.literals:
|
|
167
|
+
return {}
|
|
168
|
+
|
|
169
|
+
literals = {named_literal.name: named_literal.value for named_literal in inputs.proto_inputs.literals}
|
|
170
|
+
return await TypeEngine.literal_map_to_kwargs(
|
|
171
|
+
literals_pb2.LiteralMap(literals=literals), native_interface.get_input_types()
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
153
175
|
async def convert_from_native_to_outputs(o: Any, interface: NativeInterface, task_name: str = "") -> Outputs:
|
|
154
176
|
# Always make it a tuple even if it's just one item to simplify logic below
|
|
155
177
|
if not isinstance(o, tuple):
|
flyte/_run.py
CHANGED
|
@@ -376,9 +376,10 @@ class _Runner:
|
|
|
376
376
|
raise err
|
|
377
377
|
return outputs
|
|
378
378
|
|
|
379
|
-
async def _run_local(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) ->
|
|
379
|
+
async def _run_local(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) -> Run:
|
|
380
380
|
from flyte._internal.controllers import create_controller
|
|
381
381
|
from flyte._internal.controllers._local_controller import LocalController
|
|
382
|
+
from flyte.remote import Run
|
|
382
383
|
from flyte.report import Report
|
|
383
384
|
|
|
384
385
|
controller = cast(LocalController, create_controller("local"))
|
|
@@ -409,9 +410,37 @@ class _Runner:
|
|
|
409
410
|
if obj._call_as_synchronous:
|
|
410
411
|
fut = controller.submit_sync(obj, *args, **kwargs)
|
|
411
412
|
awaitable = asyncio.wrap_future(fut)
|
|
412
|
-
|
|
413
|
+
outputs = await awaitable
|
|
413
414
|
else:
|
|
414
|
-
|
|
415
|
+
outputs = await controller.submit(obj, *args, **kwargs)
|
|
416
|
+
|
|
417
|
+
class _LocalRun(Run):
|
|
418
|
+
def __init__(self, outputs: Tuple[Any, ...] | Any):
|
|
419
|
+
from flyte._protos.workflow import run_definition_pb2
|
|
420
|
+
|
|
421
|
+
self._outputs = outputs
|
|
422
|
+
super().__init__(
|
|
423
|
+
pb2=run_definition_pb2.Run(
|
|
424
|
+
action=run_definition_pb2.Action(
|
|
425
|
+
id=run_definition_pb2.ActionIdentifier(
|
|
426
|
+
name="a0",
|
|
427
|
+
run=run_definition_pb2.RunIdentifier(name="dry-run"),
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
)
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
@property
|
|
434
|
+
def url(self) -> str:
|
|
435
|
+
return "local-run"
|
|
436
|
+
|
|
437
|
+
def wait(self, quiet: bool = False, wait_for: Literal["terminal", "running"] = "terminal"):
|
|
438
|
+
pass
|
|
439
|
+
|
|
440
|
+
def outputs(self) -> R:
|
|
441
|
+
return cast(R, self._outputs)
|
|
442
|
+
|
|
443
|
+
return _LocalRun(outputs)
|
|
415
444
|
|
|
416
445
|
@syncify
|
|
417
446
|
async def run(
|
flyte/_task_environment.py
CHANGED
|
@@ -90,7 +90,11 @@ class TaskEnvironment(Environment):
|
|
|
90
90
|
|
|
91
91
|
"""
|
|
92
92
|
cache = kwargs.pop("cache", None)
|
|
93
|
-
reusable =
|
|
93
|
+
reusable = None
|
|
94
|
+
reusable_set = False
|
|
95
|
+
if "reusable" in kwargs:
|
|
96
|
+
reusable_set = True
|
|
97
|
+
reusable = kwargs.pop("reusable", None)
|
|
94
98
|
|
|
95
99
|
# validate unknown kwargs if needed
|
|
96
100
|
if kwargs:
|
|
@@ -106,7 +110,7 @@ class TaskEnvironment(Environment):
|
|
|
106
110
|
kwargs["cache"] = cache
|
|
107
111
|
if env is not None:
|
|
108
112
|
kwargs["env"] = env
|
|
109
|
-
if
|
|
113
|
+
if reusable_set:
|
|
110
114
|
kwargs["reusable"] = reusable
|
|
111
115
|
if secrets is not None:
|
|
112
116
|
kwargs["secrets"] = secrets
|
flyte/_tools.py
CHANGED
|
@@ -25,3 +25,16 @@ def is_in_cluster() -> bool:
|
|
|
25
25
|
if os.getenv("_UN_CLS"):
|
|
26
26
|
return True
|
|
27
27
|
return False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def ipywidgets_check() -> bool:
|
|
31
|
+
"""
|
|
32
|
+
Check if the interface is running in IPython with ipywidgets support.
|
|
33
|
+
:return: True if running in IPython with ipywidgets support, False otherwise.
|
|
34
|
+
"""
|
|
35
|
+
try:
|
|
36
|
+
import ipywidgets # noqa: F401
|
|
37
|
+
|
|
38
|
+
return True
|
|
39
|
+
except (ImportError, NameError):
|
|
40
|
+
return False
|
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 = '0.2.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 2, 0, '
|
|
20
|
+
__version__ = version = '0.2.0b27'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 2, 0, 'b27')
|
flyte/cli/_get.py
CHANGED
|
@@ -5,6 +5,8 @@ import rich_click as click
|
|
|
5
5
|
from rich.console import Console
|
|
6
6
|
from rich.pretty import pretty_repr
|
|
7
7
|
|
|
8
|
+
import flyte.remote._action
|
|
9
|
+
|
|
8
10
|
from . import _common as common
|
|
9
11
|
|
|
10
12
|
|
|
@@ -122,17 +124,18 @@ def action(
|
|
|
122
124
|
"""
|
|
123
125
|
Get all actions for a run or details for a specific action.
|
|
124
126
|
"""
|
|
125
|
-
import flyte.remote as remote
|
|
126
127
|
|
|
127
128
|
cfg.init(project=project, domain=domain)
|
|
128
129
|
|
|
129
130
|
console = Console()
|
|
130
131
|
if action_name:
|
|
131
|
-
console.print(pretty_repr(remote.Action.get(run_name=run_name, name=action_name)))
|
|
132
|
+
console.print(pretty_repr(flyte.remote._action.Action.get(run_name=run_name, name=action_name)))
|
|
132
133
|
else:
|
|
133
134
|
# List all actions for the run
|
|
134
135
|
console.print(
|
|
135
|
-
common.get_table(
|
|
136
|
+
common.get_table(
|
|
137
|
+
f"Actions for {run_name}", flyte.remote._action.Action.listall(for_run_name=run_name), simple=cfg.simple
|
|
138
|
+
)
|
|
136
139
|
)
|
|
137
140
|
|
|
138
141
|
|
|
@@ -201,7 +204,7 @@ def logs(
|
|
|
201
204
|
task.cancel()
|
|
202
205
|
|
|
203
206
|
if action_name:
|
|
204
|
-
obj = remote.Action.get(run_name=run_name, name=action_name)
|
|
207
|
+
obj = flyte.remote._action.Action.get(run_name=run_name, name=action_name)
|
|
205
208
|
else:
|
|
206
209
|
obj = remote.Run.get(run_name)
|
|
207
210
|
asyncio.run(_run_log_view(obj))
|
|
@@ -269,20 +272,20 @@ def io(
|
|
|
269
272
|
cfg.init(project=project, domain=domain)
|
|
270
273
|
console = Console()
|
|
271
274
|
if action_name:
|
|
272
|
-
obj = remote.ActionDetails.get(run_name=run_name, name=action_name)
|
|
275
|
+
obj = flyte.remote._action.ActionDetails.get(run_name=run_name, name=action_name)
|
|
273
276
|
else:
|
|
274
277
|
obj = remote.RunDetails.get(run_name)
|
|
275
278
|
|
|
276
279
|
async def _get_io(
|
|
277
|
-
details: Union[remote.RunDetails, remote.ActionDetails],
|
|
278
|
-
) -> Tuple[remote.ActionInputs | None, remote.ActionOutputs | None | str]:
|
|
280
|
+
details: Union[remote.RunDetails, flyte.remote._action.ActionDetails],
|
|
281
|
+
) -> Tuple[flyte.remote._action.ActionInputs | None, flyte.remote._action.ActionOutputs | None | str]:
|
|
279
282
|
if inputs_only or outputs_only:
|
|
280
283
|
if inputs_only:
|
|
281
284
|
return await details.inputs(), None
|
|
282
285
|
elif outputs_only:
|
|
283
286
|
return None, await details.outputs()
|
|
284
287
|
inputs = await details.inputs()
|
|
285
|
-
outputs: remote.ActionOutputs | None | str = None
|
|
288
|
+
outputs: flyte.remote._action.ActionOutputs | None | str = None
|
|
286
289
|
try:
|
|
287
290
|
outputs = await details.outputs()
|
|
288
291
|
except Exception:
|
flyte/remote/__init__.py
CHANGED
|
@@ -18,9 +18,10 @@ __all__ = [
|
|
|
18
18
|
"upload_file",
|
|
19
19
|
]
|
|
20
20
|
|
|
21
|
+
from ._action import Action, ActionDetails, ActionInputs, ActionOutputs
|
|
21
22
|
from ._client.auth import create_channel
|
|
22
23
|
from ._data import upload_dir, upload_file
|
|
23
24
|
from ._project import Project
|
|
24
|
-
from ._run import
|
|
25
|
+
from ._run import Run, RunDetails
|
|
25
26
|
from ._secret import Secret, SecretTypes
|
|
26
27
|
from ._task import Task
|