object.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. """Classes for immutable object vars."""
  2. from __future__ import annotations
  3. import dataclasses
  4. import sys
  5. import typing
  6. from functools import cached_property
  7. from inspect import isclass
  8. from typing import (
  9. Any,
  10. Dict,
  11. List,
  12. NoReturn,
  13. Tuple,
  14. Type,
  15. TypeVar,
  16. Union,
  17. get_args,
  18. overload,
  19. )
  20. from typing_extensions import get_origin
  21. from reflex.experimental.vars.base import (
  22. ImmutableVar,
  23. LiteralVar,
  24. figure_out_type,
  25. )
  26. from reflex.experimental.vars.number import NumberVar
  27. from reflex.experimental.vars.sequence import ArrayVar, StringVar
  28. from reflex.utils.exceptions import VarAttributeError
  29. from reflex.utils.types import GenericType, get_attribute_access_type
  30. from reflex.vars import ImmutableVarData, Var, VarData
  31. OBJECT_TYPE = TypeVar("OBJECT_TYPE")
  32. KEY_TYPE = TypeVar("KEY_TYPE")
  33. VALUE_TYPE = TypeVar("VALUE_TYPE")
  34. ARRAY_INNER_TYPE = TypeVar("ARRAY_INNER_TYPE")
  35. OTHER_KEY_TYPE = TypeVar("OTHER_KEY_TYPE")
  36. class ObjectVar(ImmutableVar[OBJECT_TYPE]):
  37. """Base class for immutable object vars."""
  38. @overload
  39. def _key_type(self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]]) -> KEY_TYPE: ...
  40. @overload
  41. def _key_type(self) -> Type: ...
  42. def _key_type(self) -> Type:
  43. """Get the type of the keys of the object.
  44. Returns:
  45. The type of the keys of the object.
  46. """
  47. fixed_type = (
  48. self._var_type if isclass(self._var_type) else get_origin(self._var_type)
  49. )
  50. args = get_args(self._var_type) if issubclass(fixed_type, dict) else ()
  51. return args[0] if args else Any
  52. @overload
  53. def _value_type(self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]]) -> VALUE_TYPE: ...
  54. @overload
  55. def _value_type(self) -> Type: ...
  56. def _value_type(self) -> Type:
  57. """Get the type of the values of the object.
  58. Returns:
  59. The type of the values of the object.
  60. """
  61. fixed_type = (
  62. self._var_type if isclass(self._var_type) else get_origin(self._var_type)
  63. )
  64. args = get_args(self._var_type) if issubclass(fixed_type, dict) else ()
  65. return args[1] if args else Any
  66. @overload
  67. def keys(
  68. self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
  69. ) -> ArrayVar[List[KEY_TYPE]]: ...
  70. @overload
  71. def keys(self) -> ArrayVar: ...
  72. def keys(self) -> ArrayVar:
  73. """Get the keys of the object.
  74. Returns:
  75. The keys of the object.
  76. """
  77. return ObjectKeysOperation(self)
  78. @overload
  79. def values(
  80. self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
  81. ) -> ArrayVar[List[VALUE_TYPE]]: ...
  82. @overload
  83. def values(self) -> ArrayVar: ...
  84. def values(self) -> ArrayVar:
  85. """Get the values of the object.
  86. Returns:
  87. The values of the object.
  88. """
  89. return ObjectValuesOperation(self)
  90. @overload
  91. def entries(
  92. self: ObjectVar[Dict[KEY_TYPE, VALUE_TYPE]],
  93. ) -> ArrayVar[List[Tuple[KEY_TYPE, VALUE_TYPE]]]: ...
  94. @overload
  95. def entries(self) -> ArrayVar: ...
  96. def entries(self) -> ArrayVar:
  97. """Get the entries of the object.
  98. Returns:
  99. The entries of the object.
  100. """
  101. return ObjectEntriesOperation(self)
  102. def merge(self, other: ObjectVar) -> ObjectMergeOperation:
  103. """Merge two objects.
  104. Args:
  105. other: The other object to merge.
  106. Returns:
  107. The merged object.
  108. """
  109. return ObjectMergeOperation(self, other)
  110. # NoReturn is used here to catch when key value is Any
  111. @overload
  112. def __getitem__(
  113. self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
  114. key: Var | Any,
  115. ) -> ImmutableVar: ...
  116. @overload
  117. def __getitem__(
  118. self: (
  119. ObjectVar[Dict[KEY_TYPE, int]]
  120. | ObjectVar[Dict[KEY_TYPE, float]]
  121. | ObjectVar[Dict[KEY_TYPE, int | float]]
  122. ),
  123. key: Var | Any,
  124. ) -> NumberVar: ...
  125. @overload
  126. def __getitem__(
  127. self: ObjectVar[Dict[KEY_TYPE, str]],
  128. key: Var | Any,
  129. ) -> StringVar: ...
  130. @overload
  131. def __getitem__(
  132. self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
  133. key: Var | Any,
  134. ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
  135. @overload
  136. def __getitem__(
  137. self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
  138. key: Var | Any,
  139. ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
  140. @overload
  141. def __getitem__(
  142. self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
  143. key: Var | Any,
  144. ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
  145. @overload
  146. def __getitem__(
  147. self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
  148. key: Var | Any,
  149. ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
  150. def __getitem__(self, key: Var | Any) -> ImmutableVar:
  151. """Get an item from the object.
  152. Args:
  153. key: The key to get from the object.
  154. Returns:
  155. The item from the object.
  156. """
  157. return ObjectItemOperation(self, key).guess_type()
  158. # NoReturn is used here to catch when key value is Any
  159. @overload
  160. def __getattr__(
  161. self: ObjectVar[Dict[KEY_TYPE, NoReturn]],
  162. name: str,
  163. ) -> ImmutableVar: ...
  164. @overload
  165. def __getattr__(
  166. self: (
  167. ObjectVar[Dict[KEY_TYPE, int]]
  168. | ObjectVar[Dict[KEY_TYPE, float]]
  169. | ObjectVar[Dict[KEY_TYPE, int | float]]
  170. ),
  171. name: str,
  172. ) -> NumberVar: ...
  173. @overload
  174. def __getattr__(
  175. self: ObjectVar[Dict[KEY_TYPE, str]],
  176. name: str,
  177. ) -> StringVar: ...
  178. @overload
  179. def __getattr__(
  180. self: ObjectVar[Dict[KEY_TYPE, list[ARRAY_INNER_TYPE]]],
  181. name: str,
  182. ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
  183. @overload
  184. def __getattr__(
  185. self: ObjectVar[Dict[KEY_TYPE, set[ARRAY_INNER_TYPE]]],
  186. name: str,
  187. ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
  188. @overload
  189. def __getattr__(
  190. self: ObjectVar[Dict[KEY_TYPE, tuple[ARRAY_INNER_TYPE, ...]]],
  191. name: str,
  192. ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
  193. @overload
  194. def __getattr__(
  195. self: ObjectVar[Dict[KEY_TYPE, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
  196. name: str,
  197. ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
  198. def __getattr__(self, name) -> ImmutableVar:
  199. """Get an attribute of the var.
  200. Args:
  201. name: The name of the attribute.
  202. Raises:
  203. VarAttributeError: The State var has no such attribute or may have been annotated wrongly.
  204. Returns:
  205. The attribute of the var.
  206. """
  207. fixed_type = (
  208. self._var_type if isclass(self._var_type) else get_origin(self._var_type)
  209. )
  210. if not issubclass(fixed_type, dict):
  211. attribute_type = get_attribute_access_type(self._var_type, name)
  212. if attribute_type is None:
  213. raise VarAttributeError(
  214. f"The State var `{self._var_name}` has no attribute '{name}' or may have been annotated "
  215. f"wrongly."
  216. )
  217. return ObjectItemOperation(self, name, attribute_type).guess_type()
  218. else:
  219. return ObjectItemOperation(self, name).guess_type()
  220. @dataclasses.dataclass(
  221. eq=False,
  222. frozen=True,
  223. **{"slots": True} if sys.version_info >= (3, 10) else {},
  224. )
  225. class LiteralObjectVar(LiteralVar, ObjectVar[OBJECT_TYPE]):
  226. """Base class for immutable literal object vars."""
  227. _var_value: Dict[Union[Var, Any], Union[Var, Any]] = dataclasses.field(
  228. default_factory=dict
  229. )
  230. def __init__(
  231. self: LiteralObjectVar[OBJECT_TYPE],
  232. _var_value: OBJECT_TYPE,
  233. _var_type: Type[OBJECT_TYPE] | None = None,
  234. _var_data: VarData | None = None,
  235. ):
  236. """Initialize the object var.
  237. Args:
  238. _var_value: The value of the var.
  239. _var_type: The type of the var.
  240. _var_data: Additional hooks and imports associated with the Var.
  241. """
  242. super(LiteralObjectVar, self).__init__(
  243. _var_name="",
  244. _var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),
  245. _var_data=ImmutableVarData.merge(_var_data),
  246. )
  247. object.__setattr__(
  248. self,
  249. "_var_value",
  250. _var_value,
  251. )
  252. object.__delattr__(self, "_var_name")
  253. def _key_type(self) -> Type:
  254. """Get the type of the keys of the object.
  255. Returns:
  256. The type of the keys of the object.
  257. """
  258. args_list = typing.get_args(self._var_type)
  259. return args_list[0] if args_list else Any
  260. def _value_type(self) -> Type:
  261. """Get the type of the values of the object.
  262. Returns:
  263. The type of the values of the object.
  264. """
  265. args_list = typing.get_args(self._var_type)
  266. return args_list[1] if args_list else Any
  267. def __getattr__(self, name):
  268. """Get an attribute of the var.
  269. Args:
  270. name: The name of the attribute.
  271. Returns:
  272. The attribute of the var.
  273. """
  274. if name == "_var_name":
  275. return self._cached_var_name
  276. return super(type(self), self).__getattr__(name)
  277. @cached_property
  278. def _cached_var_name(self) -> str:
  279. """The name of the var.
  280. Returns:
  281. The name of the var.
  282. """
  283. return (
  284. "({ "
  285. + ", ".join(
  286. [
  287. f"[{str(LiteralVar.create(key))}] : {str(LiteralVar.create(value))}"
  288. for key, value in self._var_value.items()
  289. ]
  290. )
  291. + " })"
  292. )
  293. @cached_property
  294. def _cached_get_all_var_data(self) -> ImmutableVarData | None:
  295. """Get all VarData associated with the Var.
  296. Returns:
  297. The VarData of the components and all of its children.
  298. """
  299. return ImmutableVarData.merge(
  300. *[
  301. value._get_all_var_data()
  302. for key, value in self._var_value
  303. if isinstance(value, Var)
  304. ],
  305. *[
  306. key._get_all_var_data()
  307. for key, value in self._var_value
  308. if isinstance(key, Var)
  309. ],
  310. self._var_data,
  311. )
  312. def _get_all_var_data(self) -> ImmutableVarData | None:
  313. """Wrapper method for cached property.
  314. Returns:
  315. The VarData of the components and all of its children.
  316. """
  317. return self._cached_get_all_var_data
  318. def json(self) -> str:
  319. """Get the JSON representation of the object.
  320. Returns:
  321. The JSON representation of the object.
  322. """
  323. return (
  324. "{"
  325. + ", ".join(
  326. [
  327. f"{LiteralVar.create(key).json()}:{LiteralVar.create(value).json()}"
  328. for key, value in self._var_value.items()
  329. ]
  330. )
  331. + "}"
  332. )
  333. def __hash__(self) -> int:
  334. """Get the hash of the var.
  335. Returns:
  336. The hash of the var.
  337. """
  338. return hash((self.__class__.__name__, self._var_name))
  339. @dataclasses.dataclass(
  340. eq=False,
  341. frozen=True,
  342. **{"slots": True} if sys.version_info >= (3, 10) else {},
  343. )
  344. class ObjectToArrayOperation(ArrayVar):
  345. """Base class for object to array operations."""
  346. value: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
  347. def __init__(
  348. self,
  349. _var_value: ObjectVar,
  350. _var_type: Type = list,
  351. _var_data: VarData | None = None,
  352. ):
  353. """Initialize the object to array operation.
  354. Args:
  355. _var_value: The value of the operation.
  356. _var_data: Additional hooks and imports associated with the operation.
  357. """
  358. super(ObjectToArrayOperation, self).__init__(
  359. _var_name="",
  360. _var_type=_var_type,
  361. _var_data=ImmutableVarData.merge(_var_data),
  362. )
  363. object.__setattr__(self, "value", _var_value)
  364. object.__delattr__(self, "_var_name")
  365. @cached_property
  366. def _cached_var_name(self) -> str:
  367. """The name of the operation.
  368. Raises:
  369. NotImplementedError: Must implement _cached_var_name.
  370. """
  371. raise NotImplementedError(
  372. "ObjectToArrayOperation must implement _cached_var_name"
  373. )
  374. def __getattr__(self, name):
  375. """Get an attribute of the operation.
  376. Args:
  377. name: The name of the attribute.
  378. Returns:
  379. The attribute of the operation.
  380. """
  381. if name == "_var_name":
  382. return self._cached_var_name
  383. return super(type(self), self).__getattr__(name)
  384. @cached_property
  385. def _cached_get_all_var_data(self) -> ImmutableVarData | None:
  386. """Get all VarData associated with the operation.
  387. Returns:
  388. The VarData of the components and all of its children.
  389. """
  390. return ImmutableVarData.merge(
  391. self.value._get_all_var_data(),
  392. self._var_data,
  393. )
  394. def _get_all_var_data(self) -> ImmutableVarData | None:
  395. """Wrapper method for cached property.
  396. Returns:
  397. The VarData of the components and all of its children.
  398. """
  399. return self._cached_get_all_var_data
  400. class ObjectKeysOperation(ObjectToArrayOperation):
  401. """Operation to get the keys of an object."""
  402. def __init__(
  403. self,
  404. value: ObjectVar,
  405. _var_data: VarData | None = None,
  406. ):
  407. """Initialize the object keys operation.
  408. Args:
  409. value: The value of the operation.
  410. _var_data: Additional hooks and imports associated with the operation.
  411. """
  412. super(ObjectKeysOperation, self).__init__(
  413. value, List[value._key_type()], _var_data
  414. )
  415. @cached_property
  416. def _cached_var_name(self) -> str:
  417. """The name of the operation.
  418. Returns:
  419. The name of the operation.
  420. """
  421. return f"Object.keys({self.value._var_name})"
  422. class ObjectValuesOperation(ObjectToArrayOperation):
  423. """Operation to get the values of an object."""
  424. def __init__(
  425. self,
  426. value: ObjectVar,
  427. _var_data: VarData | None = None,
  428. ):
  429. """Initialize the object values operation.
  430. Args:
  431. value: The value of the operation.
  432. _var_data: Additional hooks and imports associated with the operation.
  433. """
  434. super(ObjectValuesOperation, self).__init__(
  435. value, List[value._value_type()], _var_data
  436. )
  437. @cached_property
  438. def _cached_var_name(self) -> str:
  439. """The name of the operation.
  440. Returns:
  441. The name of the operation.
  442. """
  443. return f"Object.values({self.value._var_name})"
  444. class ObjectEntriesOperation(ObjectToArrayOperation):
  445. """Operation to get the entries of an object."""
  446. def __init__(
  447. self,
  448. value: ObjectVar,
  449. _var_data: VarData | None = None,
  450. ):
  451. """Initialize the object entries operation.
  452. Args:
  453. value: The value of the operation.
  454. _var_data: Additional hooks and imports associated with the operation.
  455. """
  456. super(ObjectEntriesOperation, self).__init__(
  457. value, List[Tuple[value._key_type(), value._value_type()]], _var_data
  458. )
  459. @cached_property
  460. def _cached_var_name(self) -> str:
  461. """The name of the operation.
  462. Returns:
  463. The name of the operation.
  464. """
  465. return f"Object.entries({self.value._var_name})"
  466. @dataclasses.dataclass(
  467. eq=False,
  468. frozen=True,
  469. **{"slots": True} if sys.version_info >= (3, 10) else {},
  470. )
  471. class ObjectMergeOperation(ObjectVar):
  472. """Operation to merge two objects."""
  473. left: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
  474. right: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
  475. def __init__(
  476. self,
  477. left: ObjectVar,
  478. right: ObjectVar,
  479. _var_data: VarData | None = None,
  480. ):
  481. """Initialize the object merge operation.
  482. Args:
  483. left: The left object to merge.
  484. right: The right object to merge.
  485. _var_data: Additional hooks and imports associated with the operation.
  486. """
  487. super(ObjectMergeOperation, self).__init__(
  488. _var_name="",
  489. _var_type=left._var_type,
  490. _var_data=ImmutableVarData.merge(_var_data),
  491. )
  492. object.__setattr__(self, "left", left)
  493. object.__setattr__(self, "right", right)
  494. object.__delattr__(self, "_var_name")
  495. @cached_property
  496. def _cached_var_name(self) -> str:
  497. """The name of the operation.
  498. Returns:
  499. The name of the operation.
  500. """
  501. return f"Object.assign({self.left._var_name}, {self.right._var_name})"
  502. def __getattr__(self, name):
  503. """Get an attribute of the operation.
  504. Args:
  505. name: The name of the attribute.
  506. Returns:
  507. The attribute of the operation.
  508. """
  509. if name == "_var_name":
  510. return self._cached_var_name
  511. return super(type(self), self).__getattr__(name)
  512. @cached_property
  513. def _cached_get_all_var_data(self) -> ImmutableVarData | None:
  514. """Get all VarData associated with the operation.
  515. Returns:
  516. The VarData of the components and all of its children.
  517. """
  518. return ImmutableVarData.merge(
  519. self.left._get_all_var_data(),
  520. self.right._get_all_var_data(),
  521. self._var_data,
  522. )
  523. def _get_all_var_data(self) -> ImmutableVarData | None:
  524. """Wrapper method for cached property.
  525. Returns:
  526. The VarData of the components and all of its children.
  527. """
  528. return self._cached_get_all_var_data
  529. @dataclasses.dataclass(
  530. eq=False,
  531. frozen=True,
  532. **{"slots": True} if sys.version_info >= (3, 10) else {},
  533. )
  534. class ObjectItemOperation(ImmutableVar):
  535. """Operation to get an item from an object."""
  536. value: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
  537. key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
  538. def __init__(
  539. self,
  540. value: ObjectVar,
  541. key: Var | Any,
  542. _var_type: GenericType | None = None,
  543. _var_data: VarData | None = None,
  544. ):
  545. """Initialize the object item operation.
  546. Args:
  547. value: The value of the operation.
  548. key: The key to get from the object.
  549. _var_data: Additional hooks and imports associated with the operation.
  550. """
  551. super(ObjectItemOperation, self).__init__(
  552. _var_name="",
  553. _var_type=value._value_type() if _var_type is None else _var_type,
  554. _var_data=ImmutableVarData.merge(_var_data),
  555. )
  556. object.__setattr__(self, "value", value)
  557. object.__setattr__(
  558. self, "key", key if isinstance(key, Var) else LiteralVar.create(key)
  559. )
  560. object.__delattr__(self, "_var_name")
  561. @cached_property
  562. def _cached_var_name(self) -> str:
  563. """The name of the operation.
  564. Returns:
  565. The name of the operation.
  566. """
  567. return f"{str(self.value)}[{str(self.key)}]"
  568. def __getattr__(self, name):
  569. """Get an attribute of the operation.
  570. Args:
  571. name: The name of the attribute.
  572. Returns:
  573. The attribute of the operation.
  574. """
  575. if name == "_var_name":
  576. return self._cached_var_name
  577. return super(type(self), self).__getattr__(name)
  578. @cached_property
  579. def _cached_get_all_var_data(self) -> ImmutableVarData | None:
  580. """Get all VarData associated with the operation.
  581. Returns:
  582. The VarData of the components and all of its children.
  583. """
  584. return ImmutableVarData.merge(
  585. self.value._get_all_var_data(),
  586. self.key._get_all_var_data(),
  587. self._var_data,
  588. )
  589. def _get_all_var_data(self) -> ImmutableVarData | None:
  590. """Wrapper method for cached property.
  591. Returns:
  592. The VarData of the components and all of its children.
  593. """
  594. return self._cached_get_all_var_data
  595. @dataclasses.dataclass(
  596. eq=False,
  597. frozen=True,
  598. **{"slots": True} if sys.version_info >= (3, 10) else {},
  599. )
  600. class ToObjectOperation(ObjectVar):
  601. """Operation to convert a var to an object."""
  602. _original_var: Var = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
  603. def __init__(
  604. self,
  605. _original_var: Var,
  606. _var_type: Type = dict,
  607. _var_data: VarData | None = None,
  608. ):
  609. """Initialize the to object operation.
  610. Args:
  611. _original_var: The original var to convert.
  612. _var_type: The type of the var.
  613. _var_data: Additional hooks and imports associated with the operation.
  614. """
  615. super(ToObjectOperation, self).__init__(
  616. _var_name="",
  617. _var_type=_var_type,
  618. _var_data=ImmutableVarData.merge(_var_data),
  619. )
  620. object.__setattr__(self, "_original_var", _original_var)
  621. object.__delattr__(self, "_var_name")
  622. @cached_property
  623. def _cached_var_name(self) -> str:
  624. """The name of the operation.
  625. Returns:
  626. The name of the operation.
  627. """
  628. return str(self._original_var)
  629. def __getattr__(self, name):
  630. """Get an attribute of the operation.
  631. Args:
  632. name: The name of the attribute.
  633. Returns:
  634. The attribute of the operation.
  635. """
  636. if name == "_var_name":
  637. return self._cached_var_name
  638. return super(type(self), self).__getattr__(name)
  639. @cached_property
  640. def _cached_get_all_var_data(self) -> ImmutableVarData | None:
  641. """Get all VarData associated with the operation.
  642. Returns:
  643. The VarData of the components and all of its children.
  644. """
  645. return ImmutableVarData.merge(
  646. self._original_var._get_all_var_data(),
  647. self._var_data,
  648. )
  649. def _get_all_var_data(self) -> ImmutableVarData | None:
  650. """Wrapper method for cached property.
  651. Returns:
  652. The VarData of the components and all of its children.
  653. """
  654. return self._cached_get_all_var_data