foreach.py 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. """Create a list of components from an iterable."""
  2. from __future__ import annotations
  3. import functools
  4. from typing import Callable, Iterable
  5. from reflex.utils.exceptions import UntypedVarError
  6. from reflex.vars.base import LiteralVar, Var
  7. from reflex.vars.object import ObjectVar
  8. from reflex.vars.sequence import ArrayVar
  9. class ForeachVarError(TypeError):
  10. """Raised when the iterable type is Any."""
  11. class ForeachRenderError(TypeError):
  12. """Raised when there is an error with the foreach render function."""
  13. def foreach(
  14. iterable: Var[Iterable] | Iterable,
  15. render_fn: Callable,
  16. ) -> Var:
  17. """Create a foreach component.
  18. Args:
  19. iterable: The iterable to create components from.
  20. render_fn: A function from the render args to the component.
  21. Returns:
  22. The foreach component.
  23. Raises:
  24. ForeachVarError: If the iterable is of type Any.
  25. """
  26. iterable = LiteralVar.create(iterable).guess_type()
  27. if isinstance(iterable, ObjectVar):
  28. iterable = iterable.items()
  29. if not isinstance(iterable, ArrayVar):
  30. raise ForeachVarError(
  31. f"Could not foreach over var `{iterable!s}` of type {iterable._var_type!s}. "
  32. "(If you are trying to foreach over a state var, add a type annotation to the var). "
  33. "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
  34. )
  35. return iterable.foreach(render_fn)
  36. class Foreach:
  37. """Create a list of components from an iterable."""
  38. create = staticmethod(foreach)