flyte 0.0.1b3__py3-none-any.whl → 0.2.0a0__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 (319) hide show
  1. flyte/__init__.py +20 -4
  2. flyte/_bin/runtime.py +33 -7
  3. flyte/_build.py +3 -2
  4. flyte/_cache/cache.py +1 -2
  5. flyte/_code_bundle/_packaging.py +1 -1
  6. flyte/_code_bundle/_utils.py +0 -16
  7. flyte/_code_bundle/bundle.py +43 -12
  8. flyte/_context.py +8 -2
  9. flyte/_deploy.py +56 -15
  10. flyte/_environment.py +45 -4
  11. flyte/_excepthook.py +37 -0
  12. flyte/_group.py +2 -1
  13. flyte/_image.py +8 -4
  14. flyte/_initialize.py +112 -254
  15. flyte/_interface.py +3 -3
  16. flyte/_internal/controllers/__init__.py +19 -6
  17. flyte/_internal/controllers/_local_controller.py +83 -8
  18. flyte/_internal/controllers/_trace.py +2 -1
  19. flyte/_internal/controllers/remote/__init__.py +27 -7
  20. flyte/_internal/controllers/remote/_action.py +7 -2
  21. flyte/_internal/controllers/remote/_client.py +5 -1
  22. flyte/_internal/controllers/remote/_controller.py +159 -26
  23. flyte/_internal/controllers/remote/_core.py +13 -5
  24. flyte/_internal/controllers/remote/_informer.py +4 -4
  25. flyte/_internal/controllers/remote/_service_protocol.py +6 -6
  26. flyte/_internal/imagebuild/docker_builder.py +12 -1
  27. flyte/_internal/imagebuild/image_builder.py +16 -11
  28. flyte/_internal/runtime/convert.py +164 -21
  29. flyte/_internal/runtime/entrypoints.py +1 -1
  30. flyte/_internal/runtime/io.py +3 -3
  31. flyte/_internal/runtime/task_serde.py +140 -20
  32. flyte/_internal/runtime/taskrunner.py +4 -3
  33. flyte/_internal/runtime/types_serde.py +1 -1
  34. flyte/_logging.py +12 -1
  35. flyte/_map.py +215 -0
  36. flyte/_pod.py +19 -0
  37. flyte/_protos/common/list_pb2.py +3 -3
  38. flyte/_protos/common/list_pb2.pyi +2 -0
  39. flyte/_protos/logs/dataplane/payload_pb2.py +28 -24
  40. flyte/_protos/logs/dataplane/payload_pb2.pyi +11 -2
  41. flyte/_protos/workflow/common_pb2.py +27 -0
  42. flyte/_protos/workflow/common_pb2.pyi +14 -0
  43. flyte/_protos/workflow/environment_pb2.py +29 -0
  44. flyte/_protos/workflow/environment_pb2.pyi +12 -0
  45. flyte/_protos/workflow/queue_service_pb2.py +40 -41
  46. flyte/_protos/workflow/queue_service_pb2.pyi +35 -30
  47. flyte/_protos/workflow/queue_service_pb2_grpc.py +15 -15
  48. flyte/_protos/workflow/run_definition_pb2.py +61 -61
  49. flyte/_protos/workflow/run_definition_pb2.pyi +8 -4
  50. flyte/_protos/workflow/run_service_pb2.py +20 -24
  51. flyte/_protos/workflow/run_service_pb2.pyi +2 -6
  52. flyte/_protos/workflow/state_service_pb2.py +36 -28
  53. flyte/_protos/workflow/state_service_pb2.pyi +19 -15
  54. flyte/_protos/workflow/state_service_pb2_grpc.py +28 -28
  55. flyte/_protos/workflow/task_definition_pb2.py +29 -22
  56. flyte/_protos/workflow/task_definition_pb2.pyi +21 -5
  57. flyte/_protos/workflow/task_service_pb2.py +27 -11
  58. flyte/_protos/workflow/task_service_pb2.pyi +29 -1
  59. flyte/_protos/workflow/task_service_pb2_grpc.py +34 -0
  60. flyte/_run.py +166 -95
  61. flyte/_task.py +110 -28
  62. flyte/_task_environment.py +55 -72
  63. flyte/_trace.py +6 -14
  64. flyte/_utils/__init__.py +6 -0
  65. flyte/_utils/async_cache.py +139 -0
  66. flyte/_utils/coro_management.py +0 -2
  67. flyte/_utils/helpers.py +45 -19
  68. flyte/_utils/org_discovery.py +57 -0
  69. flyte/_version.py +2 -2
  70. flyte/cli/__init__.py +3 -0
  71. flyte/cli/_abort.py +28 -0
  72. flyte/{_cli → cli}/_common.py +73 -23
  73. flyte/cli/_create.py +145 -0
  74. flyte/{_cli → cli}/_delete.py +4 -4
  75. flyte/{_cli → cli}/_deploy.py +26 -14
  76. flyte/cli/_gen.py +163 -0
  77. flyte/{_cli → cli}/_get.py +98 -23
  78. {union/_cli → flyte/cli}/_params.py +106 -147
  79. flyte/{_cli → cli}/_run.py +99 -20
  80. flyte/cli/main.py +166 -0
  81. flyte/config/__init__.py +3 -0
  82. flyte/config/_config.py +216 -0
  83. flyte/config/_internal.py +64 -0
  84. flyte/config/_reader.py +207 -0
  85. flyte/errors.py +29 -0
  86. flyte/extras/_container.py +33 -43
  87. flyte/io/__init__.py +17 -1
  88. flyte/io/_dir.py +2 -2
  89. flyte/io/_file.py +3 -4
  90. flyte/io/{structured_dataset → _structured_dataset}/basic_dfs.py +1 -1
  91. flyte/io/{structured_dataset → _structured_dataset}/structured_dataset.py +1 -1
  92. flyte/{_datastructures.py → models.py} +56 -7
  93. flyte/remote/__init__.py +2 -1
  94. flyte/remote/_client/_protocols.py +2 -0
  95. flyte/remote/_client/auth/_auth_utils.py +14 -0
  96. flyte/remote/_client/auth/_channel.py +34 -3
  97. flyte/remote/_client/auth/_token_client.py +3 -3
  98. flyte/remote/_client/controlplane.py +13 -13
  99. flyte/remote/_console.py +1 -1
  100. flyte/remote/_data.py +10 -6
  101. flyte/remote/_logs.py +89 -29
  102. flyte/remote/_project.py +8 -9
  103. flyte/remote/_run.py +228 -131
  104. flyte/remote/_secret.py +12 -12
  105. flyte/remote/_task.py +179 -15
  106. flyte/report/_report.py +4 -4
  107. flyte/storage/__init__.py +5 -0
  108. flyte/storage/_config.py +233 -0
  109. flyte/storage/_storage.py +23 -3
  110. flyte/syncify/__init__.py +56 -0
  111. flyte/syncify/_api.py +371 -0
  112. flyte/types/__init__.py +23 -0
  113. flyte/types/_interface.py +22 -7
  114. flyte/{io/pickle/transformer.py → types/_pickle.py} +2 -1
  115. flyte/types/_type_engine.py +95 -18
  116. flyte-0.2.0a0.dist-info/METADATA +249 -0
  117. flyte-0.2.0a0.dist-info/RECORD +218 -0
  118. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/entry_points.txt +1 -1
  119. flyte/_api_commons.py +0 -3
  120. flyte/_cli/__init__.py +0 -0
  121. flyte/_cli/_create.py +0 -42
  122. flyte/_cli/main.py +0 -72
  123. flyte/_internal/controllers/pbhash.py +0 -39
  124. flyte/io/_dataframe.py +0 -0
  125. flyte/io/pickle/__init__.py +0 -0
  126. flyte-0.0.1b3.dist-info/METADATA +0 -179
  127. flyte-0.0.1b3.dist-info/RECORD +0 -390
  128. union/__init__.py +0 -54
  129. union/_api_commons.py +0 -3
  130. union/_bin/__init__.py +0 -0
  131. union/_bin/runtime.py +0 -113
  132. union/_build.py +0 -25
  133. union/_cache/__init__.py +0 -12
  134. union/_cache/cache.py +0 -141
  135. union/_cache/defaults.py +0 -9
  136. union/_cache/policy_function_body.py +0 -42
  137. union/_cli/__init__.py +0 -0
  138. union/_cli/_common.py +0 -263
  139. union/_cli/_create.py +0 -40
  140. union/_cli/_delete.py +0 -23
  141. union/_cli/_deploy.py +0 -120
  142. union/_cli/_get.py +0 -162
  143. union/_cli/_run.py +0 -150
  144. union/_cli/main.py +0 -72
  145. union/_code_bundle/__init__.py +0 -8
  146. union/_code_bundle/_ignore.py +0 -113
  147. union/_code_bundle/_packaging.py +0 -187
  148. union/_code_bundle/_utils.py +0 -342
  149. union/_code_bundle/bundle.py +0 -176
  150. union/_context.py +0 -146
  151. union/_datastructures.py +0 -295
  152. union/_deploy.py +0 -185
  153. union/_doc.py +0 -29
  154. union/_docstring.py +0 -26
  155. union/_environment.py +0 -43
  156. union/_group.py +0 -31
  157. union/_hash.py +0 -23
  158. union/_image.py +0 -760
  159. union/_initialize.py +0 -585
  160. union/_interface.py +0 -84
  161. union/_internal/__init__.py +0 -3
  162. union/_internal/controllers/__init__.py +0 -77
  163. union/_internal/controllers/_local_controller.py +0 -77
  164. union/_internal/controllers/pbhash.py +0 -39
  165. union/_internal/controllers/remote/__init__.py +0 -40
  166. union/_internal/controllers/remote/_action.py +0 -131
  167. union/_internal/controllers/remote/_client.py +0 -43
  168. union/_internal/controllers/remote/_controller.py +0 -169
  169. union/_internal/controllers/remote/_core.py +0 -341
  170. union/_internal/controllers/remote/_informer.py +0 -260
  171. union/_internal/controllers/remote/_service_protocol.py +0 -44
  172. union/_internal/imagebuild/__init__.py +0 -11
  173. union/_internal/imagebuild/docker_builder.py +0 -416
  174. union/_internal/imagebuild/image_builder.py +0 -243
  175. union/_internal/imagebuild/remote_builder.py +0 -0
  176. union/_internal/resolvers/__init__.py +0 -0
  177. union/_internal/resolvers/_task_module.py +0 -31
  178. union/_internal/resolvers/common.py +0 -24
  179. union/_internal/resolvers/default.py +0 -27
  180. union/_internal/runtime/__init__.py +0 -0
  181. union/_internal/runtime/convert.py +0 -163
  182. union/_internal/runtime/entrypoints.py +0 -121
  183. union/_internal/runtime/io.py +0 -136
  184. union/_internal/runtime/resources_serde.py +0 -134
  185. union/_internal/runtime/task_serde.py +0 -202
  186. union/_internal/runtime/taskrunner.py +0 -179
  187. union/_internal/runtime/types_serde.py +0 -53
  188. union/_logging.py +0 -124
  189. union/_protos/__init__.py +0 -0
  190. union/_protos/common/authorization_pb2.py +0 -66
  191. union/_protos/common/authorization_pb2.pyi +0 -106
  192. union/_protos/common/identifier_pb2.py +0 -71
  193. union/_protos/common/identifier_pb2.pyi +0 -82
  194. union/_protos/common/identity_pb2.py +0 -48
  195. union/_protos/common/identity_pb2.pyi +0 -72
  196. union/_protos/common/identity_pb2_grpc.py +0 -4
  197. union/_protos/common/list_pb2.py +0 -36
  198. union/_protos/common/list_pb2.pyi +0 -69
  199. union/_protos/common/list_pb2_grpc.py +0 -4
  200. union/_protos/common/policy_pb2.py +0 -37
  201. union/_protos/common/policy_pb2.pyi +0 -27
  202. union/_protos/common/policy_pb2_grpc.py +0 -4
  203. union/_protos/common/role_pb2.py +0 -37
  204. union/_protos/common/role_pb2.pyi +0 -51
  205. union/_protos/common/role_pb2_grpc.py +0 -4
  206. union/_protos/common/runtime_version_pb2.py +0 -28
  207. union/_protos/common/runtime_version_pb2.pyi +0 -24
  208. union/_protos/common/runtime_version_pb2_grpc.py +0 -4
  209. union/_protos/logs/dataplane/payload_pb2.py +0 -96
  210. union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  211. union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  212. union/_protos/secret/definition_pb2.py +0 -49
  213. union/_protos/secret/definition_pb2.pyi +0 -93
  214. union/_protos/secret/definition_pb2_grpc.py +0 -4
  215. union/_protos/secret/payload_pb2.py +0 -62
  216. union/_protos/secret/payload_pb2.pyi +0 -94
  217. union/_protos/secret/payload_pb2_grpc.py +0 -4
  218. union/_protos/secret/secret_pb2.py +0 -38
  219. union/_protos/secret/secret_pb2.pyi +0 -6
  220. union/_protos/secret/secret_pb2_grpc.py +0 -198
  221. union/_protos/validate/validate/validate_pb2.py +0 -76
  222. union/_protos/workflow/node_execution_service_pb2.py +0 -26
  223. union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  224. union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  225. union/_protos/workflow/queue_service_pb2.py +0 -75
  226. union/_protos/workflow/queue_service_pb2.pyi +0 -103
  227. union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  228. union/_protos/workflow/run_definition_pb2.py +0 -100
  229. union/_protos/workflow/run_definition_pb2.pyi +0 -256
  230. union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  231. union/_protos/workflow/run_logs_service_pb2.py +0 -41
  232. union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  233. union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  234. union/_protos/workflow/run_service_pb2.py +0 -133
  235. union/_protos/workflow/run_service_pb2.pyi +0 -173
  236. union/_protos/workflow/run_service_pb2_grpc.py +0 -412
  237. union/_protos/workflow/state_service_pb2.py +0 -58
  238. union/_protos/workflow/state_service_pb2.pyi +0 -69
  239. union/_protos/workflow/state_service_pb2_grpc.py +0 -138
  240. union/_protos/workflow/task_definition_pb2.py +0 -72
  241. union/_protos/workflow/task_definition_pb2.pyi +0 -65
  242. union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  243. union/_protos/workflow/task_service_pb2.py +0 -44
  244. union/_protos/workflow/task_service_pb2.pyi +0 -31
  245. union/_protos/workflow/task_service_pb2_grpc.py +0 -104
  246. union/_resources.py +0 -226
  247. union/_retry.py +0 -32
  248. union/_reusable_environment.py +0 -25
  249. union/_run.py +0 -374
  250. union/_secret.py +0 -61
  251. union/_task.py +0 -354
  252. union/_task_environment.py +0 -186
  253. union/_timeout.py +0 -47
  254. union/_tools.py +0 -27
  255. union/_utils/__init__.py +0 -11
  256. union/_utils/asyn.py +0 -119
  257. union/_utils/file_handling.py +0 -71
  258. union/_utils/helpers.py +0 -46
  259. union/_utils/lazy_module.py +0 -54
  260. union/_utils/uv_script_parser.py +0 -49
  261. union/_version.py +0 -21
  262. union/connectors/__init__.py +0 -0
  263. union/errors.py +0 -128
  264. union/extras/__init__.py +0 -5
  265. union/extras/_container.py +0 -263
  266. union/io/__init__.py +0 -11
  267. union/io/_dataframe.py +0 -0
  268. union/io/_dir.py +0 -425
  269. union/io/_file.py +0 -418
  270. union/io/pickle/__init__.py +0 -0
  271. union/io/pickle/transformer.py +0 -117
  272. union/io/structured_dataset/__init__.py +0 -122
  273. union/io/structured_dataset/basic_dfs.py +0 -219
  274. union/io/structured_dataset/structured_dataset.py +0 -1057
  275. union/py.typed +0 -0
  276. union/remote/__init__.py +0 -23
  277. union/remote/_client/__init__.py +0 -0
  278. union/remote/_client/_protocols.py +0 -129
  279. union/remote/_client/auth/__init__.py +0 -12
  280. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  281. union/remote/_client/auth/_authenticators/base.py +0 -391
  282. union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
  283. union/remote/_client/auth/_authenticators/device_code.py +0 -120
  284. union/remote/_client/auth/_authenticators/external_command.py +0 -77
  285. union/remote/_client/auth/_authenticators/factory.py +0 -200
  286. union/remote/_client/auth/_authenticators/pkce.py +0 -515
  287. union/remote/_client/auth/_channel.py +0 -184
  288. union/remote/_client/auth/_client_config.py +0 -83
  289. union/remote/_client/auth/_default_html.py +0 -32
  290. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  291. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
  292. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
  293. union/remote/_client/auth/_keyring.py +0 -154
  294. union/remote/_client/auth/_token_client.py +0 -258
  295. union/remote/_client/auth/errors.py +0 -16
  296. union/remote/_client/controlplane.py +0 -86
  297. union/remote/_data.py +0 -149
  298. union/remote/_logs.py +0 -74
  299. union/remote/_project.py +0 -86
  300. union/remote/_run.py +0 -820
  301. union/remote/_secret.py +0 -132
  302. union/remote/_task.py +0 -193
  303. union/report/__init__.py +0 -3
  304. union/report/_report.py +0 -178
  305. union/report/_template.html +0 -124
  306. union/storage/__init__.py +0 -24
  307. union/storage/_remote_fs.py +0 -34
  308. union/storage/_storage.py +0 -247
  309. union/storage/_utils.py +0 -5
  310. union/types/__init__.py +0 -11
  311. union/types/_renderer.py +0 -162
  312. union/types/_string_literals.py +0 -120
  313. union/types/_type_engine.py +0 -2131
  314. union/types/_utils.py +0 -80
  315. /union/_protos/common/authorization_pb2_grpc.py → /flyte/_protos/workflow/common_pb2_grpc.py +0 -0
  316. /union/_protos/common/identifier_pb2_grpc.py → /flyte/_protos/workflow/environment_pb2_grpc.py +0 -0
  317. /flyte/io/{structured_dataset → _structured_dataset}/__init__.py +0 -0
  318. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/WHEEL +0 -0
  319. {flyte-0.0.1b3.dist-info → flyte-0.2.0a0.dist-info}/top_level.txt +0 -0
flyte/cli/main.py ADDED
@@ -0,0 +1,166 @@
1
+ import rich_click as click
2
+
3
+ from flyte._logging import initialize_logger, logger
4
+
5
+ from ._abort import abort
6
+ from ._common import CLIConfig
7
+ from ._create import create
8
+ from ._delete import delete
9
+ from ._deploy import deploy
10
+ from ._gen import gen
11
+ from ._get import get
12
+ from ._run import run
13
+
14
+ help_config = click.RichHelpConfiguration(
15
+ use_markdown=True,
16
+ use_markdown_emoji=True,
17
+ command_groups={
18
+ "flyte": [
19
+ {
20
+ "name": "Run and stop tasks",
21
+ "commands": ["run", "abort"],
22
+ },
23
+ {
24
+ "name": "Management",
25
+ "commands": ["create", "deploy", "get", "delete"],
26
+ },
27
+ {
28
+ "name": "Documentation generation",
29
+ "commands": ["gen"],
30
+ },
31
+ ]
32
+ },
33
+ )
34
+
35
+
36
+ def _verbosity_to_loglevel(verbosity: int) -> int | None:
37
+ """
38
+ Converts a verbosity level from the CLI to a logging level.
39
+
40
+ :param verbosity: verbosity level from the CLI
41
+ :return: logging level
42
+ """
43
+ import logging
44
+
45
+ match verbosity:
46
+ case 0:
47
+ return None
48
+ case 1:
49
+ return logging.WARNING
50
+ case 2:
51
+ return logging.INFO
52
+ case _:
53
+ return logging.DEBUG
54
+
55
+
56
+ @click.group(cls=click.RichGroup)
57
+ @click.option(
58
+ "--endpoint",
59
+ type=str,
60
+ required=False,
61
+ help="The endpoint to connect to. This will override any configuration file and simply use `pkce` to connect.",
62
+ )
63
+ @click.option(
64
+ "--insecure",
65
+ is_flag=True,
66
+ required=False,
67
+ help="Use an insecure connection to the endpoint. If not specified, the CLI will use TLS.",
68
+ type=bool,
69
+ default=None,
70
+ show_default=True,
71
+ )
72
+ @click.option(
73
+ "-v",
74
+ "--verbose",
75
+ required=False,
76
+ help="Show verbose messages and exception traces. Repeating multiple times increases the verbosity (e.g., -vvv).",
77
+ count=True,
78
+ default=0,
79
+ type=int,
80
+ )
81
+ @click.option(
82
+ "--org",
83
+ type=str,
84
+ required=False,
85
+ help="The organization to which the command applies.",
86
+ )
87
+ @click.option(
88
+ "-c",
89
+ "--config",
90
+ "config_file",
91
+ required=False,
92
+ type=click.Path(exists=True),
93
+ help="Path to the configuration file to use. If not specified, the default configuration file is used.",
94
+ )
95
+ @click.rich_config(help_config=help_config)
96
+ @click.pass_context
97
+ def main(
98
+ ctx: click.Context,
99
+ endpoint: str | None,
100
+ insecure: bool,
101
+ verbose: int,
102
+ org: str | None,
103
+ config_file: str | None,
104
+ ):
105
+ """
106
+ The Flyte CLI is the command line interface for working with the Flyte SDK and backend.
107
+
108
+ It follows a simple verb/noun structure,
109
+ where the top-level commands are verbs that describe the action to be taken,
110
+ and the subcommands are nouns that describe the object of the action.
111
+
112
+ The root command can be used to configure the CLI for persistent settings,
113
+ such as the endpoint, organization, and verbosity level.
114
+
115
+ Set endpoint and organization:
116
+
117
+ ```bash
118
+ $ flyte --endpoint <endpoint> --org <org> get project <project_name>
119
+ ```
120
+
121
+ Increase verbosity level (This is useful for debugging,
122
+ this will show more logs and exception traces):
123
+
124
+ ```bash
125
+ $ flyte -vvv get logs <run-name>
126
+ ```
127
+
128
+ Override the default config file:
129
+
130
+ ```bash
131
+ $ flyte --config /path/to/config.yaml run ...
132
+ ```
133
+
134
+ * [Documentation](https://www.union.ai/docs/flyte/user-guide/)
135
+ * [GitHub](https://github.com/flyteorg/flyte): Please leave a star if you like Flyte!
136
+ * [Slack](https://slack.flyte.org): Join the community and ask questions.
137
+ * [Issues](https://github.com/flyteorg/flyte/issues)
138
+
139
+ """
140
+ import flyte.config as config
141
+
142
+ log_level = _verbosity_to_loglevel(verbose)
143
+ if log_level is not None:
144
+ initialize_logger(log_level)
145
+
146
+ cfg = config.auto(config_file=config_file)
147
+ if cfg.source:
148
+ logger.debug(f"Using config file discovered at location `{cfg.source.absolute()}`")
149
+
150
+ ctx.obj = CLIConfig(
151
+ log_level=log_level,
152
+ endpoint=endpoint,
153
+ insecure=insecure,
154
+ org=org,
155
+ config=cfg,
156
+ ctx=ctx,
157
+ )
158
+
159
+
160
+ main.add_command(run)
161
+ main.add_command(deploy)
162
+ main.add_command(get) # type: ignore
163
+ main.add_command(create) # type: ignore
164
+ main.add_command(abort) # type: ignore
165
+ main.add_command(gen) # type: ignore
166
+ main.add_command(delete) # type: ignore
@@ -0,0 +1,3 @@
1
+ from flyte.config._config import Config, auto, get_config_file, set_if_exists
2
+
3
+ __all__ = ["Config", "auto", "get_config_file", "set_if_exists"]
@@ -0,0 +1,216 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import os
5
+ import pathlib
6
+ import typing
7
+ from dataclasses import dataclass, field
8
+ from typing import TYPE_CHECKING
9
+
10
+ import rich.repr
11
+
12
+ from flyte._logging import logger
13
+ from flyte.config import _internal
14
+ from flyte.config._reader import ConfigFile, get_config_file, read_file_if_exists
15
+
16
+ _all__ = ["ConfigFile", "PlatformConfig", "TaskConfig"]
17
+
18
+ if TYPE_CHECKING:
19
+ from flyte.remote._client.auth import AuthType
20
+
21
+
22
+ @rich.repr.auto
23
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
24
+ class PlatformConfig(object):
25
+ """
26
+ This object contains the settings to talk to a Flyte backend (the DNS location of your Admin server basically).
27
+
28
+ :param endpoint: DNS for Flyte backend
29
+ :param insecure: Whether or not to use SSL
30
+ :param insecure_skip_verify: Whether to skip SSL certificate verification
31
+ :param console_endpoint: endpoint for console if different from Flyte backend
32
+ :param command: This command is executed to return a token using an external process
33
+ :param proxy_command: This command is executed to return a token for proxy authorization using an external process
34
+ :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
35
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
36
+ :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
37
+ allow the Flyte engine to read the password directly from the environment variable. Note that this is
38
+ less secure! Please only use this if mounting the secret as a file is impossible
39
+ :param scopes: List of scopes to request. This is only applicable to the client credentials flow
40
+ :param auth_mode: The OAuth mode to use. Defaults to pkce flow
41
+ :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
42
+ :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
43
+ """
44
+
45
+ endpoint: str | None = None
46
+ insecure: bool = False
47
+ insecure_skip_verify: bool = False
48
+ ca_cert_file_path: typing.Optional[str] = None
49
+ console_endpoint: typing.Optional[str] = None
50
+ command: typing.Optional[typing.List[str]] = None
51
+ proxy_command: typing.Optional[typing.List[str]] = None
52
+ client_id: typing.Optional[str] = None
53
+ client_credentials_secret: typing.Optional[str] = None
54
+ scopes: typing.List[str] = field(default_factory=list)
55
+ auth_mode: "AuthType" = "Pkce"
56
+ audience: typing.Optional[str] = None
57
+ rpc_retries: int = 3
58
+ http_proxy_url: typing.Optional[str] = None
59
+
60
+ @classmethod
61
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "PlatformConfig":
62
+ """
63
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
64
+ :param config_file:
65
+ :return:
66
+ """
67
+
68
+ config_file = get_config_file(config_file)
69
+ kwargs: typing.Dict[str, typing.Any] = {}
70
+ kwargs = set_if_exists(kwargs, "insecure", _internal.Platform.INSECURE.read(config_file))
71
+ kwargs = set_if_exists(
72
+ kwargs, "insecure_skip_verify", _internal.Platform.INSECURE_SKIP_VERIFY.read(config_file)
73
+ )
74
+ kwargs = set_if_exists(kwargs, "ca_cert_file_path", _internal.Platform.CA_CERT_FILE_PATH.read(config_file))
75
+ kwargs = set_if_exists(kwargs, "command", _internal.Credentials.COMMAND.read(config_file))
76
+ kwargs = set_if_exists(kwargs, "proxy_command", _internal.Credentials.PROXY_COMMAND.read(config_file))
77
+ kwargs = set_if_exists(kwargs, "client_id", _internal.Credentials.CLIENT_ID.read(config_file))
78
+
79
+ is_client_secret = False
80
+ client_credentials_secret = read_file_if_exists(
81
+ _internal.Credentials.CLIENT_CREDENTIALS_SECRET_LOCATION.read(config_file)
82
+ )
83
+ if client_credentials_secret:
84
+ is_client_secret = True
85
+ if client_credentials_secret.endswith("\n"):
86
+ logger.info("Newline stripped from client secret")
87
+ client_credentials_secret = client_credentials_secret.strip()
88
+ kwargs = set_if_exists(
89
+ kwargs,
90
+ "client_credentials_secret",
91
+ client_credentials_secret,
92
+ )
93
+
94
+ client_credentials_secret_env_var = _internal.Credentials.CLIENT_CREDENTIALS_SECRET_ENV_VAR.read(config_file)
95
+ if client_credentials_secret_env_var:
96
+ client_credentials_secret = os.getenv(client_credentials_secret_env_var)
97
+ if client_credentials_secret:
98
+ is_client_secret = True
99
+ kwargs = set_if_exists(kwargs, "client_credentials_secret", client_credentials_secret)
100
+ kwargs = set_if_exists(kwargs, "scopes", _internal.Credentials.SCOPES.read(config_file))
101
+ kwargs = set_if_exists(kwargs, "auth_mode", _internal.Credentials.AUTH_MODE.read(config_file))
102
+ if is_client_secret:
103
+ kwargs = set_if_exists(kwargs, "auth_mode", "ClientSecret")
104
+ kwargs = set_if_exists(kwargs, "endpoint", _internal.Platform.URL.read(config_file))
105
+ kwargs = set_if_exists(kwargs, "console_endpoint", _internal.Platform.CONSOLE_ENDPOINT.read(config_file))
106
+
107
+ kwargs = set_if_exists(kwargs, "http_proxy_url", _internal.Platform.HTTP_PROXY_URL.read(config_file))
108
+ return PlatformConfig(**kwargs)
109
+
110
+ def replace(self, **kwargs: typing.Any) -> "PlatformConfig":
111
+ """
112
+ Returns a new PlatformConfig instance with the values from the kwargs overriding the current instance.
113
+ """
114
+ return dataclasses.replace(self, **kwargs)
115
+
116
+ @classmethod
117
+ def for_endpoint(cls, endpoint: str, insecure: bool = False) -> "PlatformConfig":
118
+ return PlatformConfig(endpoint=endpoint, insecure=insecure)
119
+
120
+
121
+ @rich.repr.auto
122
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
123
+ class TaskConfig(object):
124
+ org: str | None = None
125
+ project: str | None = None
126
+ domain: str | None = None
127
+
128
+ @classmethod
129
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "TaskConfig":
130
+ """
131
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
132
+ :param config_file:
133
+ :return:
134
+ """
135
+ config_file = get_config_file(config_file)
136
+ kwargs: typing.Dict[str, typing.Any] = {}
137
+ kwargs = set_if_exists(kwargs, "org", _internal.Task.ORG.read(config_file))
138
+ kwargs = set_if_exists(kwargs, "project", _internal.Task.PROJECT.read(config_file))
139
+ kwargs = set_if_exists(kwargs, "domain", _internal.Task.DOMAIN.read(config_file))
140
+ return TaskConfig(**kwargs)
141
+
142
+
143
+ @rich.repr.auto
144
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
145
+ class Config(object):
146
+ """
147
+ This the parent configuration object and holds all the underlying configuration object types. An instance of
148
+ this object holds all the config necessary to
149
+
150
+ 1. Interactive session with Flyte backend
151
+ 2. Some parts are required for Serialization, for example Platform Config is not required
152
+ 3. Runtime of a task
153
+ """
154
+
155
+ platform: PlatformConfig = field(default=PlatformConfig())
156
+ task: TaskConfig = field(default=TaskConfig())
157
+ source: pathlib.Path | None = None
158
+
159
+ def with_params(
160
+ self,
161
+ platform: PlatformConfig | None = None,
162
+ task: TaskConfig | None = None,
163
+ ) -> "Config":
164
+ return Config(
165
+ platform=platform or self.platform,
166
+ task=task or self.task,
167
+ )
168
+
169
+ @classmethod
170
+ def auto(cls, config_file: typing.Union[str, ConfigFile, None] = None) -> "Config":
171
+ """
172
+ Automatically constructs the Config Object. The order of precedence is as follows
173
+ 1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
174
+ 2. If not found in environment then values ar read from the config file
175
+ 3. If not found in the file, then the default values are used.
176
+
177
+ :param config_file: file path to read the config from, if not specified default locations are searched
178
+ :return: Config
179
+ """
180
+ config_file = get_config_file(config_file)
181
+ if config_file is None:
182
+ logger.debug("No config file found, using default values")
183
+ return Config()
184
+ return Config(
185
+ platform=PlatformConfig.auto(config_file), task=TaskConfig.auto(config_file), source=config_file.path
186
+ )
187
+
188
+
189
+ def set_if_exists(d: dict, k: str, val: typing.Any) -> dict:
190
+ """
191
+ Given a dict ``d`` sets the key ``k`` with value of config ``v``, if the config value ``v`` is set
192
+ and return the updated dictionary.
193
+ """
194
+ exists = isinstance(val, bool) or bool(val is not None and val)
195
+ if exists:
196
+ d[k] = val
197
+ return d
198
+
199
+
200
+ def auto(config_file: typing.Union[str, ConfigFile, None] = None) -> Config:
201
+ """
202
+ Automatically constructs the Config Object. The order of precedence is as follows
203
+ 1. If specified, read the config from the provided file path.
204
+ 2. If not specified, the config file is searched in the default locations.
205
+ a. ./config.yaml if it exists (current working directory)
206
+ b. `UCTL_CONFIG` environment variable
207
+ c. `FLYTECTL_CONFIG` environment variable
208
+ d. ~/.union/config.yaml if it exists
209
+ e. ~/.flyte/config.yaml if it exists
210
+ 3. If any value is not found in the config file, the default value is used.
211
+ 4. For any value there are environment variables that match the config variable names, those will override
212
+
213
+ :param config_file: file path to read the config from, if not specified default locations are searched
214
+ :return: Config
215
+ """
216
+ return Config.auto(config_file)
@@ -0,0 +1,64 @@
1
+ from flyte.config._reader import ConfigEntry, YamlConfigEntry
2
+
3
+
4
+ class Platform(object):
5
+ URL = ConfigEntry(YamlConfigEntry("admin.endpoint"))
6
+ INSECURE = ConfigEntry(YamlConfigEntry("admin.insecure", bool))
7
+ INSECURE_SKIP_VERIFY = ConfigEntry(YamlConfigEntry("admin.insecureSkipVerify", bool))
8
+ CONSOLE_ENDPOINT = ConfigEntry(YamlConfigEntry("console.endpoint"))
9
+ CA_CERT_FILE_PATH = ConfigEntry(YamlConfigEntry("admin.caCertFilePath"))
10
+ HTTP_PROXY_URL = ConfigEntry(YamlConfigEntry("admin.httpProxyURL"))
11
+
12
+
13
+ class Credentials(object):
14
+ SECTION = "credentials"
15
+ COMMAND = ConfigEntry(YamlConfigEntry("admin.command", list))
16
+ """
17
+ This command is executed to return a token using an external process.
18
+ """
19
+
20
+ PROXY_COMMAND = ConfigEntry(YamlConfigEntry("admin.proxyCommand", list))
21
+ """
22
+ This command is executed to return a token for authorization with a proxy
23
+ in front of Flyte using an external process.
24
+ """
25
+
26
+ CLIENT_ID = ConfigEntry(YamlConfigEntry("admin.clientId"))
27
+ """
28
+ This is the public identifier for the app which handles authorization for a Flyte deployment.
29
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
30
+ """
31
+
32
+ CLIENT_CREDENTIALS_SECRET_LOCATION = ConfigEntry(YamlConfigEntry("admin.clientSecretLocation"))
33
+ """
34
+ Used for basic auth, which is automatically called during pyflyte. This will allow the Flyte engine to read the
35
+ password from a mounted file.
36
+ """
37
+
38
+ CLIENT_CREDENTIALS_SECRET_ENV_VAR = ConfigEntry(YamlConfigEntry("admin.clientSecretEnvVar"))
39
+ """
40
+ Used for basic auth, which is automatically called during pyflyte. This will allow the Flyte engine to read the
41
+ password from a mounted environment variable.
42
+ """
43
+
44
+ SCOPES = ConfigEntry(YamlConfigEntry("admin.scopes", list))
45
+ """
46
+ This setting can be used to manually pass in scopes into authenticator flows - eg.) for Auth0 compatibility
47
+ """
48
+
49
+ AUTH_MODE = ConfigEntry(YamlConfigEntry("admin.authType"))
50
+ """
51
+ The auth mode defines the behavior used to request and refresh credentials. The currently supported modes include:
52
+ - 'standard' or 'Pkce': This uses the pkce-enhanced authorization code flow by opening a browser window to initiate
53
+ credentials access.
54
+ - "DeviceFlow": This uses the Device Authorization Flow
55
+ - 'basic', 'client_credentials' or 'clientSecret': This uses symmetric key auth in which the end user enters a
56
+ client id and a client secret and public key encryption is used to facilitate authentication.
57
+ - None: No auth will be attempted.
58
+ """
59
+
60
+
61
+ class Task(object):
62
+ ORG = ConfigEntry(YamlConfigEntry("task.org"))
63
+ PROJECT = ConfigEntry(YamlConfigEntry("task.project"))
64
+ DOMAIN = ConfigEntry(YamlConfigEntry("task.domain"))
@@ -0,0 +1,207 @@
1
+ import os
2
+ import pathlib
3
+ import typing
4
+ from dataclasses import dataclass
5
+ from functools import lru_cache
6
+ from os import getenv
7
+ from pathlib import Path
8
+
9
+ import yaml
10
+
11
+ from flyte._logging import logger
12
+
13
+ # This is the default config file name for flyte
14
+ FLYTECTL_CONFIG_ENV_VAR = "FLYTECTL_CONFIG"
15
+ UCTL_CONFIG_ENV_VAR = "UCTL_CONFIG"
16
+
17
+
18
+ @dataclass
19
+ class YamlConfigEntry(object):
20
+ """
21
+ Creates a record for the config entry.
22
+ Args:
23
+ switch: dot-delimited string that should match flytectl args. Leaving it as dot-delimited instead of a list
24
+ of strings because it's easier to maintain alignment with flytectl.
25
+ config_value_type: Expected type of the value
26
+ """
27
+
28
+ switch: str
29
+ config_value_type: typing.Type = str
30
+
31
+ def get_env_name(self) -> str:
32
+ var_name = self.switch.upper().replace(".", "_")
33
+ return f"FLYTE_{var_name}"
34
+
35
+ def read_from_env(self, transform: typing.Optional[typing.Callable] = None) -> typing.Optional[typing.Any]:
36
+ """
37
+ Reads the config entry from environment variable, the structure of the env var is current
38
+ ``FLYTE_{SECTION}_{OPTION}`` all upper cased. We will change this in the future.
39
+ :return:
40
+ """
41
+ env = self.get_env_name()
42
+ v = os.environ.get(env, None)
43
+ if v is None:
44
+ return None
45
+ return transform(v) if transform else v
46
+
47
+ def read_from_file(
48
+ self, cfg: "ConfigFile", transform: typing.Optional[typing.Callable] = None
49
+ ) -> typing.Optional[typing.Any]:
50
+ if not cfg:
51
+ return None
52
+ try:
53
+ v = cfg.get(self)
54
+ if isinstance(v, bool) or bool(v is not None and v):
55
+ return transform(v) if transform else v
56
+ except Exception:
57
+ ...
58
+
59
+ return None
60
+
61
+
62
+ @dataclass
63
+ class ConfigEntry(object):
64
+ """
65
+ A top level Config entry holder, that holds multiple different representations of the config.
66
+ Legacy means the INI style config files. YAML support is for the flytectl config file, which is there by default
67
+ when flytectl starts a sandbox
68
+ """
69
+
70
+ yaml_entry: YamlConfigEntry
71
+ transform: typing.Optional[typing.Callable[[str], typing.Any]] = None
72
+
73
+ def read(self, cfg: typing.Optional["ConfigFile"] = None) -> typing.Optional[typing.Any]:
74
+ """
75
+ Reads the config Entry from the various sources in the following order,
76
+ #. First try to read from the relevant environment variable,
77
+ #. If missing, then try to read from the legacy config file, if one was parsed.
78
+ #. If missing, then try to read from the yaml file.
79
+
80
+ The constructor for ConfigFile currently does not allow specification of both the ini and yaml style formats.
81
+
82
+ :param cfg:
83
+ :return:
84
+ """
85
+ from_env = self.yaml_entry.read_from_env(self.transform)
86
+ if from_env is not None:
87
+ return from_env
88
+ if cfg and cfg.yaml_config and self.yaml_entry:
89
+ return self.yaml_entry.read_from_file(cfg, self.transform)
90
+
91
+ return None
92
+
93
+
94
+ class ConfigFile(object):
95
+ def __init__(self, location: str):
96
+ """
97
+ Load the config from this location
98
+ """
99
+ self._location = location
100
+ self._yaml_config = self._read_yaml_config(location)
101
+
102
+ @property
103
+ def path(self) -> pathlib.Path:
104
+ """
105
+ Returns the path to the config file.
106
+ :return: Path to the config file
107
+ """
108
+ return pathlib.Path(self._location)
109
+
110
+ @staticmethod
111
+ def _read_yaml_config(location: str) -> typing.Optional[typing.Dict[str, typing.Any]]:
112
+ with open(location, "r") as fh:
113
+ try:
114
+ yaml_contents = yaml.safe_load(fh)
115
+ return yaml_contents
116
+ except yaml.YAMLError as exc:
117
+ logger.warning(f"Error {exc} reading yaml config file at {location}, ignoring...")
118
+ return None
119
+
120
+ def _get_from_yaml(self, c: YamlConfigEntry) -> typing.Any:
121
+ keys = c.switch.split(".") # flytectl switches are dot delimited
122
+ d = typing.cast(typing.Dict[str, typing.Any], self.yaml_config)
123
+ try:
124
+ for k in keys:
125
+ d = d[k]
126
+ return d
127
+ except KeyError:
128
+ return None
129
+
130
+ def get(self, c: YamlConfigEntry) -> typing.Any:
131
+ return self._get_from_yaml(c)
132
+
133
+ @property
134
+ def yaml_config(self) -> typing.Dict[str, typing.Any] | None:
135
+ return self._yaml_config
136
+
137
+
138
+ def resolve_config_path() -> pathlib.Path | None:
139
+ """
140
+ Config is read from the following locations in order of precedence:
141
+ 1. ./config.yaml if it exists
142
+ 2. `UCTL_CONFIG` environment variable
143
+ 3. `FLYTECTL_CONFIG` environment variable
144
+ 4. ~/.union/config.yaml if it exists
145
+ 5. ~/.flyte/config.yaml if it exists
146
+ """
147
+ current_location_config = Path("config.yaml")
148
+ if current_location_config.exists():
149
+ return current_location_config
150
+ logger.debug("No ./config.yaml found, returning None")
151
+
152
+ uctl_path_from_env = getenv(UCTL_CONFIG_ENV_VAR, None)
153
+ if uctl_path_from_env:
154
+ return pathlib.Path(uctl_path_from_env)
155
+ logger.debug("No UCTL_CONFIG environment variable found, checking FLYTECTL_CONFIG")
156
+
157
+ flytectl_path_from_env = getenv(FLYTECTL_CONFIG_ENV_VAR, None)
158
+ if flytectl_path_from_env:
159
+ return pathlib.Path(flytectl_path_from_env)
160
+ logger.debug("No FLYTECTL_CONFIG environment variable found, checking default locations")
161
+
162
+ home_dir_union_config = Path(Path.home(), ".union", "config.yaml")
163
+ if home_dir_union_config.exists():
164
+ return home_dir_union_config
165
+ logger.debug("No ~/.union/config.yaml found, checking current directory")
166
+
167
+ home_dir_flytectl_config = Path(Path.home(), ".flyte", "config.yaml")
168
+ if home_dir_flytectl_config.exists():
169
+ return home_dir_flytectl_config
170
+ logger.debug("No ~/.flyte/config.yaml found, checking current directory")
171
+
172
+ return None
173
+
174
+
175
+ @lru_cache
176
+ def get_config_file(c: typing.Union[str, ConfigFile, None]) -> ConfigFile | None:
177
+ """
178
+ Checks if the given argument is a file or a configFile and returns a loaded configFile else returns None
179
+ """
180
+ if "PYTEST_VERSION" in os.environ:
181
+ # Use default local config in the pytest environment
182
+ return None
183
+ if isinstance(c, str):
184
+ logger.debug(f"Using specified config file at {c}")
185
+ return ConfigFile(c)
186
+ elif isinstance(c, ConfigFile):
187
+ return c
188
+ config_path = resolve_config_path()
189
+ if config_path:
190
+ return ConfigFile(str(config_path))
191
+ return None
192
+
193
+
194
+ def read_file_if_exists(filename: typing.Optional[str], encoding=None) -> typing.Optional[str]:
195
+ """
196
+ Reads the contents of the file if passed a path. Otherwise, returns None.
197
+
198
+ :param filename: The file path to load
199
+ :param encoding: The encoding to use when reading the file.
200
+ :return: The contents of the file as a string or None.
201
+ """
202
+ if not filename:
203
+ return None
204
+
205
+ file = pathlib.Path(filename)
206
+ logger.debug(f"Reading file contents from [{file}] with current directory [{os.getcwd()}].")
207
+ return file.read_text(encoding=encoding)
flyte/errors.py CHANGED
@@ -141,3 +141,32 @@ class ReferenceTaskError(RuntimeUserError):
141
141
 
142
142
  def __init__(self, message: str):
143
143
  super().__init__("ReferenceTaskUsageError", message, "user")
144
+
145
+
146
+ class LogsNotYetAvailableError(BaseRuntimeError):
147
+ """
148
+ This error is raised when the logs are not yet available for a task.
149
+ """
150
+
151
+ def __init__(self, message: str):
152
+ super().__init__("LogsNotYetAvailable", "system", message, None)
153
+
154
+
155
+ class RuntimeDataValidationError(RuntimeUserError):
156
+ """
157
+ This error is raised when the user tries to access a resource that does not exist or is invalid.
158
+ """
159
+
160
+ def __init__(self, var: str, e: Exception, task_name: str = ""):
161
+ super().__init__(
162
+ "DataValiationError", f"In task {task_name} variable {var}, failed to serialize/deserialize because {e}"
163
+ )
164
+
165
+
166
+ class DeploymentError(RuntimeUserError):
167
+ """
168
+ This error is raised when the deployment of a task fails, or some preconditions for deployment are not met.
169
+ """
170
+
171
+ def __init__(self, message: str):
172
+ super().__init__("DeploymentError", message, "user")