flyte 0.2.0b5__py3-none-any.whl → 0.2.0b7__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 CHANGED
@@ -38,6 +38,7 @@ __all__ = [
38
38
  "deploy",
39
39
  "group",
40
40
  "init",
41
+ "init_auto_from_config",
41
42
  "run",
42
43
  "trace",
43
44
  "with_runcontext",
@@ -49,7 +50,7 @@ from ._deploy import deploy
49
50
  from ._environment import Environment
50
51
  from ._group import group
51
52
  from ._image import Image
52
- from ._initialize import init
53
+ from ._initialize import init, init_auto_from_config
53
54
  from ._resources import GPU, TPU, Device, Resources
54
55
  from ._retry import RetryStrategy
55
56
  from ._reusable_environment import ReusePolicy
@@ -14,7 +14,6 @@ import tempfile
14
14
  import typing
15
15
  from datetime import datetime, timezone
16
16
  from functools import lru_cache
17
- from pathlib import Path
18
17
  from types import ModuleType
19
18
  from typing import List, Literal, Optional, Tuple, Union
20
19
 
@@ -322,18 +321,3 @@ def hash_file(file_path: typing.Union[os.PathLike, str]) -> Tuple[bytes, str, in
322
321
  size += len(chunk)
323
322
 
324
323
  return h.digest(), h.hexdigest(), size
325
-
326
-
327
- def _find_project_root(source_path) -> str:
328
- """
329
- Find the root of the project.
330
- The root of the project is considered to be the first ancestor from source_path that does
331
- not contain a __init__.py file.
332
-
333
- N.B.: This assumption only holds for regular packages (as opposed to namespace packages)
334
- """
335
- # Start from the directory right above source_path
336
- path = Path(source_path).parent.resolve()
337
- while os.path.exists(os.path.join(path, "__init__.py")):
338
- path = path.parent
339
- return str(path)
@@ -146,7 +146,7 @@ async def build_code_bundle(
146
146
  logger.info(f"Code bundle created at {bundle_path}, size: {tar_size} MB, archive size: {archive_size} MB")
147
147
  if not dryrun:
148
148
  hash_digest, remote_path = await upload_file(bundle_path)
149
- logger.info(f"Code bundle uploaded to {remote_path}")
149
+ logger.debug(f"Code bundle uploaded to {remote_path}")
150
150
  else:
151
151
  remote_path = "na"
152
152
  if copy_bundle_to:
flyte/_initialize.py CHANGED
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Callable, List, Literal, Optional, TypeVar
10
10
  from flyte.errors import InitializationError
11
11
  from flyte.syncify import syncify
12
12
 
13
- from ._logging import initialize_logger
13
+ from ._logging import initialize_logger, logger
14
14
  from ._tools import ipython_check
15
15
 
16
16
  if TYPE_CHECKING:
@@ -130,7 +130,6 @@ async def init(
130
130
  rpc_retries: int = 3,
131
131
  http_proxy_url: str | None = None,
132
132
  storage: Storage | None = None,
133
- config: Config | None = None,
134
133
  ) -> None:
135
134
  """
136
135
  Initialize the Flyte system with the given configuration. This method should be called before any other Flyte
@@ -179,42 +178,72 @@ async def init(
179
178
  global _init_config # noqa: PLW0603
180
179
 
181
180
  with _init_lock:
182
- if config is None:
183
- import flyte.config as _f_cfg
184
-
185
- config = _f_cfg.Config()
186
- platform_cfg = config.platform
187
- task_cfg = config.task
188
181
  client = None
189
- if endpoint or platform_cfg.endpoint or api_key:
182
+ if endpoint or api_key:
190
183
  client = await _initialize_client(
191
184
  api_key=api_key,
192
- auth_type=auth_type or platform_cfg.auth_mode,
193
- endpoint=endpoint or platform_cfg.endpoint,
185
+ auth_type=auth_type,
186
+ endpoint=endpoint,
194
187
  headless=headless,
195
- insecure=insecure or platform_cfg.insecure,
196
- insecure_skip_verify=insecure_skip_verify or platform_cfg.insecure_skip_verify,
197
- ca_cert_file_path=ca_cert_file_path or platform_cfg.ca_cert_file_path,
198
- command=command or platform_cfg.command,
199
- proxy_command=proxy_command or platform_cfg.proxy_command,
200
- client_id=client_id or platform_cfg.client_id,
201
- client_credentials_secret=client_credentials_secret or platform_cfg.client_credentials_secret,
188
+ insecure=insecure,
189
+ insecure_skip_verify=insecure_skip_verify,
190
+ ca_cert_file_path=ca_cert_file_path,
191
+ command=command,
192
+ proxy_command=proxy_command,
193
+ client_id=client_id,
194
+ client_credentials_secret=client_credentials_secret,
202
195
  client_config=auth_client_config,
203
- rpc_retries=rpc_retries or platform_cfg.rpc_retries,
204
- http_proxy_url=http_proxy_url or platform_cfg.http_proxy_url,
196
+ rpc_retries=rpc_retries,
197
+ http_proxy_url=http_proxy_url,
205
198
  )
206
199
 
207
200
  root_dir = root_dir or get_cwd_editable_install() or Path.cwd()
208
201
  _init_config = _InitConfig(
209
202
  root_dir=root_dir,
210
- project=project or task_cfg.project,
211
- domain=domain or task_cfg.domain,
203
+ project=project,
204
+ domain=domain,
212
205
  client=client,
213
206
  storage=storage,
214
- org=org or task_cfg.org,
207
+ org=org,
215
208
  )
216
209
 
217
210
 
211
+ @syncify
212
+ async def init_auto_from_config(path_or_config: str | Config | None = None) -> None:
213
+ """
214
+ Initialize the Flyte system using a configuration file or Config object. This method should be called before any
215
+ other Flyte remote API methods are called. Thread-safe implementation.
216
+
217
+ :param path_or_config: Path to the configuration file or Config object
218
+ :return: None
219
+ """
220
+ import flyte.config as config
221
+
222
+ cfg: config.Config
223
+ if path_or_config is None or isinstance(path_or_config, str):
224
+ # If a string is passed, treat it as a path to the config file
225
+ cfg = config.auto(path_or_config)
226
+ else:
227
+ # If a Config object is passed, use it directly
228
+ cfg = path_or_config
229
+
230
+ logger.debug(f"Flyte config initialized as {cfg}")
231
+ await init.aio(
232
+ org=cfg.task.org,
233
+ project=cfg.task.project,
234
+ domain=cfg.task.domain,
235
+ endpoint=cfg.platform.endpoint,
236
+ insecure=cfg.platform.insecure,
237
+ insecure_skip_verify=cfg.platform.insecure_skip_verify,
238
+ ca_cert_file_path=cfg.platform.ca_cert_file_path,
239
+ auth_type=cfg.platform.auth_mode,
240
+ command=cfg.platform.command,
241
+ proxy_command=cfg.platform.proxy_command,
242
+ client_id=cfg.platform.client_id,
243
+ client_credentials_secret=cfg.platform.client_credentials_secret,
244
+ )
245
+
246
+
218
247
  def _get_init_config() -> Optional[_InitConfig]:
219
248
  """
220
249
  Get the current initialization configuration. Thread-safe implementation.
@@ -32,7 +32,7 @@ class Controller:
32
32
  max_system_retries: int = 5,
33
33
  resource_log_interval_sec: float = 10.0,
34
34
  min_backoff_on_err_sec: float = 0.1,
35
- thread_wait_timeout_sec: float = 0.5,
35
+ thread_wait_timeout_sec: float = 5.0,
36
36
  enqueue_timeout_sec: float = 5.0,
37
37
  ):
38
38
  """
flyte/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.0b5'
21
- __version_tuple__ = version_tuple = (0, 2, 0, 'b5')
20
+ __version__ = version = '0.2.0b7'
21
+ __version_tuple__ = version_tuple = (0, 2, 0, 'b7')
flyte/cli/_common.py CHANGED
@@ -19,11 +19,13 @@ from rich.table import Table
19
19
  from rich.traceback import Traceback
20
20
 
21
21
  import flyte.errors
22
+ from flyte._logging import logger
22
23
  from flyte.config import Config
23
24
 
24
25
  PREFERRED_BORDER_COLOR = "dim cyan"
25
26
  PREFERRED_ACCENT_COLOR = "bold #FFD700"
26
27
  HEADER_STYLE = f"{PREFERRED_ACCENT_COLOR} on black"
28
+ PANELS = False
27
29
 
28
30
  PROJECT_OPTION = click.Option(
29
31
  param_decls=["-p", "--project"],
@@ -71,11 +73,11 @@ class CLIConfig:
71
73
  This is the global state for the CLI. It is manipulated by the main command.
72
74
  """
73
75
 
76
+ config: Config
74
77
  log_level: int | None = logging.ERROR
75
78
  endpoint: str | None = None
76
79
  insecure: bool = False
77
80
  org_override: str | None = None
78
- config: Config | None = None
79
81
 
80
82
  def replace(self, **kwargs) -> CLIConfig:
81
83
  """
@@ -84,22 +86,26 @@ class CLIConfig:
84
86
  return replace(self, **kwargs)
85
87
 
86
88
  def init(self, project: str | None = None, domain: str | None = None):
87
- import flyte
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
-
94
- flyte.init(
95
- endpoint=self.endpoint,
96
- insecure=self.insecure,
97
- org=self.org_override,
98
- project=project,
99
- domain=domain,
100
- config=self.config,
89
+ from flyte.config._config import TaskConfig
90
+
91
+ task_cfg = TaskConfig(
92
+ org=self.org_override or self.config.task.org,
93
+ project=project or self.config.task.project,
94
+ domain=domain or self.config.task.domain,
101
95
  )
102
96
 
97
+ kwargs: Dict[str, Any] = {}
98
+ if self.endpoint:
99
+ kwargs["endpoint"] = self.endpoint
100
+ if self.insecure is not None:
101
+ kwargs["insecure"] = self.insecure
102
+ platform_cfg = self.config.platform.replace(**kwargs)
103
+
104
+ updated_config = self.config.with_params(platform_cfg, task_cfg)
105
+
106
+ logger.debug(f"Initializing CLI with config: {updated_config}")
107
+ flyte.init_auto_from_config(updated_config)
108
+
103
109
 
104
110
  class InvokeBaseMixin:
105
111
  """
@@ -316,6 +322,8 @@ def get_panel(title: str, renderable: Any) -> Panel:
316
322
  """
317
323
  Get a panel from a list of values.
318
324
  """
325
+ if not PANELS:
326
+ return renderable
319
327
  return Panel.fit(
320
328
  renderable,
321
329
  title=f"[{PREFERRED_ACCENT_COLOR}]{title}[/{PREFERRED_ACCENT_COLOR}]",
flyte/cli/_run.py CHANGED
@@ -12,8 +12,6 @@ from click import Context, Parameter
12
12
  from rich.console import Console
13
13
  from typing_extensions import get_args
14
14
 
15
- import flyte
16
-
17
15
  from .._code_bundle._utils import CopyFiles
18
16
  from .._task import TaskTemplate
19
17
  from ..remote import Run
@@ -95,11 +93,19 @@ class RunTaskCommand(click.Command):
95
93
  super().__init__(obj_name, *args, **kwargs)
96
94
 
97
95
  def invoke(self, ctx: Context):
98
- obj: CLIConfig = ctx.obj or CLIConfig()
99
- assert obj.endpoint, "CLI Config should have an endpoint"
96
+ obj: CLIConfig = ctx.obj
97
+ if obj is None:
98
+ import flyte.config
99
+
100
+ obj = CLIConfig(flyte.config.auto())
101
+
102
+ if not self.run_args.local:
103
+ assert obj.endpoint, "CLI Config should have an endpoint"
100
104
  obj.init(self.run_args.project, self.run_args.domain)
101
105
 
102
106
  async def _run():
107
+ import flyte
108
+
103
109
  r = flyte.with_runcontext(
104
110
  copy_style=self.run_args.copy_style,
105
111
  version=self.run_args.copy_style,
@@ -112,8 +118,8 @@ class RunTaskCommand(click.Command):
112
118
  common.get_panel(
113
119
  "Run",
114
120
  f"[green bold]Created Run: {r.name} [/green bold] "
115
- f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n\n"
116
- f"[blue bold]{r.url}[/blue bold]",
121
+ f"(Project: {r.action.action_id.run.project}, Domain: {r.action.action_id.run.domain})\n"
122
+ f"➡️ [blue bold]{r.url}[/blue bold]",
117
123
  )
118
124
  )
119
125
  if self.run_args.follow:
flyte/cli/main.py CHANGED
@@ -2,7 +2,6 @@ import rich_click as click
2
2
 
3
3
  from flyte._logging import initialize_logger, logger
4
4
 
5
- from ..config import Config
6
5
  from ._abort import abort
7
6
  from ._common import CLIConfig
8
7
  from ._create import create
@@ -39,12 +38,13 @@ def _verbosity_to_loglevel(verbosity: int) -> int | None:
39
38
  help="The endpoint to connect to, this will override any config and simply used pkce to connect.",
40
39
  )
41
40
  @click.option(
42
- "--insecure",
41
+ "--insecure/--secure",
43
42
  is_flag=True,
44
43
  required=False,
45
- help="insecure",
44
+ help="Use insecure connection to the endpoint. If secure is specified, the CLI will use TLS",
46
45
  type=bool,
47
46
  default=None,
47
+ show_default=True,
48
48
  )
49
49
  @click.option(
50
50
  "-v",
@@ -89,19 +89,25 @@ def main(
89
89
  The flyte cli follows a simple verb based structure, where the top-level commands are verbs that describe the action
90
90
  to be taken, and the subcommands are nouns that describe the object of the action.
91
91
  """
92
+ import flyte.config as config
93
+
92
94
  log_level = _verbosity_to_loglevel(verbose)
93
95
  if log_level is not None:
94
96
  initialize_logger(log_level)
95
97
 
96
- config = Config.auto(config_file=config_file)
97
- logger.debug(f"Using config file discovered at location {config.source}")
98
+ cfg = config.auto(config_file=config_file)
99
+ logger.debug(f"Using config file discovered at location {cfg.source}")
100
+
101
+ final_insecure = cfg.platform.insecure
102
+ if insecure is not None:
103
+ final_insecure = insecure
98
104
 
99
105
  ctx.obj = CLIConfig(
100
106
  log_level=log_level,
101
- endpoint=endpoint or config.platform.endpoint,
102
- insecure=insecure or config.platform.insecure,
103
- org_override=org or config.task.org,
104
- config=config,
107
+ endpoint=endpoint or cfg.platform.endpoint,
108
+ insecure=final_insecure,
109
+ org_override=org or cfg.task.org,
110
+ config=cfg,
105
111
  )
106
112
  logger.debug(f"Final materialized Cli config: {ctx.obj}")
107
113
 
flyte/config/__init__.py CHANGED
@@ -1,190 +1,3 @@
1
- from __future__ import annotations
1
+ from flyte.config._config import Config, auto, get_config_file, set_if_exists
2
2
 
3
- import os
4
- import pathlib
5
- import typing
6
- from dataclasses import dataclass, field
7
- from typing import TYPE_CHECKING
8
-
9
- import rich.repr
10
-
11
- from flyte._logging import logger
12
- from flyte.config import _internal
13
- from flyte.config._config import ConfigFile, get_config_file, read_file_if_exists
14
-
15
- _all__ = ["ConfigFile", "PlatformConfig", "TaskConfig"]
16
-
17
- if TYPE_CHECKING:
18
- from flyte.remote._client.auth import AuthType
19
-
20
-
21
- @rich.repr.auto
22
- @dataclass(init=True, repr=True, eq=True, frozen=True)
23
- class PlatformConfig(object):
24
- """
25
- This object contains the settings to talk to a Flyte backend (the DNS location of your Admin server basically).
26
-
27
- :param endpoint: DNS for Flyte backend
28
- :param insecure: Whether or not to use SSL
29
- :param insecure_skip_verify: Whether to skip SSL certificate verification
30
- :param console_endpoint: endpoint for console if different from Flyte backend
31
- :param command: This command is executed to return a token using an external process
32
- :param proxy_command: This command is executed to return a token for proxy authorization using an external process
33
- :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
34
- More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
35
- :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
36
- allow the Flyte engine to read the password directly from the environment variable. Note that this is
37
- less secure! Please only use this if mounting the secret as a file is impossible
38
- :param scopes: List of scopes to request. This is only applicable to the client credentials flow
39
- :param auth_mode: The OAuth mode to use. Defaults to pkce flow
40
- :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
41
- :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
42
- """
43
-
44
- endpoint: str | None = None
45
- insecure: bool = False
46
- insecure_skip_verify: bool = False
47
- ca_cert_file_path: typing.Optional[str] = None
48
- console_endpoint: typing.Optional[str] = None
49
- command: typing.Optional[typing.List[str]] = None
50
- proxy_command: typing.Optional[typing.List[str]] = None
51
- client_id: typing.Optional[str] = None
52
- client_credentials_secret: typing.Optional[str] = None
53
- scopes: typing.List[str] = field(default_factory=list)
54
- auth_mode: "AuthType" = "Pkce"
55
- audience: typing.Optional[str] = None
56
- rpc_retries: int = 3
57
- http_proxy_url: typing.Optional[str] = None
58
-
59
- @classmethod
60
- def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "PlatformConfig":
61
- """
62
- Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
63
- :param config_file:
64
- :return:
65
- """
66
-
67
- config_file = get_config_file(config_file)
68
- kwargs: typing.Dict[str, typing.Any] = {}
69
- kwargs = set_if_exists(kwargs, "insecure", _internal.Platform.INSECURE.read(config_file))
70
- kwargs = set_if_exists(
71
- kwargs, "insecure_skip_verify", _internal.Platform.INSECURE_SKIP_VERIFY.read(config_file)
72
- )
73
- kwargs = set_if_exists(kwargs, "ca_cert_file_path", _internal.Platform.CA_CERT_FILE_PATH.read(config_file))
74
- kwargs = set_if_exists(kwargs, "command", _internal.Credentials.COMMAND.read(config_file))
75
- kwargs = set_if_exists(kwargs, "proxy_command", _internal.Credentials.PROXY_COMMAND.read(config_file))
76
- kwargs = set_if_exists(kwargs, "client_id", _internal.Credentials.CLIENT_ID.read(config_file))
77
-
78
- is_client_secret = False
79
- client_credentials_secret = read_file_if_exists(
80
- _internal.Credentials.CLIENT_CREDENTIALS_SECRET_LOCATION.read(config_file)
81
- )
82
- if client_credentials_secret:
83
- is_client_secret = True
84
- if client_credentials_secret.endswith("\n"):
85
- logger.info("Newline stripped from client secret")
86
- client_credentials_secret = client_credentials_secret.strip()
87
- kwargs = set_if_exists(
88
- kwargs,
89
- "client_credentials_secret",
90
- client_credentials_secret,
91
- )
92
-
93
- client_credentials_secret_env_var = _internal.Credentials.CLIENT_CREDENTIALS_SECRET_ENV_VAR.read(config_file)
94
- if client_credentials_secret_env_var:
95
- client_credentials_secret = os.getenv(client_credentials_secret_env_var)
96
- if client_credentials_secret:
97
- is_client_secret = True
98
- kwargs = set_if_exists(kwargs, "client_credentials_secret", client_credentials_secret)
99
- kwargs = set_if_exists(kwargs, "scopes", _internal.Credentials.SCOPES.read(config_file))
100
- kwargs = set_if_exists(kwargs, "auth_mode", _internal.Credentials.AUTH_MODE.read(config_file))
101
- if is_client_secret:
102
- kwargs = set_if_exists(kwargs, "auth_mode", "ClientSecret")
103
- kwargs = set_if_exists(kwargs, "endpoint", _internal.Platform.URL.read(config_file))
104
- kwargs = set_if_exists(kwargs, "console_endpoint", _internal.Platform.CONSOLE_ENDPOINT.read(config_file))
105
-
106
- kwargs = set_if_exists(kwargs, "http_proxy_url", _internal.Platform.HTTP_PROXY_URL.read(config_file))
107
- return PlatformConfig(**kwargs)
108
-
109
- @classmethod
110
- def for_endpoint(cls, endpoint: str, insecure: bool = False) -> "PlatformConfig":
111
- return PlatformConfig(endpoint=endpoint, insecure=insecure)
112
-
113
-
114
- @rich.repr.auto
115
- @dataclass(init=True, repr=True, eq=True, frozen=True)
116
- class TaskConfig(object):
117
- org: str | None = None
118
- project: str | None = None
119
- domain: str | None = None
120
-
121
- @classmethod
122
- def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "TaskConfig":
123
- """
124
- Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
125
- :param config_file:
126
- :return:
127
- """
128
- config_file = get_config_file(config_file)
129
- kwargs: typing.Dict[str, typing.Any] = {}
130
- kwargs = set_if_exists(kwargs, "org", _internal.Task.ORG.read(config_file))
131
- kwargs = set_if_exists(kwargs, "project", _internal.Task.PROJECT.read(config_file))
132
- kwargs = set_if_exists(kwargs, "domain", _internal.Task.DOMAIN.read(config_file))
133
- return TaskConfig(**kwargs)
134
-
135
-
136
- @rich.repr.auto
137
- @dataclass(init=True, repr=True, eq=True, frozen=True)
138
- class Config(object):
139
- """
140
- This the parent configuration object and holds all the underlying configuration object types. An instance of
141
- this object holds all the config necessary to
142
-
143
- 1. Interactive session with Flyte backend
144
- 2. Some parts are required for Serialization, for example Platform Config is not required
145
- 3. Runtime of a task
146
- """
147
-
148
- platform: PlatformConfig = field(default=PlatformConfig())
149
- task: TaskConfig = field(default=TaskConfig())
150
- source: pathlib.Path | None = None
151
-
152
- def with_params(
153
- self,
154
- platform: PlatformConfig | None = None,
155
- task: TaskConfig | None = None,
156
- ) -> "Config":
157
- return Config(
158
- platform=platform or self.platform,
159
- task=task or self.task,
160
- )
161
-
162
- @classmethod
163
- def auto(cls, config_file: typing.Union[str, ConfigFile, None] = None) -> "Config":
164
- """
165
- Automatically constructs the Config Object. The order of precedence is as follows
166
- 1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
167
- 2. If not found in environment then values ar read from the config file
168
- 3. If not found in the file, then the default values are used.
169
-
170
- :param config_file: file path to read the config from, if not specified default locations are searched
171
- :return: Config
172
- """
173
- config_file = get_config_file(config_file)
174
- if config_file is None:
175
- logger.debug("No config file found, using default values")
176
- return Config()
177
- return Config(
178
- platform=PlatformConfig.auto(config_file), task=TaskConfig.auto(config_file), source=config_file.path
179
- )
180
-
181
-
182
- def set_if_exists(d: dict, k: str, val: typing.Any) -> dict:
183
- """
184
- Given a dict ``d`` sets the key ``k`` with value of config ``v``, if the config value ``v`` is set
185
- and return the updated dictionary.
186
- """
187
- exists = isinstance(val, bool) or bool(val is not None and val)
188
- if exists:
189
- d[k] = val
190
- return d
3
+ __all__ = ["Config", "auto", "get_config_file", "set_if_exists"]