flyte 0.0.1b3__py3-none-any.whl → 0.2.0b0__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 (209) hide show
  1. flyte/_cli/_common.py +12 -0
  2. {union → flyte}/_cli/_params.py +106 -147
  3. flyte/_cli/_run.py +24 -2
  4. flyte/_cli/main.py +28 -2
  5. flyte/_image.py +1 -2
  6. flyte/_initialize.py +24 -15
  7. flyte/_internal/runtime/convert.py +6 -0
  8. flyte/_run.py +0 -1
  9. flyte/_version.py +2 -2
  10. flyte/config/__init__.py +168 -0
  11. flyte/config/_config.py +196 -0
  12. flyte/config/_internal.py +64 -0
  13. flyte/remote/_console.py +1 -1
  14. flyte/types/_type_engine.py +4 -3
  15. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/METADATA +1 -1
  16. flyte-0.2.0b0.dist-info/RECORD +204 -0
  17. flyte-0.0.1b3.dist-info/RECORD +0 -390
  18. union/__init__.py +0 -54
  19. union/_api_commons.py +0 -3
  20. union/_bin/__init__.py +0 -0
  21. union/_bin/runtime.py +0 -113
  22. union/_build.py +0 -25
  23. union/_cache/__init__.py +0 -12
  24. union/_cache/cache.py +0 -141
  25. union/_cache/defaults.py +0 -9
  26. union/_cache/policy_function_body.py +0 -42
  27. union/_cli/__init__.py +0 -0
  28. union/_cli/_common.py +0 -263
  29. union/_cli/_create.py +0 -40
  30. union/_cli/_delete.py +0 -23
  31. union/_cli/_deploy.py +0 -120
  32. union/_cli/_get.py +0 -162
  33. union/_cli/_run.py +0 -150
  34. union/_cli/main.py +0 -72
  35. union/_code_bundle/__init__.py +0 -8
  36. union/_code_bundle/_ignore.py +0 -113
  37. union/_code_bundle/_packaging.py +0 -187
  38. union/_code_bundle/_utils.py +0 -342
  39. union/_code_bundle/bundle.py +0 -176
  40. union/_context.py +0 -146
  41. union/_datastructures.py +0 -295
  42. union/_deploy.py +0 -185
  43. union/_doc.py +0 -29
  44. union/_docstring.py +0 -26
  45. union/_environment.py +0 -43
  46. union/_group.py +0 -31
  47. union/_hash.py +0 -23
  48. union/_image.py +0 -760
  49. union/_initialize.py +0 -585
  50. union/_interface.py +0 -84
  51. union/_internal/__init__.py +0 -3
  52. union/_internal/controllers/__init__.py +0 -77
  53. union/_internal/controllers/_local_controller.py +0 -77
  54. union/_internal/controllers/pbhash.py +0 -39
  55. union/_internal/controllers/remote/__init__.py +0 -40
  56. union/_internal/controllers/remote/_action.py +0 -131
  57. union/_internal/controllers/remote/_client.py +0 -43
  58. union/_internal/controllers/remote/_controller.py +0 -169
  59. union/_internal/controllers/remote/_core.py +0 -341
  60. union/_internal/controllers/remote/_informer.py +0 -260
  61. union/_internal/controllers/remote/_service_protocol.py +0 -44
  62. union/_internal/imagebuild/__init__.py +0 -11
  63. union/_internal/imagebuild/docker_builder.py +0 -416
  64. union/_internal/imagebuild/image_builder.py +0 -243
  65. union/_internal/imagebuild/remote_builder.py +0 -0
  66. union/_internal/resolvers/__init__.py +0 -0
  67. union/_internal/resolvers/_task_module.py +0 -31
  68. union/_internal/resolvers/common.py +0 -24
  69. union/_internal/resolvers/default.py +0 -27
  70. union/_internal/runtime/__init__.py +0 -0
  71. union/_internal/runtime/convert.py +0 -163
  72. union/_internal/runtime/entrypoints.py +0 -121
  73. union/_internal/runtime/io.py +0 -136
  74. union/_internal/runtime/resources_serde.py +0 -134
  75. union/_internal/runtime/task_serde.py +0 -202
  76. union/_internal/runtime/taskrunner.py +0 -179
  77. union/_internal/runtime/types_serde.py +0 -53
  78. union/_logging.py +0 -124
  79. union/_protos/__init__.py +0 -0
  80. union/_protos/common/authorization_pb2.py +0 -66
  81. union/_protos/common/authorization_pb2.pyi +0 -106
  82. union/_protos/common/authorization_pb2_grpc.py +0 -4
  83. union/_protos/common/identifier_pb2.py +0 -71
  84. union/_protos/common/identifier_pb2.pyi +0 -82
  85. union/_protos/common/identifier_pb2_grpc.py +0 -4
  86. union/_protos/common/identity_pb2.py +0 -48
  87. union/_protos/common/identity_pb2.pyi +0 -72
  88. union/_protos/common/identity_pb2_grpc.py +0 -4
  89. union/_protos/common/list_pb2.py +0 -36
  90. union/_protos/common/list_pb2.pyi +0 -69
  91. union/_protos/common/list_pb2_grpc.py +0 -4
  92. union/_protos/common/policy_pb2.py +0 -37
  93. union/_protos/common/policy_pb2.pyi +0 -27
  94. union/_protos/common/policy_pb2_grpc.py +0 -4
  95. union/_protos/common/role_pb2.py +0 -37
  96. union/_protos/common/role_pb2.pyi +0 -51
  97. union/_protos/common/role_pb2_grpc.py +0 -4
  98. union/_protos/common/runtime_version_pb2.py +0 -28
  99. union/_protos/common/runtime_version_pb2.pyi +0 -24
  100. union/_protos/common/runtime_version_pb2_grpc.py +0 -4
  101. union/_protos/logs/dataplane/payload_pb2.py +0 -96
  102. union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  103. union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  104. union/_protos/secret/definition_pb2.py +0 -49
  105. union/_protos/secret/definition_pb2.pyi +0 -93
  106. union/_protos/secret/definition_pb2_grpc.py +0 -4
  107. union/_protos/secret/payload_pb2.py +0 -62
  108. union/_protos/secret/payload_pb2.pyi +0 -94
  109. union/_protos/secret/payload_pb2_grpc.py +0 -4
  110. union/_protos/secret/secret_pb2.py +0 -38
  111. union/_protos/secret/secret_pb2.pyi +0 -6
  112. union/_protos/secret/secret_pb2_grpc.py +0 -198
  113. union/_protos/validate/validate/validate_pb2.py +0 -76
  114. union/_protos/workflow/node_execution_service_pb2.py +0 -26
  115. union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  116. union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  117. union/_protos/workflow/queue_service_pb2.py +0 -75
  118. union/_protos/workflow/queue_service_pb2.pyi +0 -103
  119. union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  120. union/_protos/workflow/run_definition_pb2.py +0 -100
  121. union/_protos/workflow/run_definition_pb2.pyi +0 -256
  122. union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  123. union/_protos/workflow/run_logs_service_pb2.py +0 -41
  124. union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  125. union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  126. union/_protos/workflow/run_service_pb2.py +0 -133
  127. union/_protos/workflow/run_service_pb2.pyi +0 -173
  128. union/_protos/workflow/run_service_pb2_grpc.py +0 -412
  129. union/_protos/workflow/state_service_pb2.py +0 -58
  130. union/_protos/workflow/state_service_pb2.pyi +0 -69
  131. union/_protos/workflow/state_service_pb2_grpc.py +0 -138
  132. union/_protos/workflow/task_definition_pb2.py +0 -72
  133. union/_protos/workflow/task_definition_pb2.pyi +0 -65
  134. union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  135. union/_protos/workflow/task_service_pb2.py +0 -44
  136. union/_protos/workflow/task_service_pb2.pyi +0 -31
  137. union/_protos/workflow/task_service_pb2_grpc.py +0 -104
  138. union/_resources.py +0 -226
  139. union/_retry.py +0 -32
  140. union/_reusable_environment.py +0 -25
  141. union/_run.py +0 -374
  142. union/_secret.py +0 -61
  143. union/_task.py +0 -354
  144. union/_task_environment.py +0 -186
  145. union/_timeout.py +0 -47
  146. union/_tools.py +0 -27
  147. union/_utils/__init__.py +0 -11
  148. union/_utils/asyn.py +0 -119
  149. union/_utils/file_handling.py +0 -71
  150. union/_utils/helpers.py +0 -46
  151. union/_utils/lazy_module.py +0 -54
  152. union/_utils/uv_script_parser.py +0 -49
  153. union/_version.py +0 -21
  154. union/connectors/__init__.py +0 -0
  155. union/errors.py +0 -128
  156. union/extras/__init__.py +0 -5
  157. union/extras/_container.py +0 -263
  158. union/io/__init__.py +0 -11
  159. union/io/_dataframe.py +0 -0
  160. union/io/_dir.py +0 -425
  161. union/io/_file.py +0 -418
  162. union/io/pickle/__init__.py +0 -0
  163. union/io/pickle/transformer.py +0 -117
  164. union/io/structured_dataset/__init__.py +0 -122
  165. union/io/structured_dataset/basic_dfs.py +0 -219
  166. union/io/structured_dataset/structured_dataset.py +0 -1057
  167. union/py.typed +0 -0
  168. union/remote/__init__.py +0 -23
  169. union/remote/_client/__init__.py +0 -0
  170. union/remote/_client/_protocols.py +0 -129
  171. union/remote/_client/auth/__init__.py +0 -12
  172. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  173. union/remote/_client/auth/_authenticators/base.py +0 -391
  174. union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
  175. union/remote/_client/auth/_authenticators/device_code.py +0 -120
  176. union/remote/_client/auth/_authenticators/external_command.py +0 -77
  177. union/remote/_client/auth/_authenticators/factory.py +0 -200
  178. union/remote/_client/auth/_authenticators/pkce.py +0 -515
  179. union/remote/_client/auth/_channel.py +0 -184
  180. union/remote/_client/auth/_client_config.py +0 -83
  181. union/remote/_client/auth/_default_html.py +0 -32
  182. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  183. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
  184. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
  185. union/remote/_client/auth/_keyring.py +0 -154
  186. union/remote/_client/auth/_token_client.py +0 -258
  187. union/remote/_client/auth/errors.py +0 -16
  188. union/remote/_client/controlplane.py +0 -86
  189. union/remote/_data.py +0 -149
  190. union/remote/_logs.py +0 -74
  191. union/remote/_project.py +0 -86
  192. union/remote/_run.py +0 -820
  193. union/remote/_secret.py +0 -132
  194. union/remote/_task.py +0 -193
  195. union/report/__init__.py +0 -3
  196. union/report/_report.py +0 -178
  197. union/report/_template.html +0 -124
  198. union/storage/__init__.py +0 -24
  199. union/storage/_remote_fs.py +0 -34
  200. union/storage/_storage.py +0 -247
  201. union/storage/_utils.py +0 -5
  202. union/types/__init__.py +0 -11
  203. union/types/_renderer.py +0 -162
  204. union/types/_string_literals.py +0 -120
  205. union/types/_type_engine.py +0 -2131
  206. union/types/_utils.py +0 -80
  207. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/WHEEL +0 -0
  208. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/entry_points.txt +0 -0
  209. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/top_level.txt +0 -0
flyte/_initialize.py CHANGED
@@ -17,6 +17,7 @@ from ._logging import initialize_logger
17
17
  from ._tools import ipython_check
18
18
 
19
19
  if TYPE_CHECKING:
20
+ from flyte.config import Config
20
21
  from flyte.remote._client.auth import AuthType, ClientConfig
21
22
  from flyte.remote._client.controlplane import ClientSet
22
23
 
@@ -345,6 +346,7 @@ async def init(
345
346
  rpc_retries: int = 3,
346
347
  http_proxy_url: str | None = None,
347
348
  storage: Storage | None = None,
349
+ config: Config | None = None,
348
350
  ) -> None:
349
351
  """
350
352
  Initialize the Flyte system with the given configuration. This method should be called before any other Flyte
@@ -378,6 +380,7 @@ async def init(
378
380
  :param insecure: insecure flag for the client
379
381
  :param storage: Optional blob store (S3, GCS, Azure) configuration if needed to access (i.e. using Minio)
380
382
  :param org: Optional organization override for the client. Should be set by auth instead.
383
+ :param config: Optional config to override the init parameters
381
384
 
382
385
  :return: None
383
386
  """
@@ -392,33 +395,39 @@ async def init(
392
395
  global _init_config # noqa: PLW0603
393
396
 
394
397
  with _init_lock:
398
+ if config is None:
399
+ from flyte.config import Config
400
+
401
+ config = Config.auto()
402
+ platform_cfg = config.platform
403
+ task_cfg = config.task
395
404
  client = None
396
- if endpoint or api_key:
405
+ if endpoint or platform_cfg.endpoint or api_key:
397
406
  client = await _initialize_client(
398
407
  api_key=api_key,
399
- auth_type=auth_type,
400
- endpoint=endpoint,
408
+ auth_type=auth_type or platform_cfg.auth_mode,
409
+ endpoint=endpoint or platform_cfg.endpoint,
401
410
  headless=headless,
402
- insecure=insecure,
403
- insecure_skip_verify=insecure_skip_verify,
404
- ca_cert_file_path=ca_cert_file_path,
405
- command=command,
406
- proxy_command=proxy_command,
407
- client_id=client_id,
408
- client_credentials_secret=client_credentials_secret,
411
+ insecure=insecure or platform_cfg.insecure,
412
+ insecure_skip_verify=insecure_skip_verify or platform_cfg.insecure_skip_verify,
413
+ ca_cert_file_path=ca_cert_file_path or platform_cfg.ca_cert_file_path,
414
+ command=command or platform_cfg.command,
415
+ proxy_command=proxy_command or platform_cfg.proxy_command,
416
+ client_id=client_id or platform_cfg.client_id,
417
+ client_credentials_secret=client_credentials_secret or platform_cfg.client_credentials_secret,
409
418
  client_config=auth_client_config,
410
- rpc_retries=rpc_retries,
411
- http_proxy_url=http_proxy_url,
419
+ rpc_retries=rpc_retries or platform_cfg.rpc_retries,
420
+ http_proxy_url=http_proxy_url or platform_cfg.http_proxy_url,
412
421
  )
413
422
 
414
423
  root_dir = root_dir or get_cwd_editable_install() or Path.cwd()
415
424
  _init_config = _InitConfig(
416
425
  root_dir=root_dir,
417
- project=project,
418
- domain=domain,
426
+ project=project or task_cfg.project,
427
+ domain=domain or task_cfg.domain,
419
428
  client=client,
420
429
  storage=storage,
421
- org=org,
430
+ org=org or task_cfg.org,
422
431
  )
423
432
 
424
433
 
@@ -60,6 +60,12 @@ async def convert_from_native_to_inputs(interface: NativeInterface, *args, **kwa
60
60
  kwargs = interface.convert_to_kwargs(*args, **kwargs)
61
61
  if len(kwargs) == 0:
62
62
  return Inputs.empty()
63
+ # fill in defaults if missing
64
+ for input_name, (input_type, default_value) in interface.inputs.items():
65
+ if input_name not in kwargs:
66
+ if default_value is not None:
67
+ kwargs[input_name] = default_value
68
+ # todo: fill in Nones for optional inputs
63
69
  if len(kwargs) < len(interface.inputs):
64
70
  raise ValueError(
65
71
  f"Received {len(kwargs)} inputs but interface has {len(interface.inputs)}. "
flyte/_run.py CHANGED
@@ -277,7 +277,6 @@ class _Runner:
277
277
  from flyte._internal.runtime.entrypoints import direct_dispatch
278
278
 
279
279
  controller = create_controller(ct="local")
280
-
281
280
  inputs = await convert_from_native_to_inputs(obj.native_interface, *args, **kwargs)
282
281
  if self._name is None:
283
282
  action = ActionID.create_random()
flyte/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.0.1b3'
21
- __version_tuple__ = version_tuple = (0, 0, 1, 'b3')
20
+ __version__ = version = '0.2.0b0'
21
+ __version_tuple__ = version_tuple = (0, 2, 0, 'b0')
@@ -0,0 +1,168 @@
1
+ import os
2
+ import typing
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING
5
+
6
+ from flyte._logging import logger
7
+ from flyte.config import _internal
8
+ from flyte.config._config import ConfigFile, get_config_file, read_file_if_exists
9
+
10
+ _all__ = ["ConfigFile", "PlatformConfig", "TaskConfig"]
11
+
12
+ if TYPE_CHECKING:
13
+ from flyte.remote._client.auth import AuthType
14
+
15
+
16
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
17
+ class PlatformConfig(object):
18
+ """
19
+ This object contains the settings to talk to a Flyte backend (the DNS location of your Admin server basically).
20
+
21
+ :param endpoint: DNS for Flyte backend
22
+ :param insecure: Whether or not to use SSL
23
+ :param insecure_skip_verify: Whether to skip SSL certificate verification
24
+ :param console_endpoint: endpoint for console if different from Flyte backend
25
+ :param command: This command is executed to return a token using an external process
26
+ :param proxy_command: This command is executed to return a token for proxy authorization using an external process
27
+ :param client_id: This is the public identifier for the app which handles authorization for a Flyte deployment.
28
+ More details here: https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/.
29
+ :param client_credentials_secret: Used for service auth, which is automatically called during pyflyte. This will
30
+ allow the Flyte engine to read the password directly from the environment variable. Note that this is
31
+ less secure! Please only use this if mounting the secret as a file is impossible
32
+ :param scopes: List of scopes to request. This is only applicable to the client credentials flow
33
+ :param auth_mode: The OAuth mode to use. Defaults to pkce flow
34
+ :param ca_cert_file_path: [optional] str Root Cert to be loaded and used to verify admin
35
+ :param http_proxy_url: [optional] HTTP Proxy to be used for OAuth requests
36
+ """
37
+
38
+ endpoint: str | None = None
39
+ insecure: bool = False
40
+ insecure_skip_verify: bool = False
41
+ ca_cert_file_path: typing.Optional[str] = None
42
+ console_endpoint: typing.Optional[str] = None
43
+ command: typing.Optional[typing.List[str]] = None
44
+ proxy_command: typing.Optional[typing.List[str]] = None
45
+ client_id: typing.Optional[str] = None
46
+ client_credentials_secret: typing.Optional[str] = None
47
+ scopes: typing.List[str] = field(default_factory=list)
48
+ auth_mode: "AuthType" = "Pkce"
49
+ audience: typing.Optional[str] = None
50
+ rpc_retries: int = 3
51
+ http_proxy_url: typing.Optional[str] = None
52
+
53
+ @classmethod
54
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "PlatformConfig":
55
+ """
56
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
57
+ :param config_file:
58
+ :return:
59
+ """
60
+ from .._initialize import set_if_exists
61
+
62
+ config_file = get_config_file(config_file)
63
+ kwargs: typing.Dict[str, typing.Any] = {}
64
+ kwargs = set_if_exists(kwargs, "insecure", _internal.Platform.INSECURE.read(config_file))
65
+ kwargs = set_if_exists(
66
+ kwargs, "insecure_skip_verify", _internal.Platform.INSECURE_SKIP_VERIFY.read(config_file)
67
+ )
68
+ kwargs = set_if_exists(kwargs, "ca_cert_file_path", _internal.Platform.CA_CERT_FILE_PATH.read(config_file))
69
+ kwargs = set_if_exists(kwargs, "command", _internal.Credentials.COMMAND.read(config_file))
70
+ kwargs = set_if_exists(kwargs, "proxy_command", _internal.Credentials.PROXY_COMMAND.read(config_file))
71
+ kwargs = set_if_exists(kwargs, "client_id", _internal.Credentials.CLIENT_ID.read(config_file))
72
+
73
+ is_client_secret = False
74
+ client_credentials_secret = read_file_if_exists(
75
+ _internal.Credentials.CLIENT_CREDENTIALS_SECRET_LOCATION.read(config_file)
76
+ )
77
+ if client_credentials_secret:
78
+ is_client_secret = True
79
+ if client_credentials_secret.endswith("\n"):
80
+ logger.info("Newline stripped from client secret")
81
+ client_credentials_secret = client_credentials_secret.strip()
82
+ kwargs = set_if_exists(
83
+ kwargs,
84
+ "client_credentials_secret",
85
+ client_credentials_secret,
86
+ )
87
+
88
+ client_credentials_secret_env_var = _internal.Credentials.CLIENT_CREDENTIALS_SECRET_ENV_VAR.read(config_file)
89
+ if client_credentials_secret_env_var:
90
+ client_credentials_secret = os.getenv(client_credentials_secret_env_var)
91
+ if client_credentials_secret:
92
+ is_client_secret = True
93
+ kwargs = set_if_exists(kwargs, "client_credentials_secret", client_credentials_secret)
94
+ kwargs = set_if_exists(kwargs, "scopes", _internal.Credentials.SCOPES.read(config_file))
95
+ kwargs = set_if_exists(kwargs, "auth_mode", _internal.Credentials.AUTH_MODE.read(config_file))
96
+ if is_client_secret:
97
+ kwargs = set_if_exists(kwargs, "auth_mode", "ClientSecret")
98
+ kwargs = set_if_exists(kwargs, "endpoint", _internal.Platform.URL.read(config_file))
99
+ kwargs = set_if_exists(kwargs, "console_endpoint", _internal.Platform.CONSOLE_ENDPOINT.read(config_file))
100
+
101
+ kwargs = set_if_exists(kwargs, "http_proxy_url", _internal.Platform.HTTP_PROXY_URL.read(config_file))
102
+ return PlatformConfig(**kwargs)
103
+
104
+ @classmethod
105
+ def for_endpoint(cls, endpoint: str, insecure: bool = False) -> "PlatformConfig":
106
+ return PlatformConfig(endpoint=endpoint, insecure=insecure)
107
+
108
+
109
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
110
+ class TaskConfig(object):
111
+ org: str | None = None
112
+ project: str | None = None
113
+ domain: str | None = None
114
+
115
+ @classmethod
116
+ def auto(cls, config_file: typing.Optional[typing.Union[str, ConfigFile]] = None) -> "TaskConfig":
117
+ """
118
+ Reads from a config file, and overrides from Environment variables. Refer to ConfigEntry for details
119
+ :param config_file:
120
+ :return:
121
+ """
122
+ from flyte._initialize import set_if_exists
123
+
124
+ config_file = get_config_file(config_file)
125
+ kwargs: typing.Dict[str, typing.Any] = {}
126
+ kwargs = set_if_exists(kwargs, "org", _internal.Task.ORG.read(config_file))
127
+ kwargs = set_if_exists(kwargs, "project", _internal.Task.PROJECT.read(config_file))
128
+ kwargs = set_if_exists(kwargs, "domain", _internal.Task.DOMAIN.read(config_file))
129
+ return TaskConfig(**kwargs)
130
+
131
+
132
+ @dataclass(init=True, repr=True, eq=True, frozen=True)
133
+ class Config(object):
134
+ """
135
+ This the parent configuration object and holds all the underlying configuration object types. An instance of
136
+ this object holds all the config necessary to
137
+
138
+ 1. Interactive session with Flyte backend
139
+ 2. Some parts are required for Serialization, for example Platform Config is not required
140
+ 3. Runtime of a task
141
+ """
142
+
143
+ platform: PlatformConfig = field(default=PlatformConfig())
144
+ task: TaskConfig = field(default=TaskConfig())
145
+
146
+ def with_params(
147
+ self,
148
+ platform: PlatformConfig | None = None,
149
+ task: TaskConfig | None = None,
150
+ ) -> "Config":
151
+ return Config(
152
+ platform=platform or self.platform,
153
+ task=task or self.task,
154
+ )
155
+
156
+ @classmethod
157
+ def auto(cls, config_file: typing.Union[str, ConfigFile, None] = None) -> "Config":
158
+ """
159
+ Automatically constructs the Config Object. The order of precedence is as follows
160
+ 1. first try to find any env vars that match the config vars specified in the FLYTE_CONFIG format.
161
+ 2. If not found in environment then values ar read from the config file
162
+ 3. If not found in the file, then the default values are used.
163
+
164
+ :param config_file: file path to read the config from, if not specified default locations are searched
165
+ :return: Config
166
+ """
167
+ config_file = get_config_file(config_file)
168
+ return Config(platform=PlatformConfig.auto(config_file), task=TaskConfig.auto(config_file))
@@ -0,0 +1,196 @@
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
+ @staticmethod
103
+ def _read_yaml_config(location: str) -> typing.Optional[typing.Dict[str, typing.Any]]:
104
+ with open(location, "r") as fh:
105
+ try:
106
+ yaml_contents = yaml.safe_load(fh)
107
+ return yaml_contents
108
+ except yaml.YAMLError as exc:
109
+ logger.warning(f"Error {exc} reading yaml config file at {location}, ignoring...")
110
+ return None
111
+
112
+ def _get_from_yaml(self, c: YamlConfigEntry) -> typing.Any:
113
+ keys = c.switch.split(".") # flytectl switches are dot delimited
114
+ d = typing.cast(typing.Dict[str, typing.Any], self.yaml_config)
115
+ try:
116
+ for k in keys:
117
+ d = d[k]
118
+ return d
119
+ except KeyError:
120
+ return None
121
+
122
+ def get(self, c: YamlConfigEntry) -> typing.Any:
123
+ return self._get_from_yaml(c)
124
+
125
+ @property
126
+ def yaml_config(self) -> typing.Dict[str, typing.Any] | None:
127
+ return self._yaml_config
128
+
129
+
130
+ def resolve_config_path() -> pathlib.Path | None:
131
+ """
132
+ Config is read from the following locations in order of precedence:
133
+ 1. `UCTL_CONFIG` environment variable
134
+ 2. `FLYTECTL_CONFIG` environment variable
135
+ 3. ~/.union/config.yaml if it exists
136
+ 4. ~/.flyte/config.yaml if it exists
137
+ 5. ./config.yaml if it exists
138
+ """
139
+ uctl_path_from_env = getenv(UCTL_CONFIG_ENV_VAR, None)
140
+ if uctl_path_from_env:
141
+ return pathlib.Path(uctl_path_from_env)
142
+ logger.debug("No UCTL_CONFIG environment variable found, checking FLYTECTL_CONFIG")
143
+
144
+ flytectl_path_from_env = getenv(FLYTECTL_CONFIG_ENV_VAR, None)
145
+ if flytectl_path_from_env:
146
+ return pathlib.Path(flytectl_path_from_env)
147
+ logger.debug("No FLYTECTL_CONFIG environment variable found, checking default locations")
148
+
149
+ home_dir_union_config = Path(Path.home(), ".union", "config.yaml")
150
+ if home_dir_union_config.exists():
151
+ return home_dir_union_config
152
+ logger.debug("No ~/.union/config.yaml found, checking current directory")
153
+
154
+ home_dir_flytectl_config = Path(Path.home(), ".flyte", "config.yaml")
155
+ if home_dir_flytectl_config.exists():
156
+ return home_dir_flytectl_config
157
+ logger.debug("No ~/.flyte/config.yaml found, checking current directory")
158
+
159
+ current_location_config = Path("config.yaml")
160
+ if current_location_config.exists():
161
+ return current_location_config
162
+ logger.debug("No ./config.yaml found, returning None")
163
+ return None
164
+
165
+
166
+ @lru_cache
167
+ def get_config_file(c: typing.Union[str, ConfigFile, None]) -> ConfigFile | None:
168
+ """
169
+ Checks if the given argument is a file or a configFile and returns a loaded configFile else returns None
170
+ """
171
+ if "PYTEST_VERSION" in os.environ:
172
+ # Use default local config in the pytest environment
173
+ return None
174
+ if isinstance(c, str):
175
+ logger.debug(f"Using specified config file at {c}")
176
+ return ConfigFile(c)
177
+ config_path = resolve_config_path()
178
+ if config_path:
179
+ return ConfigFile(str(config_path))
180
+ return None
181
+
182
+
183
+ def read_file_if_exists(filename: typing.Optional[str], encoding=None) -> typing.Optional[str]:
184
+ """
185
+ Reads the contents of the file if passed a path. Otherwise, returns None.
186
+
187
+ :param filename: The file path to load
188
+ :param encoding: The encoding to use when reading the file.
189
+ :return: The contents of the file as a string or None.
190
+ """
191
+ if not filename:
192
+ return None
193
+
194
+ file = pathlib.Path(filename)
195
+ logger.debug(f"Reading file contents from [{file}] with current directory [{os.getcwd()}].")
196
+ return file.read_text(encoding=encoding)
@@ -0,0 +1,64 @@
1
+ from flyte.config._config 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"))
flyte/remote/_console.py CHANGED
@@ -7,7 +7,7 @@ def _get_http_domain(endpoint: str, insecure: bool) -> str:
7
7
  if parsed.scheme == "dns":
8
8
  domain = parsed.path.lstrip("/")
9
9
  else:
10
- domain = parsed.netloc
10
+ domain = parsed.netloc or parsed.path
11
11
  # TODO: make console url configurable
12
12
  if domain.split(":")[0] == "localhost":
13
13
  domain = "localhost:8080"
@@ -450,7 +450,6 @@ class DataclassTransformer(TypeTransformer[object]):
450
450
  # However, FooSchema is created by flytekit and it's not equal to the user-defined dataclass (Foo).
451
451
  # Therefore, we should iterate all attributes in the dataclass and check the type of value in dataclass
452
452
  # matches the expected_type.
453
-
454
453
  expected_fields_dict = {}
455
454
 
456
455
  for f in dataclasses.fields(expected_type):
@@ -1992,7 +1991,9 @@ DatetimeTransformer = SimpleTransformer(
1992
1991
  datetime.datetime,
1993
1992
  types_pb2.LiteralType(simple=types_pb2.SimpleType.DATETIME),
1994
1993
  lambda x: Literal(scalar=Scalar(primitive=Primitive(datetime=x))),
1995
- lambda x: x.scalar.primitive.datetime if x.scalar.primitive.HasField("datetime") else None,
1994
+ lambda x: x.scalar.primitive.datetime.ToDatetime().replace(tzinfo=datetime.timezone.utc)
1995
+ if x.scalar.primitive.HasField("datetime")
1996
+ else None,
1996
1997
  )
1997
1998
 
1998
1999
  TimedeltaTransformer = SimpleTransformer(
@@ -2000,7 +2001,7 @@ TimedeltaTransformer = SimpleTransformer(
2000
2001
  datetime.timedelta,
2001
2002
  types_pb2.LiteralType(simple=types_pb2.SimpleType.DURATION),
2002
2003
  lambda x: Literal(scalar=Scalar(primitive=Primitive(duration=x))),
2003
- lambda x: x.scalar.primitive.duration if x.scalar.primitive.HasField("duration") else None,
2004
+ lambda x: x.scalar.primitive.duration.ToTimedelta() if x.scalar.primitive.HasField("duration") else None,
2004
2005
  )
2005
2006
 
2006
2007
  DateTransformer = SimpleTransformer(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flyte
3
- Version: 0.0.1b3
3
+ Version: 0.2.0b0
4
4
  Summary: Add your description here
5
5
  Author-email: Ketan Umare <kumare3@users.noreply.github.com>
6
6
  Requires-Python: >=3.10