flyte 0.2.0b1__py3-none-any.whl → 2.0.0b46__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.
- flyte/__init__.py +83 -30
- flyte/_bin/connect.py +61 -0
- flyte/_bin/debug.py +38 -0
- flyte/_bin/runtime.py +87 -19
- flyte/_bin/serve.py +351 -0
- flyte/_build.py +3 -2
- flyte/_cache/cache.py +6 -5
- flyte/_cache/local_cache.py +216 -0
- flyte/_code_bundle/_ignore.py +31 -5
- flyte/_code_bundle/_packaging.py +42 -11
- flyte/_code_bundle/_utils.py +57 -34
- flyte/_code_bundle/bundle.py +130 -27
- flyte/_constants.py +1 -0
- flyte/_context.py +21 -5
- flyte/_custom_context.py +73 -0
- flyte/_debug/constants.py +37 -0
- flyte/_debug/utils.py +17 -0
- flyte/_debug/vscode.py +315 -0
- flyte/_deploy.py +396 -75
- flyte/_deployer.py +109 -0
- flyte/_environment.py +94 -11
- flyte/_excepthook.py +37 -0
- flyte/_group.py +2 -1
- flyte/_hash.py +1 -16
- flyte/_image.py +544 -231
- flyte/_initialize.py +456 -316
- flyte/_interface.py +40 -5
- flyte/_internal/controllers/__init__.py +22 -8
- flyte/_internal/controllers/_local_controller.py +159 -35
- flyte/_internal/controllers/_trace.py +18 -10
- flyte/_internal/controllers/remote/__init__.py +38 -9
- flyte/_internal/controllers/remote/_action.py +82 -12
- flyte/_internal/controllers/remote/_client.py +6 -2
- flyte/_internal/controllers/remote/_controller.py +290 -64
- flyte/_internal/controllers/remote/_core.py +155 -95
- flyte/_internal/controllers/remote/_informer.py +40 -20
- flyte/_internal/controllers/remote/_service_protocol.py +2 -2
- flyte/_internal/imagebuild/__init__.py +2 -10
- flyte/_internal/imagebuild/docker_builder.py +391 -84
- flyte/_internal/imagebuild/image_builder.py +111 -55
- flyte/_internal/imagebuild/remote_builder.py +409 -0
- flyte/_internal/imagebuild/utils.py +79 -0
- flyte/_internal/resolvers/_app_env_module.py +92 -0
- flyte/_internal/resolvers/_task_module.py +5 -38
- flyte/_internal/resolvers/app_env.py +26 -0
- flyte/_internal/resolvers/common.py +8 -1
- flyte/_internal/resolvers/default.py +2 -2
- flyte/_internal/runtime/convert.py +319 -36
- flyte/_internal/runtime/entrypoints.py +106 -18
- flyte/_internal/runtime/io.py +71 -23
- flyte/_internal/runtime/resources_serde.py +21 -7
- flyte/_internal/runtime/reuse.py +125 -0
- flyte/_internal/runtime/rusty.py +196 -0
- flyte/_internal/runtime/task_serde.py +239 -66
- flyte/_internal/runtime/taskrunner.py +48 -8
- flyte/_internal/runtime/trigger_serde.py +162 -0
- flyte/_internal/runtime/types_serde.py +7 -16
- flyte/_keyring/file.py +115 -0
- flyte/_link.py +30 -0
- flyte/_logging.py +241 -42
- flyte/_map.py +312 -0
- flyte/_metrics.py +59 -0
- flyte/_module.py +74 -0
- flyte/_pod.py +30 -0
- flyte/_resources.py +296 -33
- flyte/_retry.py +1 -7
- flyte/_reusable_environment.py +72 -7
- flyte/_run.py +462 -132
- flyte/_secret.py +47 -11
- flyte/_serve.py +333 -0
- flyte/_task.py +245 -56
- flyte/_task_environment.py +219 -97
- flyte/_task_plugins.py +47 -0
- flyte/_tools.py +8 -8
- flyte/_trace.py +15 -24
- flyte/_trigger.py +1027 -0
- flyte/_utils/__init__.py +12 -1
- flyte/_utils/asyn.py +3 -1
- flyte/_utils/async_cache.py +139 -0
- flyte/_utils/coro_management.py +5 -4
- flyte/_utils/description_parser.py +19 -0
- flyte/_utils/docker_credentials.py +173 -0
- flyte/_utils/helpers.py +45 -19
- flyte/_utils/module_loader.py +123 -0
- flyte/_utils/org_discovery.py +57 -0
- flyte/_utils/uv_script_parser.py +8 -1
- flyte/_version.py +16 -3
- flyte/app/__init__.py +27 -0
- flyte/app/_app_environment.py +362 -0
- flyte/app/_connector_environment.py +40 -0
- flyte/app/_deploy.py +130 -0
- flyte/app/_parameter.py +343 -0
- flyte/app/_runtime/__init__.py +3 -0
- flyte/app/_runtime/app_serde.py +383 -0
- flyte/app/_types.py +113 -0
- flyte/app/extras/__init__.py +9 -0
- flyte/app/extras/_auth_middleware.py +217 -0
- flyte/app/extras/_fastapi.py +93 -0
- flyte/app/extras/_model_loader/__init__.py +3 -0
- flyte/app/extras/_model_loader/config.py +7 -0
- flyte/app/extras/_model_loader/loader.py +288 -0
- flyte/cli/__init__.py +12 -0
- flyte/cli/_abort.py +28 -0
- flyte/cli/_build.py +114 -0
- flyte/cli/_common.py +493 -0
- flyte/cli/_create.py +371 -0
- flyte/cli/_delete.py +45 -0
- flyte/cli/_deploy.py +401 -0
- flyte/cli/_gen.py +316 -0
- flyte/cli/_get.py +446 -0
- flyte/cli/_option.py +33 -0
- flyte/{_cli → cli}/_params.py +57 -17
- flyte/cli/_plugins.py +209 -0
- flyte/cli/_prefetch.py +292 -0
- flyte/cli/_run.py +690 -0
- flyte/cli/_serve.py +338 -0
- flyte/cli/_update.py +86 -0
- flyte/cli/_user.py +20 -0
- flyte/cli/main.py +246 -0
- flyte/config/__init__.py +2 -167
- flyte/config/_config.py +215 -163
- flyte/config/_internal.py +10 -1
- flyte/config/_reader.py +225 -0
- flyte/connectors/__init__.py +11 -0
- flyte/connectors/_connector.py +330 -0
- flyte/connectors/_server.py +194 -0
- flyte/connectors/utils.py +159 -0
- flyte/errors.py +134 -2
- flyte/extend.py +24 -0
- flyte/extras/_container.py +69 -56
- flyte/git/__init__.py +3 -0
- flyte/git/_config.py +279 -0
- flyte/io/__init__.py +8 -1
- flyte/io/{structured_dataset → _dataframe}/__init__.py +32 -30
- flyte/io/{structured_dataset → _dataframe}/basic_dfs.py +75 -68
- flyte/io/{structured_dataset/structured_dataset.py → _dataframe/dataframe.py} +207 -242
- flyte/io/_dir.py +575 -113
- flyte/io/_file.py +587 -141
- flyte/io/_hashing_io.py +342 -0
- flyte/io/extend.py +7 -0
- flyte/models.py +635 -0
- flyte/prefetch/__init__.py +22 -0
- flyte/prefetch/_hf_model.py +563 -0
- flyte/remote/__init__.py +14 -3
- flyte/remote/_action.py +879 -0
- flyte/remote/_app.py +346 -0
- flyte/remote/_auth_metadata.py +42 -0
- flyte/remote/_client/_protocols.py +62 -4
- flyte/remote/_client/auth/_auth_utils.py +19 -0
- flyte/remote/_client/auth/_authenticators/base.py +8 -2
- flyte/remote/_client/auth/_authenticators/device_code.py +4 -5
- flyte/remote/_client/auth/_authenticators/factory.py +4 -0
- flyte/remote/_client/auth/_authenticators/passthrough.py +79 -0
- flyte/remote/_client/auth/_authenticators/pkce.py +17 -18
- flyte/remote/_client/auth/_channel.py +47 -18
- flyte/remote/_client/auth/_client_config.py +5 -3
- flyte/remote/_client/auth/_keyring.py +15 -2
- flyte/remote/_client/auth/_token_client.py +3 -3
- flyte/remote/_client/controlplane.py +206 -18
- flyte/remote/_common.py +66 -0
- flyte/remote/_data.py +107 -22
- flyte/remote/_logs.py +116 -33
- flyte/remote/_project.py +21 -19
- flyte/remote/_run.py +164 -631
- flyte/remote/_secret.py +72 -29
- flyte/remote/_task.py +387 -46
- flyte/remote/_trigger.py +368 -0
- flyte/remote/_user.py +43 -0
- flyte/report/_report.py +10 -6
- flyte/storage/__init__.py +13 -1
- flyte/storage/_config.py +237 -0
- flyte/storage/_parallel_reader.py +289 -0
- flyte/storage/_storage.py +268 -59
- flyte/syncify/__init__.py +56 -0
- flyte/syncify/_api.py +414 -0
- flyte/types/__init__.py +39 -0
- flyte/types/_interface.py +22 -7
- flyte/{io/pickle/transformer.py → types/_pickle.py} +37 -9
- flyte/types/_string_literals.py +8 -9
- flyte/types/_type_engine.py +226 -126
- flyte/types/_utils.py +1 -1
- flyte-2.0.0b46.data/scripts/debug.py +38 -0
- flyte-2.0.0b46.data/scripts/runtime.py +194 -0
- flyte-2.0.0b46.dist-info/METADATA +352 -0
- flyte-2.0.0b46.dist-info/RECORD +221 -0
- flyte-2.0.0b46.dist-info/entry_points.txt +8 -0
- flyte-2.0.0b46.dist-info/licenses/LICENSE +201 -0
- flyte/_api_commons.py +0 -3
- flyte/_cli/_common.py +0 -299
- flyte/_cli/_create.py +0 -42
- flyte/_cli/_delete.py +0 -23
- flyte/_cli/_deploy.py +0 -140
- flyte/_cli/_get.py +0 -235
- flyte/_cli/_run.py +0 -174
- flyte/_cli/main.py +0 -98
- flyte/_datastructures.py +0 -342
- flyte/_internal/controllers/pbhash.py +0 -39
- flyte/_protos/common/authorization_pb2.py +0 -66
- flyte/_protos/common/authorization_pb2.pyi +0 -108
- flyte/_protos/common/authorization_pb2_grpc.py +0 -4
- flyte/_protos/common/identifier_pb2.py +0 -71
- flyte/_protos/common/identifier_pb2.pyi +0 -82
- flyte/_protos/common/identifier_pb2_grpc.py +0 -4
- flyte/_protos/common/identity_pb2.py +0 -48
- flyte/_protos/common/identity_pb2.pyi +0 -72
- flyte/_protos/common/identity_pb2_grpc.py +0 -4
- flyte/_protos/common/list_pb2.py +0 -36
- flyte/_protos/common/list_pb2.pyi +0 -69
- flyte/_protos/common/list_pb2_grpc.py +0 -4
- flyte/_protos/common/policy_pb2.py +0 -37
- flyte/_protos/common/policy_pb2.pyi +0 -27
- flyte/_protos/common/policy_pb2_grpc.py +0 -4
- flyte/_protos/common/role_pb2.py +0 -37
- flyte/_protos/common/role_pb2.pyi +0 -53
- flyte/_protos/common/role_pb2_grpc.py +0 -4
- flyte/_protos/common/runtime_version_pb2.py +0 -28
- flyte/_protos/common/runtime_version_pb2.pyi +0 -24
- flyte/_protos/common/runtime_version_pb2_grpc.py +0 -4
- flyte/_protos/logs/dataplane/payload_pb2.py +0 -96
- flyte/_protos/logs/dataplane/payload_pb2.pyi +0 -168
- flyte/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
- flyte/_protos/secret/definition_pb2.py +0 -49
- flyte/_protos/secret/definition_pb2.pyi +0 -93
- flyte/_protos/secret/definition_pb2_grpc.py +0 -4
- flyte/_protos/secret/payload_pb2.py +0 -62
- flyte/_protos/secret/payload_pb2.pyi +0 -94
- flyte/_protos/secret/payload_pb2_grpc.py +0 -4
- flyte/_protos/secret/secret_pb2.py +0 -38
- flyte/_protos/secret/secret_pb2.pyi +0 -6
- flyte/_protos/secret/secret_pb2_grpc.py +0 -198
- flyte/_protos/secret/secret_pb2_grpc_grpc.py +0 -198
- flyte/_protos/validate/validate/validate_pb2.py +0 -76
- flyte/_protos/workflow/node_execution_service_pb2.py +0 -26
- flyte/_protos/workflow/node_execution_service_pb2.pyi +0 -4
- flyte/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
- flyte/_protos/workflow/queue_service_pb2.py +0 -106
- flyte/_protos/workflow/queue_service_pb2.pyi +0 -141
- flyte/_protos/workflow/queue_service_pb2_grpc.py +0 -172
- flyte/_protos/workflow/run_definition_pb2.py +0 -128
- flyte/_protos/workflow/run_definition_pb2.pyi +0 -310
- flyte/_protos/workflow/run_definition_pb2_grpc.py +0 -4
- flyte/_protos/workflow/run_logs_service_pb2.py +0 -41
- flyte/_protos/workflow/run_logs_service_pb2.pyi +0 -28
- flyte/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
- flyte/_protos/workflow/run_service_pb2.py +0 -133
- flyte/_protos/workflow/run_service_pb2.pyi +0 -175
- flyte/_protos/workflow/run_service_pb2_grpc.py +0 -412
- flyte/_protos/workflow/state_service_pb2.py +0 -58
- flyte/_protos/workflow/state_service_pb2.pyi +0 -71
- flyte/_protos/workflow/state_service_pb2_grpc.py +0 -138
- flyte/_protos/workflow/task_definition_pb2.py +0 -72
- flyte/_protos/workflow/task_definition_pb2.pyi +0 -65
- flyte/_protos/workflow/task_definition_pb2_grpc.py +0 -4
- flyte/_protos/workflow/task_service_pb2.py +0 -44
- flyte/_protos/workflow/task_service_pb2.pyi +0 -31
- flyte/_protos/workflow/task_service_pb2_grpc.py +0 -104
- flyte/io/_dataframe.py +0 -0
- flyte/io/pickle/__init__.py +0 -0
- flyte/remote/_console.py +0 -18
- flyte-0.2.0b1.dist-info/METADATA +0 -179
- flyte-0.2.0b1.dist-info/RECORD +0 -204
- flyte-0.2.0b1.dist-info/entry_points.txt +0 -3
- /flyte/{_cli → _debug}/__init__.py +0 -0
- /flyte/{_protos → _keyring}/__init__.py +0 -0
- {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/WHEEL +0 -0
- {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/top_level.txt +0 -0
flyte/_run.py
CHANGED
|
@@ -1,45 +1,79 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import pathlib
|
|
5
|
+
import sys
|
|
4
6
|
import uuid
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import flyte.
|
|
9
|
-
from flyte import
|
|
10
|
-
|
|
11
|
-
from .
|
|
12
|
-
from ._context import contextual_run, internal_ctx
|
|
13
|
-
from ._datastructures import ActionID, Checkpoints, RawDataPath, SerializationContext, TaskContext
|
|
14
|
-
from ._environment import Environment
|
|
15
|
-
from ._initialize import (
|
|
16
|
-
ABFS,
|
|
17
|
-
GCS,
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union, cast
|
|
9
|
+
|
|
10
|
+
import flyte.errors
|
|
11
|
+
from flyte._context import contextual_run, internal_ctx
|
|
12
|
+
from flyte._environment import Environment
|
|
13
|
+
from flyte._initialize import (
|
|
18
14
|
_get_init_config,
|
|
19
15
|
get_client,
|
|
20
|
-
|
|
16
|
+
get_init_config,
|
|
21
17
|
get_storage,
|
|
22
18
|
requires_initialization,
|
|
23
19
|
requires_storage,
|
|
24
20
|
)
|
|
25
|
-
from .
|
|
26
|
-
from .
|
|
27
|
-
from .
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
from flyte._logging import LogFormat, logger
|
|
22
|
+
from flyte._task import F, P, R, TaskTemplate
|
|
23
|
+
from flyte.models import (
|
|
24
|
+
ActionID,
|
|
25
|
+
Checkpoints,
|
|
26
|
+
CodeBundle,
|
|
27
|
+
RawDataPath,
|
|
28
|
+
SerializationContext,
|
|
29
|
+
TaskContext,
|
|
30
|
+
)
|
|
31
|
+
from flyte.syncify import syncify
|
|
32
|
+
|
|
33
|
+
from ._constants import FLYTE_SYS_PATH
|
|
33
34
|
|
|
34
35
|
if TYPE_CHECKING:
|
|
35
36
|
from flyte.remote import Run
|
|
37
|
+
from flyte.remote._task import LazyEntity
|
|
36
38
|
|
|
37
39
|
from ._code_bundle import CopyFiles
|
|
40
|
+
from ._internal.imagebuild.image_builder import ImageCache
|
|
38
41
|
|
|
39
42
|
Mode = Literal["local", "remote", "hybrid"]
|
|
43
|
+
CacheLookupScope = Literal["global", "project-domain"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class _CacheKey:
|
|
48
|
+
obj_id: int
|
|
49
|
+
dry_run: bool
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class _CacheValue:
|
|
54
|
+
code_bundle: CodeBundle | None
|
|
55
|
+
image_cache: Optional[ImageCache]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
_RUN_CACHE: Dict[_CacheKey, _CacheValue] = {}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def _get_code_bundle_for_run(name: str) -> CodeBundle | None:
|
|
62
|
+
"""
|
|
63
|
+
Get the code bundle for the run with the given name.
|
|
64
|
+
This is used to get the code bundle for the run when running in hybrid mode.
|
|
65
|
+
"""
|
|
66
|
+
from flyte._internal.runtime.task_serde import extract_code_bundle
|
|
67
|
+
from flyte.remote import Run
|
|
68
|
+
|
|
69
|
+
run = await Run.get.aio(name=name)
|
|
70
|
+
if run:
|
|
71
|
+
run_details = await run.details.aio()
|
|
72
|
+
spec = run_details.action_details.pb2.resolved_task_spec
|
|
73
|
+
return extract_code_bundle(spec)
|
|
74
|
+
return None
|
|
40
75
|
|
|
41
76
|
|
|
42
|
-
@syncer.wrap
|
|
43
77
|
class _Runner:
|
|
44
78
|
def __init__(
|
|
45
79
|
self,
|
|
@@ -54,13 +88,29 @@ class _Runner:
|
|
|
54
88
|
raw_data_path: str | None = None,
|
|
55
89
|
metadata_path: str | None = None,
|
|
56
90
|
run_base_dir: str | None = None,
|
|
91
|
+
overwrite_cache: bool = False,
|
|
92
|
+
project: str | None = None,
|
|
93
|
+
domain: str | None = None,
|
|
94
|
+
env_vars: Dict[str, str] | None = None,
|
|
95
|
+
labels: Dict[str, str] | None = None,
|
|
96
|
+
annotations: Dict[str, str] | None = None,
|
|
97
|
+
interruptible: bool | None = None,
|
|
98
|
+
log_level: int | None = None,
|
|
99
|
+
log_format: LogFormat = "console",
|
|
100
|
+
reset_root_logger: bool = False,
|
|
101
|
+
disable_run_cache: bool = False,
|
|
102
|
+
queue: Optional[str] = None,
|
|
103
|
+
custom_context: Dict[str, str] | None = None,
|
|
104
|
+
cache_lookup_scope: CacheLookupScope = "global",
|
|
57
105
|
):
|
|
106
|
+
from flyte._tools import ipython_check
|
|
107
|
+
|
|
58
108
|
init_config = _get_init_config()
|
|
59
109
|
client = init_config.client if init_config else None
|
|
60
110
|
if not force_mode and client is not None:
|
|
61
111
|
force_mode = "remote"
|
|
62
112
|
force_mode = force_mode or "local"
|
|
63
|
-
logger.debug(f"Effective run mode: {force_mode}
|
|
113
|
+
logger.debug(f"Effective run mode: `{force_mode}`, client configured: `{client is not None}`")
|
|
64
114
|
self._mode = force_mode
|
|
65
115
|
self._name = name
|
|
66
116
|
self._service_account = service_account
|
|
@@ -70,105 +120,249 @@ class _Runner:
|
|
|
70
120
|
self._copy_bundle_to = copy_bundle_to
|
|
71
121
|
self._interactive_mode = interactive_mode if interactive_mode else ipython_check()
|
|
72
122
|
self._raw_data_path = raw_data_path
|
|
73
|
-
self._metadata_path = metadata_path
|
|
74
|
-
self._run_base_dir = run_base_dir
|
|
123
|
+
self._metadata_path = metadata_path
|
|
124
|
+
self._run_base_dir = run_base_dir
|
|
125
|
+
self._overwrite_cache = overwrite_cache
|
|
126
|
+
self._project = project
|
|
127
|
+
self._domain = domain
|
|
128
|
+
self._env_vars = env_vars
|
|
129
|
+
self._labels = labels
|
|
130
|
+
self._annotations = annotations
|
|
131
|
+
self._interruptible = interruptible
|
|
132
|
+
self._log_level = log_level
|
|
133
|
+
self._log_format = log_format
|
|
134
|
+
self._reset_root_logger = reset_root_logger
|
|
135
|
+
self._disable_run_cache = disable_run_cache
|
|
136
|
+
self._queue = queue
|
|
137
|
+
self._custom_context = custom_context or {}
|
|
138
|
+
self._cache_lookup_scope = cache_lookup_scope
|
|
75
139
|
|
|
76
140
|
@requires_initialization
|
|
77
|
-
async def _run_remote(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) -> Run:
|
|
141
|
+
async def _run_remote(self, obj: TaskTemplate[P, R, F] | LazyEntity, *args: P.args, **kwargs: P.kwargs) -> Run:
|
|
142
|
+
import grpc
|
|
143
|
+
from flyteidl2.common import identifier_pb2
|
|
144
|
+
from flyteidl2.core import literals_pb2, security_pb2
|
|
145
|
+
from flyteidl2.task import run_pb2
|
|
146
|
+
from flyteidl2.workflow import run_definition_pb2, run_service_pb2
|
|
147
|
+
from google.protobuf import wrappers_pb2
|
|
148
|
+
|
|
78
149
|
from flyte.remote import Run
|
|
150
|
+
from flyte.remote._task import LazyEntity, TaskDetails
|
|
79
151
|
|
|
80
152
|
from ._code_bundle import build_code_bundle, build_pkl_bundle
|
|
81
|
-
from ._deploy import build_images
|
|
153
|
+
from ._deploy import build_images
|
|
82
154
|
from ._internal.runtime.convert import convert_from_native_to_inputs
|
|
83
155
|
from ._internal.runtime.task_serde import translate_task_to_wire
|
|
84
|
-
from ._protos.workflow import run_definition_pb2, run_service_pb2
|
|
85
156
|
|
|
86
|
-
cfg =
|
|
157
|
+
cfg = get_init_config()
|
|
158
|
+
project = self._project or cfg.project
|
|
159
|
+
domain = self._domain or cfg.domain
|
|
87
160
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
161
|
+
task: TaskTemplate[P, R, F] | TaskDetails
|
|
162
|
+
if isinstance(obj, (LazyEntity, TaskDetails)):
|
|
163
|
+
if isinstance(obj, LazyEntity):
|
|
164
|
+
task = await obj.fetch.aio()
|
|
165
|
+
else:
|
|
166
|
+
task = obj
|
|
167
|
+
task_spec = task.pb2.spec
|
|
168
|
+
inputs = await convert_from_native_to_inputs(
|
|
169
|
+
task.interface, *args, custom_context=self._custom_context, **kwargs
|
|
170
|
+
)
|
|
171
|
+
version = task.pb2.task_id.version
|
|
172
|
+
code_bundle = None
|
|
173
|
+
elif isinstance(obj, TaskTemplate):
|
|
174
|
+
task = cast(TaskTemplate[P, R, F], obj)
|
|
175
|
+
if obj.parent_env is None:
|
|
176
|
+
raise ValueError("Task is not attached to an environment. Please attach the task to an environment")
|
|
177
|
+
|
|
178
|
+
if (
|
|
179
|
+
not self._disable_run_cache
|
|
180
|
+
and _RUN_CACHE.get(_CacheKey(obj_id=id(obj), dry_run=self._dry_run)) is not None
|
|
181
|
+
):
|
|
182
|
+
cached_value = _RUN_CACHE[_CacheKey(obj_id=id(obj), dry_run=self._dry_run)]
|
|
183
|
+
code_bundle = cached_value.code_bundle
|
|
184
|
+
image_cache = cached_value.image_cache
|
|
185
|
+
else:
|
|
186
|
+
if not self._dry_run:
|
|
187
|
+
image_cache = await build_images.aio(cast(Environment, obj.parent_env()))
|
|
188
|
+
else:
|
|
189
|
+
image_cache = None
|
|
190
|
+
|
|
191
|
+
if self._interactive_mode:
|
|
192
|
+
code_bundle = await build_pkl_bundle(
|
|
193
|
+
obj,
|
|
194
|
+
upload_to_controlplane=not self._dry_run,
|
|
195
|
+
copy_bundle_to=self._copy_bundle_to,
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
if self._copy_files != "none":
|
|
199
|
+
code_bundle = await build_code_bundle(
|
|
200
|
+
from_dir=cfg.root_dir,
|
|
201
|
+
dryrun=self._dry_run,
|
|
202
|
+
copy_bundle_to=self._copy_bundle_to,
|
|
203
|
+
copy_style=self._copy_files,
|
|
204
|
+
)
|
|
205
|
+
else:
|
|
206
|
+
code_bundle = None
|
|
207
|
+
if not self._disable_run_cache:
|
|
208
|
+
_RUN_CACHE[_CacheKey(obj_id=id(obj), dry_run=self._dry_run)] = _CacheValue(
|
|
209
|
+
code_bundle=code_bundle, image_cache=image_cache
|
|
210
|
+
)
|
|
93
211
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
212
|
+
version = self._version or (
|
|
213
|
+
code_bundle.computed_version if code_bundle and code_bundle.computed_version else None
|
|
214
|
+
)
|
|
215
|
+
if not version:
|
|
216
|
+
raise ValueError("Version is required when running a task")
|
|
217
|
+
s_ctx = SerializationContext(
|
|
218
|
+
code_bundle=code_bundle,
|
|
219
|
+
version=version,
|
|
220
|
+
image_cache=image_cache,
|
|
221
|
+
root_dir=cfg.root_dir,
|
|
222
|
+
)
|
|
223
|
+
task_spec = translate_task_to_wire(obj, s_ctx)
|
|
224
|
+
inputs = await convert_from_native_to_inputs(
|
|
225
|
+
obj.native_interface, *args, custom_context=self._custom_context, **kwargs
|
|
97
226
|
)
|
|
98
227
|
else:
|
|
99
|
-
|
|
100
|
-
code_bundle = await build_code_bundle(
|
|
101
|
-
from_dir=cfg.root_dir, dryrun=self._dry_run, copy_bundle_to=self._copy_bundle_to
|
|
102
|
-
)
|
|
103
|
-
else:
|
|
104
|
-
code_bundle = None
|
|
228
|
+
raise ValueError(f"Not supported Task Type: {type(task)}")
|
|
105
229
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
230
|
+
env = self._env_vars or {}
|
|
231
|
+
if env.get("LOG_LEVEL") is None:
|
|
232
|
+
if self._log_level:
|
|
233
|
+
env["LOG_LEVEL"] = str(self._log_level)
|
|
234
|
+
else:
|
|
235
|
+
env["LOG_LEVEL"] = str(logger.getEffectiveLevel())
|
|
236
|
+
env["LOG_FORMAT"] = self._log_format
|
|
237
|
+
if self._reset_root_logger:
|
|
238
|
+
env["FLYTE_RESET_ROOT_LOGGER"] = "1"
|
|
239
|
+
|
|
240
|
+
# These paths will be appended to sys.path at runtime.
|
|
241
|
+
if cfg.sync_local_sys_paths:
|
|
242
|
+
env[FLYTE_SYS_PATH] = ":".join(
|
|
243
|
+
f"./{pathlib.Path(p).relative_to(cfg.root_dir)}" for p in sys.path if p.startswith(str(cfg.root_dir))
|
|
244
|
+
)
|
|
119
245
|
|
|
120
246
|
if not self._dry_run:
|
|
121
247
|
if get_client() is None:
|
|
122
248
|
# This can only happen, if the user forces flyte.run(mode="remote") without initializing the client
|
|
123
|
-
raise InitializationError(
|
|
249
|
+
raise flyte.errors.InitializationError(
|
|
124
250
|
"ClientNotInitializedError",
|
|
125
251
|
"user",
|
|
126
252
|
"flyte.run requires client to be initialized. "
|
|
127
|
-
"Call flyte.init() with a valid endpoint
|
|
253
|
+
"Call flyte.init() with a valid endpoint/api-key before using this function"
|
|
254
|
+
"or Call flyte.init_from_config() with a valid path to the config file",
|
|
128
255
|
)
|
|
129
256
|
run_id = None
|
|
130
257
|
project_id = None
|
|
131
258
|
if self._name:
|
|
132
|
-
run_id =
|
|
133
|
-
project=
|
|
134
|
-
domain=
|
|
259
|
+
run_id = identifier_pb2.RunIdentifier(
|
|
260
|
+
project=project,
|
|
261
|
+
domain=domain,
|
|
135
262
|
org=cfg.org,
|
|
136
263
|
name=self._name if self._name else None,
|
|
137
264
|
)
|
|
138
265
|
else:
|
|
139
266
|
project_id = identifier_pb2.ProjectIdentifier(
|
|
140
|
-
name=
|
|
141
|
-
domain=
|
|
267
|
+
name=project,
|
|
268
|
+
domain=domain,
|
|
142
269
|
organization=cfg.org,
|
|
143
270
|
)
|
|
144
271
|
# Fill in task id inside the task template if it's not provided.
|
|
145
272
|
# Maybe this should be done here, or the backend.
|
|
146
273
|
if task_spec.task_template.id.project == "":
|
|
147
|
-
task_spec.task_template.id.project =
|
|
274
|
+
task_spec.task_template.id.project = project if project else ""
|
|
148
275
|
if task_spec.task_template.id.domain == "":
|
|
149
|
-
task_spec.task_template.id.domain =
|
|
276
|
+
task_spec.task_template.id.domain = domain if domain else ""
|
|
150
277
|
if task_spec.task_template.id.org == "":
|
|
151
278
|
task_spec.task_template.id.org = cfg.org if cfg.org else ""
|
|
152
279
|
if task_spec.task_template.id.version == "":
|
|
153
280
|
task_spec.task_template.id.version = version
|
|
154
281
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
282
|
+
kv_pairs: List[literals_pb2.KeyValuePair] = []
|
|
283
|
+
for k, v in env.items():
|
|
284
|
+
if not isinstance(v, str):
|
|
285
|
+
raise ValueError(f"Environment variable {k} must be a string, got {type(v)}")
|
|
286
|
+
kv_pairs.append(literals_pb2.KeyValuePair(key=k, value=v))
|
|
287
|
+
|
|
288
|
+
env_kv = run_pb2.Envs(values=kv_pairs)
|
|
289
|
+
annotations = run_pb2.Annotations(values=self._annotations)
|
|
290
|
+
labels = run_pb2.Labels(values=self._labels)
|
|
291
|
+
raw_data_storage = (
|
|
292
|
+
run_pb2.RawDataStorage(raw_data_prefix=self._raw_data_path) if self._raw_data_path else None
|
|
293
|
+
)
|
|
294
|
+
security_context = (
|
|
295
|
+
security_pb2.SecurityContext(run_as=security_pb2.Identity(k8s_service_account=self._service_account))
|
|
296
|
+
if self._service_account
|
|
297
|
+
else None
|
|
162
298
|
)
|
|
163
|
-
|
|
299
|
+
|
|
300
|
+
def _to_cache_lookup_scope(scope: CacheLookupScope | None = None) -> run_pb2.CacheLookupScope:
|
|
301
|
+
if scope == "global":
|
|
302
|
+
return run_pb2.CacheLookupScope.CACHE_LOOKUP_SCOPE_GLOBAL
|
|
303
|
+
elif scope == "project-domain":
|
|
304
|
+
return run_pb2.CacheLookupScope.CACHE_LOOKUP_SCOPE_PROJECT_DOMAIN
|
|
305
|
+
elif scope is None:
|
|
306
|
+
return run_pb2.CacheLookupScope.CACHE_LOOKUP_SCOPE_UNSPECIFIED
|
|
307
|
+
else:
|
|
308
|
+
raise ValueError(f"Unknown cache lookup scope: {scope}")
|
|
309
|
+
|
|
310
|
+
try:
|
|
311
|
+
resp = await get_client().run_service.CreateRun(
|
|
312
|
+
run_service_pb2.CreateRunRequest(
|
|
313
|
+
run_id=run_id,
|
|
314
|
+
project_id=project_id,
|
|
315
|
+
task_spec=task_spec,
|
|
316
|
+
inputs=inputs.proto_inputs,
|
|
317
|
+
run_spec=run_pb2.RunSpec(
|
|
318
|
+
overwrite_cache=self._overwrite_cache,
|
|
319
|
+
interruptible=wrappers_pb2.BoolValue(value=self._interruptible)
|
|
320
|
+
if self._interruptible is not None
|
|
321
|
+
else None,
|
|
322
|
+
annotations=annotations,
|
|
323
|
+
labels=labels,
|
|
324
|
+
envs=env_kv,
|
|
325
|
+
cluster=self._queue or task.queue,
|
|
326
|
+
raw_data_storage=raw_data_storage,
|
|
327
|
+
security_context=security_context,
|
|
328
|
+
cache_config=run_pb2.CacheConfig(
|
|
329
|
+
overwrite_cache=self._overwrite_cache,
|
|
330
|
+
cache_lookup_scope=_to_cache_lookup_scope(self._cache_lookup_scope)
|
|
331
|
+
if self._cache_lookup_scope
|
|
332
|
+
else None,
|
|
333
|
+
),
|
|
334
|
+
),
|
|
335
|
+
),
|
|
336
|
+
)
|
|
337
|
+
return Run(pb2=resp.run)
|
|
338
|
+
except grpc.aio.AioRpcError as e:
|
|
339
|
+
if e.code() == grpc.StatusCode.UNAVAILABLE:
|
|
340
|
+
raise flyte.errors.RuntimeSystemError(
|
|
341
|
+
"SystemUnavailableError",
|
|
342
|
+
"Flyte system is currently unavailable. check your configuration, or the service status.",
|
|
343
|
+
) from e
|
|
344
|
+
elif e.code() == grpc.StatusCode.INVALID_ARGUMENT:
|
|
345
|
+
raise flyte.errors.RuntimeUserError("InvalidArgumentError", e.details())
|
|
346
|
+
elif e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
347
|
+
# TODO maybe this should be a pass and return existing run?
|
|
348
|
+
raise flyte.errors.RuntimeUserError(
|
|
349
|
+
"RunAlreadyExistsError",
|
|
350
|
+
f"A run with the name '{self._name}' already exists. Please choose a different name.",
|
|
351
|
+
)
|
|
352
|
+
else:
|
|
353
|
+
raise flyte.errors.RuntimeSystemError(
|
|
354
|
+
"RunCreationError",
|
|
355
|
+
f"Failed to create run: {e.details()}",
|
|
356
|
+
) from e
|
|
164
357
|
|
|
165
358
|
class DryRun(Run):
|
|
166
359
|
def __init__(self, _task_spec, _inputs, _code_bundle):
|
|
167
360
|
super().__init__(
|
|
168
361
|
pb2=run_definition_pb2.Run(
|
|
169
362
|
action=run_definition_pb2.Action(
|
|
170
|
-
id=
|
|
171
|
-
name="a0",
|
|
363
|
+
id=identifier_pb2.ActionIdentifier(
|
|
364
|
+
name="a0",
|
|
365
|
+
run=identifier_pb2.RunIdentifier(name="dry-run"),
|
|
172
366
|
)
|
|
173
367
|
)
|
|
174
368
|
)
|
|
@@ -181,35 +375,50 @@ class _Runner:
|
|
|
181
375
|
|
|
182
376
|
@requires_storage
|
|
183
377
|
@requires_initialization
|
|
184
|
-
async def _run_hybrid(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) -> R:
|
|
378
|
+
async def _run_hybrid(self, obj: TaskTemplate[P, R, F], *args: P.args, **kwargs: P.kwargs) -> R:
|
|
185
379
|
"""
|
|
186
380
|
Run a task in hybrid mode. This means that the parent action will be run locally, but the child actions will be
|
|
187
381
|
run in the cluster remotely. This is currently only used for testing,
|
|
188
382
|
over the longer term we will productize this.
|
|
189
383
|
"""
|
|
384
|
+
import flyte.report
|
|
190
385
|
from flyte._code_bundle import build_code_bundle, build_pkl_bundle
|
|
191
|
-
from flyte.
|
|
192
|
-
from flyte.
|
|
386
|
+
from flyte._deploy import build_images
|
|
387
|
+
from flyte.models import RawDataPath
|
|
388
|
+
from flyte.storage import ABFS, GCS, S3
|
|
193
389
|
|
|
194
|
-
|
|
390
|
+
from ._internal import create_controller
|
|
391
|
+
from ._internal.runtime.taskrunner import run_task
|
|
392
|
+
|
|
393
|
+
cfg = get_init_config()
|
|
195
394
|
|
|
196
395
|
if obj.parent_env is None:
|
|
197
396
|
raise ValueError("Task is not attached to an environment. Please attach the task to an environment.")
|
|
198
397
|
|
|
199
|
-
|
|
200
|
-
image_cache = await build_images(deploy_plan)
|
|
398
|
+
image_cache = await build_images.aio(cast(Environment, obj.parent_env()))
|
|
201
399
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
400
|
+
code_bundle = None
|
|
401
|
+
if self._name is not None:
|
|
402
|
+
# Check if remote run service has this run name already and if exists, then extract the code bundle from it.
|
|
403
|
+
code_bundle = await _get_code_bundle_for_run(name=self._name)
|
|
404
|
+
|
|
405
|
+
if not code_bundle:
|
|
406
|
+
if self._interactive_mode:
|
|
407
|
+
code_bundle = await build_pkl_bundle(
|
|
408
|
+
obj,
|
|
409
|
+
upload_to_controlplane=not self._dry_run,
|
|
410
|
+
copy_bundle_to=self._copy_bundle_to,
|
|
210
411
|
)
|
|
211
412
|
else:
|
|
212
|
-
|
|
413
|
+
if self._copy_files != "none":
|
|
414
|
+
code_bundle = await build_code_bundle(
|
|
415
|
+
from_dir=cfg.root_dir,
|
|
416
|
+
dryrun=self._dry_run,
|
|
417
|
+
copy_bundle_to=self._copy_bundle_to,
|
|
418
|
+
copy_style=self._copy_files,
|
|
419
|
+
)
|
|
420
|
+
else:
|
|
421
|
+
code_bundle = None
|
|
213
422
|
|
|
214
423
|
version = self._version or (
|
|
215
424
|
code_bundle.computed_version if code_bundle and code_bundle.computed_version else None
|
|
@@ -217,14 +426,14 @@ class _Runner:
|
|
|
217
426
|
if not version:
|
|
218
427
|
raise ValueError("Version is required when running a task")
|
|
219
428
|
|
|
220
|
-
project = cfg.project
|
|
221
|
-
domain = cfg.domain
|
|
222
|
-
org = cfg.org
|
|
429
|
+
project = cfg.project
|
|
430
|
+
domain = cfg.domain
|
|
431
|
+
org = cfg.org
|
|
223
432
|
action_name = "a0"
|
|
224
433
|
run_name = self._name
|
|
225
434
|
random_id = str(uuid.uuid4())[:6]
|
|
226
435
|
|
|
227
|
-
controller = create_controller(
|
|
436
|
+
controller = create_controller("remote", endpoint="localhost:8090", insecure=True)
|
|
228
437
|
action = ActionID(name=action_name, run_name=run_name, project=project, domain=domain, org=org)
|
|
229
438
|
|
|
230
439
|
inputs = obj.native_interface.convert_to_kwargs(*args, **kwargs)
|
|
@@ -240,9 +449,10 @@ class _Runner:
|
|
|
240
449
|
" flyte.with_runcontext(run_base_dir='s3://bucket/metadata/outputs')",
|
|
241
450
|
)
|
|
242
451
|
output_path = self._run_base_dir
|
|
452
|
+
run_base_dir = self._run_base_dir
|
|
243
453
|
raw_data_path = f"{output_path}/rd/{random_id}"
|
|
244
454
|
raw_data_path_obj = RawDataPath(path=raw_data_path)
|
|
245
|
-
checkpoint_path = f"{raw_data_path}/
|
|
455
|
+
checkpoint_path = f"{raw_data_path}/checkpoint"
|
|
246
456
|
prev_checkpoint = f"{raw_data_path}/prev_checkpoint"
|
|
247
457
|
checkpoints = Checkpoints(checkpoint_path, prev_checkpoint)
|
|
248
458
|
|
|
@@ -253,11 +463,12 @@ class _Runner:
|
|
|
253
463
|
checkpoints=checkpoints,
|
|
254
464
|
code_bundle=code_bundle,
|
|
255
465
|
output_path=output_path,
|
|
256
|
-
version=version,
|
|
466
|
+
version=version if version else "na",
|
|
257
467
|
raw_data_path=raw_data_path_obj,
|
|
258
468
|
compiled_image_cache=image_cache,
|
|
259
|
-
run_base_dir=
|
|
469
|
+
run_base_dir=run_base_dir,
|
|
260
470
|
report=flyte.report.Report(name=action.name),
|
|
471
|
+
custom_context=self._custom_context,
|
|
261
472
|
)
|
|
262
473
|
async with ctx.replace_task_context(tctx):
|
|
263
474
|
return await run_task(tctx=tctx, controller=controller, task=obj, inputs=inputs)
|
|
@@ -267,44 +478,101 @@ class _Runner:
|
|
|
267
478
|
raise err
|
|
268
479
|
return outputs
|
|
269
480
|
|
|
270
|
-
async def _run_local(self, obj: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) ->
|
|
481
|
+
async def _run_local(self, obj: TaskTemplate[P, R, F], *args: P.args, **kwargs: P.kwargs) -> Run:
|
|
482
|
+
from flyteidl2.common import identifier_pb2
|
|
483
|
+
|
|
271
484
|
from flyte._internal.controllers import create_controller
|
|
272
|
-
from flyte._internal.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
)
|
|
277
|
-
from flyte._internal.runtime.entrypoints import direct_dispatch
|
|
485
|
+
from flyte._internal.controllers._local_controller import LocalController
|
|
486
|
+
from flyte.remote import ActionOutputs, Run
|
|
487
|
+
from flyte.report import Report
|
|
488
|
+
|
|
489
|
+
controller = cast(LocalController, create_controller("local"))
|
|
278
490
|
|
|
279
|
-
controller = create_controller(ct="local")
|
|
280
|
-
inputs = await convert_from_native_to_inputs(obj.native_interface, *args, **kwargs)
|
|
281
491
|
if self._name is None:
|
|
282
492
|
action = ActionID.create_random()
|
|
283
493
|
else:
|
|
284
494
|
action = ActionID(name=self._name)
|
|
285
|
-
|
|
286
|
-
|
|
495
|
+
|
|
496
|
+
metadata_path = self._metadata_path
|
|
497
|
+
if metadata_path is None:
|
|
498
|
+
metadata_path = pathlib.Path("/") / "tmp" / "flyte" / "metadata" / action.name
|
|
499
|
+
else:
|
|
500
|
+
metadata_path = pathlib.Path(metadata_path) / action.name
|
|
501
|
+
output_path = metadata_path / "a0"
|
|
502
|
+
if self._raw_data_path is None:
|
|
503
|
+
path = pathlib.Path("/") / "tmp" / "flyte" / "raw_data" / action.name
|
|
504
|
+
raw_data_path = RawDataPath(path=str(path))
|
|
505
|
+
else:
|
|
506
|
+
raw_data_path = RawDataPath(path=self._raw_data_path)
|
|
507
|
+
|
|
508
|
+
ctx = internal_ctx()
|
|
509
|
+
tctx = TaskContext(
|
|
287
510
|
action=action,
|
|
288
|
-
raw_data_path=internal_ctx().raw_data,
|
|
289
|
-
version="na",
|
|
290
|
-
controller=controller,
|
|
291
|
-
inputs=inputs,
|
|
292
|
-
output_path=self._metadata_path,
|
|
293
|
-
run_base_dir=self._metadata_path,
|
|
294
511
|
checkpoints=Checkpoints(
|
|
295
|
-
prev_checkpoint_path=internal_ctx().raw_data.path,
|
|
512
|
+
prev_checkpoint_path=internal_ctx().raw_data.path,
|
|
513
|
+
checkpoint_path=internal_ctx().raw_data.path,
|
|
296
514
|
),
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
515
|
+
code_bundle=None,
|
|
516
|
+
output_path=str(output_path),
|
|
517
|
+
run_base_dir=str(metadata_path),
|
|
518
|
+
version="na",
|
|
519
|
+
raw_data_path=raw_data_path,
|
|
520
|
+
compiled_image_cache=None,
|
|
521
|
+
report=Report(name=action.name),
|
|
522
|
+
mode="local",
|
|
523
|
+
custom_context=self._custom_context,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
with ctx.replace_task_context(tctx):
|
|
527
|
+
# make the local version always runs on a different thread, returns a wrapped future.
|
|
528
|
+
if obj._call_as_synchronous:
|
|
529
|
+
fut = controller.submit_sync(obj, *args, **kwargs)
|
|
530
|
+
awaitable = asyncio.wrap_future(fut)
|
|
531
|
+
outputs = await awaitable
|
|
532
|
+
else:
|
|
533
|
+
outputs = await controller.submit(obj, *args, **kwargs)
|
|
534
|
+
|
|
535
|
+
class _LocalRun(Run):
|
|
536
|
+
def __init__(self, outputs: Tuple[Any, ...] | Any):
|
|
537
|
+
from flyteidl2.workflow import run_definition_pb2
|
|
538
|
+
|
|
539
|
+
self._outputs = outputs
|
|
540
|
+
super().__init__(
|
|
541
|
+
pb2=run_definition_pb2.Run(
|
|
542
|
+
action=run_definition_pb2.Action(
|
|
543
|
+
id=identifier_pb2.ActionIdentifier(
|
|
544
|
+
name="a0",
|
|
545
|
+
run=identifier_pb2.RunIdentifier(name="dry-run"),
|
|
546
|
+
)
|
|
547
|
+
)
|
|
548
|
+
)
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
@property
|
|
552
|
+
def url(self) -> str:
|
|
553
|
+
return str(metadata_path)
|
|
554
|
+
|
|
555
|
+
@syncify
|
|
556
|
+
async def wait( # type: ignore[override]
|
|
557
|
+
self,
|
|
558
|
+
quiet: bool = False,
|
|
559
|
+
wait_for: Literal["terminal", "running"] = "terminal",
|
|
560
|
+
) -> None:
|
|
561
|
+
pass
|
|
562
|
+
|
|
563
|
+
@syncify
|
|
564
|
+
async def outputs(self) -> ActionOutputs: # type: ignore[override]
|
|
565
|
+
return cast(ActionOutputs, self._outputs)
|
|
566
|
+
|
|
567
|
+
return _LocalRun(outputs)
|
|
568
|
+
|
|
569
|
+
@syncify # type: ignore[arg-type]
|
|
570
|
+
async def run(
|
|
571
|
+
self,
|
|
572
|
+
task: TaskTemplate[P, Union[R, Run], F] | LazyEntity,
|
|
573
|
+
*args: P.args,
|
|
574
|
+
**kwargs: P.kwargs,
|
|
575
|
+
) -> Union[R, Run]:
|
|
308
576
|
"""
|
|
309
577
|
Run an async `@env.task` or `TaskTemplate` instance. The existing async context will be used.
|
|
310
578
|
|
|
@@ -326,13 +594,22 @@ class _Runner:
|
|
|
326
594
|
:param kwargs: Keyword arguments to pass to the Task
|
|
327
595
|
:return: Run instance or the result of the task
|
|
328
596
|
"""
|
|
597
|
+
from flyte.remote._task import LazyEntity, TaskDetails
|
|
598
|
+
|
|
599
|
+
if isinstance(task, (LazyEntity, TaskDetails)) and self._mode != "remote":
|
|
600
|
+
raise ValueError("Remote task can only be run in remote mode.")
|
|
601
|
+
|
|
602
|
+
if not isinstance(task, TaskTemplate) and not isinstance(task, (LazyEntity, TaskDetails)):
|
|
603
|
+
raise TypeError(f"On Flyte tasks can be run, not generic functions or methods '{type(task)}'.")
|
|
604
|
+
|
|
329
605
|
if self._mode == "remote":
|
|
330
606
|
return await self._run_remote(task, *args, **kwargs)
|
|
607
|
+
task = cast(TaskTemplate, task)
|
|
331
608
|
if self._mode == "hybrid":
|
|
332
609
|
return await self._run_hybrid(task, *args, **kwargs)
|
|
333
610
|
|
|
334
611
|
# TODO We could use this for remote as well and users could simply pass flyte:// or s3:// or file://
|
|
335
|
-
|
|
612
|
+
with internal_ctx().new_raw_data_path(
|
|
336
613
|
raw_data_path=RawDataPath.from_local_folder(local_folder=self._raw_data_path)
|
|
337
614
|
):
|
|
338
615
|
return await self._run_local(task, *args, **kwargs)
|
|
@@ -350,6 +627,20 @@ def with_runcontext(
|
|
|
350
627
|
interactive_mode: bool | None = None,
|
|
351
628
|
raw_data_path: str | None = None,
|
|
352
629
|
run_base_dir: str | None = None,
|
|
630
|
+
overwrite_cache: bool = False,
|
|
631
|
+
project: str | None = None,
|
|
632
|
+
domain: str | None = None,
|
|
633
|
+
env_vars: Dict[str, str] | None = None,
|
|
634
|
+
labels: Dict[str, str] | None = None,
|
|
635
|
+
annotations: Dict[str, str] | None = None,
|
|
636
|
+
interruptible: bool | None = None,
|
|
637
|
+
log_level: int | None = None,
|
|
638
|
+
log_format: LogFormat = "console",
|
|
639
|
+
reset_root_logger: bool = False,
|
|
640
|
+
disable_run_cache: bool = False,
|
|
641
|
+
queue: Optional[str] = None,
|
|
642
|
+
custom_context: Dict[str, str] | None = None,
|
|
643
|
+
cache_lookup_scope: CacheLookupScope = "global",
|
|
353
644
|
) -> _Runner:
|
|
354
645
|
"""
|
|
355
646
|
Launch a new run with the given parameters as the context.
|
|
@@ -377,12 +668,37 @@ def with_runcontext(
|
|
|
377
668
|
:param interactive_mode: Optional, can be forced to True or False.
|
|
378
669
|
If not provided, it will be set based on the current environment. For example Jupyter notebooks are considered
|
|
379
670
|
interactive mode, while scripts are not. This is used to determine how the code bundle is created.
|
|
380
|
-
:param raw_data_path: Use this path to store the raw data for the run
|
|
381
|
-
|
|
671
|
+
:param raw_data_path: Use this path to store the raw data for the run for local and remote, and can be used to
|
|
672
|
+
store raw data in specific locations.
|
|
673
|
+
:param run_base_dir: Optional The base directory to use for the run. This is used to store the metadata for the run,
|
|
674
|
+
that is passed between tasks.
|
|
675
|
+
:param overwrite_cache: Optional If true, the cache will be overwritten for the run
|
|
676
|
+
:param project: Optional The project to use for the run
|
|
677
|
+
:param domain: Optional The domain to use for the run
|
|
678
|
+
:param env_vars: Optional Environment variables to set for the run
|
|
679
|
+
:param labels: Optional Labels to set for the run
|
|
680
|
+
:param annotations: Optional Annotations to set for the run
|
|
681
|
+
:param interruptible: Optional If true, the run can be scheduled on interruptible instances and false implies
|
|
682
|
+
that all tasks in the run should only be scheduled on non-interruptible instances. If not specified the
|
|
683
|
+
original setting on all tasks is retained.
|
|
684
|
+
:param log_level: Optional Log level to set for the run. If not provided, it will be set to the default log level
|
|
685
|
+
set using `flyte.init()`
|
|
686
|
+
:param log_format: Optional Log format to set for the run. If not provided, it will be set to the default log format
|
|
687
|
+
:param reset_root_logger: If true, the root logger will be preserved and not modified by Flyte.
|
|
688
|
+
:param disable_run_cache: Optional If true, the run cache will be disabled. This is useful for testing purposes.
|
|
689
|
+
:param queue: Optional The queue to use for the run. This is used to specify the cluster to use for the run.
|
|
690
|
+
:param custom_context: Optional global input context to pass to the task. This will be available via
|
|
691
|
+
get_custom_context() within the task and will automatically propagate to sub-tasks.
|
|
692
|
+
Acts as base/default values that can be overridden by context managers in the code.
|
|
693
|
+
:param cache_lookup_scope: Optional Scope to use for the run. This is used to specify the scope to use for cache
|
|
694
|
+
lookups. If not specified, it will be set to the default scope (global unless overridden at the system level).
|
|
695
|
+
|
|
382
696
|
:return: runner
|
|
383
697
|
"""
|
|
384
698
|
if mode == "hybrid" and not name and not run_base_dir:
|
|
385
699
|
raise ValueError("Run name and run base dir are required for hybrid mode")
|
|
700
|
+
if copy_style == "none" and not version:
|
|
701
|
+
raise ValueError("Version is required when copy_style is 'none'")
|
|
386
702
|
return _Runner(
|
|
387
703
|
force_mode=mode,
|
|
388
704
|
name=name,
|
|
@@ -394,11 +710,25 @@ def with_runcontext(
|
|
|
394
710
|
interactive_mode=interactive_mode,
|
|
395
711
|
raw_data_path=raw_data_path,
|
|
396
712
|
run_base_dir=run_base_dir,
|
|
713
|
+
overwrite_cache=overwrite_cache,
|
|
714
|
+
env_vars=env_vars,
|
|
715
|
+
labels=labels,
|
|
716
|
+
annotations=annotations,
|
|
717
|
+
interruptible=interruptible,
|
|
718
|
+
project=project,
|
|
719
|
+
domain=domain,
|
|
720
|
+
log_level=log_level,
|
|
721
|
+
log_format=log_format,
|
|
722
|
+
reset_root_logger=reset_root_logger,
|
|
723
|
+
disable_run_cache=disable_run_cache,
|
|
724
|
+
queue=queue,
|
|
725
|
+
custom_context=custom_context,
|
|
726
|
+
cache_lookup_scope=cache_lookup_scope,
|
|
397
727
|
)
|
|
398
728
|
|
|
399
729
|
|
|
400
|
-
@
|
|
401
|
-
async def run(task: TaskTemplate[P, R], *args: P.args, **kwargs: P.kwargs) ->
|
|
730
|
+
@syncify
|
|
731
|
+
async def run(task: TaskTemplate[P, R, F], *args: P.args, **kwargs: P.kwargs) -> Run:
|
|
402
732
|
"""
|
|
403
733
|
Run a task with the given parameters
|
|
404
734
|
:param task: task to run
|