var.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. """Define a state var."""
  2. from __future__ import annotations
  3. import json
  4. from abc import ABC
  5. from typing import (
  6. TYPE_CHECKING,
  7. Any,
  8. Callable,
  9. Dict,
  10. List,
  11. Optional,
  12. Type,
  13. Union,
  14. _GenericAlias, # type: ignore
  15. )
  16. from plotly.graph_objects import Figure
  17. from plotly.io import to_json
  18. from pydantic.fields import ModelField
  19. from pynecone import constants, utils
  20. from pynecone.base import Base
  21. if TYPE_CHECKING:
  22. from pynecone.state import State
  23. class Var(ABC):
  24. """An abstract var."""
  25. # The name of the var.
  26. name: str
  27. # The type of the var.
  28. type_: Type
  29. # The name of the enclosing state.
  30. state: str = ""
  31. # Whether this is a local javascript variable.
  32. is_local: bool = False
  33. # Whether the var is a string literal.
  34. is_string: bool = False
  35. @classmethod
  36. def create(
  37. cls, value: Any, is_local: bool = True, is_string: bool = False
  38. ) -> Optional[Var]:
  39. """Create a var from a value.
  40. Args:
  41. value: The value to create the var from.
  42. is_local: Whether the var is local.
  43. is_string: Whether the var is a string literal.
  44. Returns:
  45. The var.
  46. """
  47. # Check for none values.
  48. if value is None:
  49. return None
  50. # If the value is already a var, do nothing.
  51. if isinstance(value, Var):
  52. return value
  53. type_ = type(value)
  54. # Special case for plotly figures.
  55. if isinstance(value, Figure):
  56. value = json.loads(to_json(value))["data"] # type: ignore
  57. type_ = Figure
  58. name = value if isinstance(value, str) else json.dumps(value)
  59. return BaseVar(name=name, type_=type_, is_local=is_local, is_string=is_string)
  60. @classmethod
  61. def __class_getitem__(cls, type_: str) -> _GenericAlias:
  62. """Get a typed var.
  63. Args:
  64. type_: The type of the var.
  65. Returns:
  66. The var class item.
  67. """
  68. return _GenericAlias(cls, type_)
  69. def equals(self, other: Var) -> bool:
  70. """Check if two vars are equal.
  71. Args:
  72. other: The other var to compare.
  73. Returns:
  74. Whether the vars are equal.
  75. """
  76. return (
  77. self.name == other.name
  78. and self.type_ == other.type_
  79. and self.state == other.state
  80. and self.is_local == other.is_local
  81. )
  82. def to_string(self) -> Var:
  83. """Convert a var to a string.
  84. Returns:
  85. The stringified var.
  86. """
  87. return self.operation(fn="JSON.stringify")
  88. def __hash__(self) -> int:
  89. """Define a hash function for a var.
  90. Returns:
  91. The hash of the var.
  92. """
  93. return hash((self.name, str(self.type_)))
  94. def __str__(self) -> str:
  95. """Wrap the var so it can be used in templates.
  96. Returns:
  97. The wrapped var, i.e. {state.var}.
  98. """
  99. out = self.full_name if self.is_local else utils.wrap(self.full_name, "{")
  100. if self.is_string:
  101. out = utils.format_string(out)
  102. return out
  103. def __getitem__(self, i: Any) -> Var:
  104. """Index into a var.
  105. Args:
  106. i: The index to index into.
  107. Returns:
  108. The indexed var.
  109. Raises:
  110. TypeError: If the var is not indexable.
  111. """
  112. # Indexing is only supported for lists, dicts, and dataframes.
  113. if not (
  114. utils._issubclass(self.type_, Union[List, Dict])
  115. or utils.is_dataframe(self.type_)
  116. ):
  117. if self.type_ == Any:
  118. raise TypeError(
  119. f"Could not index into var of type Any. (If you are trying to index into a state var, add a type annotation to the var.)"
  120. )
  121. raise TypeError(
  122. f"Var {self.name} of type {self.type_} does not support indexing."
  123. )
  124. # The type of the indexed var.
  125. type_ = Any
  126. # Convert any vars to local vars.
  127. if isinstance(i, Var):
  128. i = BaseVar(name=i.name, type_=i.type_, state=i.state, is_local=True)
  129. # Handle list indexing.
  130. if utils._issubclass(self.type_, List):
  131. # List indices must be ints, slices, or vars.
  132. if not isinstance(i, utils.get_args(Union[int, slice, Var])):
  133. raise TypeError("Index must be an integer.")
  134. # Handle slices first.
  135. if isinstance(i, slice):
  136. # Get the start and stop indices.
  137. start = i.start or 0
  138. stop = i.stop or "undefined"
  139. # Use the slice function.
  140. return BaseVar(
  141. name=f"{self.name}.slice({start}, {stop})",
  142. type_=self.type_,
  143. state=self.state,
  144. )
  145. # Get the type of the indexed var.
  146. if utils.is_generic_alias(self.type_):
  147. type_ = utils.get_args(self.type_)[0]
  148. else:
  149. type_ = Any
  150. # Use `at` to support negative indices.
  151. return BaseVar(
  152. name=f"{self.name}.at({i})",
  153. type_=type_,
  154. state=self.state,
  155. )
  156. # Dictionary / dataframe indexing.
  157. # Get the type of the indexed var.
  158. if isinstance(i, str):
  159. i = utils.wrap(i, '"')
  160. if utils.is_generic_alias(self.type_):
  161. type_ = utils.get_args(self.type_)[1]
  162. else:
  163. type_ = Any
  164. # Use normal indexing here.
  165. return BaseVar(
  166. name=f"{self.name}[{i}]",
  167. type_=type_,
  168. state=self.state,
  169. )
  170. def __getattribute__(self, name: str) -> Var:
  171. """Get a var attribute.
  172. Args:
  173. name: The name of the attribute.
  174. Returns:
  175. The var attribute.
  176. Raises:
  177. Exception: If the attribute is not found.
  178. """
  179. try:
  180. return super().__getattribute__(name)
  181. except Exception as e:
  182. # Check if the attribute is one of the class fields.
  183. if (
  184. not name.startswith("_")
  185. and hasattr(self.type_, "__fields__")
  186. and name in self.type_.__fields__
  187. ):
  188. type_ = self.type_.__fields__[name].outer_type_
  189. if isinstance(type_, ModelField):
  190. type_ = type_.type_
  191. return BaseVar(
  192. name=f"{self.name}.{name}",
  193. type_=type_,
  194. state=self.state,
  195. )
  196. raise e
  197. def operation(
  198. self,
  199. op: str = "",
  200. other: Optional[Var] = None,
  201. type_: Optional[Type] = None,
  202. flip: bool = False,
  203. fn: Optional[str] = None,
  204. ) -> Var:
  205. """Perform an operation on a var.
  206. Args:
  207. op: The operation to perform.
  208. other: The other var to perform the operation on.
  209. type_: The type of the operation result.
  210. flip: Whether to flip the order of the operation.
  211. fn: A function to apply to the operation.
  212. Returns:
  213. The operation result.
  214. """
  215. # Wrap strings in quotes.
  216. if isinstance(other, str):
  217. other = Var.create(json.dumps(other))
  218. else:
  219. other = Var.create(other)
  220. if type_ is None:
  221. type_ = self.type_
  222. if other is None:
  223. name = f"{op}{self.full_name}"
  224. else:
  225. props = (other, self) if flip else (self, other)
  226. name = f"{props[0].full_name} {op} {props[1].full_name}"
  227. if fn is None:
  228. name = utils.wrap(name, "(")
  229. if fn is not None:
  230. name = f"{fn}({name})"
  231. return BaseVar(
  232. name=name,
  233. type_=type_,
  234. )
  235. def compare(self, op: str, other: Var) -> Var:
  236. """Compare two vars with inequalities.
  237. Args:
  238. op: The comparison operator.
  239. other: The other var to compare with.
  240. Returns:
  241. The comparison result.
  242. """
  243. return self.operation(op, other, bool)
  244. def __invert__(self) -> Var:
  245. """Invert a var.
  246. Returns:
  247. The inverted var.
  248. """
  249. return self.operation("!", type_=bool)
  250. def __neg__(self) -> Var:
  251. """Negate a var.
  252. Returns:
  253. The negated var.
  254. """
  255. return self.operation(fn="-")
  256. def __abs__(self) -> Var:
  257. """Get the absolute value of a var.
  258. Returns:
  259. A var with the absolute value.
  260. """
  261. return self.operation(fn="Math.abs")
  262. def length(self) -> Var:
  263. """Get the length of a list var.
  264. Returns:
  265. A var with the absolute value.
  266. Raises:
  267. TypeError: If the var is not a list.
  268. """
  269. if not utils._issubclass(self.type_, List):
  270. raise TypeError(f"Cannot get length of non-list var {self}.")
  271. return BaseVar(
  272. name=f"{self.full_name}.length",
  273. type_=int,
  274. )
  275. def __eq__(self, other: Var) -> Var:
  276. """Perform an equality comparison.
  277. Args:
  278. other: The other var to compare with.
  279. Returns:
  280. A var representing the equality comparison.
  281. """
  282. return self.compare("==", other)
  283. def __ne__(self, other: Var) -> Var:
  284. """Perform an inequality comparison.
  285. Args:
  286. other: The other var to compare with.
  287. Returns:
  288. A var representing the inequality comparison.
  289. """
  290. return self.compare("!=", other)
  291. def __gt__(self, other: Var) -> Var:
  292. """Perform a greater than comparison.
  293. Args:
  294. other: The other var to compare with.
  295. Returns:
  296. A var representing the greater than comparison.
  297. """
  298. return self.compare(">", other)
  299. def __ge__(self, other: Var) -> Var:
  300. """Perform a greater than or equal to comparison.
  301. Args:
  302. other: The other var to compare with.
  303. Returns:
  304. A var representing the greater than or equal to comparison.
  305. """
  306. return self.compare(">=", other)
  307. def __lt__(self, other: Var) -> Var:
  308. """Perform a less than comparison.
  309. Args:
  310. other: The other var to compare with.
  311. Returns:
  312. A var representing the less than comparison.
  313. """
  314. return self.compare("<", other)
  315. def __le__(self, other: Var) -> Var:
  316. """Perform a less than or equal to comparison.
  317. Args:
  318. other: The other var to compare with.
  319. Returns:
  320. A var representing the less than or equal to comparison.
  321. """
  322. return self.compare("<=", other)
  323. def __add__(self, other: Var) -> Var:
  324. """Add two vars.
  325. Args:
  326. other: The other var to add.
  327. Returns:
  328. A var representing the sum.
  329. """
  330. return self.operation("+", other)
  331. def __radd__(self, other: Var) -> Var:
  332. """Add two vars.
  333. Args:
  334. other: The other var to add.
  335. Returns:
  336. A var representing the sum.
  337. """
  338. return self.operation("+", other, flip=True)
  339. def __sub__(self, other: Var) -> Var:
  340. """Subtract two vars.
  341. Args:
  342. other: The other var to subtract.
  343. Returns:
  344. A var representing the difference.
  345. """
  346. return self.operation("-", other)
  347. def __rsub__(self, other: Var) -> Var:
  348. """Subtract two vars.
  349. Args:
  350. other: The other var to subtract.
  351. Returns:
  352. A var representing the difference.
  353. """
  354. return self.operation("-", other, flip=True)
  355. def __mul__(self, other: Var) -> Var:
  356. """Multiply two vars.
  357. Args:
  358. other: The other var to multiply.
  359. Returns:
  360. A var representing the product.
  361. """
  362. return self.operation("*", other)
  363. def __rmul__(self, other: Var) -> Var:
  364. """Multiply two vars.
  365. Args:
  366. other: The other var to multiply.
  367. Returns:
  368. A var representing the product.
  369. """
  370. return self.operation("*", other, flip=True)
  371. def __pow__(self, other: Var) -> Var:
  372. """Raise a var to a power.
  373. Args:
  374. other: The power to raise to.
  375. Returns:
  376. A var representing the power.
  377. """
  378. return self.operation(",", other, fn="Math.pow")
  379. def __rpow__(self, other: Var) -> Var:
  380. """Raise a var to a power.
  381. Args:
  382. other: The power to raise to.
  383. Returns:
  384. A var representing the power.
  385. """
  386. return self.operation(",", other, flip=True, fn="Math.pow")
  387. def __truediv__(self, other: Var) -> Var:
  388. """Divide two vars.
  389. Args:
  390. other: The other var to divide.
  391. Returns:
  392. A var representing the quotient.
  393. """
  394. return self.operation("/", other)
  395. def __rtruediv__(self, other: Var) -> Var:
  396. """Divide two vars.
  397. Args:
  398. other: The other var to divide.
  399. Returns:
  400. A var representing the quotient.
  401. """
  402. return self.operation("/", other, flip=True)
  403. def __floordiv__(self, other: Var) -> Var:
  404. """Divide two vars.
  405. Args:
  406. other: The other var to divide.
  407. Returns:
  408. A var representing the quotient.
  409. """
  410. return self.operation("/", other, fn="Math.floor")
  411. def __mod__(self, other: Var) -> Var:
  412. """Get the remainder of two vars.
  413. Args:
  414. other: The other var to divide.
  415. Returns:
  416. A var representing the remainder.
  417. """
  418. return self.operation("%", other)
  419. def __rmod__(self, other: Var) -> Var:
  420. """Get the remainder of two vars.
  421. Args:
  422. other: The other var to divide.
  423. Returns:
  424. A var representing the remainder.
  425. """
  426. return self.operation("%", other, flip=True)
  427. def __and__(self, other: Var) -> Var:
  428. """Perform a logical and.
  429. Args:
  430. other: The other var to perform the logical and with.
  431. Returns:
  432. A var representing the logical and.
  433. """
  434. return self.operation("&&", other)
  435. def __rand__(self, other: Var) -> Var:
  436. """Perform a logical and.
  437. Args:
  438. other: The other var to perform the logical and with.
  439. Returns:
  440. A var representing the logical and.
  441. """
  442. return self.operation("&&", other, flip=True)
  443. def __or__(self, other: Var) -> Var:
  444. """Perform a logical or.
  445. Args:
  446. other: The other var to perform the logical or with.
  447. Returns:
  448. A var representing the logical or.
  449. """
  450. return self.operation("||", other)
  451. def __ror__(self, other: Var) -> Var:
  452. """Perform a logical or.
  453. Args:
  454. other: The other var to perform the logical or with.
  455. Returns:
  456. A var representing the logical or.
  457. """
  458. return self.operation("||", other, flip=True)
  459. def foreach(self, fn: Callable) -> Var:
  460. """Return a list of components. after doing a foreach on this var.
  461. Args:
  462. fn: The function to call on each component.
  463. Returns:
  464. A var representing foreach operation.
  465. """
  466. arg = BaseVar(
  467. name=utils.get_unique_variable_name(),
  468. type_=self.type_,
  469. )
  470. return BaseVar(
  471. name=f"{self.full_name}.map(({arg.name}, i) => {fn(arg, key='i')})",
  472. type_=self.type_,
  473. )
  474. def to(self, type_: Type) -> Var:
  475. """Convert the type of the var.
  476. Args:
  477. type_: The type to convert to.
  478. Returns:
  479. The converted var.
  480. """
  481. return BaseVar(
  482. name=self.name,
  483. type_=type_,
  484. state=self.state,
  485. is_local=self.is_local,
  486. )
  487. @property
  488. def full_name(self) -> str:
  489. """Get the full name of the var.
  490. Returns:
  491. The full name of the var.
  492. """
  493. return self.name if self.state == "" else ".".join([self.state, self.name])
  494. def set_state(self, state: Type[State]) -> Any:
  495. """Set the state of the var.
  496. Args:
  497. state: The state to set.
  498. Returns:
  499. The var with the set state.
  500. """
  501. self.state = state.get_full_name()
  502. return self
  503. class BaseVar(Var, Base):
  504. """A base (non-computed) var of the app state."""
  505. # The name of the var.
  506. name: str
  507. # The type of the var.
  508. type_: Any
  509. # The name of the enclosing state.
  510. state: str = ""
  511. # Whether this is a local javascript variable.
  512. is_local: bool = False
  513. # Whether this var is a raw string.
  514. is_string: bool = False
  515. def __hash__(self) -> int:
  516. """Define a hash function for a var.
  517. Returns:
  518. The hash of the var.
  519. """
  520. return hash((self.name, str(self.type_)))
  521. def get_default_value(self) -> Any:
  522. """Get the default value of the var.
  523. Returns:
  524. The default value of the var.
  525. """
  526. if utils.is_generic_alias(self.type_):
  527. type_ = self.type_.__origin__
  528. else:
  529. type_ = self.type_
  530. if issubclass(type_, str):
  531. return ""
  532. if issubclass(type_, utils.get_args(Union[int, float])):
  533. return 0
  534. if issubclass(type_, bool):
  535. return False
  536. if issubclass(type_, list):
  537. return []
  538. if issubclass(type_, dict):
  539. return {}
  540. if issubclass(type_, tuple):
  541. return ()
  542. return set() if issubclass(type_, set) else None
  543. def get_setter_name(self, include_state: bool = True) -> str:
  544. """Get the name of the var's generated setter function.
  545. Args:
  546. include_state: Whether to include the state name in the setter name.
  547. Returns:
  548. The name of the setter function.
  549. """
  550. setter = constants.SETTER_PREFIX + self.name
  551. if not include_state or self.state == "":
  552. return setter
  553. return ".".join((self.state, setter))
  554. def get_setter(self) -> Callable[[State, Any], None]:
  555. """Get the var's setter function.
  556. Returns:
  557. A function that that creates a setter for the var.
  558. """
  559. def setter(state: State, value: Any):
  560. """Get the setter for the var.
  561. Args:
  562. state: The state within which we add the setter function.
  563. value: The value to set.
  564. """
  565. setattr(state, self.name, value)
  566. setter.__qualname__ = self.get_setter_name()
  567. return setter
  568. class ComputedVar(property, Var):
  569. """A field with computed getters."""
  570. @property
  571. def name(self) -> str:
  572. """Get the name of the var.
  573. Returns:
  574. The name of the var.
  575. """
  576. assert self.fget is not None, "Var must have a getter."
  577. return self.fget.__name__
  578. @property
  579. def type_(self):
  580. """Get the type of the var.
  581. Returns:
  582. The type of the var.
  583. """
  584. if "return" in self.fget.__annotations__:
  585. return self.fget.__annotations__["return"]
  586. return Any
  587. class PCList(list):
  588. """A custom list that pynecone can detect its mutation."""
  589. def __init__(
  590. self,
  591. original_list: List,
  592. reassign_field: Callable = lambda _field_name: None,
  593. field_name: str = "",
  594. ):
  595. """Initialize PCList.
  596. Args:
  597. original_list (List): The original list
  598. reassign_field (Callable):
  599. The method in the parent state to reassign the field.
  600. Default to be a no-op function
  601. field_name (str): the name of field in the parent state
  602. """
  603. self._reassign_field = lambda: reassign_field(field_name)
  604. super().__init__(original_list)
  605. def append(self, *args, **kwargs):
  606. """Append.
  607. Args:
  608. args: The args passed.
  609. kwargs: The kwargs passed.
  610. """
  611. super().append(*args, **kwargs)
  612. self._reassign_field()
  613. def __setitem__(self, *args, **kwargs):
  614. """Set item.
  615. Args:
  616. args: The args passed.
  617. kwargs: The kwargs passed.
  618. """
  619. super().__setitem__(*args, **kwargs)
  620. self._reassign_field()
  621. def __delitem__(self, *args, **kwargs):
  622. """Delete item.
  623. Args:
  624. args: The args passed.
  625. kwargs: The kwargs passed.
  626. """
  627. super().__delitem__(*args, **kwargs)
  628. self._reassign_field()
  629. def clear(self, *args, **kwargs):
  630. """Remove all item from the list.
  631. Args:
  632. args: The args passed.
  633. kwargs: The kwargs passed.
  634. """
  635. super().clear(*args, **kwargs)
  636. self._reassign_field()
  637. def extend(self, *args, **kwargs):
  638. """Add all item of a list to the end of the list.
  639. Args:
  640. args: The args passed.
  641. kwargs: The kwargs passed.
  642. """
  643. super().extend(*args, **kwargs)
  644. self._reassign_field() if hasattr(self, "_reassign_field") else None
  645. def pop(self, *args, **kwargs):
  646. """Remove an element.
  647. Args:
  648. args: The args passed.
  649. kwargs: The kwargs passed.
  650. """
  651. super().pop(*args, **kwargs)
  652. self._reassign_field()
  653. def remove(self, *args, **kwargs):
  654. """Remove an element.
  655. Args:
  656. args: The args passed.
  657. kwargs: The kwargs passed.
  658. """
  659. super().remove(*args, **kwargs)
  660. self._reassign_field()
  661. class PCDict(dict):
  662. """A custom dict that pynecone can detect its mutation."""
  663. def __init__(
  664. self,
  665. original_dict: Dict,
  666. reassign_field: Callable = lambda _field_name: None,
  667. field_name: str = "",
  668. ):
  669. """Initialize PCDict.
  670. Args:
  671. original_dict: The original dict
  672. reassign_field:
  673. The method in the parent state to reassign the field.
  674. Default to be a no-op function
  675. field_name: the name of field in the parent state
  676. """
  677. super().__init__(original_dict)
  678. self._reassign_field = lambda: reassign_field(field_name)
  679. def clear(self):
  680. """Remove all item from the list."""
  681. super().clear()
  682. self._reassign_field()
  683. def setdefault(self, *args, **kwargs):
  684. """Return value of key if or set default.
  685. Args:
  686. args: The args passed.
  687. kwargs: The kwargs passed.
  688. """
  689. super().setdefault(*args, **kwargs)
  690. self._reassign_field()
  691. def popitem(self):
  692. """Pop last item."""
  693. super().popitem()
  694. self._reassign_field()
  695. def pop(self, k, d=None):
  696. """Remove an element.
  697. Args:
  698. k: The args passed.
  699. d: The kwargs passed.
  700. """
  701. super().pop(k, d)
  702. self._reassign_field()
  703. def update(self, *args, **kwargs):
  704. """Update the dict with another dict.
  705. Args:
  706. args: The args passed.
  707. kwargs: The kwargs passed.
  708. """
  709. super().update(*args, **kwargs)
  710. self._reassign_field()
  711. def __setitem__(self, *args, **kwargs):
  712. """Set an item in the dict.
  713. Args:
  714. args: The args passed.
  715. kwargs: The kwargs passed.
  716. """
  717. super().__setitem__(*args, **kwargs)
  718. self._reassign_field() if hasattr(self, "_reassign_field") else None
  719. def __delitem__(self, *args, **kwargs):
  720. """Delete an item in the dict.
  721. Args:
  722. args: The args passed.
  723. kwargs: The kwargs passed.
  724. """
  725. super().__delitem__(*args, **kwargs)
  726. self._reassign_field()