__init__.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. "Tooltip",
  215. "Tr",
  216. "UnorderedList",
  217. "Upload",
  218. "Video",
  219. "VisuallyHidden",
  220. "Vstack",
  221. "Wrap",
  222. "WrapItem",
  223. ]
  224. _ALL_COMPONENTS += [to_snake_case(component) for component in _ALL_COMPONENTS]
  225. _ALL_COMPONENTS += [
  226. "cancel_upload",
  227. "components",
  228. "color_mode_cond",
  229. "desktop_only",
  230. "mobile_only",
  231. "tablet_only",
  232. "mobile_and_tablet",
  233. "tablet_and_desktop",
  234. "selected_files",
  235. "clear_selected_files",
  236. "EditorButtonList",
  237. "EditorOptions",
  238. "NoSSRComponent",
  239. ]
  240. _MAPPING = {
  241. "reflex.admin": ["admin", "AdminDash"],
  242. "reflex.app": ["app", "App", "UploadFile"],
  243. "reflex.base": ["base", "Base"],
  244. "reflex.compiler": ["compiler"],
  245. "reflex.compiler.utils": ["get_asset_path"],
  246. "reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
  247. "reflex.components.component": ["memo"],
  248. "reflex.components.graphing": ["recharts"],
  249. "reflex.components.datadisplay.moment": ["MomentDelta"],
  250. "reflex.config": ["config", "Config", "DBConfig"],
  251. "reflex.constants": ["constants", "Env"],
  252. "reflex.components.el": ["el"],
  253. "reflex.event": [
  254. "event",
  255. "EventChain",
  256. "background",
  257. "call_script",
  258. "clear_local_storage",
  259. "console_log",
  260. "download",
  261. "prevent_default",
  262. "redirect",
  263. "remove_cookie",
  264. "remove_local_storage",
  265. "set_clipboard",
  266. "set_focus",
  267. "set_value",
  268. "stop_propagation",
  269. "upload_files",
  270. "window_alert",
  271. ],
  272. "reflex.middleware": ["middleware", "Middleware"],
  273. "reflex.model": ["model", "session", "Model"],
  274. "reflex.page": ["page"],
  275. "reflex.route": ["route"],
  276. "reflex.state": ["state", "var", "Cookie", "LocalStorage", "State"],
  277. "reflex.style": ["style", "color_mode", "toggle_color_mode"],
  278. "reflex.testing": ["testing"],
  279. "reflex.utils": ["utils"],
  280. "reflex.vars": ["vars", "cached_var", "Var"],
  281. }
  282. def _reverse_mapping(mapping: dict[str, list]) -> dict[str, str]:
  283. """Reverse the mapping used to lazy loading, and check for conflicting name.
  284. Args:
  285. mapping: The mapping to reverse.
  286. Returns:
  287. The reversed mapping.
  288. """
  289. reversed_mapping = {}
  290. for key, values in mapping.items():
  291. for value in values:
  292. if value not in reversed_mapping:
  293. reversed_mapping[value] = key
  294. else:
  295. console.warn(
  296. f"Key {value} is present multiple times in the imports _MAPPING: {key} / {reversed_mapping[value]}"
  297. )
  298. return reversed_mapping
  299. # _MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
  300. _MAPPING = _reverse_mapping(_MAPPING)
  301. def _removeprefix(text, prefix):
  302. return text[text.startswith(prefix) and len(prefix) :]
  303. __all__ = [_removeprefix(mod, "reflex.") for mod in _MAPPING]
  304. def __getattr__(name: str) -> Type:
  305. """Lazy load all modules.
  306. Args:
  307. name: name of the module to load.
  308. Returns:
  309. The module or the attribute of the module.
  310. Raises:
  311. AttributeError: If the module or the attribute does not exist.
  312. """
  313. try:
  314. # Check for import of a module that is not in the mapping.
  315. if name not in _MAPPING:
  316. # If the name does not start with reflex, add it.
  317. if not name.startswith("reflex") and name != "__all__":
  318. name = f"reflex.{name}"
  319. return importlib.import_module(name)
  320. # Import the module.
  321. module = importlib.import_module(_MAPPING[name])
  322. # Get the attribute from the module if the name is not the module itself.
  323. return (
  324. getattr(module, name) if name != _MAPPING[name].rsplit(".")[-1] else module
  325. )
  326. except ModuleNotFoundError:
  327. raise AttributeError(f"module 'reflex' has no attribute {name}") from None