__init__.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. """Import all classes and functions the end user will need to make an app.
  2. Anything imported here will be available in the default Reflex import as `rx.*`.
  3. To signal to typecheckers that something should be reexported,
  4. we use the Flask "import name as name" syntax.
  5. """
  6. from __future__ import annotations
  7. import importlib
  8. from typing import Type
  9. from reflex.page import page as page
  10. from reflex.utils import console
  11. from reflex.utils.format import to_snake_case
  12. _ALL_COMPONENTS = [
  13. # Core
  14. "color",
  15. "cond",
  16. "foreach",
  17. "html",
  18. "match",
  19. "color_mode_cond",
  20. "connection_banner",
  21. "connection_modal",
  22. "debounce_input",
  23. # Base
  24. "fragment",
  25. "Fragment",
  26. "image",
  27. "script",
  28. # Responsive
  29. "desktop_only",
  30. "mobile_and_tablet",
  31. "mobile_only",
  32. "tablet_and_desktop",
  33. "tablet_only",
  34. # Upload
  35. "cancel_upload",
  36. "clear_selected_files",
  37. "get_upload_dir",
  38. "get_upload_url",
  39. "selected_files",
  40. "upload",
  41. # Radix
  42. "accordion",
  43. "alert_dialog",
  44. "aspect_ratio",
  45. "avatar",
  46. "badge",
  47. "blockquote",
  48. "box",
  49. "button",
  50. "callout",
  51. "card",
  52. "center",
  53. "checkbox",
  54. "code",
  55. "container",
  56. "context_menu",
  57. "dialog",
  58. "divider",
  59. "drawer",
  60. "flex",
  61. "form",
  62. "grid",
  63. "heading",
  64. "hover_card",
  65. "hstack",
  66. "icon_button",
  67. "inset",
  68. "input",
  69. "link",
  70. "menu",
  71. "popover",
  72. "progress",
  73. "radio",
  74. "scroll_area",
  75. "section",
  76. "select",
  77. "slider",
  78. "spacer",
  79. "stack",
  80. "switch",
  81. "table",
  82. "tabs",
  83. "text",
  84. "text_area",
  85. "theme",
  86. "theme_panel",
  87. "tooltip",
  88. "vstack",
  89. # Other
  90. "code_block",
  91. "data_editor",
  92. "data_editor_theme",
  93. "data_table",
  94. "plotly",
  95. "audio",
  96. "video",
  97. "editor",
  98. "EditorButtonList",
  99. "EditorOptions",
  100. "icon",
  101. "markdown",
  102. "list_item",
  103. "unordered_list",
  104. "ordered_list",
  105. "moment",
  106. ]
  107. _MAPPING = {
  108. "reflex.admin": ["admin", "AdminDash"],
  109. "reflex.app": ["app", "App", "UploadFile"],
  110. "reflex.base": ["base", "Base"],
  111. "reflex.compiler": ["compiler"],
  112. "reflex.compiler.utils": ["get_asset_path"],
  113. "reflex.components": _ALL_COMPONENTS,
  114. "reflex.components.component": ["Component", "NoSSRComponent", "memo"],
  115. "reflex.components.chakra": ["chakra"],
  116. "reflex.components.el": ["el"],
  117. "reflex.components.lucide": ["lucide"],
  118. "reflex.components.next": ["next"],
  119. "reflex.components.radix": ["radix", "color_mode"],
  120. "reflex.components.recharts": ["recharts"],
  121. "reflex.components.moment.moment": ["MomentDelta"],
  122. "reflex.config": ["config", "Config", "DBConfig"],
  123. "reflex.constants": ["constants", "Env"],
  124. "reflex.event": [
  125. "event",
  126. "EventChain",
  127. "background",
  128. "call_script",
  129. "clear_local_storage",
  130. "console_log",
  131. "download",
  132. "prevent_default",
  133. "redirect",
  134. "remove_cookie",
  135. "remove_local_storage",
  136. "set_clipboard",
  137. "set_focus",
  138. "set_value",
  139. "stop_propagation",
  140. "upload_files",
  141. "window_alert",
  142. ],
  143. "reflex.middleware": ["middleware", "Middleware"],
  144. "reflex.model": ["model", "session", "Model"],
  145. "reflex.page": ["page"],
  146. "reflex.route": ["route"],
  147. "reflex.state": ["state", "var", "Cookie", "LocalStorage", "State"],
  148. "reflex.style": ["style", "toggle_color_mode"],
  149. "reflex.testing": ["testing"],
  150. "reflex.utils": ["utils"],
  151. "reflex.vars": ["vars", "cached_var", "Var"],
  152. }
  153. def _reverse_mapping(mapping: dict[str, list]) -> dict[str, str]:
  154. """Reverse the mapping used to lazy loading, and check for conflicting name.
  155. Args:
  156. mapping: The mapping to reverse.
  157. Returns:
  158. The reversed mapping.
  159. """
  160. reversed_mapping = {}
  161. for key, values in mapping.items():
  162. for value in values:
  163. if value not in reversed_mapping:
  164. reversed_mapping[value] = key
  165. else:
  166. console.warn(
  167. f"Key {value} is present multiple times in the imports _MAPPING: {key} / {reversed_mapping[value]}"
  168. )
  169. return reversed_mapping
  170. # _MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
  171. _MAPPING = _reverse_mapping(_MAPPING)
  172. def _removeprefix(text, prefix):
  173. return text[text.startswith(prefix) and len(prefix) :]
  174. __all__ = [_removeprefix(mod, "reflex.") for mod in _MAPPING]
  175. def __getattr__(name: str) -> Type:
  176. """Lazy load all modules.
  177. Args:
  178. name: name of the module to load.
  179. Returns:
  180. The module or the attribute of the module.
  181. Raises:
  182. AttributeError: If the module or the attribute does not exist.
  183. """
  184. try:
  185. # Check for import of a module that is not in the mapping.
  186. if name not in _MAPPING:
  187. # If the name does not start with reflex, add it.
  188. if not name.startswith("reflex") and name != "__all__":
  189. name = f"reflex.{name}"
  190. return importlib.import_module(name)
  191. # Import the module.
  192. module = importlib.import_module(_MAPPING[name])
  193. # Get the attribute from the module if the name is not the module itself.
  194. return (
  195. getattr(module, name) if name != _MAPPING[name].rsplit(".")[-1] else module
  196. )
  197. except ModuleNotFoundError:
  198. raise AttributeError(f"module 'reflex' has no attribute {name}") from None