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/_debug/vscode.py ADDED
@@ -0,0 +1,307 @@
1
+ import asyncio
2
+ import json
3
+ import multiprocessing
4
+ import os
5
+ import platform
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ import tarfile
10
+ import time
11
+ from pathlib import Path
12
+ from typing import List
13
+
14
+ import aiofiles
15
+ import click
16
+ import httpx
17
+
18
+ from flyte import storage
19
+ from flyte._debug.constants import (
20
+ DEFAULT_CODE_SERVER_EXTENSIONS,
21
+ DEFAULT_CODE_SERVER_REMOTE_PATHS,
22
+ DOWNLOAD_DIR,
23
+ EXECUTABLE_NAME,
24
+ EXIT_CODE_SUCCESS,
25
+ HEARTBEAT_PATH,
26
+ MAX_IDLE_SECONDS,
27
+ )
28
+ from flyte._debug.utils import (
29
+ execute_command,
30
+ )
31
+ from flyte._internal.runtime.rusty import download_tgz
32
+ from flyte._logging import logger
33
+
34
+
35
+ async def download_file(url: str, target_dir: str) -> str:
36
+ """
37
+ Downloads a file from a given URL using HTTPX and saves it locally.
38
+
39
+ Args:
40
+ url (str): The URL of the file to download.
41
+ target_dir (str): The directory where the file should be saved. Defaults to current directory.
42
+ """
43
+ try:
44
+ filename = os.path.join(target_dir, os.path.basename(url))
45
+ if url.startswith("http"):
46
+ response = httpx.get(url, follow_redirects=True)
47
+ response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
48
+ async with aiofiles.open(filename, "wb") as f:
49
+ await f.write(response.content)
50
+ else:
51
+ await storage.get(url, filename)
52
+ logger.info(f"File '{filename}' downloaded successfully from '{url}'.")
53
+ return filename
54
+
55
+ except httpx.RequestError as e:
56
+ raise RuntimeError(f"An error occurred while requesting '{url}': {e}")
57
+ except httpx.HTTPStatusError as e:
58
+ raise RuntimeError(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
59
+ except Exception as e:
60
+ raise RuntimeError(f"An unexpected error occurred: {e}")
61
+
62
+
63
+ def get_default_extensions() -> List[str]:
64
+ extensions = os.getenv("_F_CS_E")
65
+ if extensions is not None:
66
+ return extensions.split(",")
67
+ return DEFAULT_CODE_SERVER_EXTENSIONS
68
+
69
+
70
+ def get_code_server_info() -> str:
71
+ """
72
+ Returns the code server information based on the system's architecture.
73
+
74
+ This function checks the system's architecture and returns the corresponding
75
+ code server information from the provided dictionary. The function currently
76
+ supports AMD64 and ARM64 architectures.
77
+
78
+ Returns:
79
+ str: The code server information corresponding to the system's architecture.
80
+
81
+ Raises:
82
+ ValueError: If the system's architecture is not AMD64 or ARM64.
83
+ """
84
+ code_server_path = os.getenv("_F_CS_RP")
85
+ if code_server_path is not None:
86
+ return code_server_path
87
+
88
+ machine_info = platform.machine()
89
+ logger.info(f"machine type: {machine_info}")
90
+ code_server_info_dict = DEFAULT_CODE_SERVER_REMOTE_PATHS
91
+
92
+ if "aarch64" == machine_info:
93
+ return code_server_info_dict["arm64"]
94
+ elif "x86_64" == machine_info:
95
+ return code_server_info_dict["amd64"]
96
+ else:
97
+ raise ValueError(
98
+ "Automatic download is only supported on AMD64 and ARM64 architectures."
99
+ " If you are using a different architecture, please visit the code-server official website to"
100
+ " manually download the appropriate version for your image."
101
+ )
102
+
103
+
104
+ def get_installed_extensions() -> List[str]:
105
+ """
106
+ Get the list of installed extensions.
107
+
108
+ Returns:
109
+ List[str]: The list of installed extensions.
110
+ """
111
+ installed_extensions = subprocess.run(
112
+ ["code-server", "--list-extensions"], check=False, capture_output=True, text=True
113
+ )
114
+ if installed_extensions.returncode != EXIT_CODE_SUCCESS:
115
+ logger.info(f"Command code-server --list-extensions failed with error: {installed_extensions.stderr}")
116
+ return []
117
+
118
+ return installed_extensions.stdout.splitlines()
119
+
120
+
121
+ def is_extension_installed(extension: str, installed_extensions: List[str]) -> bool:
122
+ return any(installed_extension in extension for installed_extension in installed_extensions)
123
+
124
+
125
+ async def download_vscode():
126
+ """
127
+ Download vscode server and extension from remote to local and add the directory of binary executable to $PATH.
128
+ """
129
+ # If the code server already exists in the container, skip downloading
130
+ executable_path = shutil.which(EXECUTABLE_NAME)
131
+ if executable_path is not None or os.path.exists(DOWNLOAD_DIR):
132
+ logger.info(f"Code server binary already exists at {executable_path}")
133
+ logger.info("Skipping downloading code server...")
134
+ else:
135
+ logger.info("Code server is not in $PATH, start downloading code server...")
136
+ # Create DOWNLOAD_DIR if not exist
137
+ logger.info(f"DOWNLOAD_DIR: {DOWNLOAD_DIR}")
138
+ os.makedirs(DOWNLOAD_DIR)
139
+
140
+ logger.info(f"Start downloading files to {DOWNLOAD_DIR}")
141
+ # Download remote file to local
142
+ code_server_remote_path = get_code_server_info()
143
+ code_server_tar_path = await download_file(code_server_remote_path, str(DOWNLOAD_DIR))
144
+
145
+ # Extract the tarball
146
+ with tarfile.open(code_server_tar_path, "r:gz") as tar:
147
+ tar.extractall(path=DOWNLOAD_DIR)
148
+
149
+ if os.path.exists(DOWNLOAD_DIR):
150
+ code_server_dir_name = os.path.basename(get_code_server_info()).removesuffix(".tar.gz")
151
+ code_server_bin_dir = os.path.join(DOWNLOAD_DIR, code_server_dir_name, "bin")
152
+ # Add the directory of code-server binary to $PATH
153
+ os.environ["PATH"] = code_server_bin_dir + os.pathsep + os.environ["PATH"]
154
+
155
+ # If the extension already exists in the container, skip downloading
156
+ installed_extensions = get_installed_extensions()
157
+ coros = []
158
+
159
+ for extension in get_default_extensions():
160
+ if not is_extension_installed(extension, installed_extensions):
161
+ coros.append(download_file(extension, str(DOWNLOAD_DIR)))
162
+ extension_paths = await asyncio.gather(*coros)
163
+
164
+ coros = []
165
+ for p in extension_paths:
166
+ logger.info(f"Execute extension installation command to install extension {p}")
167
+ coros.append(execute_command(f"code-server --install-extension {p}"))
168
+
169
+ await asyncio.gather(*coros)
170
+
171
+
172
+ def prepare_launch_json(ctx: click.Context, pid: int):
173
+ """
174
+ Generate the launch.json and settings.json for users to easily launch interactive debugging and task resumption.
175
+ """
176
+
177
+ virtual_venv = os.getenv("VIRTUAL_ENV", str(Path(sys.executable).parent.parent))
178
+ if virtual_venv is None:
179
+ raise RuntimeError("VIRTUAL_ENV is not found in environment variables.")
180
+
181
+ run_name = ctx.params["run_name"]
182
+ name = ctx.params["name"]
183
+ # TODO: Executor should pass correct name.
184
+ if run_name.startswith("{{"):
185
+ run_name = os.getenv("RUN_NAME", "")
186
+ if name.startswith("{{"):
187
+ name = os.getenv("ACTION_NAME", "")
188
+
189
+ launch_json = {
190
+ "version": "0.2.0",
191
+ "configurations": [
192
+ {
193
+ "name": "Interactive Debugging",
194
+ "type": "python",
195
+ "request": "launch",
196
+ "program": f"{virtual_venv}/bin/runtime.py",
197
+ "console": "integratedTerminal",
198
+ "justMyCode": True,
199
+ "args": [
200
+ "a0",
201
+ "--inputs",
202
+ ctx.params["inputs"],
203
+ "--outputs-path",
204
+ ctx.params["outputs_path"],
205
+ "--version",
206
+ ctx.params["version"],
207
+ "--run-base-dir",
208
+ ctx.params["run_base_dir"],
209
+ "--name",
210
+ name,
211
+ "--run-name",
212
+ run_name,
213
+ "--project",
214
+ ctx.params["project"],
215
+ "--domain",
216
+ ctx.params["domain"],
217
+ "--org",
218
+ ctx.params["org"],
219
+ "--image-cache",
220
+ ctx.params["image_cache"],
221
+ "--debug",
222
+ "False",
223
+ "--interactive-mode",
224
+ "True",
225
+ "--tgz",
226
+ ctx.params["tgz"],
227
+ "--dest",
228
+ ctx.params["dest"],
229
+ "--resolver",
230
+ ctx.params["resolver"],
231
+ *ctx.params["resolver_args"],
232
+ ],
233
+ },
234
+ {
235
+ "name": "Resume Task",
236
+ "type": "python",
237
+ "request": "launch",
238
+ "program": f"{virtual_venv}/bin/debug.py",
239
+ "console": "integratedTerminal",
240
+ "justMyCode": True,
241
+ "args": ["resume", "--pid", str(pid)],
242
+ },
243
+ ],
244
+ }
245
+
246
+ vscode_directory = os.path.join(os.getcwd(), ".vscode")
247
+ if not os.path.exists(vscode_directory):
248
+ os.makedirs(vscode_directory)
249
+
250
+ with open(os.path.join(vscode_directory, "launch.json"), "w") as file:
251
+ json.dump(launch_json, file, indent=4)
252
+
253
+ settings_json = {"python.defaultInterpreterPath": sys.executable}
254
+ with open(os.path.join(vscode_directory, "settings.json"), "w") as file:
255
+ json.dump(settings_json, file, indent=4)
256
+
257
+
258
+ async def _start_vscode_server(ctx: click.Context):
259
+ if ctx.params["tgz"] is None:
260
+ await download_vscode()
261
+ else:
262
+ await asyncio.gather(
263
+ download_tgz(ctx.params["dest"], ctx.params["version"], ctx.params["tgz"]), download_vscode()
264
+ )
265
+ child_process = multiprocessing.Process(
266
+ target=lambda cmd: asyncio.run(asyncio.run(execute_command(cmd))),
267
+ kwargs={"cmd": f"code-server --bind-addr 0.0.0.0:6060 --disable-workspace-trust --auth none {os.getcwd()}"},
268
+ )
269
+ child_process.start()
270
+ if child_process.pid is None:
271
+ raise RuntimeError("Failed to start vscode server.")
272
+
273
+ prepare_launch_json(ctx, child_process.pid)
274
+
275
+ start_time = time.time()
276
+ check_interval = 60 # Interval for heartbeat checking in seconds
277
+ last_heartbeat_check = time.time() - check_interval
278
+
279
+ def terminate_process():
280
+ if child_process.is_alive():
281
+ child_process.terminate()
282
+ child_process.join()
283
+
284
+ logger.info("waiting for task to resume...")
285
+ while child_process.is_alive():
286
+ current_time = time.time()
287
+ if current_time - last_heartbeat_check >= check_interval:
288
+ last_heartbeat_check = current_time
289
+ if not os.path.exists(HEARTBEAT_PATH):
290
+ delta = current_time - start_time
291
+ logger.info(f"Code server has not been connected since {delta} seconds ago.")
292
+ logger.info("Please open the browser to connect to the running server.")
293
+ else:
294
+ delta = current_time - os.path.getmtime(HEARTBEAT_PATH)
295
+ logger.info(f"The latest activity on code server is {delta} seconds ago.")
296
+
297
+ # If the time from last connection is longer than max idle seconds, terminate the vscode server.
298
+ if delta > MAX_IDLE_SECONDS:
299
+ logger.info(f"VSCode server is idle for more than {MAX_IDLE_SECONDS} seconds. Terminating...")
300
+ terminate_process()
301
+ sys.exit()
302
+
303
+ await asyncio.sleep(1)
304
+
305
+ logger.info("User has resumed the task.")
306
+ terminate_process()
307
+ return