__init__.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. "Accordion",
  14. "AccordionButton",
  15. "AccordionIcon",
  16. "AccordionItem",
  17. "AccordionPanel",
  18. "Alert",
  19. "AlertDescription",
  20. "AlertDialog",
  21. "AlertDialogBody",
  22. "AlertDialogContent",
  23. "AlertDialogFooter",
  24. "AlertDialogHeader",
  25. "AlertDialogOverlay",
  26. "AlertIcon",
  27. "AlertTitle",
  28. "AspectRatio",
  29. "Audio",
  30. "Avatar",
  31. "AvatarBadge",
  32. "AvatarGroup",
  33. "Badge",
  34. "Box",
  35. "Breadcrumb",
  36. "BreadcrumbItem",
  37. "BreadcrumbLink",
  38. "BreadcrumbSeparator",
  39. "Button",
  40. "ButtonGroup",
  41. "Card",
  42. "CardBody",
  43. "CardFooter",
  44. "CardHeader",
  45. "Center",
  46. "Checkbox",
  47. "CheckboxGroup",
  48. "CircularProgress",
  49. "CircularProgressLabel",
  50. "Circle",
  51. "Code",
  52. "CodeBlock",
  53. "Collapse",
  54. "ColorModeButton",
  55. "ColorModeIcon",
  56. "ColorModeSwitch",
  57. "Component",
  58. "Cond",
  59. "ConnectionBanner",
  60. "ConnectionModal",
  61. "Container",
  62. "DataTable",
  63. "DataEditor",
  64. "DataEditorTheme",
  65. "DatePicker",
  66. "DateTimePicker",
  67. "DebounceInput",
  68. "Divider",
  69. "Drawer",
  70. "DrawerBody",
  71. "DrawerCloseButton",
  72. "DrawerContent",
  73. "DrawerFooter",
  74. "DrawerHeader",
  75. "DrawerOverlay",
  76. "Editable",
  77. "EditableInput",
  78. "EditablePreview",
  79. "EditableTextarea",
  80. "Editor",
  81. "Email",
  82. "Fade",
  83. "Flex",
  84. "Foreach",
  85. "Form",
  86. "FormControl",
  87. "FormErrorMessage",
  88. "FormHelperText",
  89. "FormLabel",
  90. "Fragment",
  91. "Grid",
  92. "GridItem",
  93. "Heading",
  94. "Highlight",
  95. "Hstack",
  96. "Html",
  97. "Icon",
  98. "IconButton",
  99. "Image",
  100. "Input",
  101. "InputGroup",
  102. "InputLeftAddon",
  103. "InputLeftElement",
  104. "InputRightAddon",
  105. "InputRightElement",
  106. "Kbd",
  107. "Link",
  108. "LinkBox",
  109. "LinkOverlay",
  110. "List",
  111. "ListItem",
  112. "Markdown",
  113. "Menu",
  114. "MenuButton",
  115. "MenuDivider",
  116. "MenuGroup",
  117. "MenuItem",
  118. "MenuItemOption",
  119. "MenuList",
  120. "MenuOptionGroup",
  121. "Modal",
  122. "ModalBody",
  123. "ModalCloseButton",
  124. "ModalContent",
  125. "ModalFooter",
  126. "ModalHeader",
  127. "ModalOverlay",
  128. "Moment",
  129. "MultiSelect",
  130. "MultiSelectOption",
  131. "NextLink",
  132. "NumberDecrementStepper",
  133. "NumberIncrementStepper",
  134. "NumberInput",
  135. "NumberInputField",
  136. "NumberInputStepper",
  137. "Option",
  138. "OrderedList",
  139. "Password",
  140. "PinInput",
  141. "PinInputField",
  142. "Plotly",
  143. "Popover",
  144. "PopoverAnchor",
  145. "PopoverArrow",
  146. "PopoverBody",
  147. "PopoverCloseButton",
  148. "PopoverContent",
  149. "PopoverFooter",
  150. "PopoverHeader",
  151. "PopoverTrigger",
  152. "Progress",
  153. "Radio",
  154. "RadioGroup",
  155. "RangeSlider",
  156. "RangeSliderFilledTrack",
  157. "RangeSliderThumb",
  158. "RangeSliderTrack",
  159. "ResponsiveGrid",
  160. "ScaleFade",
  161. "Script",
  162. "Select",
  163. "Skeleton",
  164. "SkeletonCircle",
  165. "SkeletonText",
  166. "Slide",
  167. "SlideFade",
  168. "Slider",
  169. "SliderFilledTrack",
  170. "SliderMark",
  171. "SliderThumb",
  172. "SliderTrack",
  173. "Spacer",
  174. "Span",
  175. "Spinner",
  176. "Square",
  177. "Stack",
  178. "Stat",
  179. "StatArrow",
  180. "StatGroup",
  181. "StatHelpText",
  182. "StatLabel",
  183. "StatNumber",
  184. "Step",
  185. "StepDescription",
  186. "StepIcon",
  187. "StepIndicator",
  188. "StepNumber",
  189. "StepSeparator",
  190. "StepStatus",
  191. "StepTitle",
  192. "Stepper",
  193. "Switch",
  194. "Tab",
  195. "TabList",
  196. "TabPanel",
  197. "TabPanels",
  198. "Table",
  199. "TableCaption",
  200. "TableContainer",
  201. "Tabs",
  202. "Tag",
  203. "TagCloseButton",
  204. "TagLabel",
  205. "TagLeftIcon",
  206. "TagRightIcon",
  207. "Tbody",
  208. "Td",
  209. "Text",
  210. "TextArea",
  211. "Tfoot",
  212. "Th",
  213. "Thead",
  214. "TimePicker",
  215. "Tooltip",
  216. "Tr",
  217. "UnorderedList",
  218. "Upload",
  219. "Video",
  220. "VisuallyHidden",
  221. "Vstack",
  222. "Wrap",
  223. "WrapItem",
  224. ]
  225. _ALL_COMPONENTS += [to_snake_case(component) for component in _ALL_COMPONENTS]
  226. _ALL_COMPONENTS += [
  227. "cancel_upload",
  228. "components",
  229. "color_mode_cond",
  230. "desktop_only",
  231. "mobile_only",
  232. "tablet_only",
  233. "mobile_and_tablet",
  234. "tablet_and_desktop",
  235. "selected_files",
  236. "clear_selected_files",
  237. "EditorButtonList",
  238. "EditorOptions",
  239. "NoSSRComponent",
  240. ]
  241. _MAPPING = {
  242. "reflex.admin": ["admin", "AdminDash"],
  243. "reflex.app": ["app", "App", "UploadFile"],
  244. "reflex.base": ["base", "Base"],
  245. "reflex.compiler": ["compiler"],
  246. "reflex.compiler.utils": ["get_asset_path"],
  247. "reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
  248. "reflex.components.component": ["memo"],
  249. "reflex.components.recharts": ["recharts"],
  250. "reflex.components.moment.moment": ["MomentDelta"],
  251. "reflex.config": ["config", "Config", "DBConfig"],
  252. "reflex.constants": ["constants", "Env"],
  253. "reflex.components.el": ["el"],
  254. "reflex.event": [
  255. "event",
  256. "EventChain",
  257. "background",
  258. "call_script",
  259. "clear_local_storage",
  260. "console_log",
  261. "download",
  262. "prevent_default",
  263. "redirect",
  264. "remove_cookie",
  265. "remove_local_storage",
  266. "set_clipboard",
  267. "set_focus",
  268. "set_value",
  269. "stop_propagation",
  270. "upload_files",
  271. "window_alert",
  272. ],
  273. "reflex.middleware": ["middleware", "Middleware"],
  274. "reflex.model": ["model", "session", "Model"],
  275. "reflex.page": ["page"],
  276. "reflex.route": ["route"],
  277. "reflex.state": ["state", "var", "Cookie", "LocalStorage", "State"],
  278. "reflex.style": ["style", "color_mode", "toggle_color_mode"],
  279. "reflex.testing": ["testing"],
  280. "reflex.utils": ["utils"],
  281. "reflex.vars": ["vars", "cached_var", "Var"],
  282. }
  283. def _reverse_mapping(mapping: dict[str, list]) -> dict[str, str]:
  284. """Reverse the mapping used to lazy loading, and check for conflicting name.
  285. Args:
  286. mapping: The mapping to reverse.
  287. Returns:
  288. The reversed mapping.
  289. """
  290. reversed_mapping = {}
  291. for key, values in mapping.items():
  292. for value in values:
  293. if value not in reversed_mapping:
  294. reversed_mapping[value] = key
  295. else:
  296. console.warn(
  297. f"Key {value} is present multiple times in the imports _MAPPING: {key} / {reversed_mapping[value]}"
  298. )
  299. return reversed_mapping
  300. # _MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
  301. _MAPPING = _reverse_mapping(_MAPPING)
  302. def _removeprefix(text, prefix):
  303. return text[text.startswith(prefix) and len(prefix) :]
  304. __all__ = [_removeprefix(mod, "reflex.") for mod in _MAPPING]
  305. def __getattr__(name: str) -> Type:
  306. """Lazy load all modules.
  307. Args:
  308. name: name of the module to load.
  309. Returns:
  310. The module or the attribute of the module.
  311. Raises:
  312. AttributeError: If the module or the attribute does not exist.
  313. """
  314. try:
  315. # Check for import of a module that is not in the mapping.
  316. if name not in _MAPPING:
  317. # If the name does not start with reflex, add it.
  318. if not name.startswith("reflex") and name != "__all__":
  319. name = f"reflex.{name}"
  320. return importlib.import_module(name)
  321. # Import the module.
  322. module = importlib.import_module(_MAPPING[name])
  323. # Get the attribute from the module if the name is not the module itself.
  324. return (
  325. getattr(module, name) if name != _MAPPING[name].rsplit(".")[-1] else module
  326. )
  327. except ModuleNotFoundError:
  328. raise AttributeError(f"module 'reflex' has no attribute {name}") from None