Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run remote Launchplan from pyflyte run #1785

Merged
merged 14 commits into from
Aug 29, 2023
233 changes: 202 additions & 31 deletions flytekit/clis/sdk_in_container/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import yaml
from dataclasses_json import DataClassJsonMixin
from pytimeparse import parse
from rich.progress import Progress

Check warning on line 19 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L19

Added line #L19 was not covered by tests
from typing_extensions import get_args

from flytekit import BlobType, Literal, Scalar
Expand All @@ -42,9 +43,10 @@
from flytekit.core.type_engine import TypeEngine
from flytekit.core.workflow import PythonFunctionWorkflow, WorkflowBase
from flytekit.models import literals
from flytekit.models.interface import Variable
from flytekit.models.interface import Parameter, Variable

Check warning on line 46 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L46

Added line #L46 was not covered by tests
from flytekit.models.literals import Blob, BlobMetadata, LiteralCollection, LiteralMap, Primitive, Union
from flytekit.models.types import LiteralType, SimpleType
from flytekit.remote import FlyteLaunchPlan, FlyteRemote, FlyteTask, FlyteWorkflow

Check warning on line 49 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L49

Added line #L49 was not covered by tests
from flytekit.remote.executions import FlyteWorkflowExecution
from flytekit.remote.remote import FlyteRemote
from flytekit.tools import module_loader, script_mode
Expand Down Expand Up @@ -115,15 +117,13 @@
def convert(
self, value: typing.Any, param: typing.Optional[click.Parameter], ctx: typing.Optional[click.Context]
) -> typing.Any:

uri = FlyteContextManager.current_context().file_access.get_random_local_path()
with open(uri, "w+b") as outfile:
cloudpickle.dump(value, outfile)
return FileParam(filepath=str(pathlib.Path(uri).resolve()))


class DateTimeType(click.DateTime):

_NOW_FMT = "now"
_ADDITONAL_FORMATS = [_NOW_FMT]

Expand Down Expand Up @@ -458,6 +458,7 @@
python_type: typing.Type,
default_val: typing.Any,
get_upload_url_fn: typing.Callable,
required: bool,
) -> click.Option:
"""
This handles converting workflow input types to supported click parameters with callbacks to initialize
Expand All @@ -470,21 +471,24 @@
if literal_converter.is_bool() and not default_val:
default_val = False

description_extra = ""

Check warning on line 474 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L474

Added line #L474 was not covered by tests
if literal_var.type.simple == SimpleType.STRUCT:
if default_val:
if type(default_val) == dict or type(default_val) == list:
default_val = json.dumps(default_val)
else:
default_val = cast(DataClassJsonMixin, default_val).to_json()
if literal_var.type.metadata:
description_extra = f": {json.dumps(literal_var.type.metadata)}"

Check warning on line 482 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L482

Added line #L482 was not covered by tests

return click.Option(
param_decls=[f"--{input_name}"],
type=literal_converter.click_type,
is_flag=literal_converter.is_bool(),
default=default_val,
show_default=True,
required=default_val is None,
help=literal_var.description,
required=required,
help=literal_var.description + description_extra,
callback=literal_converter.convert,
)

Expand Down Expand Up @@ -592,6 +596,13 @@
type=str,
help="Tags to set for the execution",
),
click.Option(
param_decls=["--limit", "limit"],
required=False,
type=int,
default=10,
help="Use this to limit number of launch plans retreived from the backend, if `from-server` option is used",
),
]


Expand Down Expand Up @@ -662,12 +673,59 @@
return Entities(workflows, tasks)


def run_remote(

Check warning on line 676 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L676

Added line #L676 was not covered by tests
ctx: click.Context,
remote: FlyteRemote,
entity: typing.Union[FlyteWorkflow, FlyteTask, FlyteLaunchPlan],
project: str,
domain: str,
inputs: typing.Dict[str, typing.Any],
run_level_params: typing.Dict[str, typing.Any],
type_hints: typing.Optional[typing.Dict[str, typing.Type]] = None,
):
"""
Helper method that executes the given remote FlyteLaunchplan, FlyteWorkflow or FlyteTask
"""
options = None
service_account = run_level_params.get("service_account")

Check warning on line 690 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L689-L690

Added lines #L689 - L690 were not covered by tests
if service_account:
# options are only passed for the execution. This is to prevent errors when registering a duplicate workflow
# It is assumed that the users expectations is to override the service account only for the execution
options = Options.default_from(k8s_service_account=service_account)

Check warning on line 694 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L694

Added line #L694 was not covered by tests

execution = remote.execute(

Check warning on line 696 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L696

Added line #L696 was not covered by tests
entity,
inputs=inputs,
project=project,
domain=domain,
name=run_level_params.get("name"),
wait=run_level_params.get("wait_execution"),
options=options,
type_hints=type_hints,
overwrite_cache=run_level_params.get("overwrite_cache"),
envs=run_level_params.get("envs"),
tags=run_level_params.get("tag"),
)

console_url = remote.generate_console_url(execution)
click.secho(f"Go to {console_url} to see execution in the console.")

Check warning on line 711 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L710-L711

Added lines #L710 - L711 were not covered by tests

if run_level_params.get("dump_snippet"):
dump_flyte_remote_snippet(execution, project, domain)

Check warning on line 714 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L714

Added line #L714 was not covered by tests

if ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_FILE_NAME):
os.remove(ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_FILE_NAME))

Check warning on line 717 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L717

Added line #L717 was not covered by tests


def run_command(ctx: click.Context, entity: typing.Union[PythonFunctionWorkflow, PythonTask]):
"""
Returns a function that is used to implement WorkflowCommand and execute a flyte workflow.
"""

def _run(*args, **kwargs):
"""
Click command function that is used to execute a flyte workflow from the given entity in the file.
"""
# By the time we get to this function, all the loading has already happened

run_level_params = ctx.obj[RUN_LEVEL_PARAMS_KEY]
Expand Down Expand Up @@ -703,37 +761,137 @@
copy_all=ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_COPY_ALL),
)

options = None
service_account = run_level_params.get("service_account")
if service_account:
# options are only passed for the execution. This is to prevent errors when registering a duplicate workflow
# It is assumed that the users expectations is to override the service account only for the execution
options = Options.default_from(k8s_service_account=service_account)

execution = remote.execute(
run_remote(

Check warning on line 764 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L764

Added line #L764 was not covered by tests
ctx,
remote,
remote_entity,
inputs=inputs,
project=project,
domain=domain,
name=run_level_params.get("name"),
wait=run_level_params.get("wait_execution"),
options=options,
project,
domain,
inputs,
run_level_params,
type_hints=entity.python_interface.inputs,
overwrite_cache=run_level_params.get("overwrite_cache"),
envs=run_level_params.get("envs"),
tags=run_level_params.get("tag"),
)

console_url = remote.generate_console_url(execution)
click.secho(f"Go to {console_url} to see execution in the console.")
return _run

Check warning on line 775 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L775

Added line #L775 was not covered by tests

if run_level_params.get("dump_snippet"):
dump_flyte_remote_snippet(execution, project, domain)

if ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_FILE_NAME):
os.remove(ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_FILE_NAME))
class DynamicLaunchPlanCommand(click.RichCommand):

Check warning on line 778 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L778

Added line #L778 was not covered by tests
"""
This is a dynamic command that is created for each launch plan. This is used to execute a launch plan.
It will fetch the launch plan from remote and create parameters from all the inputs of the launch plan.
"""

return _run
def __init__(self, name: str, h: str, lp_name: str, **kwargs):
super().__init__(name=name, help=h, **kwargs)
self._lp_name = lp_name
self._lp = None

Check warning on line 787 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L784-L787

Added lines #L784 - L787 were not covered by tests

def _fetch_launch_plan(self, ctx: click.Context) -> FlyteLaunchPlan:

Check warning on line 789 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L789

Added line #L789 was not covered by tests
if self._lp:
return self._lp
project = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_PROJECT)
domain = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_DOMAIN)
r = get_and_save_remote_with_click_context(ctx, project, domain)
self._lp = r.fetch_launch_plan(project, domain, self._lp_name)
return self._lp

Check warning on line 796 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L791-L796

Added lines #L791 - L796 were not covered by tests

def _get_params(

Check warning on line 798 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L798

Added line #L798 was not covered by tests
self,
ctx: click.Context,
inputs: typing.Dict[str, Variable],
native_inputs: typing.Dict[str, type],
fixed: typing.Dict[str, Literal],
defaults: typing.Dict[str, Parameter],
) -> typing.List["click.Parameter"]:
params = []
project = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_PROJECT)
domain = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_DOMAIN)
r = get_and_save_remote_with_click_context(ctx, project, domain)
get_upload_url_fn = functools.partial(r.client.get_upload_signed_url, project=project, domain=domain)
flyte_ctx = context_manager.FlyteContextManager.current_context()

Check warning on line 811 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L806-L811

Added lines #L806 - L811 were not covered by tests
for name, var in inputs.items():
if fixed and name in fixed:
continue
required = True

Check warning on line 815 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L814-L815

Added lines #L814 - L815 were not covered by tests
if defaults and name in defaults:
required = False
params.append(

Check warning on line 818 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L817-L818

Added lines #L817 - L818 were not covered by tests
to_click_option(ctx, flyte_ctx, name, var, native_inputs[name], None, get_upload_url_fn, required)
)
return params

Check warning on line 821 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L821

Added line #L821 was not covered by tests

def get_params(self, ctx: click.Context) -> typing.List["click.Parameter"]:

Check warning on line 823 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L823

Added line #L823 was not covered by tests
if not self.params:
self.params = []
lp = self._fetch_launch_plan(ctx)

Check warning on line 826 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L825-L826

Added lines #L825 - L826 were not covered by tests
if lp.interface:
if lp.interface.inputs:
types = TypeEngine.guess_python_types(lp.interface.inputs)
self.params = self._get_params(

Check warning on line 830 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L829-L830

Added lines #L829 - L830 were not covered by tests
ctx, lp.interface.inputs, types, lp.fixed_inputs.literals, lp.default_inputs.parameters
)

return super().get_params(ctx)

Check warning on line 834 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L834

Added line #L834 was not covered by tests

def invoke(self, ctx: click.Context) -> typing.Any:

Check warning on line 836 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L836

Added line #L836 was not covered by tests
"""
Default or None values should be ignored. Only values that are provided by the user should be passed to the
remote execution.
"""
project = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_PROJECT)
domain = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_DOMAIN)
r = get_and_save_remote_with_click_context(ctx, project, domain)
lp = self._fetch_launch_plan(ctx)
run_remote(

Check warning on line 845 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L841-L845

Added lines #L841 - L845 were not covered by tests
ctx,
r,
lp,
project,
domain,
ctx.params,
ctx.obj[RUN_LEVEL_PARAMS_KEY],
type_hints=lp.python_interface.inputs if lp.python_interface else None,
)


class RemoteLaunchPlanGroup(click.RichGroup):

Check warning on line 857 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L857

Added line #L857 was not covered by tests
"""
click multicommand that retrieves launchplans from a remote flyte instance and executes them.
"""

COMMAND_NAME = "remote-launchplan"

Check warning on line 862 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L862

Added line #L862 was not covered by tests

def __init__(self):
super().__init__(

Check warning on line 865 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L864-L865

Added lines #L864 - L865 were not covered by tests
name="from-server",
help="Retrieve launchplans from a remote flyte instance and execute them.",
params=[
click.Option(
["--limit"], help="Limit the number of launchplans to retrieve.", default=10, show_default=True
)
],
)
self._lps = []

Check warning on line 874 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L874

Added line #L874 was not covered by tests

def list_commands(self, ctx):

Check warning on line 876 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L876

Added line #L876 was not covered by tests
if self._lps:
return self._lps

Check warning on line 878 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L878

Added line #L878 was not covered by tests
if ctx.obj is None:
return self._lps
project = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_PROJECT)
domain = ctx.obj[RUN_LEVEL_PARAMS_KEY].get(CTX_DOMAIN)
l = ctx.obj[RUN_LEVEL_PARAMS_KEY].get("limit")
r = get_and_save_remote_with_click_context(ctx, project, domain)
progress = Progress(transient=True)
task = progress.add_task(f"[cyan]Gathering [{l}] remote LaunchPlans...", total=None)

Check warning on line 886 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L880-L886

Added lines #L880 - L886 were not covered by tests
with progress:
progress.start_task(task)
lps = r.client.list_launch_plan_ids_paginated(project=project, domain=domain, limit=l)

Check warning on line 889 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L888-L889

Added lines #L888 - L889 were not covered by tests
self._lps = [l.name for l in lps[0]]
return self._lps

Check warning on line 891 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L891

Added line #L891 was not covered by tests

def get_command(self, ctx, name):
return DynamicLaunchPlanCommand(name=name, h="Execute a launchplan from remote.", lp_name=name)

Check warning on line 894 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L893-L894

Added lines #L893 - L894 were not covered by tests


class WorkflowCommand(click.RichGroup):
Expand All @@ -756,6 +914,8 @@
self._entities = None

def list_commands(self, ctx):
if self._entities:
return self._entities.all()

Check warning on line 918 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L918

Added line #L918 was not covered by tests
entities = get_entities_in_file(self._filename, self._should_delete)
self._entities = entities
return entities.all()
Expand Down Expand Up @@ -806,8 +966,11 @@
for input_name, input_type_val in entity.python_interface.inputs_with_defaults.items():
literal_var = entity.interface.inputs.get(input_name)
python_type, default_val = input_type_val
required = default_val is None

Check warning on line 969 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L969

Added line #L969 was not covered by tests
params.append(
to_click_option(ctx, flyte_ctx, input_name, literal_var, python_type, default_val, get_upload_url_fn)
to_click_option(
ctx, flyte_ctx, input_name, literal_var, python_type, default_val, get_upload_url_fn, required
)
)

entity_type = "Workflow" if is_workflow else "Task"
Expand All @@ -831,13 +994,21 @@
def __init__(self, *args, **kwargs):
params = get_workflow_command_base_params()
super().__init__(*args, params=params, **kwargs)
self._files = []

Check warning on line 997 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L997

Added line #L997 was not covered by tests

def list_commands(self, ctx):
return [str(p) for p in pathlib.Path(".").glob("*.py") if str(p) != "__init__.py"]
if self._files:
return self._files

Check warning on line 1001 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L1001

Added line #L1001 was not covered by tests
self._files = [str(p) for p in pathlib.Path(".").glob("*.py") if str(p) != "__init__.py"] + [
RemoteLaunchPlanGroup.COMMAND_NAME
]
return self._files

Check warning on line 1005 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L1005

Added line #L1005 was not covered by tests

def get_command(self, ctx, filename):
if ctx.obj:
ctx.obj[RUN_LEVEL_PARAMS_KEY] = ctx.params
if filename == RemoteLaunchPlanGroup.COMMAND_NAME:
return RemoteLaunchPlanGroup()

Check warning on line 1011 in flytekit/clis/sdk_in_container/run.py

View check run for this annotation

Codecov / codecov/patch

flytekit/clis/sdk_in_container/run.py#L1011

Added line #L1011 was not covered by tests
return WorkflowCommand(filename, name=filename, help=f"Run a [workflow|task] from {filename}")


Expand Down
5 changes: 5 additions & 0 deletions flytekit/core/type_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,11 @@
def to_python_value(self, ctx: FlyteContext, lv: Literal, expected_python_type: Type[T]) -> T:
return expected_python_type(lv.scalar.primitive.string_value) # type: ignore

def guess_python_type(self, literal_type: LiteralType) -> Type[enum.Enum]:
if literal_type.enum_type:
return enum.Enum("DynamicEnum", {f"{i}": i for i in literal_type.enum_type.values}) # type: ignore
raise ValueError(f"Enum transformer cannot reverse {literal_type}")

Check warning on line 1555 in flytekit/core/type_engine.py

View check run for this annotation

Codecov / codecov/patch

flytekit/core/type_engine.py#L1555

Added line #L1555 was not covered by tests


def convert_json_schema_to_python_class(schema: Dict[str, Any], schema_name: str) -> Type[Any]:
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/flytekit/unit/cli/pyflyte/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def build_image(self, img):
ImageBuildEngine.register("test", TestImageSpecBuilder())

@task
def a():
def tk():
...

mock_click_ctx = mock.MagicMock()
Expand Down Expand Up @@ -354,7 +354,7 @@ def check_image(*args, **kwargs):

mock_remote.register_script.side_effect = check_image

run_command(mock_click_ctx, a)()
run_command(mock_click_ctx, tk)()


def test_file_param():
Expand Down
3 changes: 3 additions & 0 deletions tests/flytekit/unit/core/test_type_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,9 @@
assert t.enum_type.values
assert t.enum_type.values == [c.value for c in Color]

g = TypeEngine.guess_python_type(t)

Check warning on line 891 in tests/flytekit/unit/core/test_type_engine.py

View check run for this annotation

Codecov / codecov/patch

tests/flytekit/unit/core/test_type_engine.py#L891

Added line #L891 was not covered by tests
assert [e.value for e in g] == [e.value for e in Color]

ctx = FlyteContextManager.current_context()
lv = TypeEngine.to_literal(ctx, Color.RED, Color, TypeEngine.to_literal_type(Color))
assert lv
Expand Down
Loading