flyte 2.0.0b22__py3-none-any.whl → 2.0.0b30__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.
Files changed (197) hide show
  1. flyte/__init__.py +18 -2
  2. flyte/_bin/runtime.py +43 -5
  3. flyte/_cache/cache.py +4 -2
  4. flyte/_cache/local_cache.py +216 -0
  5. flyte/_code_bundle/_ignore.py +1 -1
  6. flyte/_code_bundle/_packaging.py +4 -4
  7. flyte/_code_bundle/_utils.py +14 -8
  8. flyte/_code_bundle/bundle.py +13 -5
  9. flyte/_constants.py +1 -0
  10. flyte/_context.py +4 -1
  11. flyte/_custom_context.py +73 -0
  12. flyte/_debug/constants.py +0 -1
  13. flyte/_debug/vscode.py +6 -1
  14. flyte/_deploy.py +223 -59
  15. flyte/_environment.py +5 -0
  16. flyte/_excepthook.py +1 -1
  17. flyte/_image.py +144 -82
  18. flyte/_initialize.py +95 -12
  19. flyte/_interface.py +2 -0
  20. flyte/_internal/controllers/_local_controller.py +65 -24
  21. flyte/_internal/controllers/_trace.py +1 -1
  22. flyte/_internal/controllers/remote/_action.py +13 -11
  23. flyte/_internal/controllers/remote/_client.py +1 -1
  24. flyte/_internal/controllers/remote/_controller.py +9 -4
  25. flyte/_internal/controllers/remote/_core.py +16 -16
  26. flyte/_internal/controllers/remote/_informer.py +4 -4
  27. flyte/_internal/controllers/remote/_service_protocol.py +7 -7
  28. flyte/_internal/imagebuild/docker_builder.py +139 -84
  29. flyte/_internal/imagebuild/image_builder.py +7 -13
  30. flyte/_internal/imagebuild/remote_builder.py +65 -13
  31. flyte/_internal/imagebuild/utils.py +51 -3
  32. flyte/_internal/resolvers/_task_module.py +5 -38
  33. flyte/_internal/resolvers/default.py +2 -2
  34. flyte/_internal/runtime/convert.py +42 -20
  35. flyte/_internal/runtime/entrypoints.py +24 -1
  36. flyte/_internal/runtime/io.py +21 -8
  37. flyte/_internal/runtime/resources_serde.py +20 -6
  38. flyte/_internal/runtime/reuse.py +1 -1
  39. flyte/_internal/runtime/rusty.py +20 -5
  40. flyte/_internal/runtime/task_serde.py +33 -27
  41. flyte/_internal/runtime/taskrunner.py +10 -1
  42. flyte/_internal/runtime/trigger_serde.py +160 -0
  43. flyte/_internal/runtime/types_serde.py +1 -1
  44. flyte/_keyring/file.py +39 -9
  45. flyte/_logging.py +79 -12
  46. flyte/_map.py +31 -12
  47. flyte/_module.py +70 -0
  48. flyte/_pod.py +2 -2
  49. flyte/_resources.py +213 -31
  50. flyte/_run.py +107 -41
  51. flyte/_task.py +66 -10
  52. flyte/_task_environment.py +96 -24
  53. flyte/_task_plugins.py +4 -2
  54. flyte/_trigger.py +1000 -0
  55. flyte/_utils/__init__.py +2 -1
  56. flyte/_utils/asyn.py +3 -1
  57. flyte/_utils/docker_credentials.py +173 -0
  58. flyte/_utils/module_loader.py +17 -2
  59. flyte/_version.py +3 -3
  60. flyte/cli/_abort.py +3 -3
  61. flyte/cli/_build.py +1 -3
  62. flyte/cli/_common.py +78 -7
  63. flyte/cli/_create.py +178 -3
  64. flyte/cli/_delete.py +23 -1
  65. flyte/cli/_deploy.py +49 -11
  66. flyte/cli/_get.py +79 -34
  67. flyte/cli/_params.py +8 -6
  68. flyte/cli/_plugins.py +209 -0
  69. flyte/cli/_run.py +127 -11
  70. flyte/cli/_serve.py +64 -0
  71. flyte/cli/_update.py +37 -0
  72. flyte/cli/_user.py +17 -0
  73. flyte/cli/main.py +30 -4
  74. flyte/config/_config.py +2 -0
  75. flyte/config/_internal.py +1 -0
  76. flyte/config/_reader.py +3 -3
  77. flyte/connectors/__init__.py +11 -0
  78. flyte/connectors/_connector.py +270 -0
  79. flyte/connectors/_server.py +197 -0
  80. flyte/connectors/utils.py +135 -0
  81. flyte/errors.py +10 -1
  82. flyte/extend.py +8 -1
  83. flyte/extras/_container.py +6 -1
  84. flyte/git/_config.py +11 -9
  85. flyte/io/__init__.py +2 -0
  86. flyte/io/_dataframe/__init__.py +2 -0
  87. flyte/io/_dataframe/basic_dfs.py +1 -1
  88. flyte/io/_dataframe/dataframe.py +12 -8
  89. flyte/io/_dir.py +551 -120
  90. flyte/io/_file.py +538 -141
  91. flyte/models.py +57 -12
  92. flyte/remote/__init__.py +6 -1
  93. flyte/remote/_action.py +18 -16
  94. flyte/remote/_client/_protocols.py +39 -4
  95. flyte/remote/_client/auth/_channel.py +10 -6
  96. flyte/remote/_client/controlplane.py +17 -5
  97. flyte/remote/_console.py +3 -2
  98. flyte/remote/_data.py +4 -3
  99. flyte/remote/_logs.py +3 -3
  100. flyte/remote/_run.py +47 -7
  101. flyte/remote/_secret.py +26 -17
  102. flyte/remote/_task.py +21 -9
  103. flyte/remote/_trigger.py +306 -0
  104. flyte/remote/_user.py +33 -0
  105. flyte/storage/__init__.py +6 -1
  106. flyte/storage/_parallel_reader.py +274 -0
  107. flyte/storage/_storage.py +185 -103
  108. flyte/types/__init__.py +16 -0
  109. flyte/types/_interface.py +2 -2
  110. flyte/types/_pickle.py +17 -4
  111. flyte/types/_string_literals.py +8 -9
  112. flyte/types/_type_engine.py +26 -19
  113. flyte/types/_utils.py +1 -1
  114. {flyte-2.0.0b22.data → flyte-2.0.0b30.data}/scripts/runtime.py +43 -5
  115. {flyte-2.0.0b22.dist-info → flyte-2.0.0b30.dist-info}/METADATA +8 -1
  116. flyte-2.0.0b30.dist-info/RECORD +192 -0
  117. flyte/_protos/__init__.py +0 -0
  118. flyte/_protos/common/authorization_pb2.py +0 -66
  119. flyte/_protos/common/authorization_pb2.pyi +0 -108
  120. flyte/_protos/common/authorization_pb2_grpc.py +0 -4
  121. flyte/_protos/common/identifier_pb2.py +0 -99
  122. flyte/_protos/common/identifier_pb2.pyi +0 -120
  123. flyte/_protos/common/identifier_pb2_grpc.py +0 -4
  124. flyte/_protos/common/identity_pb2.py +0 -48
  125. flyte/_protos/common/identity_pb2.pyi +0 -72
  126. flyte/_protos/common/identity_pb2_grpc.py +0 -4
  127. flyte/_protos/common/list_pb2.py +0 -36
  128. flyte/_protos/common/list_pb2.pyi +0 -71
  129. flyte/_protos/common/list_pb2_grpc.py +0 -4
  130. flyte/_protos/common/policy_pb2.py +0 -37
  131. flyte/_protos/common/policy_pb2.pyi +0 -27
  132. flyte/_protos/common/policy_pb2_grpc.py +0 -4
  133. flyte/_protos/common/role_pb2.py +0 -37
  134. flyte/_protos/common/role_pb2.pyi +0 -53
  135. flyte/_protos/common/role_pb2_grpc.py +0 -4
  136. flyte/_protos/common/runtime_version_pb2.py +0 -28
  137. flyte/_protos/common/runtime_version_pb2.pyi +0 -24
  138. flyte/_protos/common/runtime_version_pb2_grpc.py +0 -4
  139. flyte/_protos/imagebuilder/definition_pb2.py +0 -60
  140. flyte/_protos/imagebuilder/definition_pb2.pyi +0 -153
  141. flyte/_protos/imagebuilder/definition_pb2_grpc.py +0 -4
  142. flyte/_protos/imagebuilder/payload_pb2.py +0 -32
  143. flyte/_protos/imagebuilder/payload_pb2.pyi +0 -21
  144. flyte/_protos/imagebuilder/payload_pb2_grpc.py +0 -4
  145. flyte/_protos/imagebuilder/service_pb2.py +0 -29
  146. flyte/_protos/imagebuilder/service_pb2.pyi +0 -5
  147. flyte/_protos/imagebuilder/service_pb2_grpc.py +0 -66
  148. flyte/_protos/logs/dataplane/payload_pb2.py +0 -100
  149. flyte/_protos/logs/dataplane/payload_pb2.pyi +0 -177
  150. flyte/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  151. flyte/_protos/secret/definition_pb2.py +0 -49
  152. flyte/_protos/secret/definition_pb2.pyi +0 -93
  153. flyte/_protos/secret/definition_pb2_grpc.py +0 -4
  154. flyte/_protos/secret/payload_pb2.py +0 -62
  155. flyte/_protos/secret/payload_pb2.pyi +0 -94
  156. flyte/_protos/secret/payload_pb2_grpc.py +0 -4
  157. flyte/_protos/secret/secret_pb2.py +0 -38
  158. flyte/_protos/secret/secret_pb2.pyi +0 -6
  159. flyte/_protos/secret/secret_pb2_grpc.py +0 -198
  160. flyte/_protos/secret/secret_pb2_grpc_grpc.py +0 -198
  161. flyte/_protos/validate/validate/validate_pb2.py +0 -76
  162. flyte/_protos/workflow/common_pb2.py +0 -27
  163. flyte/_protos/workflow/common_pb2.pyi +0 -14
  164. flyte/_protos/workflow/common_pb2_grpc.py +0 -4
  165. flyte/_protos/workflow/environment_pb2.py +0 -29
  166. flyte/_protos/workflow/environment_pb2.pyi +0 -12
  167. flyte/_protos/workflow/environment_pb2_grpc.py +0 -4
  168. flyte/_protos/workflow/node_execution_service_pb2.py +0 -26
  169. flyte/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  170. flyte/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  171. flyte/_protos/workflow/queue_service_pb2.py +0 -111
  172. flyte/_protos/workflow/queue_service_pb2.pyi +0 -168
  173. flyte/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  174. flyte/_protos/workflow/run_definition_pb2.py +0 -123
  175. flyte/_protos/workflow/run_definition_pb2.pyi +0 -352
  176. flyte/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  177. flyte/_protos/workflow/run_logs_service_pb2.py +0 -41
  178. flyte/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  179. flyte/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  180. flyte/_protos/workflow/run_service_pb2.py +0 -137
  181. flyte/_protos/workflow/run_service_pb2.pyi +0 -185
  182. flyte/_protos/workflow/run_service_pb2_grpc.py +0 -446
  183. flyte/_protos/workflow/state_service_pb2.py +0 -67
  184. flyte/_protos/workflow/state_service_pb2.pyi +0 -76
  185. flyte/_protos/workflow/state_service_pb2_grpc.py +0 -138
  186. flyte/_protos/workflow/task_definition_pb2.py +0 -82
  187. flyte/_protos/workflow/task_definition_pb2.pyi +0 -88
  188. flyte/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  189. flyte/_protos/workflow/task_service_pb2.py +0 -60
  190. flyte/_protos/workflow/task_service_pb2.pyi +0 -59
  191. flyte/_protos/workflow/task_service_pb2_grpc.py +0 -138
  192. flyte-2.0.0b22.dist-info/RECORD +0 -250
  193. {flyte-2.0.0b22.data → flyte-2.0.0b30.data}/scripts/debug.py +0 -0
  194. {flyte-2.0.0b22.dist-info → flyte-2.0.0b30.dist-info}/WHEEL +0 -0
  195. {flyte-2.0.0b22.dist-info → flyte-2.0.0b30.dist-info}/entry_points.txt +0 -0
  196. {flyte-2.0.0b22.dist-info → flyte-2.0.0b30.dist-info}/licenses/LICENSE +0 -0
  197. {flyte-2.0.0b22.dist-info → flyte-2.0.0b30.dist-info}/top_level.txt +0 -0
flyte/remote/_secret.py CHANGED
@@ -4,9 +4,9 @@ from dataclasses import dataclass
4
4
  from typing import AsyncIterator, Literal, Union
5
5
 
6
6
  import rich.repr
7
+ from flyteidl2.secret import definition_pb2, payload_pb2
7
8
 
8
- from flyte._initialize import ensure_client, get_client, get_common_config
9
- from flyte._protos.secret import definition_pb2, payload_pb2
9
+ from flyte._initialize import ensure_client, get_client, get_init_config
10
10
  from flyte.remote._common import ToJSONMixin
11
11
  from flyte.syncify import syncify
12
12
 
@@ -21,12 +21,19 @@ class Secret(ToJSONMixin):
21
21
  @classmethod
22
22
  async def create(cls, name: str, value: Union[str, bytes], type: SecretTypes = "regular"):
23
23
  ensure_client()
24
- cfg = get_common_config()
25
- secret_type = (
26
- definition_pb2.SecretType.SECRET_TYPE_GENERIC
27
- if type == "regular"
28
- else definition_pb2.SecretType.SECRET_TYPE_IMAGE_PULL_SECRET
29
- )
24
+ cfg = get_init_config()
25
+ project = cfg.project
26
+ domain = cfg.domain
27
+
28
+ if type == "regular":
29
+ secret_type = definition_pb2.SecretType.SECRET_TYPE_GENERIC
30
+
31
+ else:
32
+ secret_type = definition_pb2.SecretType.SECRET_TYPE_IMAGE_PULL_SECRET
33
+ if project or domain:
34
+ raise ValueError(
35
+ f"Project `{project}` or domain `{domain}` should not be set when creating the image pull secret."
36
+ )
30
37
 
31
38
  if isinstance(value, str):
32
39
  secret = definition_pb2.SecretSpec(
@@ -42,8 +49,8 @@ class Secret(ToJSONMixin):
42
49
  request=payload_pb2.CreateSecretRequest(
43
50
  id=definition_pb2.SecretIdentifier(
44
51
  organization=cfg.org,
45
- project=cfg.project,
46
- domain=cfg.domain,
52
+ project=project,
53
+ domain=domain,
47
54
  name=name,
48
55
  ),
49
56
  secret_spec=secret,
@@ -54,7 +61,7 @@ class Secret(ToJSONMixin):
54
61
  @classmethod
55
62
  async def get(cls, name: str) -> Secret:
56
63
  ensure_client()
57
- cfg = get_common_config()
64
+ cfg = get_init_config()
58
65
  resp = await get_client().secrets_service.GetSecret(
59
66
  request=payload_pb2.GetSecretRequest(
60
67
  id=definition_pb2.SecretIdentifier(
@@ -71,29 +78,31 @@ class Secret(ToJSONMixin):
71
78
  @classmethod
72
79
  async def listall(cls, limit: int = 100) -> AsyncIterator[Secret]:
73
80
  ensure_client()
74
- cfg = get_common_config()
75
- token = None
81
+ cfg = get_init_config()
82
+ per_cluster_tokens = None
76
83
  while True:
77
84
  resp = await get_client().secrets_service.ListSecrets( # type: ignore
78
85
  request=payload_pb2.ListSecretsRequest(
79
86
  organization=cfg.org,
80
87
  project=cfg.project,
81
88
  domain=cfg.domain,
82
- token=token,
89
+ per_cluster_tokens=per_cluster_tokens,
83
90
  limit=limit,
84
91
  ),
85
92
  )
86
- token = resp.token
93
+ per_cluster_tokens = resp.per_cluster_tokens
94
+ round_items = [v for _, v in per_cluster_tokens.items() if v]
95
+ has_next = any(round_items)
87
96
  for r in resp.secrets:
88
97
  yield cls(r)
89
- if not token:
98
+ if not has_next:
90
99
  break
91
100
 
92
101
  @syncify
93
102
  @classmethod
94
103
  async def delete(cls, name):
95
104
  ensure_client()
96
- cfg = get_common_config()
105
+ cfg = get_init_config()
97
106
  await get_client().secrets_service.DeleteSecret( # type: ignore
98
107
  request=payload_pb2.DeleteSecretRequest(
99
108
  id=definition_pb2.SecretIdentifier(
flyte/remote/_task.py CHANGED
@@ -6,19 +6,18 @@ from dataclasses import dataclass
6
6
  from typing import Any, AsyncIterator, Callable, Coroutine, Dict, Iterator, Literal, Optional, Tuple, Union, cast
7
7
 
8
8
  import rich.repr
9
- from flyteidl.core import literals_pb2
10
- from google.protobuf import timestamp
9
+ from flyteidl2.common import identifier_pb2, list_pb2
10
+ from flyteidl2.core import literals_pb2
11
+ from flyteidl2.task import task_definition_pb2, task_service_pb2
11
12
 
12
13
  import flyte
13
14
  import flyte.errors
14
15
  from flyte._cache.cache import CacheBehavior
15
16
  from flyte._context import internal_ctx
16
- from flyte._initialize import ensure_client, get_client, get_common_config
17
+ from flyte._initialize import ensure_client, get_client, get_init_config
17
18
  from flyte._internal.runtime.resources_serde import get_proto_resources
18
19
  from flyte._internal.runtime.task_serde import get_proto_retry_strategy, get_proto_timeout, get_security_context
19
20
  from flyte._logging import logger
20
- from flyte._protos.common import identifier_pb2, list_pb2
21
- from flyte._protos.workflow import task_definition_pb2, task_service_pb2
22
21
  from flyte.models import NativeInterface
23
22
  from flyte.syncify import syncify
24
23
 
@@ -35,7 +34,7 @@ def _repr_task_metadata(metadata: task_definition_pb2.TaskMetadata) -> rich.repr
35
34
  else:
36
35
  yield "deployed_by", f"App: {metadata.deployed_by.application.spec.name}"
37
36
  yield "short_name", metadata.short_name
38
- yield "deployed_at", timestamp.to_datetime(metadata.deployed_at)
37
+ yield "deployed_at", metadata.deployed_at.ToDatetime()
39
38
  yield "environment_name", metadata.environment_name
40
39
 
41
40
 
@@ -99,6 +98,7 @@ AutoVersioning = Literal["latest", "current"]
99
98
  class TaskDetails(ToJSONMixin):
100
99
  pb2: task_definition_pb2.TaskDetails
101
100
  max_inline_io_bytes: int = 10 * 1024 * 1024 # 10 MB
101
+ overriden_queue: Optional[str] = None
102
102
 
103
103
  @classmethod
104
104
  def get(
@@ -150,7 +150,7 @@ class TaskDetails(ToJSONMixin):
150
150
  if ctx is None:
151
151
  raise ValueError("auto_version=current can only be used within a task context.")
152
152
  _version = ctx.version
153
- cfg = get_common_config()
153
+ cfg = get_init_config()
154
154
  task_id = task_definition_pb2.TaskIdentifier(
155
155
  org=cfg.org,
156
156
  project=project or cfg.project,
@@ -284,6 +284,13 @@ class TaskDetails(ToJSONMixin):
284
284
  f"Reference tasks [{self.name}] cannot be executed locally, only remotely."
285
285
  )
286
286
 
287
+ @property
288
+ def queue(self) -> Optional[str]:
289
+ """
290
+ The queue to use for the task.
291
+ """
292
+ return self.overriden_queue
293
+
287
294
  def override(
288
295
  self,
289
296
  *,
@@ -295,6 +302,7 @@ class TaskDetails(ToJSONMixin):
295
302
  secrets: Optional[flyte.SecretRequest] = None,
296
303
  max_inline_io_bytes: Optional[int] = None,
297
304
  cache: Optional[flyte.Cache] = None,
305
+ queue: Optional[str] = None,
298
306
  **kwargs: Any,
299
307
  ) -> TaskDetails:
300
308
  if len(kwargs) > 0:
@@ -342,7 +350,11 @@ class TaskDetails(ToJSONMixin):
342
350
  md.cache_serializable = cache.serialize
343
351
  md.cache_ignore_input_vars[:] = list(cache.ignored_inputs or ())
344
352
 
345
- return TaskDetails(pb2, max_inline_io_bytes=max_inline_io_bytes or self.max_inline_io_bytes)
353
+ return TaskDetails(
354
+ pb2,
355
+ max_inline_io_bytes=max_inline_io_bytes or self.max_inline_io_bytes,
356
+ overriden_queue=queue,
357
+ )
346
358
 
347
359
  def __rich_repr__(self) -> rich.repr.Result:
348
360
  """
@@ -438,7 +450,7 @@ class Task(ToJSONMixin):
438
450
  sort_pb2 = list_pb2.Sort(
439
451
  key=sort_by[0], direction=list_pb2.Sort.ASCENDING if sort_by[1] == "asc" else list_pb2.Sort.DESCENDING
440
452
  )
441
- cfg = get_common_config()
453
+ cfg = get_init_config()
442
454
  filters = []
443
455
  if by_task_name:
444
456
  filters.append(
@@ -0,0 +1,306 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from functools import cached_property
5
+ from typing import AsyncIterator
6
+
7
+ import grpc.aio
8
+ from flyteidl2.common import identifier_pb2, list_pb2
9
+ from flyteidl2.task import common_pb2, task_definition_pb2
10
+ from flyteidl2.trigger import trigger_definition_pb2, trigger_service_pb2
11
+
12
+ import flyte
13
+ from flyte._initialize import ensure_client, get_client, get_init_config
14
+ from flyte._internal.runtime import trigger_serde
15
+ from flyte.syncify import syncify
16
+
17
+ from ._common import ToJSONMixin
18
+ from ._task import Task, TaskDetails
19
+
20
+
21
+ @dataclass
22
+ class TriggerDetails(ToJSONMixin):
23
+ pb2: trigger_definition_pb2.TriggerDetails
24
+
25
+ @syncify
26
+ @classmethod
27
+ async def get(cls, *, name: str, task_name: str) -> TriggerDetails:
28
+ """
29
+ Retrieve detailed information about a specific trigger by its name.
30
+ """
31
+ ensure_client()
32
+ cfg = get_init_config()
33
+ resp = await get_client().trigger_service.GetTriggerDetails(
34
+ request=trigger_service_pb2.GetTriggerDetailsRequest(
35
+ name=identifier_pb2.TriggerName(
36
+ task_name=task_name,
37
+ name=name,
38
+ org=cfg.org,
39
+ project=cfg.project,
40
+ domain=cfg.domain,
41
+ ),
42
+ )
43
+ )
44
+ return cls(pb2=resp.trigger)
45
+
46
+ @property
47
+ def name(self) -> str:
48
+ return self.id.name.name
49
+
50
+ @property
51
+ def id(self) -> identifier_pb2.TriggerIdentifier:
52
+ return self.pb2.id
53
+
54
+ @property
55
+ def task_name(self) -> str:
56
+ return self.pb2.id.name.task_name
57
+
58
+ @property
59
+ def automation_spec(self) -> common_pb2.TriggerAutomationSpec:
60
+ return self.pb2.automation_spec
61
+
62
+ @property
63
+ def metadata(self) -> trigger_definition_pb2.TriggerMetadata:
64
+ return self.pb2.metadata
65
+
66
+ @property
67
+ def status(self) -> trigger_definition_pb2.TriggerStatus:
68
+ return self.pb2.status
69
+
70
+ @property
71
+ def is_active(self) -> bool:
72
+ return self.pb2.spec.active
73
+
74
+ @cached_property
75
+ def trigger(self) -> trigger_definition_pb2.Trigger:
76
+ return trigger_definition_pb2.Trigger(
77
+ id=self.pb2.id,
78
+ automation_spec=self.automation_spec,
79
+ metadata=self.metadata,
80
+ status=self.status,
81
+ active=self.is_active,
82
+ )
83
+
84
+
85
+ @dataclass
86
+ class Trigger(ToJSONMixin):
87
+ pb2: trigger_definition_pb2.Trigger
88
+ details: TriggerDetails | None = None
89
+
90
+ @syncify
91
+ @classmethod
92
+ async def create(
93
+ cls,
94
+ trigger: flyte.Trigger,
95
+ task_name: str,
96
+ task_version: str | None = None,
97
+ ) -> Trigger:
98
+ """
99
+ Create a new trigger in the Flyte platform.
100
+
101
+ :param trigger: The flyte.Trigger object containing the trigger definition.
102
+ :param task_name: Optional name of the task to associate with the trigger.
103
+ """
104
+ ensure_client()
105
+ cfg = get_init_config()
106
+
107
+ # Fetch the task to ensure it exists and to get its input definitions
108
+ try:
109
+ lazy = (
110
+ Task.get(name=task_name, version=task_version)
111
+ if task_version
112
+ else Task.get(name=task_name, auto_version="latest")
113
+ )
114
+ task: TaskDetails = await lazy.fetch.aio()
115
+
116
+ task_trigger = await trigger_serde.to_task_trigger(
117
+ t=trigger,
118
+ task_name=task_name,
119
+ task_inputs=task.pb2.spec.task_template.interface.inputs,
120
+ task_default_inputs=list(task.pb2.spec.default_inputs),
121
+ )
122
+
123
+ resp = await get_client().trigger_service.DeployTrigger(
124
+ request=trigger_service_pb2.DeployTriggerRequest(
125
+ name=identifier_pb2.TriggerName(
126
+ name=trigger.name,
127
+ task_name=task_name,
128
+ org=cfg.org,
129
+ project=cfg.project,
130
+ domain=cfg.domain,
131
+ ),
132
+ spec=trigger_definition_pb2.TriggerSpec(
133
+ active=task_trigger.spec.active,
134
+ inputs=task_trigger.spec.inputs,
135
+ run_spec=task_trigger.spec.run_spec,
136
+ task_version=task.version,
137
+ ),
138
+ automation_spec=task_trigger.automation_spec,
139
+ )
140
+ )
141
+
142
+ details = TriggerDetails(pb2=resp.trigger)
143
+
144
+ return cls(pb2=details.trigger, details=details)
145
+ except grpc.aio.AioRpcError as e:
146
+ if e.code() == grpc.StatusCode.NOT_FOUND:
147
+ raise ValueError(f"Task {task_name}:{task_version or 'latest'} not found") from e
148
+ raise
149
+
150
+ @syncify
151
+ @classmethod
152
+ async def get(cls, *, name: str, task_name: str) -> TriggerDetails:
153
+ """
154
+ Retrieve a trigger by its name and associated task name.
155
+ """
156
+ return await TriggerDetails.get.aio(name=name, task_name=task_name)
157
+
158
+ @syncify
159
+ @classmethod
160
+ async def listall(
161
+ cls, task_name: str | None = None, task_version: str | None = None, limit: int = 100
162
+ ) -> AsyncIterator[Trigger]:
163
+ """
164
+ List all triggers associated with a specific task or all tasks if no task name is provided.
165
+ """
166
+ ensure_client()
167
+ cfg = get_init_config()
168
+ token = None
169
+ task_name_id = None
170
+ project_id = None
171
+ task_id = None
172
+ if task_name and task_version:
173
+ task_id = task_definition_pb2.TaskIdentifier(
174
+ name=task_name,
175
+ project=cfg.project,
176
+ domain=cfg.domain,
177
+ org=cfg.org,
178
+ version=task_version,
179
+ )
180
+ elif task_name:
181
+ task_name_id = task_definition_pb2.TaskName(
182
+ name=task_name,
183
+ project=cfg.project,
184
+ domain=cfg.domain,
185
+ org=cfg.org,
186
+ )
187
+ else:
188
+ project_id = identifier_pb2.ProjectIdentifier(
189
+ organization=cfg.org,
190
+ domain=cfg.domain,
191
+ name=cfg.project,
192
+ )
193
+
194
+ while True:
195
+ resp = await get_client().trigger_service.ListTriggers(
196
+ request=trigger_service_pb2.ListTriggersRequest(
197
+ project_id=project_id,
198
+ task_id=task_id,
199
+ task_name=task_name_id,
200
+ request=list_pb2.ListRequest(
201
+ limit=limit,
202
+ token=token,
203
+ ),
204
+ )
205
+ )
206
+ token = resp.token
207
+ for r in resp.triggers:
208
+ yield cls(r)
209
+ if not token:
210
+ break
211
+
212
+ @syncify
213
+ @classmethod
214
+ async def update(cls, name: str, task_name: str, active: bool):
215
+ """
216
+ Pause a trigger by its name and associated task name.
217
+ """
218
+ ensure_client()
219
+ cfg = get_init_config()
220
+ await get_client().trigger_service.UpdateTriggers(
221
+ request=trigger_service_pb2.UpdateTriggersRequest(
222
+ names=[
223
+ identifier_pb2.TriggerName(
224
+ org=cfg.org,
225
+ project=cfg.project,
226
+ domain=cfg.domain,
227
+ name=name,
228
+ task_name=task_name,
229
+ )
230
+ ],
231
+ active=active,
232
+ )
233
+ )
234
+
235
+ @syncify
236
+ @classmethod
237
+ async def delete(cls, name: str, task_name: str):
238
+ """
239
+ Delete a trigger by its name.
240
+ """
241
+ ensure_client()
242
+ cfg = get_init_config()
243
+ await get_client().trigger_service.DeleteTriggers(
244
+ request=trigger_service_pb2.DeleteTriggersRequest(
245
+ names=[
246
+ identifier_pb2.TriggerName(
247
+ org=cfg.org,
248
+ project=cfg.project,
249
+ domain=cfg.domain,
250
+ name=name,
251
+ task_name=task_name,
252
+ )
253
+ ],
254
+ )
255
+ )
256
+
257
+ @property
258
+ def id(self) -> identifier_pb2.TriggerIdentifier:
259
+ return self.pb2.id
260
+
261
+ @property
262
+ def name(self) -> str:
263
+ return self.id.name.name
264
+
265
+ @property
266
+ def task_name(self) -> str:
267
+ return self.id.name.task_name
268
+
269
+ @property
270
+ def automation_spec(self) -> common_pb2.TriggerAutomationSpec:
271
+ return self.pb2.automation_spec
272
+
273
+ async def get_details(self) -> TriggerDetails:
274
+ """
275
+ Get detailed information about this trigger.
276
+ """
277
+ if not self.details:
278
+ details = await TriggerDetails.get.aio(name=self.pb2.id.name.name)
279
+ self.details = details
280
+ return self.details
281
+
282
+ @property
283
+ def is_active(self) -> bool:
284
+ return self.pb2.active
285
+
286
+ def _rich_automation(self, automation: common_pb2.TriggerAutomationSpec):
287
+ if automation.type == common_pb2.TriggerAutomationSpec.type.TYPE_NONE:
288
+ yield "none", None
289
+ elif automation.type == common_pb2.TriggerAutomationSpec.type.TYPE_SCHEDULE:
290
+ if automation.schedule.cron is not None:
291
+ yield "cron", automation.schedule.cron
292
+ elif automation.schedule.rate is not None:
293
+ r = automation.schedule.rate
294
+ yield (
295
+ "fixed_rate",
296
+ (
297
+ f"Every [{r.value}] {r.unit} starting at "
298
+ f"{r.start_time.ToDatetime() if automation.HasField('start_time') else 'now'}"
299
+ ),
300
+ )
301
+
302
+ def __rich_repr__(self):
303
+ yield "task_name", self.task_name
304
+ yield "name", self.name
305
+ yield from self._rich_automation(self.pb2.automation_spec)
306
+ yield "auto_activate", self.is_active
flyte/remote/_user.py ADDED
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from flyteidl.service import identity_pb2
6
+ from flyteidl.service.identity_pb2 import UserInfoResponse
7
+
8
+ from .._initialize import ensure_client, get_client
9
+ from ..syncify import syncify
10
+ from ._common import ToJSONMixin
11
+
12
+
13
+ @dataclass
14
+ class User(ToJSONMixin):
15
+ pb2: UserInfoResponse
16
+
17
+ @syncify
18
+ @classmethod
19
+ async def get(cls) -> User:
20
+ """
21
+ Fetches information about the currently logged in user.
22
+ Returns: A User object containing details about the user.
23
+ """
24
+ ensure_client()
25
+
26
+ resp = await get_client().identity_service.UserInfo(identity_pb2.UserInfoRequest())
27
+ return cls(resp)
28
+
29
+ def subject(self) -> str:
30
+ return self.pb2.subject
31
+
32
+ def name(self) -> str:
33
+ return self.pb2.name
flyte/storage/__init__.py CHANGED
@@ -3,6 +3,8 @@ __all__ = [
3
3
  "GCS",
4
4
  "S3",
5
5
  "Storage",
6
+ "exists",
7
+ "exists_sync",
6
8
  "get",
7
9
  "get_configured_fsspec_kwargs",
8
10
  "get_random_local_directory",
@@ -11,13 +13,15 @@ __all__ = [
11
13
  "get_underlying_filesystem",
12
14
  "is_remote",
13
15
  "join",
16
+ "open",
14
17
  "put",
15
18
  "put_stream",
16
- "put_stream",
17
19
  ]
18
20
 
19
21
  from ._config import ABFS, GCS, S3, Storage
20
22
  from ._storage import (
23
+ exists,
24
+ exists_sync,
21
25
  get,
22
26
  get_configured_fsspec_kwargs,
23
27
  get_random_local_directory,
@@ -26,6 +30,7 @@ from ._storage import (
26
30
  get_underlying_filesystem,
27
31
  is_remote,
28
32
  join,
33
+ open,
29
34
  put,
30
35
  put_stream,
31
36
  )