flyte 0.0.1b3__py3-none-any.whl → 0.2.0a0__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 +20 -4
- flyte/_bin/runtime.py +33 -7
- flyte/_build.py +3 -2
- flyte/_cache/cache.py +1 -2
- flyte/_code_bundle/_packaging.py +1 -1
- flyte/_code_bundle/_utils.py +0 -16
- flyte/_code_bundle/bundle.py +43 -12
- flyte/_context.py +8 -2
- flyte/_deploy.py +56 -15
- flyte/_environment.py +45 -4
- flyte/_excepthook.py +37 -0
- flyte/_group.py +2 -1
- flyte/_image.py +8 -4
- flyte/_initialize.py +112 -254
- flyte/_interface.py +3 -3
- flyte/_internal/controllers/__init__.py +19 -6
- flyte/_internal/controllers/_local_controller.py +83 -8
- flyte/_internal/controllers/_trace.py +2 -1
- flyte/_internal/controllers/remote/__init__.py +27 -7
- flyte/_internal/controllers/remote/_action.py +7 -2
- flyte/_internal/controllers/remote/_client.py +5 -1
- flyte/_internal/controllers/remote/_controller.py +159 -26
- flyte/_internal/controllers/remote/_core.py +13 -5
- flyte/_internal/controllers/remote/_informer.py +4 -4
- flyte/_internal/controllers/remote/_service_protocol.py +6 -6
- flyte/_internal/imagebuild/docker_builder.py +12 -1
- flyte/_internal/imagebuild/image_builder.py +16 -11
- flyte/_internal/runtime/convert.py +164 -21
- flyte/_internal/runtime/entrypoints.py +1 -1
- flyte/_internal/runtime/io.py +3 -3
- flyte/_internal/runtime/task_serde.py +140 -20
- flyte/_internal/runtime/taskrunner.py +4 -3
- flyte/_internal/runtime/types_serde.py +1 -1
- flyte/_logging.py +12 -1
- flyte/_map.py +215 -0
- flyte/_pod.py +19 -0
- flyte/_protos/common/list_pb2.py +3 -3
- flyte/_protos/common/list_pb2.pyi +2 -0
- flyte/_protos/logs/dataplane/payload_pb2.py +28 -24
- flyte/_protos/logs/dataplane/payload_pb2.pyi +11 -2
- flyte/_protos/workflow/common_pb2.py +27 -0
- flyte/_protos/workflow/common_pb2.pyi +14 -0
- flyte/_protos/workflow/environment_pb2.py +29 -0
- flyte/_protos/workflow/environment_pb2.pyi +12 -0
- flyte/_protos/workflow/queue_service_pb2.py +40 -41
- flyte/_protos/workflow/queue_service_pb2.pyi +35 -30
- flyte/_protos/workflow/queue_service_pb2_grpc.py +15 -15
- flyte/_protos/workflow/run_definition_pb2.py +61 -61
- flyte/_protos/workflow/run_definition_pb2.pyi +8 -4
- flyte/_protos/workflow/run_service_pb2.py +20 -24
- flyte/_protos/workflow/run_service_pb2.pyi +2 -6
- flyte/_protos/workflow/state_service_pb2.py +36 -28
- flyte/_protos/workflow/state_service_pb2.pyi +19 -15
- flyte/_protos/workflow/state_service_pb2_grpc.py +28 -28
- flyte/_protos/workflow/task_definition_pb2.py +29 -22
- flyte/_protos/workflow/task_definition_pb2.pyi +21 -5
- flyte/_protos/workflow/task_service_pb2.py +27 -11
- flyte/_protos/workflow/task_service_pb2.pyi +29 -1
- flyte/_protos/workflow/task_service_pb2_grpc.py +34 -0
- flyte/_run.py +166 -95
- flyte/_task.py +110 -28
- flyte/_task_environment.py +55 -72
- flyte/_trace.py +6 -14
- flyte/_utils/__init__.py +6 -0
- flyte/_utils/async_cache.py +139 -0
- flyte/_utils/coro_management.py +0 -2
- flyte/_utils/helpers.py +45 -19
- flyte/_utils/org_discovery.py +57 -0
- flyte/_version.py +2 -2
- flyte/cli/__init__.py +3 -0
- flyte/cli/_abort.py +28 -0
- flyte/{_cli → cli}/_common.py +73 -23
- flyte/cli/_create.py +145 -0
- flyte/{_cli → cli}/_delete.py +4 -4
- flyte/{_cli → cli}/_deploy.py +26 -14
- flyte/cli/_gen.py +163 -0
- flyte/{_cli → cli}/_get.py +98 -23
- {union/_cli → flyte/cli}/_params.py +106 -147
- flyte/{_cli → cli}/_run.py +99 -20
- flyte/cli/main.py +166 -0
- flyte/config/__init__.py +3 -0
- flyte/config/_config.py +216 -0
- flyte/config/_internal.py +64 -0
- flyte/config/_reader.py +207 -0
- flyte/errors.py +29 -0
- flyte/extras/_container.py +33 -43
- flyte/io/__init__.py +17 -1
- flyte/io/_dir.py +2 -2
- flyte/io/_file.py +3 -4
- flyte/io/{structured_dataset → _structured_dataset}/basic_dfs.py +1 -1
- flyte/io/{structured_dataset → _structured_dataset}/structured_dataset.py +1 -1
- flyte/{_datastructures.py → models.py} +56 -7
- flyte/remote/__init__.py +2 -1
- flyte/remote/_client/_protocols.py +2 -0
- flyte/remote/_client/auth/_auth_utils.py +14 -0
- flyte/remote/_client/auth/_channel.py +34 -3
- flyte/remote/_client/auth/_token_client.py +3 -3
- flyte/remote/_client/controlplane.py +13 -13
- flyte/remote/_console.py +1 -1
- flyte/remote/_data.py +10 -6
- flyte/remote/_logs.py +89 -29
- flyte/remote/_project.py +8 -9
- flyte/remote/_run.py +228 -131
- flyte/remote/_secret.py +12 -12
- flyte/remote/_task.py +179 -15
- flyte/report/_report.py +4 -4
- flyte/storage/__init__.py +5 -0
- flyte/storage/_config.py +233 -0
- flyte/storage/_storage.py +23 -3
- flyte/syncify/__init__.py +56 -0
- flyte/syncify/_api.py +371 -0
- flyte/types/__init__.py +23 -0
- flyte/types/_interface.py +22 -7
- flyte/{io/pickle/transformer.py → types/_pickle.py} +2 -1
- flyte/types/_type_engine.py +95 -18
- flyte-0.2.0a0.dist-info/METADATA +249 -0
- flyte-0.2.0a0.dist-info/RECORD +218 -0
- {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/entry_points.txt +1 -1
- flyte/_api_commons.py +0 -3
- flyte/_cli/__init__.py +0 -0
- flyte/_cli/_create.py +0 -42
- flyte/_cli/main.py +0 -72
- flyte/_internal/controllers/pbhash.py +0 -39
- flyte/io/_dataframe.py +0 -0
- flyte/io/pickle/__init__.py +0 -0
- flyte-0.0.1b3.dist-info/METADATA +0 -179
- flyte-0.0.1b3.dist-info/RECORD +0 -390
- union/__init__.py +0 -54
- union/_api_commons.py +0 -3
- union/_bin/__init__.py +0 -0
- union/_bin/runtime.py +0 -113
- union/_build.py +0 -25
- union/_cache/__init__.py +0 -12
- union/_cache/cache.py +0 -141
- union/_cache/defaults.py +0 -9
- union/_cache/policy_function_body.py +0 -42
- union/_cli/__init__.py +0 -0
- union/_cli/_common.py +0 -263
- union/_cli/_create.py +0 -40
- union/_cli/_delete.py +0 -23
- union/_cli/_deploy.py +0 -120
- union/_cli/_get.py +0 -162
- union/_cli/_run.py +0 -150
- union/_cli/main.py +0 -72
- union/_code_bundle/__init__.py +0 -8
- union/_code_bundle/_ignore.py +0 -113
- union/_code_bundle/_packaging.py +0 -187
- union/_code_bundle/_utils.py +0 -342
- union/_code_bundle/bundle.py +0 -176
- union/_context.py +0 -146
- union/_datastructures.py +0 -295
- union/_deploy.py +0 -185
- union/_doc.py +0 -29
- union/_docstring.py +0 -26
- union/_environment.py +0 -43
- union/_group.py +0 -31
- union/_hash.py +0 -23
- union/_image.py +0 -760
- union/_initialize.py +0 -585
- union/_interface.py +0 -84
- union/_internal/__init__.py +0 -3
- union/_internal/controllers/__init__.py +0 -77
- union/_internal/controllers/_local_controller.py +0 -77
- union/_internal/controllers/pbhash.py +0 -39
- union/_internal/controllers/remote/__init__.py +0 -40
- union/_internal/controllers/remote/_action.py +0 -131
- union/_internal/controllers/remote/_client.py +0 -43
- union/_internal/controllers/remote/_controller.py +0 -169
- union/_internal/controllers/remote/_core.py +0 -341
- union/_internal/controllers/remote/_informer.py +0 -260
- union/_internal/controllers/remote/_service_protocol.py +0 -44
- union/_internal/imagebuild/__init__.py +0 -11
- union/_internal/imagebuild/docker_builder.py +0 -416
- union/_internal/imagebuild/image_builder.py +0 -243
- union/_internal/imagebuild/remote_builder.py +0 -0
- union/_internal/resolvers/__init__.py +0 -0
- union/_internal/resolvers/_task_module.py +0 -31
- union/_internal/resolvers/common.py +0 -24
- union/_internal/resolvers/default.py +0 -27
- union/_internal/runtime/__init__.py +0 -0
- union/_internal/runtime/convert.py +0 -163
- union/_internal/runtime/entrypoints.py +0 -121
- union/_internal/runtime/io.py +0 -136
- union/_internal/runtime/resources_serde.py +0 -134
- union/_internal/runtime/task_serde.py +0 -202
- union/_internal/runtime/taskrunner.py +0 -179
- union/_internal/runtime/types_serde.py +0 -53
- union/_logging.py +0 -124
- union/_protos/__init__.py +0 -0
- union/_protos/common/authorization_pb2.py +0 -66
- union/_protos/common/authorization_pb2.pyi +0 -106
- union/_protos/common/identifier_pb2.py +0 -71
- union/_protos/common/identifier_pb2.pyi +0 -82
- union/_protos/common/identity_pb2.py +0 -48
- union/_protos/common/identity_pb2.pyi +0 -72
- union/_protos/common/identity_pb2_grpc.py +0 -4
- union/_protos/common/list_pb2.py +0 -36
- union/_protos/common/list_pb2.pyi +0 -69
- union/_protos/common/list_pb2_grpc.py +0 -4
- union/_protos/common/policy_pb2.py +0 -37
- union/_protos/common/policy_pb2.pyi +0 -27
- union/_protos/common/policy_pb2_grpc.py +0 -4
- union/_protos/common/role_pb2.py +0 -37
- union/_protos/common/role_pb2.pyi +0 -51
- union/_protos/common/role_pb2_grpc.py +0 -4
- union/_protos/common/runtime_version_pb2.py +0 -28
- union/_protos/common/runtime_version_pb2.pyi +0 -24
- union/_protos/common/runtime_version_pb2_grpc.py +0 -4
- union/_protos/logs/dataplane/payload_pb2.py +0 -96
- union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
- union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
- union/_protos/secret/definition_pb2.py +0 -49
- union/_protos/secret/definition_pb2.pyi +0 -93
- union/_protos/secret/definition_pb2_grpc.py +0 -4
- union/_protos/secret/payload_pb2.py +0 -62
- union/_protos/secret/payload_pb2.pyi +0 -94
- union/_protos/secret/payload_pb2_grpc.py +0 -4
- union/_protos/secret/secret_pb2.py +0 -38
- union/_protos/secret/secret_pb2.pyi +0 -6
- union/_protos/secret/secret_pb2_grpc.py +0 -198
- union/_protos/validate/validate/validate_pb2.py +0 -76
- union/_protos/workflow/node_execution_service_pb2.py +0 -26
- union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
- union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
- union/_protos/workflow/queue_service_pb2.py +0 -75
- union/_protos/workflow/queue_service_pb2.pyi +0 -103
- union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
- union/_protos/workflow/run_definition_pb2.py +0 -100
- union/_protos/workflow/run_definition_pb2.pyi +0 -256
- union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
- union/_protos/workflow/run_logs_service_pb2.py +0 -41
- union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
- union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
- union/_protos/workflow/run_service_pb2.py +0 -133
- union/_protos/workflow/run_service_pb2.pyi +0 -173
- union/_protos/workflow/run_service_pb2_grpc.py +0 -412
- union/_protos/workflow/state_service_pb2.py +0 -58
- union/_protos/workflow/state_service_pb2.pyi +0 -69
- union/_protos/workflow/state_service_pb2_grpc.py +0 -138
- union/_protos/workflow/task_definition_pb2.py +0 -72
- union/_protos/workflow/task_definition_pb2.pyi +0 -65
- union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
- union/_protos/workflow/task_service_pb2.py +0 -44
- union/_protos/workflow/task_service_pb2.pyi +0 -31
- union/_protos/workflow/task_service_pb2_grpc.py +0 -104
- union/_resources.py +0 -226
- union/_retry.py +0 -32
- union/_reusable_environment.py +0 -25
- union/_run.py +0 -374
- union/_secret.py +0 -61
- union/_task.py +0 -354
- union/_task_environment.py +0 -186
- union/_timeout.py +0 -47
- union/_tools.py +0 -27
- union/_utils/__init__.py +0 -11
- union/_utils/asyn.py +0 -119
- union/_utils/file_handling.py +0 -71
- union/_utils/helpers.py +0 -46
- union/_utils/lazy_module.py +0 -54
- union/_utils/uv_script_parser.py +0 -49
- union/_version.py +0 -21
- union/connectors/__init__.py +0 -0
- union/errors.py +0 -128
- union/extras/__init__.py +0 -5
- union/extras/_container.py +0 -263
- union/io/__init__.py +0 -11
- union/io/_dataframe.py +0 -0
- union/io/_dir.py +0 -425
- union/io/_file.py +0 -418
- union/io/pickle/__init__.py +0 -0
- union/io/pickle/transformer.py +0 -117
- union/io/structured_dataset/__init__.py +0 -122
- union/io/structured_dataset/basic_dfs.py +0 -219
- union/io/structured_dataset/structured_dataset.py +0 -1057
- union/py.typed +0 -0
- union/remote/__init__.py +0 -23
- union/remote/_client/__init__.py +0 -0
- union/remote/_client/_protocols.py +0 -129
- union/remote/_client/auth/__init__.py +0 -12
- union/remote/_client/auth/_authenticators/__init__.py +0 -0
- union/remote/_client/auth/_authenticators/base.py +0 -391
- union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
- union/remote/_client/auth/_authenticators/device_code.py +0 -120
- union/remote/_client/auth/_authenticators/external_command.py +0 -77
- union/remote/_client/auth/_authenticators/factory.py +0 -200
- union/remote/_client/auth/_authenticators/pkce.py +0 -515
- union/remote/_client/auth/_channel.py +0 -184
- union/remote/_client/auth/_client_config.py +0 -83
- union/remote/_client/auth/_default_html.py +0 -32
- union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
- union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
- union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
- union/remote/_client/auth/_keyring.py +0 -154
- union/remote/_client/auth/_token_client.py +0 -258
- union/remote/_client/auth/errors.py +0 -16
- union/remote/_client/controlplane.py +0 -86
- union/remote/_data.py +0 -149
- union/remote/_logs.py +0 -74
- union/remote/_project.py +0 -86
- union/remote/_run.py +0 -820
- union/remote/_secret.py +0 -132
- union/remote/_task.py +0 -193
- union/report/__init__.py +0 -3
- union/report/_report.py +0 -178
- union/report/_template.html +0 -124
- union/storage/__init__.py +0 -24
- union/storage/_remote_fs.py +0 -34
- union/storage/_storage.py +0 -247
- union/storage/_utils.py +0 -5
- union/types/__init__.py +0 -11
- union/types/_renderer.py +0 -162
- union/types/_string_literals.py +0 -120
- union/types/_type_engine.py +0 -2131
- union/types/_utils.py +0 -80
- /union/_protos/common/authorization_pb2_grpc.py → /flyte/_protos/workflow/common_pb2_grpc.py +0 -0
- /union/_protos/common/identifier_pb2_grpc.py → /flyte/_protos/workflow/environment_pb2_grpc.py +0 -0
- /flyte/io/{structured_dataset → _structured_dataset}/__init__.py +0 -0
- {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/WHEEL +0 -0
- {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/top_level.txt +0 -0
flyte/types/_type_engine.py
CHANGED
|
@@ -35,13 +35,14 @@ from mashumaro.jsonschema.models import Context, JSONSchema
|
|
|
35
35
|
from mashumaro.jsonschema.plugins import BasePlugin
|
|
36
36
|
from mashumaro.jsonschema.schema import Instance
|
|
37
37
|
from mashumaro.mixins.json import DataClassJSONMixin
|
|
38
|
+
from pydantic import BaseModel
|
|
38
39
|
from typing_extensions import Annotated, get_args, get_origin
|
|
39
40
|
|
|
40
41
|
import flyte.storage as storage
|
|
41
|
-
from flyte._datastructures import NativeInterface
|
|
42
42
|
from flyte._hash import HashMethod
|
|
43
43
|
from flyte._logging import logger
|
|
44
44
|
from flyte._utils.helpers import load_proto_from_file
|
|
45
|
+
from flyte.models import NativeInterface
|
|
45
46
|
|
|
46
47
|
from ._utils import literal_types_match
|
|
47
48
|
|
|
@@ -352,6 +353,79 @@ class RestrictedTypeTransformer(TypeTransformer[T], ABC):
|
|
|
352
353
|
raise RestrictedTypeError(f"Transformer for type {self.python_type} is restricted currently")
|
|
353
354
|
|
|
354
355
|
|
|
356
|
+
class PydanticTransformer(TypeTransformer[BaseModel]):
|
|
357
|
+
def __init__(self):
|
|
358
|
+
super().__init__("Pydantic Transformer", BaseModel, enable_type_assertions=False)
|
|
359
|
+
|
|
360
|
+
def get_literal_type(self, t: Type[BaseModel]) -> LiteralType:
|
|
361
|
+
schema = t.model_json_schema()
|
|
362
|
+
fields = t.__annotations__.items()
|
|
363
|
+
|
|
364
|
+
literal_type = {}
|
|
365
|
+
for name, python_type in fields:
|
|
366
|
+
try:
|
|
367
|
+
literal_type[name] = TypeEngine.to_literal_type(python_type)
|
|
368
|
+
except Exception as e:
|
|
369
|
+
logger.warning(
|
|
370
|
+
"Field {} of type {} cannot be converted to a literal type. Error: {}".format(name, python_type, e)
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# This is for attribute access in FlytePropeller.
|
|
374
|
+
ts = TypeStructure(tag="", dataclass_type=literal_type)
|
|
375
|
+
|
|
376
|
+
meta_struct = struct_pb2.Struct()
|
|
377
|
+
meta_struct.update(
|
|
378
|
+
{
|
|
379
|
+
CACHE_KEY_METADATA: {
|
|
380
|
+
SERIALIZATION_FORMAT: MESSAGEPACK,
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
return LiteralType(
|
|
386
|
+
simple=SimpleType.STRUCT,
|
|
387
|
+
metadata=schema,
|
|
388
|
+
structure=ts,
|
|
389
|
+
annotation=TypeAnnotation(annotations=meta_struct),
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
async def to_literal(
|
|
393
|
+
self,
|
|
394
|
+
python_val: BaseModel,
|
|
395
|
+
python_type: Type[BaseModel],
|
|
396
|
+
expected: LiteralType,
|
|
397
|
+
) -> Literal:
|
|
398
|
+
json_str = python_val.model_dump_json()
|
|
399
|
+
dict_obj = json.loads(json_str)
|
|
400
|
+
msgpack_bytes = msgpack.dumps(dict_obj)
|
|
401
|
+
return Literal(scalar=Scalar(binary=Binary(value=msgpack_bytes, tag=MESSAGEPACK)))
|
|
402
|
+
|
|
403
|
+
def from_binary_idl(self, binary_idl_object: Binary, expected_python_type: Type[BaseModel]) -> BaseModel:
|
|
404
|
+
if binary_idl_object.tag == MESSAGEPACK:
|
|
405
|
+
dict_obj = msgpack.loads(binary_idl_object.value, strict_map_key=False)
|
|
406
|
+
json_str = json.dumps(dict_obj)
|
|
407
|
+
python_val = expected_python_type.model_validate_json(
|
|
408
|
+
json_data=json_str, strict=False, context={"deserialize": True}
|
|
409
|
+
)
|
|
410
|
+
return python_val
|
|
411
|
+
else:
|
|
412
|
+
raise TypeTransformerFailedError(f"Unsupported binary format: `{binary_idl_object.tag}`")
|
|
413
|
+
|
|
414
|
+
async def to_python_value(self, lv: Literal, expected_python_type: Type[BaseModel]) -> BaseModel:
|
|
415
|
+
"""
|
|
416
|
+
There are two kinds of literal values to handle:
|
|
417
|
+
1. Protobuf Structs (from the UI)
|
|
418
|
+
2. Binary scalars (from other sources)
|
|
419
|
+
We need to account for both cases accordingly.
|
|
420
|
+
"""
|
|
421
|
+
if lv and lv.HasField("scalar") and lv.scalar.HasField("binary"):
|
|
422
|
+
return self.from_binary_idl(lv.scalar.binary, expected_python_type) # type: ignore
|
|
423
|
+
|
|
424
|
+
json_str = _json_format.MessageToJson(lv.scalar.generic)
|
|
425
|
+
python_val = expected_python_type.model_validate_json(json_str, strict=False, context={"deserialize": True})
|
|
426
|
+
return python_val
|
|
427
|
+
|
|
428
|
+
|
|
355
429
|
class PydanticSchemaPlugin(BasePlugin):
|
|
356
430
|
"""This allows us to generate proper schemas for Pydantic models."""
|
|
357
431
|
|
|
@@ -450,7 +524,6 @@ class DataclassTransformer(TypeTransformer[object]):
|
|
|
450
524
|
# However, FooSchema is created by flytekit and it's not equal to the user-defined dataclass (Foo).
|
|
451
525
|
# Therefore, we should iterate all attributes in the dataclass and check the type of value in dataclass
|
|
452
526
|
# matches the expected_type.
|
|
453
|
-
|
|
454
527
|
expected_fields_dict = {}
|
|
455
528
|
|
|
456
529
|
for f in dataclasses.fields(expected_type):
|
|
@@ -563,9 +636,8 @@ class DataclassTransformer(TypeTransformer[object]):
|
|
|
563
636
|
|
|
564
637
|
# This is for attribute access in FlytePropeller.
|
|
565
638
|
ts = TypeStructure(tag="", dataclass_type=literal_type)
|
|
566
|
-
from google.protobuf.struct_pb2 import Struct
|
|
567
639
|
|
|
568
|
-
meta_struct = Struct()
|
|
640
|
+
meta_struct = struct_pb2.Struct()
|
|
569
641
|
meta_struct.update(
|
|
570
642
|
{
|
|
571
643
|
CACHE_KEY_METADATA: {
|
|
@@ -628,7 +700,7 @@ class DataclassTransformer(TypeTransformer[object]):
|
|
|
628
700
|
field.type = self._get_origin_type_in_annotation(cast(type, field.type))
|
|
629
701
|
return python_type
|
|
630
702
|
|
|
631
|
-
|
|
703
|
+
def from_binary_idl(self, binary_idl_object: Binary, expected_python_type: Type[T]) -> T:
|
|
632
704
|
if binary_idl_object.tag == MESSAGEPACK:
|
|
633
705
|
if issubclass(expected_python_type, DataClassJSONMixin):
|
|
634
706
|
dict_obj = msgpack.loads(binary_idl_object.value, strict_map_key=False)
|
|
@@ -653,9 +725,10 @@ class DataclassTransformer(TypeTransformer[object]):
|
|
|
653
725
|
"user defined datatypes in Flytekit"
|
|
654
726
|
)
|
|
655
727
|
|
|
656
|
-
if lv.scalar and lv.scalar.binary:
|
|
657
|
-
return
|
|
728
|
+
if lv.HasField("scalar") and lv.scalar.HasField("binary"):
|
|
729
|
+
return self.from_binary_idl(lv.scalar.binary, expected_python_type) # type: ignore
|
|
658
730
|
|
|
731
|
+
# todo: revisit this, it should always be a binary in v2.
|
|
659
732
|
json_str = _json_format.MessageToJson(lv.scalar.generic)
|
|
660
733
|
|
|
661
734
|
# The `from_json` function is provided from mashumaro's `DataClassJSONMixin`.
|
|
@@ -971,11 +1044,10 @@ class TypeEngine(typing.Generic[T]):
|
|
|
971
1044
|
return cls._REGISTRY[python_type.__origin__]
|
|
972
1045
|
|
|
973
1046
|
# Handling UnionType specially - PEP 604
|
|
974
|
-
|
|
975
|
-
import types
|
|
1047
|
+
import types
|
|
976
1048
|
|
|
977
|
-
|
|
978
|
-
|
|
1049
|
+
if isinstance(python_type, types.UnionType):
|
|
1050
|
+
return cls._REGISTRY[types.UnionType]
|
|
979
1051
|
|
|
980
1052
|
if python_type in cls._REGISTRY:
|
|
981
1053
|
return cls._REGISTRY[python_type]
|
|
@@ -1009,7 +1081,7 @@ class TypeEngine(typing.Generic[T]):
|
|
|
1009
1081
|
return cls._DATACLASS_TRANSFORMER
|
|
1010
1082
|
|
|
1011
1083
|
display_pickle_warning(str(python_type))
|
|
1012
|
-
from flyte.
|
|
1084
|
+
from flyte.types._pickle import FlytePickleTransformer
|
|
1013
1085
|
|
|
1014
1086
|
return FlytePickleTransformer()
|
|
1015
1087
|
|
|
@@ -1022,7 +1094,7 @@ class TypeEngine(typing.Generic[T]):
|
|
|
1022
1094
|
# Avoid a race condition where concurrent threads may exit lazy_import_transformers before the transformers
|
|
1023
1095
|
# have been imported. This could be implemented without a lock if you assume python assignments are atomic
|
|
1024
1096
|
# and re-registering transformers is acceptable, but I decided to play it safe.
|
|
1025
|
-
from flyte.io
|
|
1097
|
+
from flyte.io import lazy_import_structured_dataset_handler
|
|
1026
1098
|
|
|
1027
1099
|
# todo: bring in extras transformers (pytorch, etc.)
|
|
1028
1100
|
lazy_import_structured_dataset_handler()
|
|
@@ -1208,7 +1280,9 @@ class TypeEngine(typing.Generic[T]):
|
|
|
1208
1280
|
python_type = type_hints.get(k, type(d[k]))
|
|
1209
1281
|
e: BaseException = literal_map[k].exception() # type: ignore
|
|
1210
1282
|
if isinstance(e, TypeError):
|
|
1211
|
-
raise TypeError(
|
|
1283
|
+
raise TypeError(
|
|
1284
|
+
f"Error converting: Var:{k}, type:{type(v)}, into:{python_type}, received_value {v}"
|
|
1285
|
+
)
|
|
1212
1286
|
else:
|
|
1213
1287
|
raise e
|
|
1214
1288
|
literal_map[k] = v.result()
|
|
@@ -1658,7 +1732,7 @@ class DictTransformer(TypeTransformer[dict]):
|
|
|
1658
1732
|
Converts a Python dictionary to a Flyte-specific ``Literal`` using MessagePack encoding.
|
|
1659
1733
|
Falls back to Pickle if encoding fails and `allow_pickle` is True.
|
|
1660
1734
|
"""
|
|
1661
|
-
from flyte.
|
|
1735
|
+
from flyte.types._pickle import FlytePickle
|
|
1662
1736
|
|
|
1663
1737
|
try:
|
|
1664
1738
|
# Handle dictionaries with non-string keys (e.g., Dict[int, Type])
|
|
@@ -1764,7 +1838,7 @@ class DictTransformer(TypeTransformer[dict]):
|
|
|
1764
1838
|
# pr: han-ru is this part still necessary?
|
|
1765
1839
|
if lv and lv.HasField("scalar") and lv.scalar.HasField("generic"):
|
|
1766
1840
|
if lv.metadata and lv.metadata.get("format", None) == "pickle":
|
|
1767
|
-
from flyte.
|
|
1841
|
+
from flyte.types._pickle import FlytePickle
|
|
1768
1842
|
|
|
1769
1843
|
uri = json.loads(_json_format.MessageToJson(lv.scalar.generic)).get("pickle_file")
|
|
1770
1844
|
return await FlytePickle.from_pickle(uri)
|
|
@@ -1992,7 +2066,9 @@ DatetimeTransformer = SimpleTransformer(
|
|
|
1992
2066
|
datetime.datetime,
|
|
1993
2067
|
types_pb2.LiteralType(simple=types_pb2.SimpleType.DATETIME),
|
|
1994
2068
|
lambda x: Literal(scalar=Scalar(primitive=Primitive(datetime=x))),
|
|
1995
|
-
lambda x: x.scalar.primitive.datetime
|
|
2069
|
+
lambda x: x.scalar.primitive.datetime.ToDatetime().replace(tzinfo=datetime.timezone.utc)
|
|
2070
|
+
if x.scalar.primitive.HasField("datetime")
|
|
2071
|
+
else None,
|
|
1996
2072
|
)
|
|
1997
2073
|
|
|
1998
2074
|
TimedeltaTransformer = SimpleTransformer(
|
|
@@ -2000,7 +2076,7 @@ TimedeltaTransformer = SimpleTransformer(
|
|
|
2000
2076
|
datetime.timedelta,
|
|
2001
2077
|
types_pb2.LiteralType(simple=types_pb2.SimpleType.DURATION),
|
|
2002
2078
|
lambda x: Literal(scalar=Scalar(primitive=Primitive(duration=x))),
|
|
2003
|
-
lambda x: x.scalar.primitive.duration if x.scalar.primitive.HasField("duration") else None,
|
|
2079
|
+
lambda x: x.scalar.primitive.duration.ToTimedelta() if x.scalar.primitive.HasField("duration") else None,
|
|
2004
2080
|
)
|
|
2005
2081
|
|
|
2006
2082
|
DateTransformer = SimpleTransformer(
|
|
@@ -2038,6 +2114,7 @@ def _register_default_type_transformers():
|
|
|
2038
2114
|
TypeEngine.register(DictTransformer())
|
|
2039
2115
|
TypeEngine.register(EnumTransformer())
|
|
2040
2116
|
TypeEngine.register(ProtobufTransformer())
|
|
2117
|
+
TypeEngine.register(PydanticTransformer())
|
|
2041
2118
|
|
|
2042
2119
|
# inner type is. Also unsupported are typing's Tuples. Even though you can look inside them, Flyte's type system
|
|
2043
2120
|
# doesn't support these currently.
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flyte
|
|
3
|
+
Version: 0.2.0a0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: Ketan Umare <kumare3@users.noreply.github.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: aiofiles>=24.1.0
|
|
9
|
+
Requires-Dist: click>=8.2.1
|
|
10
|
+
Requires-Dist: flyteidl==1.15.4b0
|
|
11
|
+
Requires-Dist: cloudpickle>=3.1.1
|
|
12
|
+
Requires-Dist: fsspec>=2025.3.0
|
|
13
|
+
Requires-Dist: grpcio>=1.71.0
|
|
14
|
+
Requires-Dist: obstore>=0.6.0
|
|
15
|
+
Requires-Dist: protobuf>=6.30.1
|
|
16
|
+
Requires-Dist: pydantic>=2.10.6
|
|
17
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
18
|
+
Requires-Dist: rich-click>=1.8.9
|
|
19
|
+
Requires-Dist: httpx>=0.28.1
|
|
20
|
+
Requires-Dist: keyring>=25.6.0
|
|
21
|
+
Requires-Dist: msgpack>=1.1.0
|
|
22
|
+
Requires-Dist: toml>=0.10.2
|
|
23
|
+
Requires-Dist: async-lru>=2.0.5
|
|
24
|
+
Requires-Dist: mashumaro
|
|
25
|
+
Requires-Dist: dataclasses_json
|
|
26
|
+
|
|
27
|
+
# Flyte v2 SDK
|
|
28
|
+
|
|
29
|
+
The next-generation SDK for Flyte.
|
|
30
|
+
|
|
31
|
+
[](https://github.com/unionai/unionv2/actions/workflows/publish.yml)
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
1. Run `uv venv`, and `source .venv/bin/activate` to create a new virtual environment.
|
|
36
|
+
2. Install the latest version of the SDK by running the following:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
uv pip install --no-cache --prerelease=allow --upgrade flyte
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
4. Create the config and point it to your cluster by running the following:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
flyte create config --endpoint <your-endpoint-url> --project <your-project> --domain <your-domain>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This will create a `config.yaml` file in the current directory which will be referenced ahead of any other `config.yaml`s found in your system.
|
|
49
|
+
|
|
50
|
+
5. Now you can run code with the CLI:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
flyte run <path-to-your-script> <task-name>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Hello World Example
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# hello_world.py
|
|
60
|
+
|
|
61
|
+
import flyte
|
|
62
|
+
|
|
63
|
+
env = flyte.TaskEnvironment(name="hello_world")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@env.task
|
|
67
|
+
async def say_hello(data: str) -> str:
|
|
68
|
+
return f"Hello {data}"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@env.task
|
|
72
|
+
async def say_hello_nested(data: str) -> str:
|
|
73
|
+
return await say_hello.override(resources=flyte.Resources(gpu="A100 80G:4")).execute(data)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
import asyncio
|
|
78
|
+
|
|
79
|
+
# to run pure python - the SDK is not invoked at all
|
|
80
|
+
asyncio.run(say_hello_nested("test"))
|
|
81
|
+
|
|
82
|
+
# To run locally, but run through type system etc
|
|
83
|
+
flyte.init()
|
|
84
|
+
flyte.run(say_hello_nested, "World")
|
|
85
|
+
|
|
86
|
+
# To run remote
|
|
87
|
+
flyte.init(endpoint="dns:///localhost:8090", insecure=True)
|
|
88
|
+
flyte.run(say_hello_nested, "World")
|
|
89
|
+
# It is possible to switch local and remote, but keeping init to have and endpoint, but , changing context during run
|
|
90
|
+
flyte.with_runcontext(mode="local").run(...) # this will run locally only
|
|
91
|
+
|
|
92
|
+
# To run remote with a config
|
|
93
|
+
flyte.init_from_config("config.yaml")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## CLI
|
|
97
|
+
|
|
98
|
+
All commands can be run from any root directory.
|
|
99
|
+
For examples, it is not needed to have `__init__.py` in the directory.
|
|
100
|
+
If you run from a directory, the code will automatically package and upload all modules that are imported.
|
|
101
|
+
You can change the behavior by using `--copy-style` flag.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
flyte run hello_world.py say_hello --data "World"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
To follow the logs for the `a0` action, you can use the `--follow` flag:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
flyte run --follow hello_world.py say_hello --data "World"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Note that `--follow` has to be used with the `run` command.
|
|
114
|
+
|
|
115
|
+
Change copy style:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
flyte run --copy-style all hello_world.py say_hello_nested --data "World"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Building Images
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import flyte
|
|
125
|
+
|
|
126
|
+
env = flyte.TaskEnvironment(
|
|
127
|
+
name="hello_world",
|
|
128
|
+
image=flyte.Image.auto().with_apt_packages(...).with_pip_packages(...),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Deploying
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
flyte deploy hello_world.py say_hello_nested
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Get information
|
|
140
|
+
|
|
141
|
+
Get all runs:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
flyte get run
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Get a specific run:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
flyte get run "run-name"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Get all actions for a run:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
flyte get actions "run-name"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Get a specific action for a run:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
flyte get action "run-name" "action-name"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Get action logs:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
flyte get logs "run-name" ["action-name"]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This defaults to root action if no action name is provided
|
|
172
|
+
|
|
173
|
+
## Running workflows programmatically in Python
|
|
174
|
+
|
|
175
|
+
You can run any workflow programmatically within the script module using __main__:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
if __name__ == "__main__":
|
|
179
|
+
import flyte
|
|
180
|
+
flyte.init()
|
|
181
|
+
flyte.run(say_hello_nested, "World")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Running scripts with dependencies specified in metadata headers
|
|
185
|
+
|
|
186
|
+
You can also run a `uv` script with dependencies specified in metadata headers
|
|
187
|
+
and build the task image automatically based on those dependencies:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
# container_images.py
|
|
191
|
+
|
|
192
|
+
# /// script
|
|
193
|
+
# dependencies = [
|
|
194
|
+
# "polars",
|
|
195
|
+
# "flyte>=0.2.0b12"
|
|
196
|
+
# ]
|
|
197
|
+
# ///
|
|
198
|
+
|
|
199
|
+
import polars as pl
|
|
200
|
+
|
|
201
|
+
import flyte
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
env = flyte.TaskEnvironment(
|
|
205
|
+
name="polars_image",
|
|
206
|
+
image=flyte.Image.from_uv_script(
|
|
207
|
+
__file__,
|
|
208
|
+
name="flyte",
|
|
209
|
+
registry="ghcr.io/<you-username>"
|
|
210
|
+
arch=("linux/amd64", "linux/arm64"),
|
|
211
|
+
).with_apt_packages("ca-certificates"),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@env.task
|
|
216
|
+
async def create_dataframe() -> pl.DataFrame:
|
|
217
|
+
return pl.DataFrame(
|
|
218
|
+
{"name": ["Alice", "Bob", "Charlie"], "age": [25, 32, 37], "city": ["New York", "Paris", "Berlin"]}
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@env.task
|
|
223
|
+
async def print_dataframe(dataframe: pl.DataFrame):
|
|
224
|
+
print(dataframe)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@env.task
|
|
228
|
+
async def workflow():
|
|
229
|
+
df = await create_dataframe()
|
|
230
|
+
await print_dataframe(df)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
if __name__ == "__main__":
|
|
234
|
+
flyte.init_from_config("config.yaml")
|
|
235
|
+
run = flyte.run(workflow)
|
|
236
|
+
print(run.name)
|
|
237
|
+
print(run.url)
|
|
238
|
+
run.wait(run)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
When you execute
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
uv run hello_world.py
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`uv` will automatically update the local virtual environment with the dependencies specified in the metadata headers.
|
|
248
|
+
Then, Flyte will build the task image using those dependencies and push it to the registry you specify.
|
|
249
|
+
Flyte will then deploy the tasks to the cluster where the system will pull the image and run the tasks using it.
|