flyte 0.0.1b0__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/__init__.py +62 -0
- flyte/_api_commons.py +3 -0
- flyte/_bin/__init__.py +0 -0
- flyte/_bin/runtime.py +126 -0
- flyte/_build.py +25 -0
- flyte/_cache/__init__.py +12 -0
- flyte/_cache/cache.py +146 -0
- flyte/_cache/defaults.py +9 -0
- flyte/_cache/policy_function_body.py +42 -0
- flyte/_cli/__init__.py +0 -0
- flyte/_cli/_common.py +287 -0
- flyte/_cli/_create.py +42 -0
- flyte/_cli/_delete.py +23 -0
- flyte/_cli/_deploy.py +140 -0
- flyte/_cli/_get.py +235 -0
- flyte/_cli/_run.py +152 -0
- flyte/_cli/main.py +72 -0
- flyte/_code_bundle/__init__.py +8 -0
- flyte/_code_bundle/_ignore.py +113 -0
- flyte/_code_bundle/_packaging.py +187 -0
- flyte/_code_bundle/_utils.py +339 -0
- flyte/_code_bundle/bundle.py +178 -0
- flyte/_context.py +146 -0
- flyte/_datastructures.py +342 -0
- flyte/_deploy.py +202 -0
- flyte/_doc.py +29 -0
- flyte/_docstring.py +32 -0
- flyte/_environment.py +43 -0
- flyte/_group.py +31 -0
- flyte/_hash.py +23 -0
- flyte/_image.py +760 -0
- flyte/_initialize.py +634 -0
- flyte/_interface.py +84 -0
- flyte/_internal/__init__.py +3 -0
- flyte/_internal/controllers/__init__.py +115 -0
- flyte/_internal/controllers/_local_controller.py +118 -0
- flyte/_internal/controllers/_trace.py +40 -0
- flyte/_internal/controllers/pbhash.py +39 -0
- flyte/_internal/controllers/remote/__init__.py +40 -0
- flyte/_internal/controllers/remote/_action.py +141 -0
- flyte/_internal/controllers/remote/_client.py +43 -0
- flyte/_internal/controllers/remote/_controller.py +361 -0
- flyte/_internal/controllers/remote/_core.py +402 -0
- flyte/_internal/controllers/remote/_informer.py +361 -0
- flyte/_internal/controllers/remote/_service_protocol.py +50 -0
- flyte/_internal/imagebuild/__init__.py +11 -0
- flyte/_internal/imagebuild/docker_builder.py +416 -0
- flyte/_internal/imagebuild/image_builder.py +241 -0
- flyte/_internal/imagebuild/remote_builder.py +0 -0
- flyte/_internal/resolvers/__init__.py +0 -0
- flyte/_internal/resolvers/_task_module.py +54 -0
- flyte/_internal/resolvers/common.py +31 -0
- flyte/_internal/resolvers/default.py +28 -0
- flyte/_internal/runtime/__init__.py +0 -0
- flyte/_internal/runtime/convert.py +199 -0
- flyte/_internal/runtime/entrypoints.py +135 -0
- flyte/_internal/runtime/io.py +136 -0
- flyte/_internal/runtime/resources_serde.py +138 -0
- flyte/_internal/runtime/task_serde.py +210 -0
- flyte/_internal/runtime/taskrunner.py +190 -0
- flyte/_internal/runtime/types_serde.py +54 -0
- flyte/_logging.py +124 -0
- flyte/_protos/__init__.py +0 -0
- flyte/_protos/common/authorization_pb2.py +66 -0
- flyte/_protos/common/authorization_pb2.pyi +108 -0
- flyte/_protos/common/authorization_pb2_grpc.py +4 -0
- flyte/_protos/common/identifier_pb2.py +71 -0
- flyte/_protos/common/identifier_pb2.pyi +82 -0
- flyte/_protos/common/identifier_pb2_grpc.py +4 -0
- flyte/_protos/common/identity_pb2.py +48 -0
- flyte/_protos/common/identity_pb2.pyi +72 -0
- flyte/_protos/common/identity_pb2_grpc.py +4 -0
- flyte/_protos/common/list_pb2.py +36 -0
- flyte/_protos/common/list_pb2.pyi +69 -0
- flyte/_protos/common/list_pb2_grpc.py +4 -0
- flyte/_protos/common/policy_pb2.py +37 -0
- flyte/_protos/common/policy_pb2.pyi +27 -0
- flyte/_protos/common/policy_pb2_grpc.py +4 -0
- flyte/_protos/common/role_pb2.py +37 -0
- flyte/_protos/common/role_pb2.pyi +53 -0
- flyte/_protos/common/role_pb2_grpc.py +4 -0
- flyte/_protos/common/runtime_version_pb2.py +28 -0
- flyte/_protos/common/runtime_version_pb2.pyi +24 -0
- flyte/_protos/common/runtime_version_pb2_grpc.py +4 -0
- flyte/_protos/logs/dataplane/payload_pb2.py +96 -0
- flyte/_protos/logs/dataplane/payload_pb2.pyi +168 -0
- flyte/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
- flyte/_protos/secret/definition_pb2.py +49 -0
- flyte/_protos/secret/definition_pb2.pyi +93 -0
- flyte/_protos/secret/definition_pb2_grpc.py +4 -0
- flyte/_protos/secret/payload_pb2.py +62 -0
- flyte/_protos/secret/payload_pb2.pyi +94 -0
- flyte/_protos/secret/payload_pb2_grpc.py +4 -0
- flyte/_protos/secret/secret_pb2.py +38 -0
- flyte/_protos/secret/secret_pb2.pyi +6 -0
- flyte/_protos/secret/secret_pb2_grpc.py +198 -0
- flyte/_protos/secret/secret_pb2_grpc_grpc.py +198 -0
- flyte/_protos/validate/validate/validate_pb2.py +76 -0
- flyte/_protos/workflow/node_execution_service_pb2.py +26 -0
- flyte/_protos/workflow/node_execution_service_pb2.pyi +4 -0
- flyte/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
- flyte/_protos/workflow/queue_service_pb2.py +106 -0
- flyte/_protos/workflow/queue_service_pb2.pyi +141 -0
- flyte/_protos/workflow/queue_service_pb2_grpc.py +172 -0
- flyte/_protos/workflow/run_definition_pb2.py +128 -0
- flyte/_protos/workflow/run_definition_pb2.pyi +310 -0
- flyte/_protos/workflow/run_definition_pb2_grpc.py +4 -0
- flyte/_protos/workflow/run_logs_service_pb2.py +41 -0
- flyte/_protos/workflow/run_logs_service_pb2.pyi +28 -0
- flyte/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
- flyte/_protos/workflow/run_service_pb2.py +133 -0
- flyte/_protos/workflow/run_service_pb2.pyi +175 -0
- flyte/_protos/workflow/run_service_pb2_grpc.py +412 -0
- flyte/_protos/workflow/state_service_pb2.py +58 -0
- flyte/_protos/workflow/state_service_pb2.pyi +71 -0
- flyte/_protos/workflow/state_service_pb2_grpc.py +138 -0
- flyte/_protos/workflow/task_definition_pb2.py +72 -0
- flyte/_protos/workflow/task_definition_pb2.pyi +65 -0
- flyte/_protos/workflow/task_definition_pb2_grpc.py +4 -0
- flyte/_protos/workflow/task_service_pb2.py +44 -0
- flyte/_protos/workflow/task_service_pb2.pyi +31 -0
- flyte/_protos/workflow/task_service_pb2_grpc.py +104 -0
- flyte/_resources.py +226 -0
- flyte/_retry.py +32 -0
- flyte/_reusable_environment.py +25 -0
- flyte/_run.py +411 -0
- flyte/_secret.py +61 -0
- flyte/_task.py +367 -0
- flyte/_task_environment.py +200 -0
- flyte/_timeout.py +47 -0
- flyte/_tools.py +27 -0
- flyte/_trace.py +128 -0
- flyte/_utils/__init__.py +20 -0
- flyte/_utils/asyn.py +119 -0
- flyte/_utils/coro_management.py +25 -0
- flyte/_utils/file_handling.py +72 -0
- flyte/_utils/helpers.py +108 -0
- flyte/_utils/lazy_module.py +54 -0
- flyte/_utils/uv_script_parser.py +49 -0
- flyte/_version.py +21 -0
- flyte/connectors/__init__.py +0 -0
- flyte/errors.py +143 -0
- flyte/extras/__init__.py +5 -0
- flyte/extras/_container.py +273 -0
- flyte/io/__init__.py +11 -0
- flyte/io/_dataframe.py +0 -0
- flyte/io/_dir.py +448 -0
- flyte/io/_file.py +468 -0
- flyte/io/pickle/__init__.py +0 -0
- flyte/io/pickle/transformer.py +117 -0
- flyte/io/structured_dataset/__init__.py +129 -0
- flyte/io/structured_dataset/basic_dfs.py +219 -0
- flyte/io/structured_dataset/structured_dataset.py +1061 -0
- flyte/py.typed +0 -0
- flyte/remote/__init__.py +25 -0
- flyte/remote/_client/__init__.py +0 -0
- flyte/remote/_client/_protocols.py +131 -0
- flyte/remote/_client/auth/__init__.py +12 -0
- flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
- flyte/remote/_client/auth/_authenticators/base.py +397 -0
- flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
- flyte/remote/_client/auth/_authenticators/device_code.py +118 -0
- flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
- flyte/remote/_client/auth/_authenticators/factory.py +200 -0
- flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
- flyte/remote/_client/auth/_channel.py +184 -0
- flyte/remote/_client/auth/_client_config.py +83 -0
- flyte/remote/_client/auth/_default_html.py +32 -0
- flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
- flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
- flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
- flyte/remote/_client/auth/_keyring.py +143 -0
- flyte/remote/_client/auth/_token_client.py +260 -0
- flyte/remote/_client/auth/errors.py +16 -0
- flyte/remote/_client/controlplane.py +95 -0
- flyte/remote/_console.py +18 -0
- flyte/remote/_data.py +155 -0
- flyte/remote/_logs.py +116 -0
- flyte/remote/_project.py +86 -0
- flyte/remote/_run.py +873 -0
- flyte/remote/_secret.py +132 -0
- flyte/remote/_task.py +227 -0
- flyte/report/__init__.py +3 -0
- flyte/report/_report.py +178 -0
- flyte/report/_template.html +124 -0
- flyte/storage/__init__.py +24 -0
- flyte/storage/_remote_fs.py +34 -0
- flyte/storage/_storage.py +251 -0
- flyte/storage/_utils.py +5 -0
- flyte/types/__init__.py +13 -0
- flyte/types/_interface.py +25 -0
- flyte/types/_renderer.py +162 -0
- flyte/types/_string_literals.py +120 -0
- flyte/types/_type_engine.py +2210 -0
- flyte/types/_utils.py +80 -0
- flyte-0.0.1b0.dist-info/METADATA +179 -0
- flyte-0.0.1b0.dist-info/RECORD +390 -0
- flyte-0.0.1b0.dist-info/WHEEL +5 -0
- flyte-0.0.1b0.dist-info/entry_points.txt +3 -0
- flyte-0.0.1b0.dist-info/top_level.txt +1 -0
- union/__init__.py +54 -0
- union/_api_commons.py +3 -0
- union/_bin/__init__.py +0 -0
- union/_bin/runtime.py +113 -0
- union/_build.py +25 -0
- union/_cache/__init__.py +12 -0
- union/_cache/cache.py +141 -0
- union/_cache/defaults.py +9 -0
- union/_cache/policy_function_body.py +42 -0
- union/_cli/__init__.py +0 -0
- union/_cli/_common.py +263 -0
- union/_cli/_create.py +40 -0
- union/_cli/_delete.py +23 -0
- union/_cli/_deploy.py +120 -0
- union/_cli/_get.py +162 -0
- union/_cli/_params.py +579 -0
- union/_cli/_run.py +150 -0
- union/_cli/main.py +72 -0
- union/_code_bundle/__init__.py +8 -0
- union/_code_bundle/_ignore.py +113 -0
- union/_code_bundle/_packaging.py +187 -0
- union/_code_bundle/_utils.py +342 -0
- union/_code_bundle/bundle.py +176 -0
- union/_context.py +146 -0
- union/_datastructures.py +295 -0
- union/_deploy.py +185 -0
- union/_doc.py +29 -0
- union/_docstring.py +26 -0
- union/_environment.py +43 -0
- union/_group.py +31 -0
- union/_hash.py +23 -0
- union/_image.py +760 -0
- union/_initialize.py +585 -0
- union/_interface.py +84 -0
- union/_internal/__init__.py +3 -0
- union/_internal/controllers/__init__.py +77 -0
- union/_internal/controllers/_local_controller.py +77 -0
- union/_internal/controllers/pbhash.py +39 -0
- union/_internal/controllers/remote/__init__.py +40 -0
- union/_internal/controllers/remote/_action.py +131 -0
- union/_internal/controllers/remote/_client.py +43 -0
- union/_internal/controllers/remote/_controller.py +169 -0
- union/_internal/controllers/remote/_core.py +341 -0
- union/_internal/controllers/remote/_informer.py +260 -0
- union/_internal/controllers/remote/_service_protocol.py +44 -0
- union/_internal/imagebuild/__init__.py +11 -0
- union/_internal/imagebuild/docker_builder.py +416 -0
- union/_internal/imagebuild/image_builder.py +243 -0
- union/_internal/imagebuild/remote_builder.py +0 -0
- union/_internal/resolvers/__init__.py +0 -0
- union/_internal/resolvers/_task_module.py +31 -0
- union/_internal/resolvers/common.py +24 -0
- union/_internal/resolvers/default.py +27 -0
- union/_internal/runtime/__init__.py +0 -0
- union/_internal/runtime/convert.py +163 -0
- union/_internal/runtime/entrypoints.py +121 -0
- union/_internal/runtime/io.py +136 -0
- union/_internal/runtime/resources_serde.py +134 -0
- union/_internal/runtime/task_serde.py +202 -0
- union/_internal/runtime/taskrunner.py +179 -0
- union/_internal/runtime/types_serde.py +53 -0
- union/_logging.py +124 -0
- union/_protos/__init__.py +0 -0
- union/_protos/common/authorization_pb2.py +66 -0
- union/_protos/common/authorization_pb2.pyi +106 -0
- union/_protos/common/authorization_pb2_grpc.py +4 -0
- union/_protos/common/identifier_pb2.py +71 -0
- union/_protos/common/identifier_pb2.pyi +82 -0
- union/_protos/common/identifier_pb2_grpc.py +4 -0
- union/_protos/common/identity_pb2.py +48 -0
- union/_protos/common/identity_pb2.pyi +72 -0
- union/_protos/common/identity_pb2_grpc.py +4 -0
- union/_protos/common/list_pb2.py +36 -0
- union/_protos/common/list_pb2.pyi +69 -0
- union/_protos/common/list_pb2_grpc.py +4 -0
- union/_protos/common/policy_pb2.py +37 -0
- union/_protos/common/policy_pb2.pyi +27 -0
- union/_protos/common/policy_pb2_grpc.py +4 -0
- union/_protos/common/role_pb2.py +37 -0
- union/_protos/common/role_pb2.pyi +51 -0
- union/_protos/common/role_pb2_grpc.py +4 -0
- union/_protos/common/runtime_version_pb2.py +28 -0
- union/_protos/common/runtime_version_pb2.pyi +24 -0
- union/_protos/common/runtime_version_pb2_grpc.py +4 -0
- union/_protos/logs/dataplane/payload_pb2.py +96 -0
- union/_protos/logs/dataplane/payload_pb2.pyi +168 -0
- union/_protos/logs/dataplane/payload_pb2_grpc.py +4 -0
- union/_protos/secret/definition_pb2.py +49 -0
- union/_protos/secret/definition_pb2.pyi +93 -0
- union/_protos/secret/definition_pb2_grpc.py +4 -0
- union/_protos/secret/payload_pb2.py +62 -0
- union/_protos/secret/payload_pb2.pyi +94 -0
- union/_protos/secret/payload_pb2_grpc.py +4 -0
- union/_protos/secret/secret_pb2.py +38 -0
- union/_protos/secret/secret_pb2.pyi +6 -0
- union/_protos/secret/secret_pb2_grpc.py +198 -0
- union/_protos/validate/validate/validate_pb2.py +76 -0
- union/_protos/workflow/node_execution_service_pb2.py +26 -0
- union/_protos/workflow/node_execution_service_pb2.pyi +4 -0
- union/_protos/workflow/node_execution_service_pb2_grpc.py +32 -0
- union/_protos/workflow/queue_service_pb2.py +75 -0
- union/_protos/workflow/queue_service_pb2.pyi +103 -0
- union/_protos/workflow/queue_service_pb2_grpc.py +172 -0
- union/_protos/workflow/run_definition_pb2.py +100 -0
- union/_protos/workflow/run_definition_pb2.pyi +256 -0
- union/_protos/workflow/run_definition_pb2_grpc.py +4 -0
- union/_protos/workflow/run_logs_service_pb2.py +41 -0
- union/_protos/workflow/run_logs_service_pb2.pyi +28 -0
- union/_protos/workflow/run_logs_service_pb2_grpc.py +69 -0
- union/_protos/workflow/run_service_pb2.py +133 -0
- union/_protos/workflow/run_service_pb2.pyi +173 -0
- union/_protos/workflow/run_service_pb2_grpc.py +412 -0
- union/_protos/workflow/state_service_pb2.py +58 -0
- union/_protos/workflow/state_service_pb2.pyi +69 -0
- union/_protos/workflow/state_service_pb2_grpc.py +138 -0
- union/_protos/workflow/task_definition_pb2.py +72 -0
- union/_protos/workflow/task_definition_pb2.pyi +65 -0
- union/_protos/workflow/task_definition_pb2_grpc.py +4 -0
- union/_protos/workflow/task_service_pb2.py +44 -0
- union/_protos/workflow/task_service_pb2.pyi +31 -0
- union/_protos/workflow/task_service_pb2_grpc.py +104 -0
- union/_resources.py +226 -0
- union/_retry.py +32 -0
- union/_reusable_environment.py +25 -0
- union/_run.py +374 -0
- union/_secret.py +61 -0
- union/_task.py +354 -0
- union/_task_environment.py +186 -0
- union/_timeout.py +47 -0
- union/_tools.py +27 -0
- union/_utils/__init__.py +11 -0
- union/_utils/asyn.py +119 -0
- union/_utils/file_handling.py +71 -0
- union/_utils/helpers.py +46 -0
- union/_utils/lazy_module.py +54 -0
- union/_utils/uv_script_parser.py +49 -0
- union/_version.py +21 -0
- union/connectors/__init__.py +0 -0
- union/errors.py +128 -0
- union/extras/__init__.py +5 -0
- union/extras/_container.py +263 -0
- union/io/__init__.py +11 -0
- union/io/_dataframe.py +0 -0
- union/io/_dir.py +425 -0
- union/io/_file.py +418 -0
- union/io/pickle/__init__.py +0 -0
- union/io/pickle/transformer.py +117 -0
- union/io/structured_dataset/__init__.py +122 -0
- union/io/structured_dataset/basic_dfs.py +219 -0
- union/io/structured_dataset/structured_dataset.py +1057 -0
- union/py.typed +0 -0
- union/remote/__init__.py +23 -0
- union/remote/_client/__init__.py +0 -0
- union/remote/_client/_protocols.py +129 -0
- union/remote/_client/auth/__init__.py +12 -0
- union/remote/_client/auth/_authenticators/__init__.py +0 -0
- union/remote/_client/auth/_authenticators/base.py +391 -0
- union/remote/_client/auth/_authenticators/client_credentials.py +73 -0
- union/remote/_client/auth/_authenticators/device_code.py +120 -0
- union/remote/_client/auth/_authenticators/external_command.py +77 -0
- union/remote/_client/auth/_authenticators/factory.py +200 -0
- union/remote/_client/auth/_authenticators/pkce.py +515 -0
- union/remote/_client/auth/_channel.py +184 -0
- union/remote/_client/auth/_client_config.py +83 -0
- union/remote/_client/auth/_default_html.py +32 -0
- union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
- union/remote/_client/auth/_grpc_utils/auth_interceptor.py +204 -0
- union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +144 -0
- union/remote/_client/auth/_keyring.py +154 -0
- union/remote/_client/auth/_token_client.py +258 -0
- union/remote/_client/auth/errors.py +16 -0
- union/remote/_client/controlplane.py +86 -0
- union/remote/_data.py +149 -0
- union/remote/_logs.py +74 -0
- union/remote/_project.py +86 -0
- union/remote/_run.py +820 -0
- union/remote/_secret.py +132 -0
- union/remote/_task.py +193 -0
- union/report/__init__.py +3 -0
- union/report/_report.py +178 -0
- union/report/_template.html +124 -0
- union/storage/__init__.py +24 -0
- union/storage/_remote_fs.py +34 -0
- union/storage/_storage.py +247 -0
- union/storage/_utils.py +5 -0
- union/types/__init__.py +11 -0
- union/types/_renderer.py +162 -0
- union/types/_string_literals.py +120 -0
- union/types/_type_engine.py +2131 -0
- union/types/_utils.py +80 -0
flyte/remote/_data.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import hashlib
|
|
3
|
+
import os
|
|
4
|
+
import typing
|
|
5
|
+
import uuid
|
|
6
|
+
from base64 import b64encode
|
|
7
|
+
from datetime import timedelta
|
|
8
|
+
from functools import lru_cache
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Tuple
|
|
11
|
+
|
|
12
|
+
import aiofiles
|
|
13
|
+
import grpc
|
|
14
|
+
import httpx
|
|
15
|
+
from flyteidl.service import dataproxy_pb2
|
|
16
|
+
from google.protobuf import duration_pb2
|
|
17
|
+
|
|
18
|
+
from flyte._initialize import CommonInit, get_client, get_common_config, requires_client
|
|
19
|
+
from flyte.errors import RuntimeSystemError
|
|
20
|
+
|
|
21
|
+
_UPLOAD_EXPIRES_IN = timedelta(seconds=60)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_extra_headers_for_protocol(native_url: str) -> typing.Dict[str, str]:
|
|
25
|
+
"""
|
|
26
|
+
For Azure Blob Storage, we need to set certain headers for http request.
|
|
27
|
+
This is used when we work with signed urls.
|
|
28
|
+
:param native_url:
|
|
29
|
+
:return:
|
|
30
|
+
"""
|
|
31
|
+
if native_url.startswith("abfs://"):
|
|
32
|
+
return {"x-ms-blob-type": "BlockBlob"}
|
|
33
|
+
return {}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@lru_cache
|
|
37
|
+
def hash_file(file_path: typing.Union[os.PathLike, str]) -> Tuple[bytes, str, int]:
|
|
38
|
+
"""
|
|
39
|
+
Hash a file and produce a digest to be used as a version
|
|
40
|
+
"""
|
|
41
|
+
h = hashlib.md5()
|
|
42
|
+
size = 0
|
|
43
|
+
|
|
44
|
+
with open(file_path, "rb") as file:
|
|
45
|
+
while True:
|
|
46
|
+
# Reading is buffered, so we can read smaller chunks.
|
|
47
|
+
chunk = file.read(h.block_size)
|
|
48
|
+
if not chunk:
|
|
49
|
+
break
|
|
50
|
+
h.update(chunk)
|
|
51
|
+
size += len(chunk)
|
|
52
|
+
|
|
53
|
+
return h.digest(), h.hexdigest(), size
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def _upload_single_file(
|
|
57
|
+
cfg: CommonInit, fp: Path, verify: bool = True, basedir: str | None = None
|
|
58
|
+
) -> Tuple[str, str]:
|
|
59
|
+
md5_bytes, str_digest, _ = hash_file(fp)
|
|
60
|
+
from flyte._logging import logger
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
expires_in_pb = duration_pb2.Duration()
|
|
64
|
+
expires_in_pb.FromTimedelta(_UPLOAD_EXPIRES_IN)
|
|
65
|
+
client = get_client()
|
|
66
|
+
resp = await client.dataproxy_service.CreateUploadLocation( # type: ignore
|
|
67
|
+
dataproxy_pb2.CreateUploadLocationRequest(
|
|
68
|
+
project=cfg.project,
|
|
69
|
+
domain=cfg.domain,
|
|
70
|
+
content_md5=md5_bytes,
|
|
71
|
+
filename=fp.name,
|
|
72
|
+
expires_in=expires_in_pb,
|
|
73
|
+
filename_root=basedir,
|
|
74
|
+
add_content_md5_metadata=True,
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
except grpc.aio.AioRpcError as e:
|
|
78
|
+
if e.code() == grpc.StatusCode.NOT_FOUND:
|
|
79
|
+
raise RuntimeSystemError(
|
|
80
|
+
"NotFound", f"Failed to get signed url for {fp}, please check your project and domain."
|
|
81
|
+
)
|
|
82
|
+
elif e.code() == grpc.StatusCode.PERMISSION_DENIED:
|
|
83
|
+
raise RuntimeSystemError(
|
|
84
|
+
"PermissionDenied", f"Failed to get signed url for {fp}, please check your permissions."
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
raise RuntimeSystemError(e.code().value, f"Failed to get signed url for {fp}.")
|
|
88
|
+
except Exception as e:
|
|
89
|
+
raise RuntimeSystemError(type(e).__name__, f"Failed to get signed url for {fp}.") from e
|
|
90
|
+
logger.debug(f"Uploading to signed url {resp.signed_url} for {fp}")
|
|
91
|
+
extra_headers = get_extra_headers_for_protocol(resp.native_url)
|
|
92
|
+
extra_headers.update(resp.headers)
|
|
93
|
+
encoded_md5 = b64encode(md5_bytes)
|
|
94
|
+
content_length = fp.stat().st_size
|
|
95
|
+
|
|
96
|
+
async with aiofiles.open(str(fp), "rb") as file:
|
|
97
|
+
extra_headers.update({"Content-Length": str(content_length), "Content-MD5": encoded_md5.decode("utf-8")})
|
|
98
|
+
async with httpx.AsyncClient(verify=verify) as aclient:
|
|
99
|
+
put_resp = await aclient.put(resp.signed_url, headers=extra_headers, content=file)
|
|
100
|
+
if put_resp.status_code != 200:
|
|
101
|
+
raise RuntimeSystemError(
|
|
102
|
+
"UploadFailed",
|
|
103
|
+
f"Failed to upload {fp} to {resp.signed_url}, status code: {put_resp.status_code}",
|
|
104
|
+
)
|
|
105
|
+
# TODO in old code we did this
|
|
106
|
+
# if self._config.platform.insecure_skip_verify is True
|
|
107
|
+
# else self._config.platform.ca_cert_file_path,
|
|
108
|
+
logger.debug(f"Uploaded with digest {str_digest}, blob location is {resp.native_url}")
|
|
109
|
+
return str_digest, resp.native_url
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@requires_client
|
|
113
|
+
async def upload_file(fp: Path, verify: bool = True) -> Tuple[str, str]:
|
|
114
|
+
"""
|
|
115
|
+
Uploads a file to a remote location and returns the remote URI.
|
|
116
|
+
|
|
117
|
+
:param fp: The file path to upload.
|
|
118
|
+
:param verify: Whether to verify the certificate for HTTPS requests.
|
|
119
|
+
:return: A tuple containing the MD5 digest and the remote URI.
|
|
120
|
+
"""
|
|
121
|
+
# This is a placeholder implementation. Replace with actual upload logic.
|
|
122
|
+
cfg = get_common_config()
|
|
123
|
+
if not fp.is_file():
|
|
124
|
+
raise ValueError(f"{fp} is not a single file, upload arg must be a single file.")
|
|
125
|
+
return await _upload_single_file(cfg, fp, verify=verify)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@requires_client
|
|
129
|
+
async def upload_dir(dir_path: Path, verify: bool = True) -> str:
|
|
130
|
+
"""
|
|
131
|
+
Uploads a directory to a remote location and returns the remote URI.
|
|
132
|
+
|
|
133
|
+
:param dir_path: The directory path to upload.
|
|
134
|
+
:param verify: Whether to verify the certificate for HTTPS requests.
|
|
135
|
+
:return: The remote URI of the uploaded directory.
|
|
136
|
+
"""
|
|
137
|
+
# This is a placeholder implementation. Replace with actual upload logic.
|
|
138
|
+
cfg = get_common_config()
|
|
139
|
+
if not dir_path.is_dir():
|
|
140
|
+
raise ValueError(f"{dir_path} is not a directory, upload arg must be a directory.")
|
|
141
|
+
|
|
142
|
+
prefix = uuid.uuid4().hex
|
|
143
|
+
|
|
144
|
+
files = dir_path.rglob("*")
|
|
145
|
+
uploaded_files = []
|
|
146
|
+
for file in files:
|
|
147
|
+
if file.is_file():
|
|
148
|
+
uploaded_files.append(_upload_single_file(cfg, file, verify=verify, basedir=prefix))
|
|
149
|
+
|
|
150
|
+
urls = await asyncio.gather(*uploaded_files)
|
|
151
|
+
native_url = urls[0][1] # Assuming all files are uploaded to the same prefix
|
|
152
|
+
# native_url is of the form s3://my-s3-bucket/flytesnacks/development/{prefix}/source/empty.md
|
|
153
|
+
uri = native_url.split(prefix)[0] + "/" + prefix
|
|
154
|
+
|
|
155
|
+
return uri
|
flyte/remote/_logs.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from collections import deque
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import AsyncGenerator, AsyncIterator
|
|
5
|
+
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.live import Live
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.text import Text
|
|
10
|
+
|
|
11
|
+
from flyte._api_commons import syncer
|
|
12
|
+
from flyte._initialize import get_client, requires_client
|
|
13
|
+
from flyte._protos.logs.dataplane import payload_pb2
|
|
14
|
+
from flyte._protos.workflow import run_definition_pb2, run_logs_service_pb2
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _format_line(logline: payload_pb2.LogLine, show_ts: bool) -> Text:
|
|
18
|
+
style_map = {
|
|
19
|
+
payload_pb2.LogLineOriginator.SYSTEM: "bold magenta",
|
|
20
|
+
payload_pb2.LogLineOriginator.USER: "cyan",
|
|
21
|
+
payload_pb2.LogLineOriginator.UNKNOWN: "light red",
|
|
22
|
+
}
|
|
23
|
+
style = style_map.get(logline.originator, "")
|
|
24
|
+
if "flyte" in logline.message and "flyte.errors" not in logline.message:
|
|
25
|
+
style = "dim"
|
|
26
|
+
ts = ""
|
|
27
|
+
if show_ts:
|
|
28
|
+
ts = f"[{logline.timestamp.ToDatetime().isoformat()}]"
|
|
29
|
+
return Text(f"{ts} {logline.message}", style=style)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AsyncLogViewer:
|
|
33
|
+
"""
|
|
34
|
+
A class to view logs asynchronously in the console or terminal or jupyter notebook.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, log_source: AsyncIterator, max_lines: int = 30, name: str = "Logs", show_ts: bool = False):
|
|
38
|
+
self.console = Console()
|
|
39
|
+
self.log_source = log_source
|
|
40
|
+
self.max_lines = max_lines
|
|
41
|
+
self.lines: deque = deque(maxlen=max_lines + 1)
|
|
42
|
+
self.name = name
|
|
43
|
+
self.show_ts = show_ts
|
|
44
|
+
self.total_lines = 0
|
|
45
|
+
|
|
46
|
+
def _render(self):
|
|
47
|
+
log_text = Text()
|
|
48
|
+
for line in self.lines:
|
|
49
|
+
log_text.append(line)
|
|
50
|
+
return Panel(log_text, title=self.name, border_style="yellow")
|
|
51
|
+
|
|
52
|
+
async def run(self):
|
|
53
|
+
with Live(self._render(), refresh_per_second=10, console=self.console) as live:
|
|
54
|
+
try:
|
|
55
|
+
async for logline in self.log_source:
|
|
56
|
+
formatted = _format_line(logline, show_ts=self.show_ts)
|
|
57
|
+
self.lines.append(formatted)
|
|
58
|
+
self.total_lines += 1
|
|
59
|
+
live.update(self._render())
|
|
60
|
+
except asyncio.CancelledError:
|
|
61
|
+
pass
|
|
62
|
+
self.console.print(f"Scrolled {self.total_lines} lines of logs.")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class Logs:
|
|
67
|
+
@classmethod
|
|
68
|
+
@requires_client
|
|
69
|
+
@syncer.wrap
|
|
70
|
+
async def tail(
|
|
71
|
+
cls, action_id: run_definition_pb2.ActionIdentifier, attempt: int = 1
|
|
72
|
+
) -> AsyncGenerator[payload_pb2.LogLine, None]:
|
|
73
|
+
"""
|
|
74
|
+
Tail the logs for a given action ID and attempt.
|
|
75
|
+
:param action_id: The action ID to tail logs for.
|
|
76
|
+
:param attempt: The attempt number (default is 0).
|
|
77
|
+
"""
|
|
78
|
+
resp = get_client().logs_service.TailLogs(
|
|
79
|
+
run_logs_service_pb2.TailLogsRequest(action_id=action_id, attempt=attempt)
|
|
80
|
+
)
|
|
81
|
+
async for log_set in resp:
|
|
82
|
+
if log_set.logs:
|
|
83
|
+
for log in log_set.logs:
|
|
84
|
+
for line in log.lines:
|
|
85
|
+
yield line
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
async def create_viewer(
|
|
89
|
+
cls,
|
|
90
|
+
action_id: run_definition_pb2.ActionIdentifier,
|
|
91
|
+
attempt: int = 1,
|
|
92
|
+
max_lines: int = 30,
|
|
93
|
+
show_ts: bool = False,
|
|
94
|
+
raw: bool = False,
|
|
95
|
+
):
|
|
96
|
+
"""
|
|
97
|
+
Create a log viewer for a given action ID and attempt.
|
|
98
|
+
:param action_id: Action ID to view logs for.
|
|
99
|
+
:param attempt: Attempt number (default is 1).
|
|
100
|
+
:param max_lines: Maximum number of lines to show if using the viewer. The logger will scroll
|
|
101
|
+
and keep only max_lines in view.
|
|
102
|
+
:param show_ts: Whether to show timestamps in the logs.
|
|
103
|
+
:param raw: if True, return the raw log lines instead of a viewer.
|
|
104
|
+
"""
|
|
105
|
+
if raw:
|
|
106
|
+
console = Console()
|
|
107
|
+
async for line in cls.tail.aio(cls, action_id=action_id, attempt=attempt):
|
|
108
|
+
console.print(_format_line(line, show_ts=show_ts), end="")
|
|
109
|
+
return
|
|
110
|
+
viewer = AsyncLogViewer(
|
|
111
|
+
log_source=cls.tail.aio(cls, action_id=action_id, attempt=attempt),
|
|
112
|
+
max_lines=max_lines,
|
|
113
|
+
show_ts=show_ts,
|
|
114
|
+
name=f"{action_id.run.name}:{action_id.name}",
|
|
115
|
+
)
|
|
116
|
+
await viewer.run()
|
flyte/remote/_project.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import AsyncGenerator, Literal, Tuple
|
|
6
|
+
|
|
7
|
+
import rich.repr
|
|
8
|
+
from flyteidl.admin import common_pb2, project_pb2
|
|
9
|
+
|
|
10
|
+
from flyte._api_commons import syncer
|
|
11
|
+
from flyte._initialize import get_client, get_common_config, requires_client
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class Project:
|
|
16
|
+
"""
|
|
17
|
+
A class representing a project in the Union API.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_pb2: project_pb2.Project
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
@requires_client
|
|
24
|
+
@syncer.wrap
|
|
25
|
+
async def get(cls, name: str, org: str | None = None) -> Project:
|
|
26
|
+
"""
|
|
27
|
+
Get a run by its ID or name. If both are provided, the ID will take precedence.
|
|
28
|
+
|
|
29
|
+
:param name: The name of the project.
|
|
30
|
+
:param org: The organization of the project (if applicable).
|
|
31
|
+
"""
|
|
32
|
+
service = get_client().project_domain_service # type: ignore
|
|
33
|
+
resp = await service.GetProject(
|
|
34
|
+
project_pb2.ProjectGetRequest(
|
|
35
|
+
id=name,
|
|
36
|
+
org=org,
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
return cls(resp)
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
@requires_client
|
|
43
|
+
@syncer.wrap
|
|
44
|
+
async def listall(
|
|
45
|
+
cls,
|
|
46
|
+
filters: str | None = None,
|
|
47
|
+
sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
|
|
48
|
+
) -> typing.Union[typing.Iterator[Project], AsyncGenerator[Project, None]]:
|
|
49
|
+
"""
|
|
50
|
+
Get a run by its ID or name. If both are provided, the ID will take precedence.
|
|
51
|
+
|
|
52
|
+
:param filters: The filters to apply to the project list.
|
|
53
|
+
:param sort_by: The sorting criteria for the project list, in the format (field, order).
|
|
54
|
+
:return: An iterator of projects.
|
|
55
|
+
"""
|
|
56
|
+
token = None
|
|
57
|
+
sort_by = sort_by or ("created_at", "asc")
|
|
58
|
+
sort_pb2 = common_pb2.Sort(
|
|
59
|
+
key=sort_by[0], direction=common_pb2.Sort.ASCENDING if sort_by[1] == "asc" else common_pb2.Sort.DESCENDING
|
|
60
|
+
)
|
|
61
|
+
org = get_common_config().org
|
|
62
|
+
while True:
|
|
63
|
+
resp = await get_client().project_domain_service.ListProjects( # type: ignore
|
|
64
|
+
project_pb2.ProjectListRequest(
|
|
65
|
+
limit=100,
|
|
66
|
+
token=token,
|
|
67
|
+
filters=filters,
|
|
68
|
+
sort_by=sort_pb2,
|
|
69
|
+
org=org,
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
token = resp.token
|
|
73
|
+
for p in resp.projects:
|
|
74
|
+
yield cls(p)
|
|
75
|
+
if not token:
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
def __rich_repr__(self) -> rich.repr.Result:
|
|
79
|
+
yield "name", self._pb2.name
|
|
80
|
+
yield "id", self._pb2.id
|
|
81
|
+
yield "description", self._pb2.description
|
|
82
|
+
yield "state", project_pb2.Project.ProjectState.Name(self._pb2.state)
|
|
83
|
+
yield (
|
|
84
|
+
"labels",
|
|
85
|
+
", ".join([f"{k}: {v}" for k, v in self._pb2.labels.values.items()]) if self._pb2.labels else None,
|
|
86
|
+
)
|