flyte 2.0.0b32__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 (204) hide show
  1. flyte/__init__.py +108 -0
  2. flyte/_bin/__init__.py +0 -0
  3. flyte/_bin/debug.py +38 -0
  4. flyte/_bin/runtime.py +195 -0
  5. flyte/_bin/serve.py +178 -0
  6. flyte/_build.py +26 -0
  7. flyte/_cache/__init__.py +12 -0
  8. flyte/_cache/cache.py +147 -0
  9. flyte/_cache/defaults.py +9 -0
  10. flyte/_cache/local_cache.py +216 -0
  11. flyte/_cache/policy_function_body.py +42 -0
  12. flyte/_code_bundle/__init__.py +8 -0
  13. flyte/_code_bundle/_ignore.py +121 -0
  14. flyte/_code_bundle/_packaging.py +218 -0
  15. flyte/_code_bundle/_utils.py +347 -0
  16. flyte/_code_bundle/bundle.py +266 -0
  17. flyte/_constants.py +1 -0
  18. flyte/_context.py +155 -0
  19. flyte/_custom_context.py +73 -0
  20. flyte/_debug/__init__.py +0 -0
  21. flyte/_debug/constants.py +38 -0
  22. flyte/_debug/utils.py +17 -0
  23. flyte/_debug/vscode.py +307 -0
  24. flyte/_deploy.py +408 -0
  25. flyte/_deployer.py +109 -0
  26. flyte/_doc.py +29 -0
  27. flyte/_docstring.py +32 -0
  28. flyte/_environment.py +122 -0
  29. flyte/_excepthook.py +37 -0
  30. flyte/_group.py +32 -0
  31. flyte/_hash.py +8 -0
  32. flyte/_image.py +1055 -0
  33. flyte/_initialize.py +628 -0
  34. flyte/_interface.py +119 -0
  35. flyte/_internal/__init__.py +3 -0
  36. flyte/_internal/controllers/__init__.py +129 -0
  37. flyte/_internal/controllers/_local_controller.py +239 -0
  38. flyte/_internal/controllers/_trace.py +48 -0
  39. flyte/_internal/controllers/remote/__init__.py +58 -0
  40. flyte/_internal/controllers/remote/_action.py +211 -0
  41. flyte/_internal/controllers/remote/_client.py +47 -0
  42. flyte/_internal/controllers/remote/_controller.py +583 -0
  43. flyte/_internal/controllers/remote/_core.py +465 -0
  44. flyte/_internal/controllers/remote/_informer.py +381 -0
  45. flyte/_internal/controllers/remote/_service_protocol.py +50 -0
  46. flyte/_internal/imagebuild/__init__.py +3 -0
  47. flyte/_internal/imagebuild/docker_builder.py +706 -0
  48. flyte/_internal/imagebuild/image_builder.py +277 -0
  49. flyte/_internal/imagebuild/remote_builder.py +386 -0
  50. flyte/_internal/imagebuild/utils.py +78 -0
  51. flyte/_internal/resolvers/__init__.py +0 -0
  52. flyte/_internal/resolvers/_task_module.py +21 -0
  53. flyte/_internal/resolvers/common.py +31 -0
  54. flyte/_internal/resolvers/default.py +28 -0
  55. flyte/_internal/runtime/__init__.py +0 -0
  56. flyte/_internal/runtime/convert.py +486 -0
  57. flyte/_internal/runtime/entrypoints.py +204 -0
  58. flyte/_internal/runtime/io.py +188 -0
  59. flyte/_internal/runtime/resources_serde.py +152 -0
  60. flyte/_internal/runtime/reuse.py +125 -0
  61. flyte/_internal/runtime/rusty.py +193 -0
  62. flyte/_internal/runtime/task_serde.py +362 -0
  63. flyte/_internal/runtime/taskrunner.py +209 -0
  64. flyte/_internal/runtime/trigger_serde.py +160 -0
  65. flyte/_internal/runtime/types_serde.py +54 -0
  66. flyte/_keyring/__init__.py +0 -0
  67. flyte/_keyring/file.py +115 -0
  68. flyte/_logging.py +300 -0
  69. flyte/_map.py +312 -0
  70. flyte/_module.py +72 -0
  71. flyte/_pod.py +30 -0
  72. flyte/_resources.py +473 -0
  73. flyte/_retry.py +32 -0
  74. flyte/_reusable_environment.py +102 -0
  75. flyte/_run.py +724 -0
  76. flyte/_secret.py +96 -0
  77. flyte/_task.py +550 -0
  78. flyte/_task_environment.py +316 -0
  79. flyte/_task_plugins.py +47 -0
  80. flyte/_timeout.py +47 -0
  81. flyte/_tools.py +27 -0
  82. flyte/_trace.py +119 -0
  83. flyte/_trigger.py +1000 -0
  84. flyte/_utils/__init__.py +30 -0
  85. flyte/_utils/asyn.py +121 -0
  86. flyte/_utils/async_cache.py +139 -0
  87. flyte/_utils/coro_management.py +27 -0
  88. flyte/_utils/docker_credentials.py +173 -0
  89. flyte/_utils/file_handling.py +72 -0
  90. flyte/_utils/helpers.py +134 -0
  91. flyte/_utils/lazy_module.py +54 -0
  92. flyte/_utils/module_loader.py +104 -0
  93. flyte/_utils/org_discovery.py +57 -0
  94. flyte/_utils/uv_script_parser.py +49 -0
  95. flyte/_version.py +34 -0
  96. flyte/app/__init__.py +22 -0
  97. flyte/app/_app_environment.py +157 -0
  98. flyte/app/_deploy.py +125 -0
  99. flyte/app/_input.py +160 -0
  100. flyte/app/_runtime/__init__.py +3 -0
  101. flyte/app/_runtime/app_serde.py +347 -0
  102. flyte/app/_types.py +101 -0
  103. flyte/app/extras/__init__.py +3 -0
  104. flyte/app/extras/_fastapi.py +151 -0
  105. flyte/cli/__init__.py +12 -0
  106. flyte/cli/_abort.py +28 -0
  107. flyte/cli/_build.py +114 -0
  108. flyte/cli/_common.py +468 -0
  109. flyte/cli/_create.py +371 -0
  110. flyte/cli/_delete.py +45 -0
  111. flyte/cli/_deploy.py +293 -0
  112. flyte/cli/_gen.py +176 -0
  113. flyte/cli/_get.py +370 -0
  114. flyte/cli/_option.py +33 -0
  115. flyte/cli/_params.py +554 -0
  116. flyte/cli/_plugins.py +209 -0
  117. flyte/cli/_run.py +597 -0
  118. flyte/cli/_serve.py +64 -0
  119. flyte/cli/_update.py +37 -0
  120. flyte/cli/_user.py +17 -0
  121. flyte/cli/main.py +221 -0
  122. flyte/config/__init__.py +3 -0
  123. flyte/config/_config.py +248 -0
  124. flyte/config/_internal.py +73 -0
  125. flyte/config/_reader.py +225 -0
  126. flyte/connectors/__init__.py +11 -0
  127. flyte/connectors/_connector.py +270 -0
  128. flyte/connectors/_server.py +197 -0
  129. flyte/connectors/utils.py +135 -0
  130. flyte/errors.py +243 -0
  131. flyte/extend.py +19 -0
  132. flyte/extras/__init__.py +5 -0
  133. flyte/extras/_container.py +286 -0
  134. flyte/git/__init__.py +3 -0
  135. flyte/git/_config.py +21 -0
  136. flyte/io/__init__.py +29 -0
  137. flyte/io/_dataframe/__init__.py +131 -0
  138. flyte/io/_dataframe/basic_dfs.py +223 -0
  139. flyte/io/_dataframe/dataframe.py +1026 -0
  140. flyte/io/_dir.py +910 -0
  141. flyte/io/_file.py +914 -0
  142. flyte/io/_hashing_io.py +342 -0
  143. flyte/models.py +479 -0
  144. flyte/py.typed +0 -0
  145. flyte/remote/__init__.py +35 -0
  146. flyte/remote/_action.py +738 -0
  147. flyte/remote/_app.py +57 -0
  148. flyte/remote/_client/__init__.py +0 -0
  149. flyte/remote/_client/_protocols.py +189 -0
  150. flyte/remote/_client/auth/__init__.py +12 -0
  151. flyte/remote/_client/auth/_auth_utils.py +14 -0
  152. flyte/remote/_client/auth/_authenticators/__init__.py +0 -0
  153. flyte/remote/_client/auth/_authenticators/base.py +403 -0
  154. flyte/remote/_client/auth/_authenticators/client_credentials.py +73 -0
  155. flyte/remote/_client/auth/_authenticators/device_code.py +117 -0
  156. flyte/remote/_client/auth/_authenticators/external_command.py +79 -0
  157. flyte/remote/_client/auth/_authenticators/factory.py +200 -0
  158. flyte/remote/_client/auth/_authenticators/pkce.py +516 -0
  159. flyte/remote/_client/auth/_channel.py +213 -0
  160. flyte/remote/_client/auth/_client_config.py +85 -0
  161. flyte/remote/_client/auth/_default_html.py +32 -0
  162. flyte/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  163. flyte/remote/_client/auth/_grpc_utils/auth_interceptor.py +288 -0
  164. flyte/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +151 -0
  165. flyte/remote/_client/auth/_keyring.py +152 -0
  166. flyte/remote/_client/auth/_token_client.py +260 -0
  167. flyte/remote/_client/auth/errors.py +16 -0
  168. flyte/remote/_client/controlplane.py +128 -0
  169. flyte/remote/_common.py +30 -0
  170. flyte/remote/_console.py +19 -0
  171. flyte/remote/_data.py +161 -0
  172. flyte/remote/_logs.py +185 -0
  173. flyte/remote/_project.py +88 -0
  174. flyte/remote/_run.py +386 -0
  175. flyte/remote/_secret.py +142 -0
  176. flyte/remote/_task.py +527 -0
  177. flyte/remote/_trigger.py +306 -0
  178. flyte/remote/_user.py +33 -0
  179. flyte/report/__init__.py +3 -0
  180. flyte/report/_report.py +182 -0
  181. flyte/report/_template.html +124 -0
  182. flyte/storage/__init__.py +36 -0
  183. flyte/storage/_config.py +237 -0
  184. flyte/storage/_parallel_reader.py +274 -0
  185. flyte/storage/_remote_fs.py +34 -0
  186. flyte/storage/_storage.py +456 -0
  187. flyte/storage/_utils.py +5 -0
  188. flyte/syncify/__init__.py +56 -0
  189. flyte/syncify/_api.py +375 -0
  190. flyte/types/__init__.py +52 -0
  191. flyte/types/_interface.py +40 -0
  192. flyte/types/_pickle.py +145 -0
  193. flyte/types/_renderer.py +162 -0
  194. flyte/types/_string_literals.py +119 -0
  195. flyte/types/_type_engine.py +2254 -0
  196. flyte/types/_utils.py +80 -0
  197. flyte-2.0.0b32.data/scripts/debug.py +38 -0
  198. flyte-2.0.0b32.data/scripts/runtime.py +195 -0
  199. flyte-2.0.0b32.dist-info/METADATA +351 -0
  200. flyte-2.0.0b32.dist-info/RECORD +204 -0
  201. flyte-2.0.0b32.dist-info/WHEEL +5 -0
  202. flyte-2.0.0b32.dist-info/entry_points.txt +7 -0
  203. flyte-2.0.0b32.dist-info/licenses/LICENSE +201 -0
  204. flyte-2.0.0b32.dist-info/top_level.txt +1 -0
flyte/_initialize.py ADDED
@@ -0,0 +1,628 @@
1
+ from __future__ import annotations
2
+
3
+ import functools
4
+ import threading
5
+ import typing
6
+ from dataclasses import dataclass, field, replace
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING, Callable, List, Literal, Optional, TypeVar
9
+
10
+ from flyte.errors import InitializationError
11
+ from flyte.syncify import syncify
12
+
13
+ from ._logging import LogFormat, initialize_logger, logger
14
+
15
+ if TYPE_CHECKING:
16
+ from flyte._internal.imagebuild import ImageBuildEngine
17
+ from flyte.config import Config
18
+ from flyte.remote._client.auth import AuthType, ClientConfig
19
+ from flyte.remote._client.controlplane import ClientSet
20
+ from flyte.storage import Storage
21
+
22
+ Mode = Literal["local", "remote"]
23
+
24
+
25
+ @dataclass(init=True, repr=True, eq=True, frozen=True, kw_only=True)
26
+ class CommonInit:
27
+ """
28
+ Common initialization configuration for Flyte.
29
+ """
30
+
31
+ root_dir: Path
32
+ org: str | None = None
33
+ project: str | None = None
34
+ domain: str | None = None
35
+ batch_size: int = 1000
36
+ source_config_path: Optional[Path] = None # Only used for documentation
37
+ sync_local_sys_paths: bool = True
38
+
39
+
40
+ @dataclass(init=True, kw_only=True, repr=True, eq=True, frozen=True)
41
+ class _InitConfig(CommonInit):
42
+ client: Optional[ClientSet] = None
43
+ storage: Optional[Storage] = None
44
+ image_builder: "ImageBuildEngine.ImageBuilderType" = "local"
45
+ images: typing.Dict[str, str] = field(default_factory=dict)
46
+
47
+ def replace(self, **kwargs) -> _InitConfig:
48
+ return replace(self, **kwargs)
49
+
50
+
51
+ # Global singleton to store initialization configuration
52
+ _init_config: _InitConfig | None = None
53
+ _init_lock = threading.RLock() # Reentrant lock for thread safety
54
+
55
+
56
+ async def _initialize_client(
57
+ api_key: str | None = None,
58
+ auth_type: AuthType = "Pkce",
59
+ endpoint: str | None = None,
60
+ client_config: ClientConfig | None = None,
61
+ headless: bool = False,
62
+ insecure: bool = False,
63
+ insecure_skip_verify: bool = False,
64
+ ca_cert_file_path: str | None = None,
65
+ command: List[str] | None = None,
66
+ proxy_command: List[str] | None = None,
67
+ client_id: str | None = None,
68
+ client_credentials_secret: str | None = None,
69
+ rpc_retries: int = 3,
70
+ http_proxy_url: str | None = None,
71
+ ) -> ClientSet:
72
+ """
73
+ Initialize the client based on the execution mode.
74
+ :return: The initialized client
75
+ """
76
+ from flyte.remote._client.controlplane import ClientSet
77
+
78
+ if endpoint:
79
+ return await ClientSet.for_endpoint(
80
+ endpoint,
81
+ insecure=insecure,
82
+ insecure_skip_verify=insecure_skip_verify,
83
+ auth_type=auth_type,
84
+ headless=headless,
85
+ ca_cert_file_path=ca_cert_file_path,
86
+ command=command,
87
+ proxy_command=proxy_command,
88
+ client_id=client_id,
89
+ client_credentials_secret=client_credentials_secret,
90
+ client_config=client_config,
91
+ rpc_retries=rpc_retries,
92
+ http_proxy_url=http_proxy_url,
93
+ )
94
+ elif api_key:
95
+ return await ClientSet.for_api_key(
96
+ api_key,
97
+ insecure=insecure,
98
+ insecure_skip_verify=insecure_skip_verify,
99
+ auth_type=auth_type,
100
+ headless=headless,
101
+ ca_cert_file_path=ca_cert_file_path,
102
+ command=command,
103
+ proxy_command=proxy_command,
104
+ client_id=client_id,
105
+ client_credentials_secret=client_credentials_secret,
106
+ client_config=client_config,
107
+ rpc_retries=rpc_retries,
108
+ http_proxy_url=http_proxy_url,
109
+ )
110
+
111
+ raise InitializationError(
112
+ "MissingEndpointOrApiKeyError", "user", "Either endpoint or api_key must be provided to initialize the client."
113
+ )
114
+
115
+
116
+ def _initialize_logger(log_level: int | None = None, log_format: LogFormat | None = None) -> None:
117
+ initialize_logger(log_level=log_level, log_format=log_format, enable_rich=True)
118
+
119
+
120
+ @syncify
121
+ async def init(
122
+ org: str | None = None,
123
+ project: str | None = None,
124
+ domain: str | None = None,
125
+ root_dir: Path | None = None,
126
+ log_level: int | None = None,
127
+ log_format: LogFormat | None = None,
128
+ endpoint: str | None = None,
129
+ headless: bool = False,
130
+ insecure: bool = False,
131
+ insecure_skip_verify: bool = False,
132
+ ca_cert_file_path: str | None = None,
133
+ auth_type: AuthType = "Pkce",
134
+ command: List[str] | None = None,
135
+ proxy_command: List[str] | None = None,
136
+ api_key: str | None = None,
137
+ client_id: str | None = None,
138
+ client_credentials_secret: str | None = None,
139
+ auth_client_config: ClientConfig | None = None,
140
+ rpc_retries: int = 3,
141
+ http_proxy_url: str | None = None,
142
+ storage: Storage | None = None,
143
+ batch_size: int = 1000,
144
+ image_builder: ImageBuildEngine.ImageBuilderType = "local",
145
+ images: typing.Dict[str, str] | None = None,
146
+ source_config_path: Optional[Path] = None,
147
+ sync_local_sys_paths: bool = True,
148
+ load_plugin_type_transformers: bool = True,
149
+ ) -> None:
150
+ """
151
+ Initialize the Flyte system with the given configuration. This method should be called before any other Flyte
152
+ remote API methods are called. Thread-safe implementation.
153
+
154
+ :param project: Optional project name (not used in this implementation)
155
+ :param domain: Optional domain name (not used in this implementation)
156
+ :param root_dir: Optional root directory from which to determine how to load files, and find paths to files.
157
+ This is useful for determining the root directory for the current project, and for locating files like config etc.
158
+ also use to determine all the code that needs to be copied to the remote location.
159
+ defaults to the editable install directory if the cwd is in a Python editable install, else just the cwd.
160
+ :param log_level: Optional logging level for the logger, default is set using the default initialization policies
161
+ :param log_format: Optional logging format for the logger, default is "console"
162
+ :param api_key: Optional API key for authentication
163
+ :param endpoint: Optional API endpoint URL
164
+ :param headless: Optional Whether to run in headless mode
165
+ :param insecure_skip_verify: Whether to skip SSL certificate verification
166
+ :param auth_client_config: Optional client configuration for authentication
167
+ :param auth_type: The authentication type to use (Pkce, ClientSecret, ExternalCommand, DeviceFlow)
168
+ :param command: This command is executed to return a token using an external process
169
+ :param proxy_command: This command is executed to return a token for proxy authorization using an external process
170
+ :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
171
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
172
+ :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
173
+ allow the Flyte engine to read the password directly from the environment variable. Note that this is
174
+ less secure! Please only use this if mounting the secret as a file is impossible
175
+ :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
176
+ :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
177
+ :param rpc_retries: [optional] int Number of times to retry the platform calls
178
+ :param insecure: insecure flag for the client
179
+ :param storage: Optional blob store (S3, GCS, Azure) configuration if needed to access (i.e. using Minio)
180
+ :param org: Optional organization override for the client. Should be set by auth instead.
181
+ :param batch_size: Optional batch size for operations that use listings, defaults to 1000, so limit larger than
182
+ batch_size will be split into multiple requests.
183
+ :param image_builder: Optional image builder configuration, if not provided, the default image builder will be used.
184
+ :param images: Optional dict of images that can be used by referencing the image name.
185
+ :param source_config_path: Optional path to the source configuration file (This is only used for documentation)
186
+ :param sync_local_sys_paths: Whether to include and synchronize local sys.path entries under the root directory
187
+ into the remote container (default: True).
188
+ :param load_plugin_type_transformers: If enabled (default True), load the type transformer plugins registered under
189
+ the "flyte.plugins.types" entry point group.
190
+ :return: None
191
+ """
192
+ from flyte._utils import get_cwd_editable_install, org_from_endpoint, sanitize_endpoint
193
+ from flyte.types import _load_custom_type_transformers
194
+
195
+ _initialize_logger(log_level=log_level, log_format=log_format)
196
+ if load_plugin_type_transformers:
197
+ _load_custom_type_transformers()
198
+
199
+ global _init_config # noqa: PLW0603
200
+
201
+ endpoint = sanitize_endpoint(endpoint)
202
+
203
+ with _init_lock:
204
+ client = None
205
+ if endpoint or api_key:
206
+ client = await _initialize_client(
207
+ api_key=api_key,
208
+ auth_type=auth_type,
209
+ endpoint=endpoint,
210
+ headless=headless,
211
+ insecure=insecure,
212
+ insecure_skip_verify=insecure_skip_verify,
213
+ ca_cert_file_path=ca_cert_file_path,
214
+ command=command,
215
+ proxy_command=proxy_command,
216
+ client_id=client_id,
217
+ client_credentials_secret=client_credentials_secret,
218
+ client_config=auth_client_config,
219
+ rpc_retries=rpc_retries,
220
+ http_proxy_url=http_proxy_url,
221
+ )
222
+
223
+ if not root_dir:
224
+ editable_root = get_cwd_editable_install()
225
+ if editable_root:
226
+ logger.info(f"Using editable install as root directory: {editable_root}")
227
+ root_dir = editable_root
228
+ else:
229
+ logger.info("No editable install found, using current working directory as root directory.")
230
+ root_dir = Path.cwd()
231
+
232
+ _init_config = _InitConfig(
233
+ root_dir=root_dir,
234
+ project=project,
235
+ domain=domain,
236
+ client=client,
237
+ storage=storage,
238
+ org=org or org_from_endpoint(endpoint),
239
+ batch_size=batch_size,
240
+ image_builder=image_builder,
241
+ images=images or {},
242
+ source_config_path=source_config_path,
243
+ sync_local_sys_paths=sync_local_sys_paths,
244
+ )
245
+
246
+
247
+ @syncify
248
+ async def init_from_config(
249
+ path_or_config: str | Path | Config | None = None,
250
+ root_dir: Path | None = None,
251
+ log_level: int | None = None,
252
+ log_format: LogFormat = "console",
253
+ storage: Storage | None = None,
254
+ images: tuple[str, ...] | None = None,
255
+ sync_local_sys_paths: bool = True,
256
+ ) -> None:
257
+ """
258
+ Initialize the Flyte system using a configuration file or Config object. This method should be called before any
259
+ other Flyte remote API methods are called. Thread-safe implementation.
260
+
261
+ :param path_or_config: Path to the configuration file or Config object
262
+ :param root_dir: Optional root directory from which to determine how to load files, and find paths to
263
+ files like config etc. For example if one uses the copy-style=="all", it is essential to determine the
264
+ root directory for the current project. If not provided, it defaults to the editable install directory or
265
+ if not available, the current working directory.
266
+ :param log_level: Optional logging level for the framework logger,
267
+ default is set using the default initialization policies
268
+ :param log_format: Optional logging format for the logger, default is "console"
269
+ :param storage: Optional blob store (S3, GCS, Azure) configuration if needed to access (i.e. using Minio)
270
+ :param images: List of image strings in format "imagename=imageuri" or just "imageuri".
271
+ :param sync_local_sys_paths: Whether to include and synchronize local sys.path entries under the root directory
272
+ into the remote container (default: True).
273
+ :return: None
274
+ """
275
+ from rich.highlighter import ReprHighlighter
276
+
277
+ import flyte.config as config
278
+ from flyte.cli._common import parse_images
279
+
280
+ cfg: config.Config
281
+ cfg_path: Optional[Path] = None
282
+ if path_or_config is None:
283
+ # If no path is provided, use the default config file
284
+ cfg = config.auto()
285
+ elif isinstance(path_or_config, (str, Path)):
286
+ if root_dir:
287
+ cfg_path = root_dir.expanduser() / path_or_config
288
+ else:
289
+ cfg_path = Path(path_or_config).expanduser()
290
+ if not Path(cfg_path).exists():
291
+ raise InitializationError(
292
+ "ConfigFileNotFoundError",
293
+ "user",
294
+ f"Configuration file '{cfg_path}' does not exist., current working directory is {Path.cwd()}",
295
+ )
296
+ cfg = config.auto(cfg_path)
297
+ else:
298
+ cfg = path_or_config
299
+
300
+ logger.info(f"Flyte config initialized as {cfg}", extra={"highlighter": ReprHighlighter()})
301
+
302
+ # parse image, this will overwrite the image_refs set in the config file
303
+ parse_images(cfg, images)
304
+
305
+ await init.aio(
306
+ org=cfg.task.org,
307
+ project=cfg.task.project,
308
+ domain=cfg.task.domain,
309
+ endpoint=cfg.platform.endpoint,
310
+ insecure=cfg.platform.insecure,
311
+ insecure_skip_verify=cfg.platform.insecure_skip_verify,
312
+ ca_cert_file_path=cfg.platform.ca_cert_file_path,
313
+ auth_type=cfg.platform.auth_mode,
314
+ command=cfg.platform.command,
315
+ proxy_command=cfg.platform.proxy_command,
316
+ client_id=cfg.platform.client_id,
317
+ client_credentials_secret=cfg.platform.client_credentials_secret,
318
+ root_dir=root_dir,
319
+ log_level=log_level,
320
+ log_format=log_format,
321
+ image_builder=cfg.image.builder,
322
+ images=cfg.image.image_refs,
323
+ storage=storage,
324
+ source_config_path=cfg_path,
325
+ sync_local_sys_paths=sync_local_sys_paths,
326
+ )
327
+
328
+
329
+ @syncify
330
+ async def init_in_cluster(
331
+ org: str | None = None,
332
+ project: str | None = None,
333
+ domain: str | None = None,
334
+ api_key: str | None = None,
335
+ endpoint: str | None = None,
336
+ insecure: bool = False,
337
+ ) -> dict[str, typing.Any]:
338
+ import os
339
+
340
+ from flyte._utils import str2bool
341
+
342
+ PROJECT_NAME = "FLYTE_INTERNAL_EXECUTION_PROJECT"
343
+ DOMAIN_NAME = "FLYTE_INTERNAL_EXECUTION_DOMAIN"
344
+ ORG_NAME = "_U_ORG_NAME"
345
+ ENDPOINT_OVERRIDE = "_U_EP_OVERRIDE"
346
+ INSECURE_SKIP_VERIFY_OVERRIDE = "_U_INSECURE_SKIP_VERIFY"
347
+ _UNION_EAGER_API_KEY_ENV_VAR = "_UNION_EAGER_API_KEY"
348
+
349
+ org = org or os.getenv(ORG_NAME)
350
+ project = project or os.getenv(PROJECT_NAME)
351
+ domain = domain or os.getenv(DOMAIN_NAME)
352
+ api_key = api_key or os.getenv(_UNION_EAGER_API_KEY_ENV_VAR)
353
+
354
+ remote_kwargs: dict[str, typing.Any] = {"insecure": False}
355
+ if api_key:
356
+ logger.info("Using api key from environment")
357
+ remote_kwargs["api_key"] = api_key
358
+ else:
359
+ ep = endpoint or os.environ.get(ENDPOINT_OVERRIDE, "host.docker.internal:8090")
360
+ remote_kwargs["endpoint"] = ep
361
+ if not insecure:
362
+ if "localhost" in ep or "docker" in ep:
363
+ remote_kwargs["insecure"] = True
364
+ logger.debug(f"Using controller endpoint: {ep} with kwargs: {remote_kwargs}")
365
+
366
+ # Check for insecure_skip_verify override (e.g. for self-signed certs)
367
+ insecure_skip_verify_str = os.getenv(INSECURE_SKIP_VERIFY_OVERRIDE, "")
368
+ if str2bool(insecure_skip_verify_str):
369
+ remote_kwargs["insecure_skip_verify"] = True
370
+ logger.info("SSL certificate verification disabled (insecure_skip_verify=True)")
371
+
372
+ await init.aio(org=org, project=project, domain=domain, image_builder="remote", **remote_kwargs)
373
+ return remote_kwargs
374
+
375
+
376
+ def _get_init_config() -> Optional[_InitConfig]:
377
+ """
378
+ Get the current initialization configuration. Thread-safe implementation.
379
+
380
+ :return: The current InitData if initialized, None otherwise
381
+ """
382
+ with _init_lock:
383
+ return _init_config
384
+
385
+
386
+ def get_init_config() -> _InitConfig:
387
+ """
388
+ Get the current initialization configuration. Thread-safe implementation.
389
+
390
+ :return: The current InitData if initialized, None otherwise
391
+ """
392
+ cfg = _get_init_config()
393
+ if cfg is None:
394
+ raise InitializationError(
395
+ "StorageNotInitializedError",
396
+ "user",
397
+ "Configuration has not been initialized. Call flyte.init() with a valid endpoint or",
398
+ " api-key before using this function.",
399
+ )
400
+ return cfg
401
+
402
+
403
+ def get_storage() -> Storage | None:
404
+ """
405
+ Get the current storage configuration. Thread-safe implementation.
406
+
407
+ :return: The current storage configuration
408
+ """
409
+ cfg = _get_init_config()
410
+ if cfg is None:
411
+ raise InitializationError(
412
+ "StorageNotInitializedError",
413
+ "user",
414
+ "Configuration has not been initialized. Call flyte.init() with a valid endpoint or",
415
+ " api-key before using this function.",
416
+ )
417
+ return cfg.storage
418
+
419
+
420
+ def get_client() -> ClientSet:
421
+ """
422
+ Get the current client. Thread-safe implementation.
423
+
424
+ :return: The current client
425
+ """
426
+ cfg = _get_init_config()
427
+ if cfg is None or cfg.client is None:
428
+ raise InitializationError(
429
+ "ClientNotInitializedError",
430
+ "user",
431
+ "Client has not been initialized. Call flyte.init() with a valid endpoint or"
432
+ " api-key before using this function.",
433
+ )
434
+ return cfg.client
435
+
436
+
437
+ def is_initialized() -> bool:
438
+ """
439
+ Check if the system has been initialized.
440
+
441
+ :return: True if initialized, False otherwise
442
+ """
443
+ return _get_init_config() is not None
444
+
445
+
446
+ def initialize_in_cluster() -> None:
447
+ """
448
+ Initialize the system for in-cluster execution. This is a placeholder function and does not perform any actions.
449
+
450
+ :return: None
451
+ """
452
+ init()
453
+
454
+
455
+ # Define a generic type variable for the decorated function
456
+ T = TypeVar("T", bound=Callable)
457
+
458
+
459
+ def ensure_client():
460
+ """
461
+ Ensure that the client is initialized. If not, raise an InitializationError.
462
+ This function is used to check if the client is initialized before executing any Flyte remote API methods.
463
+ """
464
+ if _get_init_config() is None or _get_init_config().client is None:
465
+ raise InitializationError(
466
+ "ClientNotInitializedError",
467
+ "user",
468
+ "Client has not been initialized. Call flyte.init() with a valid endpoint"
469
+ " or api-key before using this function.",
470
+ )
471
+
472
+
473
+ def requires_storage(func: T) -> T:
474
+ """
475
+ Decorator that checks if the storage has been initialized before executing the function.
476
+ Raises InitializationError if the storage is not initialized.
477
+
478
+ :param func: Function to decorate
479
+ :return: Decorated function that checks for initialization
480
+ """
481
+
482
+ @functools.wraps(func)
483
+ def wrapper(*args, **kwargs):
484
+ if _get_init_config() is None or _get_init_config().storage is None:
485
+ raise InitializationError(
486
+ "StorageNotInitializedError",
487
+ "user",
488
+ f"Function '{func.__name__}' requires storage to be initialized. "
489
+ f"Call flyte.init() with a valid storage configuration before using this function.",
490
+ )
491
+ return func(*args, **kwargs)
492
+
493
+ return typing.cast(T, wrapper)
494
+
495
+
496
+ def requires_upload_location(func: T) -> T:
497
+ """
498
+ Decorator that checks if the storage has been initialized before executing the function.
499
+ Raises InitializationError if the storage is not initialized.
500
+
501
+ :param func: Function to decorate
502
+ :return: Decorated function that checks for initialization
503
+ """
504
+
505
+ @functools.wraps(func)
506
+ def wrapper(*args, **kwargs) -> T:
507
+ from ._context import internal_ctx
508
+
509
+ ctx = internal_ctx()
510
+ if not ctx.raw_data:
511
+ raise InitializationError(
512
+ "No upload path configured",
513
+ "user",
514
+ f"Function '{func.__name__}' requires client to be initialized. "
515
+ f"Call flyte.init() with storage configuration before using this function.",
516
+ )
517
+ return func(*args, **kwargs)
518
+
519
+ return typing.cast(T, wrapper)
520
+
521
+
522
+ def requires_initialization(func: T) -> T:
523
+ """
524
+ Decorator that checks if the system has been initialized before executing the function.
525
+ Raises InitializationError if the system is not initialized.
526
+
527
+ :param func: Function to decorate
528
+ :return: Decorated function that checks for initialization
529
+ """
530
+
531
+ @functools.wraps(func)
532
+ def wrapper(*args, **kwargs) -> T:
533
+ if not is_initialized():
534
+ raise InitializationError(
535
+ "NotInitConfiguredError",
536
+ "user",
537
+ f"Function '{func.__name__}' requires initialization. Call flyte.init() before using this function.",
538
+ )
539
+ return func(*args, **kwargs)
540
+
541
+ return typing.cast(T, wrapper)
542
+
543
+
544
+ def require_project_and_domain(func):
545
+ """
546
+ Decorator that ensures the current Flyte configuration defines
547
+ both 'project' and 'domain'. Raises a clear error if not found.
548
+ """
549
+
550
+ @functools.wraps(func)
551
+ def wrapper(*args, **kwargs):
552
+ cfg = get_init_config()
553
+ if cfg.project is None:
554
+ raise ValueError(
555
+ "Project must be provided to initialize the client. "
556
+ "Please set 'project' in the 'task' section of your config file, "
557
+ "or pass it directly to flyte.init(project='your-project-name')."
558
+ )
559
+
560
+ if cfg.domain is None:
561
+ raise ValueError(
562
+ "Domain must be provided to initialize the client. "
563
+ "Please set 'domain' in the 'task' section of your config file, "
564
+ "or pass it directly to flyte.init(domain='your-domain-name')."
565
+ )
566
+
567
+ return func(*args, **kwargs)
568
+
569
+ return wrapper
570
+
571
+
572
+ async def _init_for_testing(
573
+ project: str | None = None,
574
+ domain: str | None = None,
575
+ root_dir: Path | None = None,
576
+ log_level: int | None = None,
577
+ client: ClientSet | None = None,
578
+ ):
579
+ from flyte._utils.helpers import get_cwd_editable_install
580
+
581
+ global _init_config # noqa: PLW0603
582
+
583
+ if log_level:
584
+ initialize_logger(log_level=log_level)
585
+
586
+ with _init_lock:
587
+ root_dir = root_dir or get_cwd_editable_install() or Path.cwd()
588
+ _init_config = _InitConfig(
589
+ root_dir=root_dir,
590
+ project=project,
591
+ domain=domain,
592
+ client=client,
593
+ )
594
+
595
+
596
+ def replace_client(client):
597
+ global _init_config # noqa: PLW0603
598
+
599
+ with _init_lock:
600
+ _init_config = _init_config.replace(client=client)
601
+
602
+
603
+ def current_domain() -> str:
604
+ """
605
+ Returns the current domain from Runtime environment (on the cluster) or from the initialized configuration.
606
+ This is safe to be used during `deploy`, `run` and within `task` code.
607
+
608
+ NOTE: This will not work if you deploy a task to a domain and then run it in another domain.
609
+
610
+ Raises InitializationError if the configuration is not initialized or domain is not set.
611
+ :return: The current domain
612
+ """
613
+ from ._context import ctx
614
+
615
+ tctx = ctx()
616
+ if tctx is not None:
617
+ domain = tctx.action.domain
618
+ if domain is not None:
619
+ return domain
620
+
621
+ cfg = _get_init_config()
622
+ if cfg is None or cfg.domain is None:
623
+ raise InitializationError(
624
+ "DomainNotInitializedError",
625
+ "user",
626
+ "Domain has not been initialized. Call flyte.init() with a valid domain before using this function.",
627
+ )
628
+ return cfg.domain