Home Assistant Unofficial Reference 2024.12.1
models.py
Go to the documentation of this file.
1 """Containers for a script or automation trace."""
2 
3 from __future__ import annotations
4 
5 import abc
6 from collections import deque
7 import datetime as dt
8 from typing import Any
9 
10 from homeassistant.core import Context
11 from homeassistant.helpers.trace import (
12  TraceElement,
13  script_execution_get,
14  trace_id_get,
15  trace_id_set,
16  trace_set_child_id,
17 )
18 import homeassistant.util.dt as dt_util
19 from homeassistant.util.limited_size_dict import LimitedSizeDict
20 import homeassistant.util.uuid as uuid_util
21 
22 type TraceData = dict[str, LimitedSizeDict[str, BaseTrace]]
23 
24 
25 class BaseTrace(abc.ABC):
26  """Base container for a script or automation trace."""
27 
28  context: Context
29  key: str
30  run_id: str
31 
32  def as_dict(self) -> dict[str, Any]:
33  """Return an dictionary version of this ActionTrace for saving."""
34  return {
35  "extended_dict": self.as_extended_dictas_extended_dict(),
36  "short_dict": self.as_short_dictas_short_dict(),
37  }
38 
39  @abc.abstractmethod
40  def as_extended_dict(self) -> dict[str, Any]:
41  """Return an extended dictionary version of this ActionTrace."""
42 
43  @abc.abstractmethod
44  def as_short_dict(self) -> dict[str, Any]:
45  """Return a brief dictionary version of this ActionTrace."""
46 
47 
48 class ActionTrace(BaseTrace):
49  """Base container for a script or automation trace."""
50 
51  _domain: str | None = None
52 
53  def __init__(
54  self,
55  item_id: str | None,
56  config: dict[str, Any] | None,
57  blueprint_inputs: dict[str, Any] | None,
58  context: Context,
59  ) -> None:
60  """Container for script trace."""
61  self._trace_trace: dict[str, deque[TraceElement]] | None = None
62  self._config_config = config
63  self._blueprint_inputs_blueprint_inputs = blueprint_inputs
64  self.context: Context = context
65  self._error_error: Exception | None = None
66  self._state_state: str = "running"
67  self._script_execution_script_execution: str | None = None
68  self.run_id: str = uuid_util.random_uuid_hex()
69  self._timestamp_finish_timestamp_finish: dt.datetime | None = None
70  self._timestamp_start: dt.datetime = dt_util.utcnow()
71  self.keykey = f"{self._domain}.{item_id}"
72  self._dict_dict: dict[str, Any] | None = None
73  self._short_dict_short_dict: dict[str, Any] | None = None
74  if trace_id_get():
75  trace_set_child_id(self.keykey, self.run_id)
76  trace_id_set((self.keykey, self.run_id))
77 
78  def set_trace(self, trace: dict[str, deque[TraceElement]] | None) -> None:
79  """Set action trace."""
80  self._trace_trace = trace
81 
82  def set_error(self, ex: Exception) -> None:
83  """Set error."""
84  self._error_error = ex
85 
86  def finished(self) -> None:
87  """Set finish time."""
88  self._timestamp_finish_timestamp_finish = dt_util.utcnow()
89  self._state_state = "stopped"
90  self._script_execution_script_execution = script_execution_get()
91 
92  def as_extended_dict(self) -> dict[str, Any]:
93  """Return an extended dictionary version of this ActionTrace."""
94  if self._dict_dict:
95  return self._dict_dict
96 
97  result = dict(self.as_short_dictas_short_dictas_short_dict())
98 
99  traces = {}
100  if self._trace_trace:
101  for key, trace_list in self._trace_trace.items():
102  traces[key] = [item.as_dict() for item in trace_list]
103 
104  result.update(
105  {
106  "trace": traces,
107  "config": self._config_config,
108  "blueprint_inputs": self._blueprint_inputs_blueprint_inputs,
109  "context": self.context,
110  }
111  )
112 
113  if self._state_state == "stopped":
114  # Execution has stopped, save the result
115  self._dict_dict = result
116  return result
117 
118  def as_short_dict(self) -> dict[str, Any]:
119  """Return a brief dictionary version of this ActionTrace."""
120  if self._short_dict_short_dict:
121  return self._short_dict_short_dict
122 
123  last_step = None
124 
125  if self._trace_trace:
126  last_step = list(self._trace_trace)[-1]
127  domain, item_id = self.keykey.split(".", 1)
128 
129  result = {
130  "last_step": last_step,
131  "run_id": self.run_id,
132  "state": self._state_state,
133  "script_execution": self._script_execution_script_execution,
134  "timestamp": {
135  "start": self._timestamp_start,
136  "finish": self._timestamp_finish_timestamp_finish,
137  },
138  "domain": domain,
139  "item_id": item_id,
140  }
141  if self._error_error is not None:
142  result["error"] = str(self._error_error)
143 
144  if self._state_state == "stopped":
145  # Execution has stopped, save the result
146  self._short_dict_short_dict = result
147  return result
148 
149 
151  """Container for a restored script or automation trace."""
152 
153  def __init__(self, data: dict[str, Any]) -> None:
154  """Restore from dict."""
155  extended_dict = data["extended_dict"]
156  short_dict = data["short_dict"]
157  context = Context(
158  user_id=extended_dict["context"]["user_id"],
159  parent_id=extended_dict["context"]["parent_id"],
160  id=extended_dict["context"]["id"],
161  )
162  self.contextcontext = context
163  self.keykey = f"{extended_dict['domain']}.{extended_dict['item_id']}"
164  self.run_idrun_id = extended_dict["run_id"]
165  self._dict_dict = extended_dict
166  self._short_dict_short_dict = short_dict
167 
168  def as_extended_dict(self) -> dict[str, Any]:
169  """Return an extended dictionary version of this RestoredTrace."""
170  return self._dict_dict # type: ignore[no-any-return]
171 
172  def as_short_dict(self) -> dict[str, Any]:
173  """Return a brief dictionary version of this RestoredTrace."""
174  return self._short_dict_short_dict # type: ignore[no-any-return]
None __init__(self, str|None item_id, dict[str, Any]|None config, dict[str, Any]|None blueprint_inputs, Context context)
Definition: models.py:59
None set_trace(self, dict[str, deque[TraceElement]]|None trace)
Definition: models.py:78
None __init__(self, dict[str, Any] data)
Definition: models.py:153
None trace_id_set(tuple[str, str] trace_id)
Definition: trace.py:125
tuple[str, str]|None trace_id_get()
Definition: trace.py:130
str|None script_execution_get()
Definition: trace.py:243
None trace_set_child_id(str child_key, str child_run_id)
Definition: trace.py:210