reflex 0.7.1a3__py3-none-any.whl → 0.7.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/web/utils/context.js.jinja2 +8 -8
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -3
- reflex/.templates/web/utils/state.js +18 -18
- reflex/admin.py +1 -2
- reflex/app.py +53 -50
- reflex/app_mixins/lifespan.py +2 -2
- reflex/app_mixins/middleware.py +1 -2
- reflex/assets.py +1 -2
- reflex/base.py +2 -2
- reflex/compiler/compiler.py +51 -16
- reflex/compiler/utils.py +4 -13
- reflex/components/base/app_wrap.pyi +7 -7
- reflex/components/base/bare.py +3 -3
- reflex/components/base/body.pyi +7 -7
- reflex/components/base/document.py +1 -3
- reflex/components/base/document.pyi +32 -32
- reflex/components/base/error_boundary.py +2 -4
- reflex/components/base/error_boundary.pyi +11 -13
- reflex/components/base/fragment.pyi +7 -7
- reflex/components/base/head.pyi +13 -13
- reflex/components/base/link.pyi +22 -22
- reflex/components/base/meta.py +5 -7
- reflex/components/base/meta.pyi +40 -40
- reflex/components/base/script.pyi +11 -14
- reflex/components/base/strict_mode.pyi +7 -7
- reflex/components/component.py +188 -113
- reflex/components/core/auto_scroll.py +8 -1
- reflex/components/core/auto_scroll.pyi +183 -210
- reflex/components/core/banner.py +2 -4
- reflex/components/core/banner.pyi +390 -444
- reflex/components/core/breakpoints.py +5 -5
- reflex/components/core/client_side_routing.pyi +14 -14
- reflex/components/core/clipboard.py +4 -4
- reflex/components/core/clipboard.pyi +12 -14
- reflex/components/core/cond.py +17 -25
- reflex/components/core/debounce.py +3 -3
- reflex/components/core/debounce.pyi +14 -14
- reflex/components/core/foreach.py +7 -2
- reflex/components/core/html.py +1 -3
- reflex/components/core/html.pyi +184 -213
- reflex/components/core/match.py +15 -19
- reflex/components/core/sticky.pyi +930 -1078
- reflex/components/core/upload.py +4 -4
- reflex/components/core/upload.pyi +62 -62
- reflex/components/datadisplay/code.py +6 -6
- reflex/components/datadisplay/code.pyi +1159 -1165
- reflex/components/datadisplay/dataeditor.py +49 -49
- reflex/components/datadisplay/dataeditor.pyi +95 -123
- reflex/components/datadisplay/logo.py +1 -3
- reflex/components/datadisplay/shiki_code_block.py +8 -10
- reflex/components/datadisplay/shiki_code_block.pyi +1678 -1720
- reflex/components/el/element.pyi +7 -7
- reflex/components/el/elements/base.pyi +183 -210
- reflex/components/el/elements/forms.py +24 -24
- reflex/components/el/elements/forms.pyi +2572 -2934
- reflex/components/el/elements/inline.py +4 -4
- reflex/components/el/elements/inline.pyi +5191 -5953
- reflex/components/el/elements/media.py +47 -47
- reflex/components/el/elements/media.pyi +4802 -5500
- reflex/components/el/elements/metadata.py +1 -3
- reflex/components/el/elements/metadata.pyi +782 -896
- reflex/components/el/elements/other.pyi +1278 -1467
- reflex/components/el/elements/scripts.pyi +580 -667
- reflex/components/el/elements/sectioning.pyi +2761 -3166
- reflex/components/el/elements/tables.pyi +1840 -2119
- reflex/components/el/elements/typography.pyi +2772 -3179
- reflex/components/gridjs/datatable.py +7 -7
- reflex/components/gridjs/datatable.pyi +19 -19
- reflex/components/lucide/icon.pyi +21 -21
- reflex/components/markdown/markdown.py +2 -2
- reflex/components/markdown/markdown.pyi +9 -9
- reflex/components/moment/moment.py +11 -12
- reflex/components/moment/moment.pyi +44 -47
- reflex/components/next/base.pyi +7 -7
- reflex/components/next/image.py +3 -3
- reflex/components/next/image.pyi +19 -21
- reflex/components/next/link.pyi +9 -9
- reflex/components/next/video.py +1 -3
- reflex/components/next/video.pyi +9 -9
- reflex/components/plotly/plotly.py +22 -45
- reflex/components/plotly/plotly.pyi +164 -164
- reflex/components/radix/primitives/accordion.py +14 -14
- reflex/components/radix/primitives/accordion.pyi +439 -487
- reflex/components/radix/primitives/base.py +1 -3
- reflex/components/radix/primitives/base.pyi +15 -15
- reflex/components/radix/primitives/drawer.py +3 -3
- reflex/components/radix/primitives/drawer.pyi +110 -116
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/form.pyi +668 -752
- reflex/components/radix/primitives/progress.py +6 -6
- reflex/components/radix/primitives/progress.pyi +225 -243
- reflex/components/radix/primitives/slider.py +6 -6
- reflex/components/radix/primitives/slider.pyi +52 -55
- reflex/components/radix/themes/base.py +3 -6
- reflex/components/radix/themes/base.pyi +197 -303
- reflex/components/radix/themes/color_mode.py +5 -5
- reflex/components/radix/themes/color_mode.pyi +366 -436
- reflex/components/radix/themes/components/alert_dialog.pyi +229 -262
- reflex/components/radix/themes/components/aspect_ratio.py +1 -3
- reflex/components/radix/themes/components/aspect_ratio.pyi +8 -8
- reflex/components/radix/themes/components/avatar.pyi +79 -94
- reflex/components/radix/themes/components/badge.pyi +252 -295
- reflex/components/radix/themes/components/button.pyi +269 -314
- reflex/components/radix/themes/components/callout.py +2 -2
- reflex/components/radix/themes/components/callout.pyi +1116 -1290
- reflex/components/radix/themes/components/card.pyi +194 -229
- reflex/components/radix/themes/components/checkbox.pyi +243 -278
- reflex/components/radix/themes/components/checkbox_cards.py +3 -7
- reflex/components/radix/themes/components/checkbox_cards.pyi +101 -135
- reflex/components/radix/themes/components/checkbox_group.py +2 -2
- reflex/components/radix/themes/components/checkbox_group.pyi +83 -96
- reflex/components/radix/themes/components/context_menu.py +18 -15
- reflex/components/radix/themes/components/context_menu.pyi +408 -458
- reflex/components/radix/themes/components/data_list.pyi +122 -147
- reflex/components/radix/themes/components/dialog.pyi +231 -264
- reflex/components/radix/themes/components/dropdown_menu.py +16 -13
- reflex/components/radix/themes/components/dropdown_menu.pyi +223 -246
- reflex/components/radix/themes/components/hover_card.py +2 -2
- reflex/components/radix/themes/components/hover_card.pyi +237 -282
- reflex/components/radix/themes/components/icon_button.pyi +269 -314
- reflex/components/radix/themes/components/inset.py +8 -8
- reflex/components/radix/themes/components/inset.pyi +232 -292
- reflex/components/radix/themes/components/popover.py +2 -2
- reflex/components/radix/themes/components/popover.pyi +229 -271
- reflex/components/radix/themes/components/progress.pyi +80 -96
- reflex/components/radix/themes/components/radio.pyi +73 -86
- reflex/components/radix/themes/components/radio_cards.py +4 -8
- reflex/components/radix/themes/components/radio_cards.pyi +117 -154
- reflex/components/radix/themes/components/radio_group.py +3 -3
- reflex/components/radix/themes/components/radio_group.pyi +250 -291
- reflex/components/radix/themes/components/scroll_area.pyi +14 -20
- reflex/components/radix/themes/components/segmented_control.py +6 -6
- reflex/components/radix/themes/components/segmented_control.pyi +89 -108
- reflex/components/radix/themes/components/select.py +7 -7
- reflex/components/radix/themes/components/select.pyi +376 -444
- reflex/components/radix/themes/components/separator.pyi +79 -93
- reflex/components/radix/themes/components/skeleton.pyi +32 -26
- reflex/components/radix/themes/components/slider.py +8 -8
- reflex/components/radix/themes/components/slider.pyi +99 -122
- reflex/components/radix/themes/components/spinner.pyi +12 -19
- reflex/components/radix/themes/components/switch.pyi +84 -99
- reflex/components/radix/themes/components/table.py +9 -9
- reflex/components/radix/themes/components/table.pyi +1440 -1794
- reflex/components/radix/themes/components/tabs.py +4 -4
- reflex/components/radix/themes/components/tabs.pyi +120 -132
- reflex/components/radix/themes/components/text_area.pyi +281 -331
- reflex/components/radix/themes/components/text_field.py +2 -2
- reflex/components/radix/themes/components/text_field.pyi +639 -734
- reflex/components/radix/themes/components/tooltip.py +6 -6
- reflex/components/radix/themes/components/tooltip.pyi +34 -43
- reflex/components/radix/themes/layout/base.pyi +85 -182
- reflex/components/radix/themes/layout/box.pyi +183 -210
- reflex/components/radix/themes/layout/center.pyi +225 -286
- reflex/components/radix/themes/layout/container.pyi +191 -224
- reflex/components/radix/themes/layout/flex.py +2 -2
- reflex/components/radix/themes/layout/flex.pyi +225 -286
- reflex/components/radix/themes/layout/grid.py +2 -2
- reflex/components/radix/themes/layout/grid.pyi +245 -315
- reflex/components/radix/themes/layout/list.py +2 -2
- reflex/components/radix/themes/layout/list.pyi +712 -815
- reflex/components/radix/themes/layout/section.pyi +187 -221
- reflex/components/radix/themes/layout/spacer.pyi +225 -286
- reflex/components/radix/themes/layout/stack.pyi +625 -768
- reflex/components/radix/themes/typography/blockquote.pyi +257 -299
- reflex/components/radix/themes/typography/code.pyi +259 -304
- reflex/components/radix/themes/typography/heading.pyi +272 -324
- reflex/components/radix/themes/typography/link.pyi +302 -358
- reflex/components/radix/themes/typography/text.pyi +1669 -1945
- reflex/components/react_player/audio.pyi +20 -22
- reflex/components/react_player/react_player.pyi +19 -19
- reflex/components/react_player/video.pyi +20 -22
- reflex/components/recharts/cartesian.py +100 -97
- reflex/components/recharts/cartesian.pyi +891 -1007
- reflex/components/recharts/charts.py +42 -42
- reflex/components/recharts/charts.pyi +212 -249
- reflex/components/recharts/general.py +22 -21
- reflex/components/recharts/general.pyi +198 -223
- reflex/components/recharts/polar.py +42 -45
- reflex/components/recharts/polar.pyi +254 -288
- reflex/components/recharts/recharts.pyi +13 -13
- reflex/components/sonner/toast.py +20 -20
- reflex/components/sonner/toast.pyi +58 -61
- reflex/components/suneditor/editor.py +9 -9
- reflex/components/suneditor/editor.pyi +78 -83
- reflex/components/tags/cond_tag.py +2 -2
- reflex/components/tags/iter_tag.py +10 -14
- reflex/components/tags/match_tag.py +2 -2
- reflex/components/tags/tag.py +10 -10
- reflex/config.py +36 -35
- reflex/constants/__init__.py +56 -53
- reflex/custom_components/custom_components.py +6 -7
- reflex/event.py +38 -42
- reflex/experimental/client_state.py +2 -4
- reflex/experimental/layout.py +2 -2
- reflex/experimental/layout.pyi +579 -663
- reflex/istate/data.py +4 -5
- reflex/middleware/hydrate_middleware.py +2 -2
- reflex/middleware/middleware.py +2 -2
- reflex/model.py +3 -5
- reflex/page.py +2 -2
- reflex/reflex.py +9 -10
- reflex/state.py +77 -49
- reflex/style.py +11 -5
- reflex/testing.py +21 -24
- reflex/utils/console.py +1 -1
- reflex/utils/decorator.py +26 -1
- reflex/utils/exec.py +6 -11
- reflex/utils/export.py +2 -3
- reflex/utils/format.py +4 -4
- reflex/utils/imports.py +12 -12
- reflex/utils/prerequisites.py +35 -84
- reflex/utils/processes.py +5 -5
- reflex/utils/pyi_generator.py +33 -22
- reflex/utils/serializers.py +60 -15
- reflex/utils/types.py +237 -56
- reflex/vars/base.py +122 -72
- reflex/vars/datetime.py +2 -2
- reflex/vars/function.py +52 -55
- reflex/vars/number.py +59 -5
- reflex/vars/object.py +57 -26
- reflex/vars/sequence.py +983 -958
- {reflex-0.7.1a3.dist-info → reflex-0.7.2.dist-info}/METADATA +3 -6
- reflex-0.7.2.dist-info/RECORD +405 -0
- {reflex-0.7.1a3.dist-info → reflex-0.7.2.dist-info}/WHEEL +1 -1
- reflex-0.7.1a3.dist-info/RECORD +0 -405
- {reflex-0.7.1a3.dist-info → reflex-0.7.2.dist-info}/LICENSE +0 -0
- {reflex-0.7.1a3.dist-info → reflex-0.7.2.dist-info}/entry_points.txt +0 -0
|
@@ -78,9 +78,9 @@ export function UploadFilesProvider({ children }) {
|
|
|
78
78
|
return newFilesById
|
|
79
79
|
})
|
|
80
80
|
return (
|
|
81
|
-
<UploadFilesContext
|
|
81
|
+
<UploadFilesContext value={[filesById, setFilesById]}>
|
|
82
82
|
{children}
|
|
83
|
-
</UploadFilesContext
|
|
83
|
+
</UploadFilesContext>
|
|
84
84
|
)
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -92,9 +92,9 @@ export function EventLoopProvider({ children }) {
|
|
|
92
92
|
clientStorage,
|
|
93
93
|
)
|
|
94
94
|
return (
|
|
95
|
-
<EventLoopContext
|
|
95
|
+
<EventLoopContext value={[addEvents, connectErrors]}>
|
|
96
96
|
{children}
|
|
97
|
-
</EventLoopContext
|
|
97
|
+
</EventLoopContext>
|
|
98
98
|
)
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -112,13 +112,13 @@ export function StateProvider({ children }) {
|
|
|
112
112
|
|
|
113
113
|
return (
|
|
114
114
|
{% for state_name in initial_state %}
|
|
115
|
-
<StateContexts.{{state_name|var_name}}
|
|
115
|
+
<StateContexts.{{state_name|var_name}} value={ {{state_name|var_name}} }>
|
|
116
116
|
{% endfor %}
|
|
117
|
-
<DispatchContext
|
|
117
|
+
<DispatchContext value={dispatchers}>
|
|
118
118
|
{children}
|
|
119
|
-
</DispatchContext
|
|
119
|
+
</DispatchContext>
|
|
120
120
|
{% for state_name in initial_state|reverse %}
|
|
121
|
-
</StateContexts.{{state_name|var_name}}
|
|
121
|
+
</StateContexts.{{state_name|var_name}}>
|
|
122
122
|
{% endfor %}
|
|
123
123
|
)
|
|
124
124
|
}
|
|
@@ -36,17 +36,17 @@ export default function RadixThemesColorModeProvider({ children }) {
|
|
|
36
36
|
const allowedModes = ["light", "dark", "system"];
|
|
37
37
|
if (!allowedModes.includes(mode)) {
|
|
38
38
|
console.error(
|
|
39
|
-
`Invalid color mode "${mode}". Defaulting to "${defaultColorMode}"
|
|
39
|
+
`Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`,
|
|
40
40
|
);
|
|
41
41
|
mode = defaultColorMode;
|
|
42
42
|
}
|
|
43
43
|
setTheme(mode);
|
|
44
44
|
};
|
|
45
45
|
return (
|
|
46
|
-
<ColorModeContext
|
|
46
|
+
<ColorModeContext
|
|
47
47
|
value={{ rawColorMode, resolvedColorMode, toggleColorMode, setColorMode }}
|
|
48
48
|
>
|
|
49
49
|
{children}
|
|
50
|
-
</ColorModeContext
|
|
50
|
+
</ColorModeContext>
|
|
51
51
|
);
|
|
52
52
|
}
|
|
@@ -179,7 +179,7 @@ export const applyEvent = async (event, socket) => {
|
|
|
179
179
|
// Handle special events
|
|
180
180
|
if (event.name == "_redirect") {
|
|
181
181
|
if (event.payload.external) {
|
|
182
|
-
window.open(event.payload.path, "_blank");
|
|
182
|
+
window.open(event.payload.path, "_blank", "noopener");
|
|
183
183
|
} else if (event.payload.replace) {
|
|
184
184
|
Router.replace(event.payload.path);
|
|
185
185
|
} else {
|
|
@@ -227,8 +227,8 @@ export const applyEvent = async (event, socket) => {
|
|
|
227
227
|
a.href = eval?.(
|
|
228
228
|
event.payload.url.replace(
|
|
229
229
|
"getBackendURL(env.UPLOAD)",
|
|
230
|
-
`"${getBackendURL(env.UPLOAD)}"
|
|
231
|
-
)
|
|
230
|
+
`"${getBackendURL(env.UPLOAD)}"`
|
|
231
|
+
)
|
|
232
232
|
);
|
|
233
233
|
}
|
|
234
234
|
a.download = event.payload.filename;
|
|
@@ -341,7 +341,7 @@ export const applyRestEvent = async (event, socket) => {
|
|
|
341
341
|
event.payload.files,
|
|
342
342
|
event.payload.upload_id,
|
|
343
343
|
event.payload.on_upload_progress,
|
|
344
|
-
socket
|
|
344
|
+
socket
|
|
345
345
|
);
|
|
346
346
|
return false;
|
|
347
347
|
}
|
|
@@ -408,7 +408,7 @@ export const connect = async (
|
|
|
408
408
|
dispatch,
|
|
409
409
|
transports,
|
|
410
410
|
setConnectErrors,
|
|
411
|
-
client_storage = {}
|
|
411
|
+
client_storage = {}
|
|
412
412
|
) => {
|
|
413
413
|
// Get backend URL object from the endpoint.
|
|
414
414
|
const endpoint = getBackendURL(EVENTURL);
|
|
@@ -499,7 +499,7 @@ export const uploadFiles = async (
|
|
|
499
499
|
files,
|
|
500
500
|
upload_id,
|
|
501
501
|
on_upload_progress,
|
|
502
|
-
socket
|
|
502
|
+
socket
|
|
503
503
|
) => {
|
|
504
504
|
// return if there's no file to upload
|
|
505
505
|
if (files === undefined || files.length === 0) {
|
|
@@ -604,7 +604,7 @@ export const Event = (
|
|
|
604
604
|
name,
|
|
605
605
|
payload = {},
|
|
606
606
|
event_actions = {},
|
|
607
|
-
handler = null
|
|
607
|
+
handler = null
|
|
608
608
|
) => {
|
|
609
609
|
return { name, payload, handler, event_actions };
|
|
610
610
|
};
|
|
@@ -631,7 +631,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
631
631
|
for (const state_key in client_storage.local_storage) {
|
|
632
632
|
const options = client_storage.local_storage[state_key];
|
|
633
633
|
const local_storage_value = localStorage.getItem(
|
|
634
|
-
options.name || state_key
|
|
634
|
+
options.name || state_key
|
|
635
635
|
);
|
|
636
636
|
if (local_storage_value !== null) {
|
|
637
637
|
client_storage_values[state_key] = local_storage_value;
|
|
@@ -642,7 +642,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
642
642
|
for (const state_key in client_storage.session_storage) {
|
|
643
643
|
const session_options = client_storage.session_storage[state_key];
|
|
644
644
|
const session_storage_value = sessionStorage.getItem(
|
|
645
|
-
session_options.name || state_key
|
|
645
|
+
session_options.name || state_key
|
|
646
646
|
);
|
|
647
647
|
if (session_storage_value != null) {
|
|
648
648
|
client_storage_values[state_key] = session_storage_value;
|
|
@@ -667,7 +667,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
667
667
|
const applyClientStorageDelta = (client_storage, delta) => {
|
|
668
668
|
// find the main state and check for is_hydrated
|
|
669
669
|
const unqualified_states = Object.keys(delta).filter(
|
|
670
|
-
(key) => key.split(".").length === 1
|
|
670
|
+
(key) => key.split(".").length === 1
|
|
671
671
|
);
|
|
672
672
|
if (unqualified_states.length === 1) {
|
|
673
673
|
const main_state = delta[unqualified_states[0]];
|
|
@@ -701,7 +701,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
|
|
|
701
701
|
const session_options = client_storage.session_storage[state_key];
|
|
702
702
|
sessionStorage.setItem(
|
|
703
703
|
session_options.name || state_key,
|
|
704
|
-
delta[substate][key]
|
|
704
|
+
delta[substate][key]
|
|
705
705
|
);
|
|
706
706
|
}
|
|
707
707
|
}
|
|
@@ -721,7 +721,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
|
|
|
721
721
|
export const useEventLoop = (
|
|
722
722
|
dispatch,
|
|
723
723
|
initial_events = () => [],
|
|
724
|
-
client_storage = {}
|
|
724
|
+
client_storage = {}
|
|
725
725
|
) => {
|
|
726
726
|
const socket = useRef(null);
|
|
727
727
|
const router = useRouter();
|
|
@@ -735,7 +735,7 @@ export const useEventLoop = (
|
|
|
735
735
|
|
|
736
736
|
event_actions = events.reduce(
|
|
737
737
|
(acc, e) => ({ ...acc, ...e.event_actions }),
|
|
738
|
-
event_actions ?? {}
|
|
738
|
+
event_actions ?? {}
|
|
739
739
|
);
|
|
740
740
|
|
|
741
741
|
const _e = args.filter((o) => o?.preventDefault !== undefined)[0];
|
|
@@ -763,7 +763,7 @@ export const useEventLoop = (
|
|
|
763
763
|
debounce(
|
|
764
764
|
combined_name,
|
|
765
765
|
() => queueEvents(events, socket),
|
|
766
|
-
event_actions.debounce
|
|
766
|
+
event_actions.debounce
|
|
767
767
|
);
|
|
768
768
|
} else {
|
|
769
769
|
queueEvents(events, socket);
|
|
@@ -782,7 +782,7 @@ export const useEventLoop = (
|
|
|
782
782
|
query,
|
|
783
783
|
asPath,
|
|
784
784
|
}))(router),
|
|
785
|
-
}))
|
|
785
|
+
}))
|
|
786
786
|
);
|
|
787
787
|
sentHydrate.current = true;
|
|
788
788
|
}
|
|
@@ -828,7 +828,7 @@ export const useEventLoop = (
|
|
|
828
828
|
dispatch,
|
|
829
829
|
["websocket"],
|
|
830
830
|
setConnectErrors,
|
|
831
|
-
client_storage
|
|
831
|
+
client_storage
|
|
832
832
|
);
|
|
833
833
|
}
|
|
834
834
|
}
|
|
@@ -876,7 +876,7 @@ export const useEventLoop = (
|
|
|
876
876
|
vars[storage_to_state_map[e.key]] = e.newValue;
|
|
877
877
|
const event = Event(
|
|
878
878
|
`${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
|
|
879
|
-
{ vars: vars }
|
|
879
|
+
{ vars: vars }
|
|
880
880
|
);
|
|
881
881
|
addEvents([event], e);
|
|
882
882
|
}
|
|
@@ -969,7 +969,7 @@ export const getRefValues = (refs) => {
|
|
|
969
969
|
return refs.map((ref) =>
|
|
970
970
|
ref.current
|
|
971
971
|
? ref.current.value || ref.current.getAttribute("aria-valuenow")
|
|
972
|
-
: null
|
|
972
|
+
: null
|
|
973
973
|
);
|
|
974
974
|
};
|
|
975
975
|
|
reflex/admin.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""The Reflex Admin Dashboard."""
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Optional
|
|
5
4
|
|
|
6
5
|
from starlette_admin.base import BaseAdmin as Admin
|
|
7
6
|
|
|
@@ -12,4 +11,4 @@ class AdminDash:
|
|
|
12
11
|
|
|
13
12
|
models: list = field(default_factory=list)
|
|
14
13
|
view_overrides: dict = field(default_factory=dict)
|
|
15
|
-
admin:
|
|
14
|
+
admin: Admin | None = None
|
reflex/app.py
CHANGED
|
@@ -25,12 +25,8 @@ from typing import (
|
|
|
25
25
|
Callable,
|
|
26
26
|
Coroutine,
|
|
27
27
|
Dict,
|
|
28
|
-
List,
|
|
29
28
|
MutableMapping,
|
|
30
|
-
Optional,
|
|
31
|
-
Set,
|
|
32
29
|
Type,
|
|
33
|
-
Union,
|
|
34
30
|
get_args,
|
|
35
31
|
get_type_hints,
|
|
36
32
|
)
|
|
@@ -167,7 +163,7 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec:
|
|
|
167
163
|
)
|
|
168
164
|
|
|
169
165
|
|
|
170
|
-
def extra_overlay_function() ->
|
|
166
|
+
def extra_overlay_function() -> Component | None:
|
|
171
167
|
"""Extra overlay function to add to the overlay component.
|
|
172
168
|
|
|
173
169
|
Returns:
|
|
@@ -250,16 +246,16 @@ class UploadFile(StarletteUploadFile):
|
|
|
250
246
|
|
|
251
247
|
file: BinaryIO
|
|
252
248
|
|
|
253
|
-
path:
|
|
249
|
+
path: Path | None = dataclasses.field(default=None)
|
|
254
250
|
|
|
255
|
-
_deprecated_filename:
|
|
251
|
+
_deprecated_filename: str | None = dataclasses.field(default=None)
|
|
256
252
|
|
|
257
|
-
size:
|
|
253
|
+
size: int | None = dataclasses.field(default=None)
|
|
258
254
|
|
|
259
255
|
headers: Headers = dataclasses.field(default_factory=Headers)
|
|
260
256
|
|
|
261
257
|
@property
|
|
262
|
-
def name(self) ->
|
|
258
|
+
def name(self) -> str | None:
|
|
263
259
|
"""Get the name of the uploaded file.
|
|
264
260
|
|
|
265
261
|
Returns:
|
|
@@ -269,7 +265,7 @@ class UploadFile(StarletteUploadFile):
|
|
|
269
265
|
return self.path.name
|
|
270
266
|
|
|
271
267
|
@property
|
|
272
|
-
def filename(self) ->
|
|
268
|
+
def filename(self) -> str | None:
|
|
273
269
|
"""Get the filename of the uploaded file.
|
|
274
270
|
|
|
275
271
|
Returns:
|
|
@@ -290,13 +286,13 @@ class UploadFile(StarletteUploadFile):
|
|
|
290
286
|
class UnevaluatedPage:
|
|
291
287
|
"""An uncompiled page."""
|
|
292
288
|
|
|
293
|
-
component:
|
|
289
|
+
component: Component | ComponentCallable
|
|
294
290
|
route: str
|
|
295
|
-
title:
|
|
296
|
-
description:
|
|
291
|
+
title: Var | str | None
|
|
292
|
+
description: Var | str | None
|
|
297
293
|
image: str
|
|
298
|
-
on_load:
|
|
299
|
-
meta:
|
|
294
|
+
on_load: EventType[()] | None
|
|
295
|
+
meta: list[dict[str, str]]
|
|
300
296
|
|
|
301
297
|
|
|
302
298
|
@dataclasses.dataclass()
|
|
@@ -322,7 +318,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
322
318
|
"""
|
|
323
319
|
|
|
324
320
|
# The global [theme](https://reflex.dev/docs/styling/theming/#theme) for the entire app.
|
|
325
|
-
theme:
|
|
321
|
+
theme: Component | None = dataclasses.field(
|
|
326
322
|
default_factory=lambda: themes.theme(accent_color="blue")
|
|
327
323
|
)
|
|
328
324
|
|
|
@@ -330,18 +326,18 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
330
326
|
style: ComponentStyle = dataclasses.field(default_factory=dict)
|
|
331
327
|
|
|
332
328
|
# A list of URLs to [stylesheets](https://reflex.dev/docs/styling/custom-stylesheets/) to include in the app.
|
|
333
|
-
stylesheets:
|
|
329
|
+
stylesheets: list[str] = dataclasses.field(default_factory=list)
|
|
334
330
|
|
|
335
331
|
# A component that is present on every page (defaults to the Connection Error banner).
|
|
336
|
-
overlay_component:
|
|
337
|
-
|
|
332
|
+
overlay_component: Component | ComponentCallable | None = dataclasses.field(
|
|
333
|
+
default=None
|
|
338
334
|
)
|
|
339
335
|
|
|
340
336
|
# Error boundary component to wrap the app with.
|
|
341
|
-
error_boundary:
|
|
337
|
+
error_boundary: ComponentCallable | None = dataclasses.field(default=None)
|
|
342
338
|
|
|
343
339
|
# App wraps to be applied to the whole app. Expected to be a dictionary of (order, name) to a function that takes whether the state is enabled and optionally returns a component.
|
|
344
|
-
app_wraps:
|
|
340
|
+
app_wraps: dict[tuple[int, str], Callable[[bool], Component | None]] = (
|
|
345
341
|
dataclasses.field(
|
|
346
342
|
default_factory=lambda: {
|
|
347
343
|
(55, "ErrorBoundary"): (
|
|
@@ -356,24 +352,24 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
356
352
|
)
|
|
357
353
|
|
|
358
354
|
# Components to add to the head of every page.
|
|
359
|
-
head_components:
|
|
355
|
+
head_components: list[Component] = dataclasses.field(default_factory=list)
|
|
360
356
|
|
|
361
357
|
# The Socket.IO AsyncServer instance.
|
|
362
|
-
sio:
|
|
358
|
+
sio: AsyncServer | None = None
|
|
363
359
|
|
|
364
360
|
# The language to add to the html root tag of every page.
|
|
365
|
-
html_lang:
|
|
361
|
+
html_lang: str | None = None
|
|
366
362
|
|
|
367
363
|
# Attributes to add to the html root tag of every page.
|
|
368
|
-
html_custom_attrs:
|
|
364
|
+
html_custom_attrs: dict[str, str] | None = None
|
|
369
365
|
|
|
370
366
|
# A map from a route to an unevaluated page.
|
|
371
|
-
_unevaluated_pages:
|
|
367
|
+
_unevaluated_pages: dict[str, UnevaluatedPage] = dataclasses.field(
|
|
372
368
|
default_factory=dict
|
|
373
369
|
)
|
|
374
370
|
|
|
375
371
|
# A map from a page route to the component to render. Users should use `add_page`.
|
|
376
|
-
_pages:
|
|
372
|
+
_pages: dict[str, Component] = dataclasses.field(default_factory=dict)
|
|
377
373
|
|
|
378
374
|
# A mapping of pages which created states as they were being evaluated.
|
|
379
375
|
_stateful_pages: Dict[str, None] = dataclasses.field(default_factory=dict)
|
|
@@ -382,24 +378,24 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
382
378
|
_api: FastAPI | None = None
|
|
383
379
|
|
|
384
380
|
# The state class to use for the app.
|
|
385
|
-
_state:
|
|
381
|
+
_state: Type[BaseState] | None = None
|
|
386
382
|
|
|
387
383
|
# Class to manage many client states.
|
|
388
|
-
_state_manager:
|
|
384
|
+
_state_manager: StateManager | None = None
|
|
389
385
|
|
|
390
386
|
# Mapping from a route to event handlers to trigger when the page loads.
|
|
391
|
-
_load_events:
|
|
387
|
+
_load_events: dict[str, list[IndividualEventType[()]]] = dataclasses.field(
|
|
392
388
|
default_factory=dict
|
|
393
389
|
)
|
|
394
390
|
|
|
395
391
|
# Admin dashboard to view and manage the database.
|
|
396
|
-
admin_dash:
|
|
392
|
+
admin_dash: AdminDash | None = None
|
|
397
393
|
|
|
398
394
|
# The async server name space.
|
|
399
|
-
_event_namespace:
|
|
395
|
+
_event_namespace: EventNamespace | None = None
|
|
400
396
|
|
|
401
397
|
# Background tasks that are currently running.
|
|
402
|
-
_background_tasks:
|
|
398
|
+
_background_tasks: set[asyncio.Task] = dataclasses.field(default_factory=set)
|
|
403
399
|
|
|
404
400
|
# Frontend Error Handler Function
|
|
405
401
|
frontend_exception_handler: Callable[[Exception], None] = (
|
|
@@ -408,7 +404,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
408
404
|
|
|
409
405
|
# Backend Error Handler Function
|
|
410
406
|
backend_exception_handler: Callable[
|
|
411
|
-
[Exception],
|
|
407
|
+
[Exception], EventSpec | list[EventSpec] | None
|
|
412
408
|
] = default_backend_exception_handler
|
|
413
409
|
|
|
414
410
|
# Put the toast provider in the app wrap.
|
|
@@ -895,7 +891,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
895
891
|
|
|
896
892
|
admin.mount_to(self.api)
|
|
897
893
|
|
|
898
|
-
def _get_frontend_packages(self, imports:
|
|
894
|
+
def _get_frontend_packages(self, imports: dict[str, set[ImportVar]]):
|
|
899
895
|
"""Gets the frontend packages to be installed and filters out the unnecessary ones.
|
|
900
896
|
|
|
901
897
|
Args:
|
|
@@ -986,12 +982,15 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
986
982
|
|
|
987
983
|
def _setup_sticky_badge(self):
|
|
988
984
|
"""Add the sticky badge to the app."""
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
985
|
+
from reflex.components.component import memo
|
|
986
|
+
|
|
987
|
+
@memo
|
|
988
|
+
def memoized_badge():
|
|
992
989
|
sticky_badge = sticky()
|
|
993
990
|
sticky_badge._add_style_recursive({})
|
|
994
|
-
|
|
991
|
+
return sticky_badge
|
|
992
|
+
|
|
993
|
+
self.app_wraps[(0, "StickyBadge")] = lambda _: memoized_badge()
|
|
995
994
|
|
|
996
995
|
def _apply_decorated_pages(self):
|
|
997
996
|
"""Add @rx.page decorated pages to the app.
|
|
@@ -1006,9 +1005,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1006
1005
|
for render, kwargs in DECORATED_PAGES[get_config().app_name]:
|
|
1007
1006
|
self.add_page(render, **kwargs)
|
|
1008
1007
|
|
|
1009
|
-
def _validate_var_dependencies(
|
|
1010
|
-
self, state: Optional[Type[BaseState]] = None
|
|
1011
|
-
) -> None:
|
|
1008
|
+
def _validate_var_dependencies(self, state: Type[BaseState] | None = None) -> None:
|
|
1012
1009
|
"""Validate the dependencies of the vars in the app.
|
|
1013
1010
|
|
|
1014
1011
|
Args:
|
|
@@ -1080,7 +1077,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1080
1077
|
self.style = evaluate_style_namespaces(self.style)
|
|
1081
1078
|
|
|
1082
1079
|
# Add the app wrappers.
|
|
1083
|
-
app_wrappers:
|
|
1080
|
+
app_wrappers: dict[tuple[int, str], Component] = {
|
|
1084
1081
|
# Default app wrap component renders {children}
|
|
1085
1082
|
(0, "AppWrap"): AppWrap.create()
|
|
1086
1083
|
}
|
|
@@ -1103,6 +1100,9 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1103
1100
|
console.debug(f"Evaluating page: {route}")
|
|
1104
1101
|
self._compile_page(route, save_page=should_compile)
|
|
1105
1102
|
|
|
1103
|
+
# Save the pages which created new states at eval time.
|
|
1104
|
+
self._write_stateful_pages_marker()
|
|
1105
|
+
|
|
1106
1106
|
# Add the optional endpoints (_upload)
|
|
1107
1107
|
self._add_optional_endpoints()
|
|
1108
1108
|
|
|
@@ -1145,6 +1145,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1145
1145
|
)[:10]
|
|
1146
1146
|
)
|
|
1147
1147
|
)
|
|
1148
|
+
# Save the pages which created new states at eval time.
|
|
1149
|
+
self._write_stateful_pages_marker()
|
|
1148
1150
|
|
|
1149
1151
|
# Add the optional endpoints (_upload)
|
|
1150
1152
|
self._add_optional_endpoints()
|
|
@@ -1366,7 +1368,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1366
1368
|
for output_path, code in compile_results:
|
|
1367
1369
|
compiler_utils.write_page(output_path, code)
|
|
1368
1370
|
|
|
1369
|
-
|
|
1371
|
+
def _write_stateful_pages_marker(self):
|
|
1372
|
+
"""Write list of routes that create dynamic states for the backend to use later."""
|
|
1370
1373
|
if self._state is not None:
|
|
1371
1374
|
stateful_pages_marker = (
|
|
1372
1375
|
prerequisites.get_backend_dir() / constants.Dirs.STATEFUL_PAGES
|
|
@@ -1541,8 +1544,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1541
1544
|
|
|
1542
1545
|
valid = bool(
|
|
1543
1546
|
return_type == EventSpec
|
|
1544
|
-
or return_type ==
|
|
1545
|
-
or return_type ==
|
|
1547
|
+
or return_type == EventSpec | None
|
|
1548
|
+
or return_type == list[EventSpec]
|
|
1546
1549
|
or return_type == inspect.Signature.empty
|
|
1547
1550
|
or return_type is None
|
|
1548
1551
|
)
|
|
@@ -1550,7 +1553,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1550
1553
|
if not valid:
|
|
1551
1554
|
raise ValueError(
|
|
1552
1555
|
f"Provided custom {handler_domain} exception handler `{_fn_name}` has the wrong return type."
|
|
1553
|
-
f"Expected `
|
|
1556
|
+
f"Expected `EventSpec | list[EventSpec] | None` but got `{return_type}`"
|
|
1554
1557
|
)
|
|
1555
1558
|
|
|
1556
1559
|
|
|
@@ -1690,7 +1693,7 @@ def upload(app: App):
|
|
|
1690
1693
|
The upload function.
|
|
1691
1694
|
"""
|
|
1692
1695
|
|
|
1693
|
-
async def upload_file(request: Request, files:
|
|
1696
|
+
async def upload_file(request: Request, files: list[FastAPIUploadFile]):
|
|
1694
1697
|
"""Upload a file.
|
|
1695
1698
|
|
|
1696
1699
|
Args:
|
|
@@ -1730,7 +1733,7 @@ def upload(app: App):
|
|
|
1730
1733
|
# get handler function
|
|
1731
1734
|
func = getattr(type(current_state), handler.split(".")[-1])
|
|
1732
1735
|
|
|
1733
|
-
# check if there exists any handler args with annotation,
|
|
1736
|
+
# check if there exists any handler args with annotation, list[UploadFile]
|
|
1734
1737
|
if isinstance(func, EventHandler):
|
|
1735
1738
|
if func.is_background:
|
|
1736
1739
|
raise UploadTypeError(
|
|
@@ -1750,7 +1753,7 @@ def upload(app: App):
|
|
|
1750
1753
|
if not handler_upload_param:
|
|
1751
1754
|
raise UploadValueError(
|
|
1752
1755
|
f"`{handler}` handler should have a parameter annotated as "
|
|
1753
|
-
"
|
|
1756
|
+
"list[rx.UploadFile]"
|
|
1754
1757
|
)
|
|
1755
1758
|
|
|
1756
1759
|
# Make a copy of the files as they are closed after the request.
|
reflex/app_mixins/lifespan.py
CHANGED
|
@@ -7,7 +7,7 @@ import contextlib
|
|
|
7
7
|
import dataclasses
|
|
8
8
|
import functools
|
|
9
9
|
import inspect
|
|
10
|
-
from typing import Callable, Coroutine
|
|
10
|
+
from typing import Callable, Coroutine
|
|
11
11
|
|
|
12
12
|
from fastapi import FastAPI
|
|
13
13
|
|
|
@@ -22,7 +22,7 @@ class LifespanMixin(AppMixin):
|
|
|
22
22
|
"""A Mixin that allow tasks to run during the whole app lifespan."""
|
|
23
23
|
|
|
24
24
|
# Lifespan tasks that are planned to run.
|
|
25
|
-
lifespan_tasks:
|
|
25
|
+
lifespan_tasks: set[asyncio.Task | Callable] = dataclasses.field(
|
|
26
26
|
default_factory=set
|
|
27
27
|
)
|
|
28
28
|
|
reflex/app_mixins/middleware.py
CHANGED
|
@@ -4,7 +4,6 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import dataclasses
|
|
7
|
-
from typing import List
|
|
8
7
|
|
|
9
8
|
from reflex.event import Event
|
|
10
9
|
from reflex.middleware import HydrateMiddleware, Middleware
|
|
@@ -18,7 +17,7 @@ class MiddlewareMixin(AppMixin):
|
|
|
18
17
|
"""Middleware Mixin that allow to add middleware to the app."""
|
|
19
18
|
|
|
20
19
|
# Middleware to add to the app. Users should use `add_middleware`. PRIVATE.
|
|
21
|
-
middleware:
|
|
20
|
+
middleware: list[Middleware] = dataclasses.field(default_factory=list)
|
|
22
21
|
|
|
23
22
|
def _init_mixin(self):
|
|
24
23
|
self.middleware.append(HydrateMiddleware())
|
reflex/assets.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Optional
|
|
6
5
|
|
|
7
6
|
from reflex import constants
|
|
8
7
|
from reflex.config import EnvironmentVariables
|
|
@@ -11,7 +10,7 @@ from reflex.config import EnvironmentVariables
|
|
|
11
10
|
def asset(
|
|
12
11
|
path: str,
|
|
13
12
|
shared: bool = False,
|
|
14
|
-
subfolder:
|
|
13
|
+
subfolder: str | None = None,
|
|
15
14
|
_stack_level: int = 1,
|
|
16
15
|
) -> str:
|
|
17
16
|
"""Add an asset to the app, either shared as a symlink or local.
|
reflex/base.py
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
from typing import TYPE_CHECKING, Any,
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Type
|
|
7
7
|
|
|
8
8
|
import pydantic.v1.main as pydantic_main
|
|
9
9
|
from pydantic.v1 import BaseModel
|
|
10
10
|
from pydantic.v1.fields import ModelField
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def validate_field_name(bases:
|
|
13
|
+
def validate_field_name(bases: list[Type["BaseModel"]], field_name: str) -> None:
|
|
14
14
|
"""Ensure that the field's name does not shadow an existing attribute of the model.
|
|
15
15
|
|
|
16
16
|
Args:
|