foreach.py 1.5 KB

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