flyte 0.2.0b1__py3-none-any.whl → 0.2.0b3__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.

Files changed (57) hide show
  1. flyte/__init__.py +3 -4
  2. flyte/_bin/runtime.py +21 -7
  3. flyte/_cache/cache.py +1 -2
  4. flyte/_cli/_common.py +26 -4
  5. flyte/_cli/_create.py +48 -0
  6. flyte/_cli/_deploy.py +4 -2
  7. flyte/_cli/_get.py +18 -7
  8. flyte/_cli/_run.py +1 -0
  9. flyte/_cli/main.py +11 -5
  10. flyte/_code_bundle/bundle.py +42 -11
  11. flyte/_context.py +1 -1
  12. flyte/_deploy.py +3 -1
  13. flyte/_group.py +1 -1
  14. flyte/_initialize.py +28 -247
  15. flyte/_internal/controllers/__init__.py +6 -6
  16. flyte/_internal/controllers/_local_controller.py +14 -5
  17. flyte/_internal/controllers/_trace.py +1 -1
  18. flyte/_internal/controllers/remote/__init__.py +27 -7
  19. flyte/_internal/controllers/remote/_action.py +1 -1
  20. flyte/_internal/controllers/remote/_client.py +5 -1
  21. flyte/_internal/controllers/remote/_controller.py +68 -24
  22. flyte/_internal/controllers/remote/_core.py +1 -1
  23. flyte/_internal/runtime/convert.py +34 -8
  24. flyte/_internal/runtime/entrypoints.py +1 -1
  25. flyte/_internal/runtime/io.py +3 -3
  26. flyte/_internal/runtime/task_serde.py +31 -1
  27. flyte/_internal/runtime/taskrunner.py +1 -1
  28. flyte/_internal/runtime/types_serde.py +1 -1
  29. flyte/_run.py +47 -28
  30. flyte/_task.py +2 -2
  31. flyte/_task_environment.py +1 -1
  32. flyte/_trace.py +5 -6
  33. flyte/_utils/__init__.py +2 -0
  34. flyte/_utils/async_cache.py +139 -0
  35. flyte/_version.py +2 -2
  36. flyte/config/__init__.py +26 -4
  37. flyte/config/_config.py +13 -4
  38. flyte/extras/_container.py +3 -3
  39. flyte/{_datastructures.py → models.py} +3 -2
  40. flyte/remote/_client/auth/_auth_utils.py +14 -0
  41. flyte/remote/_client/auth/_channel.py +28 -3
  42. flyte/remote/_client/auth/_token_client.py +3 -3
  43. flyte/remote/_client/controlplane.py +13 -13
  44. flyte/remote/_logs.py +1 -1
  45. flyte/remote/_run.py +4 -8
  46. flyte/remote/_task.py +2 -2
  47. flyte/storage/__init__.py +5 -0
  48. flyte/storage/_config.py +233 -0
  49. flyte/storage/_storage.py +23 -3
  50. flyte/types/_interface.py +1 -1
  51. flyte/types/_type_engine.py +1 -1
  52. {flyte-0.2.0b1.dist-info → flyte-0.2.0b3.dist-info}/METADATA +2 -2
  53. {flyte-0.2.0b1.dist-info → flyte-0.2.0b3.dist-info}/RECORD +56 -54
  54. flyte/_internal/controllers/pbhash.py +0 -39
  55. {flyte-0.2.0b1.dist-info → flyte-0.2.0b3.dist-info}/WHEEL +0 -0
  56. {flyte-0.2.0b1.dist-info → flyte-0.2.0b3.dist-info}/entry_points.txt +0 -0
  57. {flyte-0.2.0b1.dist-info → flyte-0.2.0b3.dist-info}/top_level.txt +0 -0
flyte/__init__.py CHANGED
@@ -17,15 +17,13 @@ async def my_task():
17
17
  """
18
18
 
19
19
  __all__ = [
20
- "ABFS",
21
- "GCS",
22
20
  "GPU",
23
- "S3",
24
21
  "TPU",
25
22
  "Cache",
26
23
  "CachePolicy",
27
24
  "CacheRequest",
28
25
  "Device",
26
+ "Environment",
29
27
  "Image",
30
28
  "Resources",
31
29
  "RetryStrategy",
@@ -48,9 +46,10 @@ __all__ = [
48
46
  from ._cache import Cache, CachePolicy, CacheRequest
49
47
  from ._context import ctx
50
48
  from ._deploy import deploy
49
+ from ._environment import Environment
51
50
  from ._group import group
52
51
  from ._image import Image
53
- from ._initialize import ABFS, GCS, S3, init
52
+ from ._initialize import init
54
53
  from ._resources import GPU, TPU, Device, Resources
55
54
  from ._retry import RetryStrategy
56
55
  from ._reusable_environment import ReusePolicy
flyte/_bin/runtime.py CHANGED
@@ -8,7 +8,7 @@ Refrain from importing any modules here. If you need to import any modules, do i
8
8
  import asyncio
9
9
  import os
10
10
  import sys
11
- from typing import List
11
+ from typing import Any, List
12
12
 
13
13
  import click
14
14
 
@@ -27,6 +27,9 @@ ORG_NAME = "_U_ORG_NAME"
27
27
  ENDPOINT_OVERRIDE = "_U_EP_OVERRIDE"
28
28
  RUN_OUTPUT_BASE_DIR = "_U_RUN_BASE"
29
29
 
30
+ # TODO: Remove this after proper auth is implemented
31
+ _UNION_EAGER_API_KEY_ENV_VAR = "_UNION_EAGER_API_KEY"
32
+
30
33
 
31
34
  @click.command("a0")
32
35
  @click.option("--inputs", "-i", required=True)
@@ -74,11 +77,11 @@ def main(
74
77
  sys.path.insert(0, ".")
75
78
 
76
79
  import flyte._utils as utils
77
- from flyte._datastructures import ActionID, Checkpoints, CodeBundle, RawDataPath
78
- from flyte._initialize import S3, initialize_in_cluster
80
+ from flyte._initialize import initialize_in_cluster
79
81
  from flyte._internal.controllers import create_controller
80
82
  from flyte._internal.imagebuild.image_builder import ImageCache
81
83
  from flyte._internal.runtime.entrypoints import load_and_run_task
84
+ from flyte.models import ActionID, Checkpoints, CodeBundle, RawDataPath
82
85
 
83
86
  assert org, "Org is required for now"
84
87
  assert project, "Project is required"
@@ -91,12 +94,23 @@ def main(
91
94
  if name.startswith("{{"):
92
95
  name = os.getenv("ACTION_NAME", "")
93
96
 
94
- ep = os.environ.get(ENDPOINT_OVERRIDE, "host.docker.internal:8090")
97
+ # Figure out how to connect
98
+ # This detection of api key is a hack for now.
99
+ controller_kwargs: dict[str, Any] = {"insecure": False}
100
+ if api_key := os.getenv(_UNION_EAGER_API_KEY_ENV_VAR):
101
+ from flyte._logging import logger
102
+
103
+ logger.warning(f"Using api key {api_key}")
104
+ controller_kwargs["api_key"] = api_key
105
+ else:
106
+ ep = os.environ.get(ENDPOINT_OVERRIDE, "host.docker.internal:8090")
107
+ controller_kwargs["endpoint"] = ep
108
+ if "localhost" in ep or "docker" in ep:
109
+ controller_kwargs["insecure"] = True
95
110
 
96
111
  bundle = CodeBundle(tgz=tgz, pkl=pkl, destination=dest, computed_version=version)
97
- # TODO configure storage correctly for cluster
98
- initialize_in_cluster(storage=S3.auto())
99
- controller = create_controller(ct="remote", endpoint=ep, insecure=True)
112
+ initialize_in_cluster()
113
+ controller = create_controller(ct="remote", **controller_kwargs)
100
114
 
101
115
  ic = ImageCache.from_transport(image_cache) if image_cache else None
102
116
 
flyte/_cache/cache.py CHANGED
@@ -14,10 +14,9 @@ from typing import (
14
14
  import rich.repr
15
15
  from typing_extensions import Literal, ParamSpec, TypeVar, get_args
16
16
 
17
- from flyte._datastructures import CodeBundle
18
-
19
17
  # if TYPE_CHECKING:
20
18
  from flyte._image import Image
19
+ from flyte.models import CodeBundle
21
20
 
22
21
  P = ParamSpec("P")
23
22
  FuncOut = TypeVar("FuncOut")
flyte/_cli/_common.py CHANGED
@@ -11,6 +11,7 @@ from types import MappingProxyType, ModuleType
11
11
  from typing import Any, Dict, Iterable, List, Optional
12
12
 
13
13
  import rich.box
14
+ import rich.repr
14
15
  import rich_click as click
15
16
  from rich.console import Console
16
17
  from rich.panel import Panel
@@ -28,7 +29,7 @@ PROJECT_OPTION = click.Option(
28
29
  param_decls=["-p", "--project"],
29
30
  required=False,
30
31
  type=str,
31
- default="default",
32
+ default=None,
32
33
  help="Project to operate on",
33
34
  show_default=True,
34
35
  )
@@ -37,7 +38,7 @@ DOMAIN_OPTION = click.Option(
37
38
  param_decls=["-d", "--domain"],
38
39
  required=False,
39
40
  type=str,
40
- default="development",
41
+ default=None,
41
42
  help="Domain to operate on",
42
43
  show_default=True,
43
44
  )
@@ -63,6 +64,7 @@ def _common_options() -> List[click.Option]:
63
64
  # This is global state for the CLI, it is manipulated by the main command
64
65
 
65
66
 
67
+ @rich.repr.auto
66
68
  @dataclass(frozen=True)
67
69
  class CLIConfig:
68
70
  """
@@ -84,13 +86,17 @@ class CLIConfig:
84
86
  def init(self, project: str | None = None, domain: str | None = None):
85
87
  import flyte
86
88
 
89
+ if self.config and self.config.task:
90
+ # If the config is already set, we can use it to initialize flyte
91
+ project = project or self.config.task.project
92
+ domain = domain or self.config.task.domain
93
+
87
94
  flyte.init(
88
95
  endpoint=self.endpoint,
89
96
  insecure=self.insecure,
90
97
  org=self.org_override,
91
98
  project=project,
92
99
  domain=domain,
93
- log_level=self.log_level,
94
100
  config=self.config,
95
101
  )
96
102
 
@@ -113,12 +119,26 @@ class InvokeBaseMixin:
113
119
  raise click.ClickException(f"Requested object NOT FOUND. Please check your input. Error: {e.details()}")
114
120
  if e.code() == grpc.StatusCode.ALREADY_EXISTS:
115
121
  raise click.ClickException("Resource already exists.")
122
+ if e.code() == grpc.StatusCode.INTERNAL:
123
+ raise click.ClickException(f"Internal server error: {e.details()}")
124
+ if e.code() == grpc.StatusCode.UNAVAILABLE:
125
+ raise click.ClickException(
126
+ f"Service is currently unavailable. Please try again later. Error: {e.details()}"
127
+ )
128
+ if e.code() == grpc.StatusCode.PERMISSION_DENIED:
129
+ raise click.ClickException(f"Permission denied. Please check your access rights. Error: {e.details()}")
130
+ if e.code() == grpc.StatusCode.INVALID_ARGUMENT:
131
+ raise click.ClickException(f"Invalid argument provided. Please check your input. Error: {e.details()}")
116
132
  raise click.ClickException(f"RPC error invoking command: {e!s}") from e
117
133
  except flyte.errors.InitializationError:
118
134
  raise click.ClickException("Initialize the CLI with a remote configuration. For example, pass --endpoint")
119
135
  except click.exceptions.Exit as e:
120
136
  # This is a normal exit, do nothing
121
137
  raise e
138
+ except click.exceptions.NoArgsIsHelpError:
139
+ # Do not raise an error if no arguments are passed, just show the help message.
140
+ # https://github.com/pallets/click/pull/1489
141
+ return None
122
142
  except Exception as e:
123
143
  if ctx.obj and ctx.obj.log_level and ctx.obj.log_level <= logging.DEBUG:
124
144
  # If the user has requested verbose output, print the full traceback
@@ -185,8 +205,10 @@ class ObjectsPerFileGroup(GroupBase):
185
205
  Group that creates a command for each object in a python file.
186
206
  """
187
207
 
188
- def __init__(self, filename: Path, *args, **kwargs):
208
+ def __init__(self, filename: Path | None = None, *args, **kwargs):
189
209
  super().__init__(*args, **kwargs)
210
+ if filename is None:
211
+ raise ValueError("filename must be provided")
190
212
  if not filename.exists():
191
213
  raise click.ClickException(f"{filename} does not exists")
192
214
  self.filename = filename
flyte/_cli/_create.py CHANGED
@@ -1,3 +1,4 @@
1
+ from pathlib import Path
1
2
  from typing import get_args
2
3
 
3
4
  import rich_click as click
@@ -40,3 +41,50 @@ def secret(
40
41
  with open(from_file, "rb") as f:
41
42
  value = f.read()
42
43
  Secret.create(name=name, value=value, type=type)
44
+
45
+
46
+ @create.command(cls=common.CommandBase)
47
+ @click.option("--endpoint", type=str, help="Endpoint of the Flyte backend.")
48
+ @click.option("--insecure", is_flag=True, help="Use insecure connection to the Flyte backend.")
49
+ @click.option(
50
+ "--org",
51
+ type=str,
52
+ required=False,
53
+ help="Organization to use, this will override the organization in the config file.",
54
+ )
55
+ @click.option(
56
+ "-o",
57
+ "--output",
58
+ type=click.Path(),
59
+ default=Path.cwd(),
60
+ help="Path to the output dir where the config will be saved, defaults to current directory.",
61
+ )
62
+ def config(
63
+ output: Path,
64
+ endpoint: str | None = None,
65
+ insecure: bool = False,
66
+ org: str | None = None,
67
+ project: str | None = None,
68
+ domain: str | None = None,
69
+ ):
70
+ """
71
+ Create a new config file.
72
+ """
73
+ import yaml
74
+
75
+ output_file = output / "config.yaml"
76
+ with open(output_file, "w") as f:
77
+ d = {
78
+ "admin": {
79
+ "endpoint": endpoint,
80
+ "insecure": insecure,
81
+ },
82
+ "task": {
83
+ "org": org,
84
+ "project": project,
85
+ "domain": domain,
86
+ },
87
+ }
88
+ yaml.dump(d, f)
89
+
90
+ click.echo(f"Config file created at {output_file}")
flyte/_cli/_deploy.py CHANGED
@@ -91,15 +91,17 @@ class EnvPerFileGroup(common.ObjectsPerFileGroup):
91
91
  """
92
92
 
93
93
  def __init__(self, filename: Path, deploy_args: DeployArguments, *args, **kwargs):
94
+ args = (filename, *args)
94
95
  super().__init__(*args, **kwargs)
95
96
  self.deploy_args = deploy_args
96
97
 
97
98
  def _filter_objects(self, module: ModuleType) -> Dict[str, Any]:
98
- return {k: v for k, v in module.__dict__.items() if isinstance(v, flyte.TaskEnvironment)}
99
+ return {k: v for k, v in module.__dict__.items() if isinstance(v, flyte.Environment)}
99
100
 
100
101
  def _get_command_for_obj(self, ctx: click.Context, obj_name: str, obj: Any) -> click.Command:
101
- obj = cast(flyte.TaskEnvironment, obj)
102
+ obj = cast(flyte.Environment, obj)
102
103
  return DeployEnvCommand(
104
+ name=obj_name,
103
105
  obj_name=obj_name,
104
106
  obj=obj,
105
107
  help=obj.description,
flyte/_cli/_get.py CHANGED
@@ -112,17 +112,17 @@ def action(
112
112
 
113
113
 
114
114
  @get.command(cls=common.CommandBase)
115
- @click.argument("run_name", type=str, required=False)
115
+ @click.argument("run_name", type=str, required=True)
116
116
  @click.argument("action_name", type=str, required=False)
117
- @click.option("--lines", "-l", type=int, default=30, help="Number of lines to show")
117
+ @click.option("--lines", "-l", type=int, default=30, help="Number of lines to show, only useful for --pretty")
118
118
  @click.option("--show-ts", is_flag=True, help="Show timestamps")
119
119
  @click.option(
120
- "--follow",
121
- "-f",
120
+ "--pretty",
122
121
  is_flag=True,
123
122
  default=False,
124
- help="Follow the logs (like tail -f), will open a panel with logs scrolling.",
123
+ help="Show logs in a auto scrolling box, where number of lines is limited to `--lines`",
125
124
  )
125
+ @click.option("--attempt", "-a", type=int, default=None, help="Attempt number to show logs for")
126
126
  @click.pass_obj
127
127
  def logs(
128
128
  cfg: common.CLIConfig,
@@ -132,7 +132,8 @@ def logs(
132
132
  domain: str | None = None,
133
133
  lines: int = 30,
134
134
  show_ts: bool = False,
135
- follow: bool = True,
135
+ pretty: bool = True,
136
+ attempt: int | None = None,
136
137
  ):
137
138
  """
138
139
  Get the current run.
@@ -142,7 +143,7 @@ def logs(
142
143
  cfg.init(project=project, domain=domain)
143
144
 
144
145
  async def _run_log_view(_obj):
145
- task = asyncio.create_task(_obj.show_logs(max_lines=lines, show_ts=show_ts, raw=not follow))
146
+ task = asyncio.create_task(_obj.show_logs(max_lines=lines, show_ts=show_ts, raw=not pretty, attempt=attempt))
146
147
  try:
147
148
  await task
148
149
  except KeyboardInterrupt:
@@ -233,3 +234,13 @@ def io(
233
234
  f"[green bold]Inputs[/green bold]\n{inputs}\n\n[blue bold]Outputs[/blue bold]\n{outputs}",
234
235
  )
235
236
  )
237
+
238
+
239
+ @get.command(cls=click.RichCommand)
240
+ @click.pass_obj
241
+ def config(cfg: common.CLIConfig):
242
+ """
243
+ Shows the automatically detected configuration to connect with remote Flyte services.
244
+ """
245
+ console = Console()
246
+ console.print(cfg)
flyte/_cli/_run.py CHANGED
@@ -73,6 +73,7 @@ class RunTaskCommand(click.Command):
73
73
 
74
74
  def invoke(self, ctx: Context):
75
75
  obj: CLIConfig = ctx.obj or CLIConfig()
76
+ assert obj.endpoint, "CLI Config should have an endpoint"
76
77
  obj.init(self.run_args.project, self.run_args.domain)
77
78
 
78
79
  r = flyte.with_runcontext(
flyte/_cli/main.py CHANGED
@@ -1,5 +1,7 @@
1
1
  import rich_click as click
2
2
 
3
+ from flyte._logging import initialize_logger, logger
4
+
3
5
  from ..config import Config
4
6
  from ._common import CLIConfig
5
7
  from ._create import create
@@ -41,7 +43,7 @@ def _verbosity_to_loglevel(verbosity: int) -> int | None:
41
43
  required=False,
42
44
  help="insecure",
43
45
  type=bool,
44
- default=False,
46
+ default=None,
45
47
  )
46
48
  @click.option(
47
49
  "-v",
@@ -53,10 +55,10 @@ def _verbosity_to_loglevel(verbosity: int) -> int | None:
53
55
  type=int,
54
56
  )
55
57
  @click.option(
56
- "--org-override",
58
+ "--org",
57
59
  type=str,
58
60
  required=False,
59
- help="Override for org",
61
+ help="Organization to use",
60
62
  )
61
63
  @click.option(
62
64
  "-c",
@@ -73,23 +75,27 @@ def main(
73
75
  endpoint: str | None,
74
76
  insecure: bool,
75
77
  verbose: int,
76
- org_override: str | None,
78
+ org: str | None,
77
79
  config_file: str | None,
78
80
  ):
79
81
  """
80
82
  v2 cli. Root command, please use one of the subcommands.
81
83
  """
82
84
  log_level = _verbosity_to_loglevel(verbose)
85
+ if log_level is not None:
86
+ initialize_logger(log_level)
83
87
 
84
88
  config = Config.auto(config_file=config_file)
89
+ logger.debug(f"Using config file discovered at location {config.source}")
85
90
 
86
91
  ctx.obj = CLIConfig(
87
92
  log_level=log_level,
88
93
  endpoint=endpoint or config.platform.endpoint,
89
94
  insecure=insecure or config.platform.insecure,
90
- org_override=org_override or config.task.org,
95
+ org_override=org or config.task.org,
91
96
  config=config,
92
97
  )
98
+ logger.debug(f"Final materialized Cli config: {ctx.obj}")
93
99
 
94
100
 
95
101
  main.add_command(run)
@@ -5,13 +5,13 @@ import os
5
5
  import pathlib
6
6
  import tempfile
7
7
  from pathlib import Path
8
- from typing import Type
8
+ from typing import ClassVar, Type
9
9
 
10
10
  from flyteidl.core.tasks_pb2 import TaskTemplate
11
11
 
12
- import flyte.storage as storage
13
- from flyte._datastructures import CodeBundle
14
12
  from flyte._logging import log, logger
13
+ from flyte._utils import AsyncLRUCache
14
+ from flyte.models import CodeBundle
15
15
 
16
16
  from ._ignore import GitIgnore, Ignore, StandardIgnore
17
17
  from ._packaging import create_bundle, list_files_to_bundle, print_ls_tree
@@ -21,10 +21,34 @@ _pickled_file_extension = ".pkl.gz"
21
21
  _tar_file_extension = ".tar.gz"
22
22
 
23
23
 
24
+ class _PklCache:
25
+ _pkl_cache: ClassVar[AsyncLRUCache[str, str]] = AsyncLRUCache[str, str](maxsize=100)
26
+
27
+ @classmethod
28
+ async def put(cls, digest: str, upload_to_path: str, from_path: pathlib.Path) -> str:
29
+ """
30
+ Get the pickled code bundle from the cache or build it if not present.
31
+
32
+ :param digest: The hash digest of the task template.
33
+ :param upload_to_path: The path to upload the pickled file to.
34
+ :param from_path: The path to read the pickled file from.
35
+ :return: CodeBundle object containing the pickled file path and the computed version.
36
+ """
37
+ import flyte.storage as storage
38
+
39
+ async def put_data() -> str:
40
+ return await storage.put(str(from_path), to_path=str(upload_to_path))
41
+
42
+ return await cls._pkl_cache.get(
43
+ key=digest,
44
+ value_func=put_data,
45
+ )
46
+
47
+
24
48
  async def build_pkl_bundle(
25
49
  o: TaskTemplate,
26
50
  upload_to_controlplane: bool = True,
27
- upload_from_dataplane_path: str | None = None,
51
+ upload_from_dataplane_base_path: str | None = None,
28
52
  copy_bundle_to: pathlib.Path | None = None,
29
53
  ) -> CodeBundle:
30
54
  """
@@ -36,16 +60,14 @@ async def build_pkl_bundle(
36
60
 
37
61
  :param o: Object to be pickled. This is the task template.
38
62
  :param upload_to_controlplane: Whether to upload the pickled file to the control plane or not
39
- :param upload_from_dataplane_path: If we are on the dataplane, this is the path where the
63
+ :param upload_from_dataplane_base_path: If we are on the dataplane, this is the path where the
40
64
  pickled file should be uploaded to. upload_to_controlplane has to be False in this case.
41
65
  :param copy_bundle_to: If set, the bundle will be copied to this path. This is used for testing purposes.
42
66
  :return: CodeBundle object containing the pickled file path and the computed version.
43
67
  """
44
68
  import cloudpickle
45
69
 
46
- import flyte.storage as storage
47
-
48
- if upload_to_controlplane and upload_from_dataplane_path:
70
+ if upload_to_controlplane and upload_from_dataplane_base_path:
49
71
  raise ValueError("Cannot upload to control plane and upload from dataplane path at the same time.")
50
72
 
51
73
  logger.debug("Building pickled code bundle.")
@@ -61,10 +83,17 @@ async def build_pkl_bundle(
61
83
  hash_digest, remote_path = await upload_file(dest)
62
84
  return CodeBundle(pkl=remote_path, computed_version=hash_digest)
63
85
 
64
- elif upload_from_dataplane_path:
65
- logger.debug(f"Uploading pickled code bundle to dataplane path {upload_from_dataplane_path}.")
86
+ elif upload_from_dataplane_base_path:
87
+ from flyte._internal.runtime import io
88
+
66
89
  _, str_digest, _ = hash_file(file_path=dest)
67
- final_path = await storage.put(str(dest), upload_from_dataplane_path)
90
+ upload_path = io.pkl_path(upload_from_dataplane_base_path, str_digest)
91
+ logger.debug(f"Uploading pickled code bundle to dataplane path {upload_path}.")
92
+ final_path = await _PklCache.put(
93
+ digest=str_digest,
94
+ upload_to_path=upload_path,
95
+ from_path=dest,
96
+ )
68
97
  return CodeBundle(pkl=final_path, computed_version=str_digest)
69
98
 
70
99
  else:
@@ -138,6 +167,8 @@ async def download_bundle(bundle: CodeBundle) -> pathlib.Path:
138
167
 
139
168
  :return: The path to the downloaded code bundle.
140
169
  """
170
+ import flyte.storage as storage
171
+
141
172
  dest = pathlib.Path(bundle.destination)
142
173
  if not dest.is_dir():
143
174
  raise ValueError(f"Destination path should be a directory, found {dest}, {dest.stat()}")
flyte/_context.py CHANGED
@@ -4,7 +4,7 @@ import contextvars
4
4
  from dataclasses import dataclass, replace
5
5
  from typing import TYPE_CHECKING, Awaitable, Callable, Optional, ParamSpec, TypeVar
6
6
 
7
- from flyte._datastructures import GroupData, RawDataPath, TaskContext
7
+ from flyte.models import GroupData, RawDataPath, TaskContext
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from flyte.report import Report
flyte/_deploy.py CHANGED
@@ -6,8 +6,9 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
6
6
 
7
7
  import rich.repr
8
8
 
9
+ from flyte.models import SerializationContext
10
+
9
11
  from ._api_commons import syncer
10
- from ._datastructures import SerializationContext
11
12
  from ._environment import Environment
12
13
  from ._image import Image
13
14
  from ._initialize import get_client, get_common_config, requires_client, requires_initialization
@@ -141,6 +142,7 @@ async def apply(deployment: DeploymentPlan, copy_style: CopyFiles, dryrun: bool
141
142
  tasks = []
142
143
  for env_name, env in deployment.envs.items():
143
144
  logger.info(f"Deploying environment {env_name}")
145
+ # TODO Make this pluggable based on the environment type
144
146
  if isinstance(env, TaskEnvironment):
145
147
  for task in env.tasks.values():
146
148
  tasks.append(_deploy_task(task, dryrun=dryrun, serialization_context=sc))
flyte/_group.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from contextlib import contextmanager
2
2
 
3
3
  from ._context import internal_ctx
4
- from ._datastructures import GroupData
4
+ from .models import GroupData
5
5
 
6
6
 
7
7
  @contextmanager