__init__.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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. "Match",
  114. "Menu",
  115. "MenuButton",
  116. "MenuDivider",
  117. "MenuGroup",
  118. "MenuItem",
  119. "MenuItemOption",
  120. "MenuList",
  121. "MenuOptionGroup",
  122. "Modal",
  123. "ModalBody",
  124. "ModalCloseButton",
  125. "ModalContent",
  126. "ModalFooter",
  127. "ModalHeader",
  128. "ModalOverlay",
  129. "Moment",
  130. "MultiSelect",
  131. "MultiSelectOption",
  132. "NextLink",
  133. "NumberDecrementStepper",
  134. "NumberIncrementStepper",
  135. "NumberInput",
  136. "NumberInputField",
  137. "NumberInputStepper",
  138. "Option",
  139. "OrderedList",
  140. "Password",
  141. "PinInput",
  142. "PinInputField",
  143. "Plotly",
  144. "Popover",
  145. "PopoverAnchor",
  146. "PopoverArrow",
  147. "PopoverBody",
  148. "PopoverCloseButton",
  149. "PopoverContent",
  150. "PopoverFooter",
  151. "PopoverHeader",
  152. "PopoverTrigger",
  153. "Progress",
  154. "Radio",
  155. "RadioGroup",
  156. "RangeSlider",
  157. "RangeSliderFilledTrack",
  158. "RangeSliderThumb",
  159. "RangeSliderTrack",
  160. "ResponsiveGrid",
  161. "ScaleFade",
  162. "Script",
  163. "Select",
  164. "Skeleton",
  165. "SkeletonCircle",
  166. "SkeletonText",
  167. "Slide",
  168. "SlideFade",
  169. "Slider",
  170. "SliderFilledTrack",
  171. "SliderMark",
  172. "SliderThumb",
  173. "SliderTrack",
  174. "Spacer",
  175. "Span",
  176. "Spinner",
  177. "Square",
  178. "Stack",
  179. "Stat",
  180. "StatArrow",
  181. "StatGroup",
  182. "StatHelpText",
  183. "StatLabel",
  184. "StatNumber",
  185. "Step",
  186. "StepDescription",
  187. "StepIcon",
  188. "StepIndicator",
  189. "StepNumber",
  190. "StepSeparator",
  191. "StepStatus",
  192. "StepTitle",
  193. "Stepper",
  194. "Switch",
  195. "Tab",
  196. "TabList",
  197. "TabPanel",
  198. "TabPanels",
  199. "Table",
  200. "TableCaption",
  201. "TableContainer",
  202. "Tabs",
  203. "Tag",
  204. "TagCloseButton",
  205. "TagLabel",
  206. "TagLeftIcon",
  207. "TagRightIcon",
  208. "Tbody",
  209. "Td",
  210. "Text",
  211. "TextArea",
  212. "Tfoot",
  213. "Th",
  214. "Thead",
  215. "TimePicker",
  216. "Tooltip",
  217. "Tr",
  218. "UnorderedList",
  219. "Upload",
  220. "Video",
  221. "VisuallyHidden",
  222. "Vstack",
  223. "Wrap",
  224. "WrapItem",
  225. ]
  226. _ALL_COMPONENTS += [to_snake_case(component) for component in _ALL_COMPONENTS]
  227. _ALL_COMPONENTS += [
  228. "cancel_upload",
  229. "components",
  230. "color_mode_cond",
  231. "desktop_only",
  232. "mobile_only",
  233. "tablet_only",
  234. "mobile_and_tablet",
  235. "tablet_and_desktop",
  236. "selected_files",
  237. "clear_selected_files",
  238. "EditorButtonList",
  239. "EditorOptions",
  240. "NoSSRComponent",
  241. ]
  242. _MAPPING = {
  243. "reflex.admin": ["admin", "AdminDash"],
  244. "reflex.app": ["app", "App", "UploadFile"],
  245. "reflex.base": ["base", "Base"],
  246. "reflex.compiler": ["compiler"],
  247. "reflex.compiler.utils": ["get_asset_path"],
  248. "reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
  249. "reflex.components.component": ["memo"],
  250. "reflex.components.recharts": ["recharts"],
  251. "reflex.components.moment.moment": ["MomentDelta"],
  252. "reflex.config": ["config", "Config", "DBConfig"],
  253. "reflex.constants": ["constants", "Env"],
  254. "reflex.components.el": ["el"],
  255. "reflex.event": [
  256. "event",
  257. "EventChain",
  258. "background",
  259. "call_script",
  260. "clear_local_storage",
  261. "console_log",
  262. "download",
  263. "prevent_default",
  264. "redirect",
  265. "remove_cookie",
  266. "remove_local_storage",
  267. "set_clipboard",
  268. "set_focus",
  269. "set_value",
  270. "stop_propagation",
  271. "upload_files",
  272. "window_alert",
  273. ],
  274. "reflex.middleware": ["middleware", "Middleware"],
  275. "reflex.model": ["model", "session", "Model"],
  276. "reflex.page": ["page"],
  277. "reflex.route": ["route"],
  278. "reflex.state": ["state", "var", "Cookie", "LocalStorage", "State"],
  279. "reflex.style": ["style", "color_mode", "toggle_color_mode"],
  280. "reflex.testing": ["testing"],
  281. "reflex.utils": ["utils"],
  282. "reflex.vars": ["vars", "cached_var", "Var"],
  283. }
  284. def _reverse_mapping(mapping: dict[str, list]) -> dict[str, str]:
  285. """Reverse the mapping used to lazy loading, and check for conflicting name.
  286. Args:
  287. mapping: The mapping to reverse.
  288. Returns:
  289. The reversed mapping.
  290. """
  291. reversed_mapping = {}
  292. for key, values in mapping.items():
  293. for value in values:
  294. if value not in reversed_mapping:
  295. reversed_mapping[value] = key
  296. else:
  297. console.warn(
  298. f"Key {value} is present multiple times in the imports _MAPPING: {key} / {reversed_mapping[value]}"
  299. )
  300. return reversed_mapping
  301. # _MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
  302. _MAPPING = _reverse_mapping(_MAPPING)
  303. def _removeprefix(text, prefix):
  304. return text[text.startswith(prefix) and len(prefix) :]
  305. __all__ = [_removeprefix(mod, "reflex.") for mod in _MAPPING]
  306. def __getattr__(name: str) -> Type:
  307. """Lazy load all modules.
  308. Args:
  309. name: name of the module to load.
  310. Returns:
  311. The module or the attribute of the module.
  312. Raises:
  313. AttributeError: If the module or the attribute does not exist.
  314. """
  315. try:
  316. # Check for import of a module that is not in the mapping.
  317. if name not in _MAPPING:
  318. # If the name does not start with reflex, add it.
  319. if not name.startswith("reflex") and name != "__all__":
  320. name = f"reflex.{name}"
  321. return importlib.import_module(name)
  322. # Import the module.
  323. module = importlib.import_module(_MAPPING[name])
  324. # Get the attribute from the module if the name is not the module itself.
  325. return (
  326. getattr(module, name) if name != _MAPPING[name].rsplit(".")[-1] else module
  327. )
  328. except ModuleNotFoundError:
  329. raise AttributeError(f"module 'reflex' has no attribute {name}") from None