wandb 0.19.10__py3-none-musllinux_1_2_aarch64.whl → 0.19.11__py3-none-musllinux_1_2_aarch64.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 (90) hide show
  1. wandb/__init__.py +1 -1
  2. wandb/__init__.pyi +3 -3
  3. wandb/_pydantic/__init__.py +2 -3
  4. wandb/_pydantic/base.py +11 -31
  5. wandb/_pydantic/utils.py +8 -1
  6. wandb/_pydantic/v1_compat.py +3 -3
  7. wandb/apis/public/api.py +590 -22
  8. wandb/apis/public/artifacts.py +13 -5
  9. wandb/apis/public/automations.py +1 -1
  10. wandb/apis/public/integrations.py +22 -10
  11. wandb/apis/public/registries/__init__.py +0 -0
  12. wandb/apis/public/registries/_freezable_list.py +179 -0
  13. wandb/apis/public/{registries.py → registries/registries_search.py} +22 -129
  14. wandb/apis/public/registries/registry.py +357 -0
  15. wandb/apis/public/registries/utils.py +140 -0
  16. wandb/apis/public/runs.py +58 -56
  17. wandb/automations/__init__.py +16 -24
  18. wandb/automations/_filters/expressions.py +12 -10
  19. wandb/automations/_filters/operators.py +10 -19
  20. wandb/automations/_filters/run_metrics.py +231 -82
  21. wandb/automations/_generated/__init__.py +27 -34
  22. wandb/automations/_generated/create_automation.py +17 -0
  23. wandb/automations/_generated/delete_automation.py +17 -0
  24. wandb/automations/_generated/fragments.py +40 -25
  25. wandb/automations/_generated/{get_triggers.py → get_automations.py} +5 -5
  26. wandb/automations/_generated/{get_triggers_by_entity.py → get_automations_by_entity.py} +7 -5
  27. wandb/automations/_generated/operations.py +35 -98
  28. wandb/automations/_generated/update_automation.py +17 -0
  29. wandb/automations/_utils.py +178 -64
  30. wandb/automations/_validators.py +94 -2
  31. wandb/automations/actions.py +113 -98
  32. wandb/automations/automations.py +47 -69
  33. wandb/automations/events.py +139 -87
  34. wandb/automations/integrations.py +23 -4
  35. wandb/automations/scopes.py +22 -20
  36. wandb/bin/gpu_stats +0 -0
  37. wandb/bin/wandb-core +0 -0
  38. wandb/env.py +11 -0
  39. wandb/old/settings.py +4 -1
  40. wandb/proto/v3/wandb_internal_pb2.py +240 -236
  41. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  42. wandb/proto/v4/wandb_internal_pb2.py +236 -236
  43. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  44. wandb/proto/v5/wandb_internal_pb2.py +236 -236
  45. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  46. wandb/proto/v6/wandb_internal_pb2.py +236 -236
  47. wandb/proto/v6/wandb_telemetry_pb2.py +10 -10
  48. wandb/sdk/artifacts/_generated/__init__.py +42 -1
  49. wandb/sdk/artifacts/_generated/add_aliases.py +21 -0
  50. wandb/sdk/artifacts/_generated/delete_aliases.py +21 -0
  51. wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +67 -0
  52. wandb/sdk/artifacts/_generated/fragments.py +35 -0
  53. wandb/sdk/artifacts/_generated/input_types.py +12 -0
  54. wandb/sdk/artifacts/_generated/operations.py +101 -0
  55. wandb/sdk/artifacts/_generated/update_artifact.py +26 -0
  56. wandb/sdk/artifacts/_graphql_fragments.py +1 -0
  57. wandb/sdk/artifacts/_validators.py +120 -1
  58. wandb/sdk/artifacts/artifact.py +380 -203
  59. wandb/sdk/artifacts/artifact_file_cache.py +4 -6
  60. wandb/sdk/artifacts/artifact_manifest_entry.py +11 -2
  61. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +182 -1
  62. wandb/sdk/artifacts/storage_policy.py +3 -0
  63. wandb/sdk/data_types/video.py +46 -32
  64. wandb/sdk/interface/interface.py +2 -3
  65. wandb/sdk/internal/internal_api.py +21 -31
  66. wandb/sdk/internal/sender.py +5 -2
  67. wandb/sdk/launch/sweeps/utils.py +8 -0
  68. wandb/sdk/projects/_generated/__init__.py +47 -0
  69. wandb/sdk/projects/_generated/delete_project.py +22 -0
  70. wandb/sdk/projects/_generated/enums.py +4 -0
  71. wandb/sdk/projects/_generated/fetch_registry.py +22 -0
  72. wandb/sdk/projects/_generated/fragments.py +41 -0
  73. wandb/sdk/projects/_generated/input_types.py +13 -0
  74. wandb/sdk/projects/_generated/operations.py +88 -0
  75. wandb/sdk/projects/_generated/rename_project.py +27 -0
  76. wandb/sdk/projects/_generated/upsert_registry_project.py +27 -0
  77. wandb/sdk/service/service.py +9 -1
  78. wandb/sdk/wandb_init.py +32 -5
  79. wandb/sdk/wandb_run.py +37 -9
  80. wandb/sdk/wandb_settings.py +6 -7
  81. wandb/sdk/wandb_setup.py +12 -0
  82. wandb/util.py +7 -3
  83. {wandb-0.19.10.dist-info → wandb-0.19.11.dist-info}/METADATA +1 -1
  84. {wandb-0.19.10.dist-info → wandb-0.19.11.dist-info}/RECORD +87 -70
  85. wandb/automations/_generated/create_filter_trigger.py +0 -21
  86. wandb/automations/_generated/delete_trigger.py +0 -19
  87. wandb/automations/_generated/update_filter_trigger.py +0 -21
  88. {wandb-0.19.10.dist-info → wandb-0.19.11.dist-info}/WHEEL +0 -0
  89. {wandb-0.19.10.dist-info → wandb-0.19.11.dist-info}/entry_points.txt +0 -0
  90. {wandb-0.19.10.dist-info → wandb-0.19.11.dist-info}/licenses/LICENSE +0 -0
@@ -4,17 +4,12 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from typing import Any, Dict, List, Literal, Optional, Union
7
+ from typing import Any, Literal, Optional, Union
8
8
 
9
- from pydantic import Field
10
- from typing_extensions import Self, TypeAlias, get_args
9
+ from pydantic import BeforeValidator, Field
10
+ from typing_extensions import Annotated, Self, get_args
11
11
 
12
- from wandb._pydantic import (
13
- SerializedToJson,
14
- field_validator,
15
- model_validator,
16
- pydantic_isinstance,
17
- )
12
+ from wandb._pydantic import GQLBase, GQLId, SerializedToJson, Typename
18
13
 
19
14
  from ._generated import (
20
15
  AlertSeverity,
@@ -25,26 +20,25 @@ from ._generated import (
25
20
  NotificationActionFields,
26
21
  NotificationActionInput,
27
22
  QueueJobActionFields,
28
- TriggeredActionType,
23
+ )
24
+ from ._validators import (
25
+ LenientStrEnum,
26
+ default_if_none,
27
+ to_input_action,
28
+ to_saved_action,
29
+ upper_if_str,
29
30
  )
30
31
  from .integrations import SlackIntegration, WebhookIntegration
31
32
 
32
- # Note: Pydantic doesn't like `list['JsonValue']` or `dict[str, 'JsonValue']`,
33
- # which causes a RecursionError.
34
- JsonValue: TypeAlias = Union[
35
- List[Any],
36
- Dict[str, Any],
37
- # NOTE: For now, we're not expecting any doubly-serialized strings, as this makes validation logic easier, but revisit and revise if needed.
38
- # str,
39
- bool,
40
- int,
41
- float,
42
- None,
43
- ]
44
33
 
45
34
  # NOTE: Name shortened for readability and defined publicly for easier access
46
- ActionType = TriggeredActionType
47
- """The type of action triggered by an automation."""
35
+ class ActionType(LenientStrEnum):
36
+ """The type of action triggered by an automation."""
37
+
38
+ QUEUE_JOB = "QUEUE_JOB" # NOTE: Deprecated for creation
39
+ NOTIFICATION = "NOTIFICATION"
40
+ GENERIC_WEBHOOK = "GENERIC_WEBHOOK"
41
+ NO_OP = "NO_OP"
48
42
 
49
43
 
50
44
  # ------------------------------------------------------------------------------
@@ -58,69 +52,99 @@ class SavedLaunchJobAction(QueueJobActionFields):
58
52
  action_type: Literal[ActionType.QUEUE_JOB] = ActionType.QUEUE_JOB
59
53
 
60
54
 
55
+ # FIXME: Find a better place to put these OR a better way to handle the
56
+ # conversion from `InputAction` -> `SavedAction`.
57
+ #
58
+ # Necessary placeholder class defs for converting:
59
+ # - `SendNotification -> SavedNotificationAction`
60
+ # - `SendWebhook -> SavedWebhookAction`
61
+ #
62
+ # The "input" types (`Send{Notification,Webhook}`) will only have an `integration_id`,
63
+ # and we don't want/need to fetch the other `{Slack,Webhook}Integration` fields if
64
+ # we can avoid it.
65
+ class _SavedActionSlackIntegration(GQLBase, extra="allow"):
66
+ typename__: Typename[Literal["SlackIntegration"]] = "SlackIntegration"
67
+ id: GQLId
68
+
69
+
70
+ class _SavedActionWebhookIntegration(GQLBase, extra="allow"):
71
+ typename__: Typename[Literal["GenericWebhookIntegration"]] = (
72
+ "GenericWebhookIntegration"
73
+ )
74
+ id: GQLId
75
+
76
+
61
77
  class SavedNotificationAction(NotificationActionFields):
62
78
  action_type: Literal[ActionType.NOTIFICATION] = ActionType.NOTIFICATION
79
+ integration: _SavedActionSlackIntegration
63
80
 
64
81
 
65
82
  class SavedWebhookAction(GenericWebhookActionFields):
66
83
  action_type: Literal[ActionType.GENERIC_WEBHOOK] = ActionType.GENERIC_WEBHOOK
84
+ integration: _SavedActionWebhookIntegration
67
85
 
68
86
  # We override the type of the `requestPayload` field since the original GraphQL
69
87
  # schema (and generated class) effectively defines it as a string, when we know
70
88
  # and need to anticipate the expected structure of the JSON-serialized data.
71
- request_payload: Optional[SerializedToJson[JsonValue]] = Field( # type: ignore[assignment]
72
- default=None, alias="requestPayload"
73
- )
89
+ request_payload: Annotated[
90
+ Optional[SerializedToJson[dict[str, Any]]],
91
+ Field(alias="requestPayload"),
92
+ ] = None # type: ignore[assignment]
74
93
 
75
94
 
76
- class SavedNoOpAction(NoOpActionFields):
95
+ class SavedNoOpAction(NoOpActionFields, frozen=True):
77
96
  action_type: Literal[ActionType.NO_OP] = ActionType.NO_OP
78
97
 
98
+ no_op: Annotated[bool, BeforeValidator(default_if_none)] = True
99
+ """Placeholder field, only needed to conform to schema requirements.
100
+
101
+ There should never be a need to set this field explicitly, as its value is ignored.
102
+ """
103
+
79
104
 
80
105
  # for type annotations
81
- SavedAction = Union[
82
- SavedLaunchJobAction,
83
- SavedNotificationAction,
84
- SavedWebhookAction,
85
- SavedNoOpAction,
106
+ SavedAction = Annotated[
107
+ Union[
108
+ SavedLaunchJobAction,
109
+ SavedNotificationAction,
110
+ SavedWebhookAction,
111
+ SavedNoOpAction,
112
+ ],
113
+ BeforeValidator(to_saved_action),
114
+ Field(discriminator="typename__"),
86
115
  ]
87
116
  # for runtime type checks
88
- SavedActionTypes: tuple[type, ...] = get_args(SavedAction)
117
+ SavedActionTypes: tuple[type, ...] = get_args(SavedAction.__origin__) # type: ignore[attr-defined]
89
118
 
90
119
 
91
120
  # ------------------------------------------------------------------------------
92
121
  # Input types: for creating or updating automations
93
- class DoNotification(NotificationActionInput):
94
- """Schema for defining a triggered notification action."""
122
+ class _BaseActionInput(GQLBase):
123
+ action_type: Annotated[ActionType, Field(frozen=True)]
124
+ """The kind of action to be triggered."""
125
+
126
+
127
+ class SendNotification(_BaseActionInput, NotificationActionInput):
128
+ """Defines an automation action that sends a (Slack) notification."""
95
129
 
96
130
  action_type: Literal[ActionType.NOTIFICATION] = ActionType.NOTIFICATION
97
131
 
98
- # Note: Validation aliases match arg names from `wandb.alert()` to allow
99
- # continuity with previous API.
100
- title: str = Field(default="", validation_alias="title")
101
- message: str = Field(default="", validation_alias="text")
102
- severity: AlertSeverity = Field(
103
- default=AlertSeverity.INFO, validation_alias="level"
104
- )
132
+ integration_id: GQLId
133
+ """The ID of the Slack integration that will be used to send the notification."""
105
134
 
106
- @field_validator("severity", mode="before")
107
- @classmethod
108
- def _validate_severity(cls, v: Any) -> Any:
109
- # Be helpful by accepting case-insensitive strings
110
- return v.upper() if isinstance(v, str) else v
135
+ # Note: Validation aliases are meant to provide continuity with prior `wandb.alert()` API.
136
+ title: str = ""
137
+ """The title of the sent notification."""
111
138
 
112
- @model_validator(mode="before")
113
- @classmethod
114
- def _from_saved(cls, v: Any) -> Any:
115
- """Convert an action on a saved automation to a new/input action."""
116
- if pydantic_isinstance(v, SavedNotificationAction):
117
- return cls(
118
- integration_id=v.integration.id,
119
- title=v.title,
120
- message=v.message,
121
- severity=v.severity,
122
- )
123
- return v
139
+ message: Annotated[str, Field(validation_alias="text")] = ""
140
+ """The message body of the sent notification."""
141
+
142
+ severity: Annotated[
143
+ AlertSeverity,
144
+ BeforeValidator(upper_if_str), # Be helpful by ensuring uppercase strings
145
+ Field(validation_alias="level"),
146
+ ] = AlertSeverity.INFO
147
+ """The severity (`INFO`, `WARN`, `ERROR`) of the sent notification."""
124
148
 
125
149
  @classmethod
126
150
  def from_integration(
@@ -132,7 +156,6 @@ class DoNotification(NotificationActionInput):
132
156
  level: AlertSeverity = AlertSeverity.INFO,
133
157
  ) -> Self:
134
158
  """Define a notification action that sends to the given (Slack) integration."""
135
- integration = SlackIntegration.model_validate(integration)
136
159
  return cls(
137
160
  integration_id=integration.id,
138
161
  title=title,
@@ -141,65 +164,57 @@ class DoNotification(NotificationActionInput):
141
164
  )
142
165
 
143
166
 
144
- class DoWebhook(GenericWebhookActionInput):
145
- """Schema for defining a triggered webhook action."""
167
+ class SendWebhook(_BaseActionInput, GenericWebhookActionInput):
168
+ """Defines an automation action that sends a webhook request."""
146
169
 
147
170
  action_type: Literal[ActionType.GENERIC_WEBHOOK] = ActionType.GENERIC_WEBHOOK
148
171
 
172
+ integration_id: GQLId
173
+ """The ID of the webhook integration that will be used to send the request."""
174
+
149
175
  # overrides the generated field type to parse/serialize JSON strings
150
- request_payload: Optional[SerializedToJson[JsonValue]] = Field( # type: ignore[assignment]
176
+ request_payload: Optional[SerializedToJson[dict[str, Any]]] = Field( # type: ignore[assignment]
151
177
  default=None, alias="requestPayload"
152
178
  )
153
-
154
- @model_validator(mode="before")
155
- @classmethod
156
- def _from_saved(cls, v: Any) -> Any:
157
- """Convert an action on a saved automation to a new/input action."""
158
- if pydantic_isinstance(v, SavedWebhookAction):
159
- return cls(
160
- integration_id=v.integration.id,
161
- request_payload=v.request_payload,
162
- )
163
- return v
179
+ """The payload, possibly with template variables, to send in the webhook request."""
164
180
 
165
181
  @classmethod
166
182
  def from_integration(
167
183
  cls,
168
184
  integration: WebhookIntegration,
169
185
  *,
170
- request_payload: Optional[SerializedToJson[JsonValue]] = None,
186
+ payload: Optional[SerializedToJson[dict[str, Any]]] = None,
171
187
  ) -> Self:
172
188
  """Define a webhook action that sends to the given (webhook) integration."""
173
- integration = WebhookIntegration.model_validate(integration)
174
- return cls(integration_id=integration.id, request_payload=request_payload)
189
+ return cls(integration_id=integration.id, request_payload=payload)
175
190
 
176
191
 
177
- class DoNothing(NoOpTriggeredActionInput):
178
- """Schema for defining a triggered no-op action."""
192
+ class DoNothing(_BaseActionInput, NoOpTriggeredActionInput, frozen=True):
193
+ """Defines an automation action that intentionally does nothing."""
179
194
 
180
195
  action_type: Literal[ActionType.NO_OP] = ActionType.NO_OP
181
196
 
182
- no_op: bool = True # prevent exclusion on `.model_dump(exclude_none=True)`
183
-
184
- @field_validator("no_op", mode="before")
185
- @classmethod
186
- def _ensure_nonnull(cls, v: Any) -> Any:
187
- # Ensuring the value isn't None complies with validation and
188
- # prevents the field (and action data) from getting excluded on
189
- # `.model_dump(exclude_none=True)`
190
- return True if (v is None) else v
191
-
197
+ no_op: Annotated[bool, BeforeValidator(default_if_none)] = True
198
+ """Placeholder field which exists only to satisfy backend schema requirements.
192
199
 
193
- DoNotification.model_rebuild()
194
- DoWebhook.model_rebuild()
195
- DoNothing.model_rebuild()
200
+ There should never be a need to set this field explicitly, as its value is ignored.
201
+ """
196
202
 
197
203
 
198
204
  # for type annotations
199
- InputAction = Union[
200
- DoNotification,
201
- DoWebhook,
202
- DoNothing,
205
+ InputAction = Annotated[
206
+ Union[
207
+ SendNotification,
208
+ SendWebhook,
209
+ DoNothing,
210
+ ],
211
+ BeforeValidator(to_input_action),
212
+ Field(discriminator="action_type"),
203
213
  ]
204
214
  # for runtime type checks
205
- InputActionTypes: tuple[type, ...] = get_args(InputAction)
215
+ InputActionTypes: tuple[type, ...] = get_args(InputAction.__origin__) # type: ignore[attr-defined]
216
+
217
+ __all__ = [
218
+ "ActionType",
219
+ *(cls.__name__ for cls in InputActionTypes),
220
+ ]
@@ -3,19 +3,17 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from datetime import datetime
6
- from typing import TYPE_CHECKING, Optional
6
+ from typing import Optional
7
7
 
8
8
  from pydantic import Field
9
+ from typing_extensions import Annotated
9
10
 
10
- from wandb._pydantic import Base, GQLId
11
+ from wandb._pydantic import GQLBase, GQLId
11
12
 
12
- from ._generated import TriggerFields, UserFields
13
+ from ._generated import TriggerFields
13
14
  from .actions import InputAction, SavedAction
14
15
  from .events import InputEvent, SavedEvent
15
- from .scopes import InputScope, SavedScope
16
-
17
- if TYPE_CHECKING:
18
- pass
16
+ from .scopes import AutomationScope
19
17
 
20
18
 
21
19
  # ------------------------------------------------------------------------------
@@ -25,85 +23,65 @@ class Automation(TriggerFields):
25
23
 
26
24
  id: GQLId
27
25
 
28
- created_by: UserFields = Field(repr=False, frozen=True, alias="createdBy")
29
- created_at: datetime = Field(repr=False, frozen=True, alias="createdAt")
30
- updated_at: Optional[datetime] = Field(repr=False, frozen=True, alias="updatedAt")
26
+ created_at: Annotated[datetime, Field(repr=False, frozen=True, alias="createdAt")]
27
+ """The date and time when this automation was created."""
28
+
29
+ updated_at: Annotated[
30
+ Optional[datetime], Field(repr=False, frozen=True, alias="updatedAt")
31
+ ] = None
32
+ """The date and time when this automation was last updated, if applicable."""
31
33
 
32
34
  name: str
33
- description: Optional[str]
35
+ """The name of this automation."""
34
36
 
35
- scope: SavedScope = Field(discriminator="typename__")
36
- event: SavedEvent
37
- action: SavedAction = Field(discriminator="typename__", alias="triggeredAction")
37
+ description: Optional[str]
38
+ """An optional description of this automation."""
38
39
 
39
40
  enabled: bool
41
+ """Whether this automation is enabled. Only enabled automations will trigger."""
40
42
 
41
- # def save(
42
- # self, api: Api | None = None, **updates: Unpack[AutomationParams]
43
- # ) -> Automation:
44
- # """Save this existing automation to the server, applying any local changes.
45
-
46
- # Args:
47
- # api: The API instance to use. If not provided, the default API instance is used.
48
- # updates:
49
- # Any final updates to apply to the automation before
50
- # saving it. These override previously-set values, if any.
51
-
52
- # Returns:
53
- # The updated automation.
54
- # """
55
- # from wandb import Api
56
-
57
- # return (api or Api()).update_automation(self, **updates)
58
-
59
- # def delete(self, api: Api | None = None) -> DeleteTriggerResult:
60
- # """Delete this automation from the server.
43
+ event: SavedEvent
44
+ """The event that will trigger this automation."""
61
45
 
62
- # Args:
63
- # api: The API instance to use. If not provided, the default API instance is used.
64
- # """
65
- # from wandb import Api
46
+ scope: AutomationScope
47
+ """The scope in which the triggering event must occur."""
66
48
 
67
- # return (api or Api()).delete_automation(self)
49
+ action: SavedAction
50
+ """The action that will execute when this automation is triggered."""
68
51
 
69
52
 
70
- class NewAutomation(Base):
71
- """An automation which can hold any of the fields of a NewAutomation, but may not be complete yet."""
53
+ class NewAutomation(GQLBase, extra="forbid", validate_default=False):
54
+ """A new automation to be created."""
72
55
 
73
56
  name: Optional[str] = None
74
- description: Optional[str] = None
75
- enabled: bool = True
76
-
77
- scope: Optional[InputScope] = Field(discriminator="typename__", default=None)
78
- event: Optional[InputEvent] = Field(discriminator="event_type", default=None)
79
- action: Optional[InputAction] = Field(discriminator="action_type", default=None)
57
+ """The name of this automation."""
80
58
 
81
- # def save(
82
- # self, api: Api | None = None, **updates: Unpack[AutomationParams]
83
- # ) -> Automation:
84
- # """Create this automation by saving it to the server.
59
+ description: Optional[str] = None
60
+ """An optional description of this automation."""
85
61
 
86
- # Args:
87
- # api: The API instance to use. If not provided, the default API instance is used.
88
- # updates:
89
- # Any final updates to apply to the automation before
90
- # saving it. These override previously-set values, if any.
62
+ enabled: Optional[bool] = None
63
+ """Whether this automation is enabled. Only enabled automations will trigger."""
91
64
 
92
- # Returns:
93
- # The created automation.
94
- # """
95
- # from wandb import Api
65
+ event: Optional[InputEvent] = None
66
+ """The event that will trigger this automation."""
96
67
 
97
- # return (api or Api()).create_automation(self, **updates)
68
+ # Ensure that the event and its scope are always consistent, if the event is set.
69
+ @property
70
+ def scope(self) -> Optional[AutomationScope]:
71
+ """The scope in which the triggering event must occur."""
72
+ return self.event.scope if self.event else None
98
73
 
74
+ @scope.setter
75
+ def scope(self, value: AutomationScope) -> None:
76
+ if self.event is None:
77
+ raise ValueError("Cannot set `scope` for an automation with no `event`")
78
+ self.event.scope = value
99
79
 
100
- class PreparedAutomation(NewAutomation):
101
- """A fully defined automation, ready to be sent to the server to create or update it."""
80
+ action: Optional[InputAction] = None
81
+ """The action that will execute when this automation is triggered."""
102
82
 
103
- name: str
104
- description: Optional[str] = None
105
- enabled: bool = True
106
83
 
107
- scope: InputScope
108
- event: InputEvent
109
- action: InputAction
84
+ __all__ = [
85
+ "Automation",
86
+ "NewAutomation",
87
+ ]