reflex 0.4.6a4__py3-none-any.whl → 0.4.7a1__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/apps/blank/code/blank.py +1 -0
- reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +1 -1
- reflex/.templates/jinja/custom_components/src.py.jinja2 +8 -8
- reflex/.templates/jinja/web/pages/index.js.jinja2 +0 -4
- reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 +2 -6
- reflex/.templates/web/utils/state.js +6 -1
- reflex/__init__.py +2 -0
- reflex/__init__.pyi +2 -0
- reflex/app.py +12 -16
- reflex/app.pyi +2 -0
- reflex/compiler/compiler.py +10 -11
- reflex/compiler/utils.py +3 -3
- reflex/components/chakra/forms/pininput.py +2 -1
- reflex/components/component.py +71 -104
- reflex/components/core/banner.py +1 -1
- reflex/components/core/upload.py +2 -1
- reflex/components/datadisplay/__init__.py +1 -0
- reflex/components/datadisplay/logo.py +49 -0
- reflex/components/el/elements/forms.py +7 -4
- reflex/components/el/elements/forms.pyi +0 -1
- reflex/components/lucide/icon.py +3 -2
- reflex/components/lucide/icon.pyi +2 -2
- reflex/components/markdown/markdown.py +10 -6
- reflex/components/markdown/markdown.pyi +0 -3
- reflex/components/radix/themes/components/select.py +10 -3
- reflex/config.py +1 -1
- reflex/config.pyi +1 -1
- reflex/constants/base.py +4 -5
- reflex/constants/base.pyi +94 -0
- reflex/constants/compiler.py +8 -0
- reflex/custom_components/custom_components.py +1 -1
- reflex/experimental/__init__.py +14 -0
- reflex/experimental/hooks.py +75 -0
- reflex/page.py +1 -1
- reflex/reflex.py +18 -32
- reflex/style.py +4 -4
- reflex/testing.py +1 -1
- reflex/utils/console.py +6 -4
- reflex/utils/exec.py +17 -1
- reflex/utils/export.py +0 -3
- reflex/utils/prerequisites.py +239 -43
- reflex/utils/processes.py +6 -1
- reflex/utils/telemetry.py +14 -2
- reflex/vars.py +6 -6
- reflex/vars.pyi +2 -1
- {reflex-0.4.6a4.dist-info → reflex-0.4.7a1.dist-info}/METADATA +15 -10
- {reflex-0.4.6a4.dist-info → reflex-0.4.7a1.dist-info}/RECORD +50 -64
- {reflex-0.4.6a4.dist-info → reflex-0.4.7a1.dist-info}/WHEEL +1 -1
- reflex/.templates/apps/sidebar/README.md +0 -69
- reflex/.templates/apps/sidebar/assets/favicon.ico +0 -0
- reflex/.templates/apps/sidebar/assets/github.svg +0 -10
- reflex/.templates/apps/sidebar/assets/logo.svg +0 -68
- reflex/.templates/apps/sidebar/assets/paneleft.svg +0 -13
- reflex/.templates/apps/sidebar/assets/reflex_black.svg +0 -37
- reflex/.templates/apps/sidebar/assets/reflex_white.svg +0 -8
- reflex/.templates/apps/sidebar/code/__init__.py +0 -1
- reflex/.templates/apps/sidebar/code/components/__init__.py +0 -0
- reflex/.templates/apps/sidebar/code/components/sidebar.py +0 -152
- reflex/.templates/apps/sidebar/code/pages/__init__.py +0 -3
- reflex/.templates/apps/sidebar/code/pages/dashboard.py +0 -22
- reflex/.templates/apps/sidebar/code/pages/index.py +0 -18
- reflex/.templates/apps/sidebar/code/pages/settings.py +0 -61
- reflex/.templates/apps/sidebar/code/sidebar.py +0 -16
- reflex/.templates/apps/sidebar/code/styles.py +0 -60
- reflex/.templates/apps/sidebar/code/templates/__init__.py +0 -1
- reflex/.templates/apps/sidebar/code/templates/template.py +0 -145
- {reflex-0.4.6a4.dist-info → reflex-0.4.7a1.dist-info}/LICENSE +0 -0
- {reflex-0.4.6a4.dist-info → reflex-0.4.7a1.dist-info}/entry_points.txt +0 -0
|
@@ -133,7 +133,7 @@ class Markdown(Component):
|
|
|
133
133
|
**props,
|
|
134
134
|
)
|
|
135
135
|
|
|
136
|
-
def
|
|
136
|
+
def _get_all_custom_components(
|
|
137
137
|
self, seen: set[str] | None = None
|
|
138
138
|
) -> set[CustomComponent]:
|
|
139
139
|
"""Get all the custom components used by the component.
|
|
@@ -144,11 +144,13 @@ class Markdown(Component):
|
|
|
144
144
|
Returns:
|
|
145
145
|
The set of custom components.
|
|
146
146
|
"""
|
|
147
|
-
custom_components = super().
|
|
147
|
+
custom_components = super()._get_all_custom_components(seen=seen)
|
|
148
148
|
|
|
149
149
|
# Get the custom components for each tag.
|
|
150
150
|
for component in self.component_map.values():
|
|
151
|
-
custom_components |= component(_MOCK_ARG).
|
|
151
|
+
custom_components |= component(_MOCK_ARG)._get_all_custom_components(
|
|
152
|
+
seen=seen
|
|
153
|
+
)
|
|
152
154
|
|
|
153
155
|
return custom_components
|
|
154
156
|
|
|
@@ -183,7 +185,9 @@ class Markdown(Component):
|
|
|
183
185
|
|
|
184
186
|
# Get the imports for each component.
|
|
185
187
|
for component in self.component_map.values():
|
|
186
|
-
imports = utils.merge_imports(
|
|
188
|
+
imports = utils.merge_imports(
|
|
189
|
+
imports, component(_MOCK_ARG)._get_all_imports()
|
|
190
|
+
)
|
|
187
191
|
|
|
188
192
|
# Get the imports for the code components.
|
|
189
193
|
imports = utils.merge_imports(
|
|
@@ -293,8 +297,8 @@ class Markdown(Component):
|
|
|
293
297
|
hooks = set()
|
|
294
298
|
for _component in self.component_map.values():
|
|
295
299
|
comp = _component(_MOCK_ARG)
|
|
296
|
-
hooks
|
|
297
|
-
hooks
|
|
300
|
+
hooks.update(comp._get_all_hooks_internal())
|
|
301
|
+
hooks.update(comp._get_all_hooks())
|
|
298
302
|
formatted_hooks = "\n".join(hooks)
|
|
299
303
|
return f"""
|
|
300
304
|
function {self._get_component_map_name()} () {{
|
|
@@ -123,9 +123,6 @@ class Markdown(Component):
|
|
|
123
123
|
The markdown component.
|
|
124
124
|
"""
|
|
125
125
|
...
|
|
126
|
-
def get_custom_components(
|
|
127
|
-
self, seen: set[str] | None = None
|
|
128
|
-
) -> set[CustomComponent]: ...
|
|
129
126
|
def get_component(self, tag: str, **props) -> Component: ...
|
|
130
127
|
def format_component(self, tag: str, **props) -> str: ...
|
|
131
128
|
def format_component_map(self) -> dict[str, str]: ...
|
|
@@ -198,6 +198,15 @@ class HighLevelSelect(SelectRoot):
|
|
|
198
198
|
Returns:
|
|
199
199
|
The select component.
|
|
200
200
|
"""
|
|
201
|
+
trigger_prop_list = [
|
|
202
|
+
"placeholder",
|
|
203
|
+
"variant",
|
|
204
|
+
"radius",
|
|
205
|
+
"width",
|
|
206
|
+
"flex_shrink",
|
|
207
|
+
"custom_attrs",
|
|
208
|
+
]
|
|
209
|
+
|
|
201
210
|
content_props = {
|
|
202
211
|
prop: props.pop(prop)
|
|
203
212
|
for prop in ["high_contrast", "position"]
|
|
@@ -205,9 +214,7 @@ class HighLevelSelect(SelectRoot):
|
|
|
205
214
|
}
|
|
206
215
|
|
|
207
216
|
trigger_props = {
|
|
208
|
-
prop: props.pop(prop)
|
|
209
|
-
for prop in ["placeholder", "variant", "radius", "width", "flex_shrink"]
|
|
210
|
-
if prop in props
|
|
217
|
+
prop: props.pop(prop) for prop in trigger_prop_list if prop in props
|
|
211
218
|
}
|
|
212
219
|
|
|
213
220
|
color_scheme = props.pop("color_scheme", None)
|
reflex/config.py
CHANGED
reflex/config.pyi
CHANGED
|
@@ -104,7 +104,7 @@ class Config(Base):
|
|
|
104
104
|
@staticmethod
|
|
105
105
|
def check_deprecated_values(**kwargs) -> None: ...
|
|
106
106
|
def update_from_env(self) -> None: ...
|
|
107
|
-
def get_event_namespace(self) -> str
|
|
107
|
+
def get_event_namespace(self) -> str: ...
|
|
108
108
|
def _set_persistent(self, **kwargs) -> None: ...
|
|
109
109
|
|
|
110
110
|
def get_config(reload: bool = ...) -> Config: ...
|
reflex/constants/base.py
CHANGED
|
@@ -88,12 +88,11 @@ class ReflexHostingCLI(SimpleNamespace):
|
|
|
88
88
|
class Templates(SimpleNamespace):
|
|
89
89
|
"""Constants related to Templates."""
|
|
90
90
|
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
template_dirs = next(os.walk(template_dir))[1]
|
|
91
|
+
# The route on Reflex backend to query which templates are available and their URLs.
|
|
92
|
+
APP_TEMPLATES_ROUTE = "/app-templates"
|
|
94
93
|
|
|
95
|
-
#
|
|
96
|
-
|
|
94
|
+
# The default template
|
|
95
|
+
DEFAULT = "blank"
|
|
97
96
|
|
|
98
97
|
class Dirs(SimpleNamespace):
|
|
99
98
|
"""Folders used by the template system of Reflex."""
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Stub file for reflex/constants/base.py"""
|
|
2
|
+
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
|
+
# ------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
7
|
+
from reflex.vars import Var, BaseVar, ComputedVar
|
|
8
|
+
from reflex.event import EventChain, EventHandler, EventSpec
|
|
9
|
+
from reflex.style import Style
|
|
10
|
+
import os
|
|
11
|
+
import platform
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from importlib import metadata
|
|
14
|
+
from types import SimpleNamespace
|
|
15
|
+
from platformdirs import PlatformDirs
|
|
16
|
+
|
|
17
|
+
IS_WINDOWS = platform.system() == "Windows"
|
|
18
|
+
|
|
19
|
+
class Dirs(SimpleNamespace):
|
|
20
|
+
WEB = ".web"
|
|
21
|
+
APP_ASSETS = "assets"
|
|
22
|
+
UTILS = "utils"
|
|
23
|
+
STATIC = "_static"
|
|
24
|
+
STATE_PATH = "/".join([UTILS, "state"])
|
|
25
|
+
COMPONENTS_PATH = "/".join([UTILS, "components"])
|
|
26
|
+
CONTEXTS_PATH = "/".join([UTILS, "context"])
|
|
27
|
+
WEB_PAGES = os.path.join(WEB, "pages")
|
|
28
|
+
WEB_STATIC = os.path.join(WEB, STATIC)
|
|
29
|
+
WEB_UTILS = os.path.join(WEB, UTILS)
|
|
30
|
+
WEB_ASSETS = os.path.join(WEB, "public")
|
|
31
|
+
ENV_JSON = os.path.join(WEB, "env.json")
|
|
32
|
+
REFLEX_JSON = os.path.join(WEB, "reflex.json")
|
|
33
|
+
POSTCSS_JS = os.path.join(WEB, "postcss.config.js")
|
|
34
|
+
|
|
35
|
+
class Reflex(SimpleNamespace):
|
|
36
|
+
MODULE_NAME = "reflex"
|
|
37
|
+
VERSION = metadata.version(MODULE_NAME)
|
|
38
|
+
JSON = os.path.join(Dirs.WEB, "reflex.json")
|
|
39
|
+
_dir = os.environ.get("REFLEX_DIR", "")
|
|
40
|
+
DIR = _dir or PlatformDirs(MODULE_NAME, False).user_data_dir
|
|
41
|
+
ROOT_DIR = os.path.dirname(
|
|
42
|
+
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
class ReflexHostingCLI(SimpleNamespace):
|
|
46
|
+
MODULE_NAME = "reflex-hosting-cli"
|
|
47
|
+
|
|
48
|
+
class Templates(SimpleNamespace):
|
|
49
|
+
APP_TEMPLATES_ROUTE = "/app-templates"
|
|
50
|
+
DEFAULT = "blank"
|
|
51
|
+
|
|
52
|
+
class Dirs(SimpleNamespace):
|
|
53
|
+
BASE = os.path.join(Reflex.ROOT_DIR, Reflex.MODULE_NAME, ".templates")
|
|
54
|
+
WEB_TEMPLATE = os.path.join(BASE, "web")
|
|
55
|
+
JINJA_TEMPLATE = os.path.join(BASE, "jinja")
|
|
56
|
+
CODE = "code"
|
|
57
|
+
|
|
58
|
+
class Next(SimpleNamespace):
|
|
59
|
+
CONFIG_FILE = "next.config.js"
|
|
60
|
+
SITEMAP_CONFIG_FILE = os.path.join(Dirs.WEB, "next-sitemap.config.js")
|
|
61
|
+
NODE_MODULES = "node_modules"
|
|
62
|
+
PACKAGE_LOCK = "package-lock.json"
|
|
63
|
+
FRONTEND_LISTENING_REGEX = "Local:[\\s]+(.*)"
|
|
64
|
+
|
|
65
|
+
class ColorMode(SimpleNamespace):
|
|
66
|
+
NAME = "colorMode"
|
|
67
|
+
USE = "useColorMode"
|
|
68
|
+
TOGGLE = "toggleColorMode"
|
|
69
|
+
|
|
70
|
+
class Env(str, Enum):
|
|
71
|
+
DEV = "dev"
|
|
72
|
+
PROD = "prod"
|
|
73
|
+
|
|
74
|
+
class LogLevel(str, Enum):
|
|
75
|
+
DEBUG = "debug"
|
|
76
|
+
INFO = "info"
|
|
77
|
+
WARNING = "warning"
|
|
78
|
+
ERROR = "error"
|
|
79
|
+
CRITICAL = "critical"
|
|
80
|
+
|
|
81
|
+
POLLING_MAX_HTTP_BUFFER_SIZE = 1000 * 1000
|
|
82
|
+
|
|
83
|
+
class Ping(SimpleNamespace):
|
|
84
|
+
INTERVAL = 25
|
|
85
|
+
TIMEOUT = 120
|
|
86
|
+
|
|
87
|
+
COOKIES = "cookies"
|
|
88
|
+
LOCAL_STORAGE = "local_storage"
|
|
89
|
+
SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE"
|
|
90
|
+
ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE"
|
|
91
|
+
PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"
|
|
92
|
+
RELOAD_CONFIG = "__REFLEX_RELOAD_CONFIG"
|
|
93
|
+
REFLEX_VAR_OPENING_TAG = "<reflex.Var>"
|
|
94
|
+
REFLEX_VAR_CLOSING_TAG = "</reflex.Var>"
|
reflex/constants/compiler.py
CHANGED
|
@@ -111,6 +111,14 @@ class Hooks(SimpleNamespace):
|
|
|
111
111
|
"""Common sets of hook declarations."""
|
|
112
112
|
|
|
113
113
|
EVENTS = f"const [{CompileVars.ADD_EVENTS}, {CompileVars.CONNECT_ERROR}] = useContext(EventLoopContext);"
|
|
114
|
+
AUTOFOCUS = """
|
|
115
|
+
// Set focus to the specified element.
|
|
116
|
+
const focusRef = useRef(null)
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (focusRef.current) {
|
|
119
|
+
focusRef.current.focus();
|
|
120
|
+
}
|
|
121
|
+
})"""
|
|
114
122
|
|
|
115
123
|
|
|
116
124
|
class MemoizationDisposition(enum.Enum):
|
|
@@ -145,7 +145,7 @@ def _populate_demo_app(name_variants: NameVariants):
|
|
|
145
145
|
|
|
146
146
|
with set_directory(demo_app_dir):
|
|
147
147
|
# We start with the blank template as basis.
|
|
148
|
-
_init(name=demo_app_name, template=constants.Templates.
|
|
148
|
+
_init(name=demo_app_name, template=constants.Templates.DEFAULT)
|
|
149
149
|
# Then overwrite the app source file with the one we want for testing custom components.
|
|
150
150
|
# This source file is rendered using jinja template file.
|
|
151
151
|
with open(f"{demo_app_name}/{demo_app_name}.py", "w") as f:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Namespace for experimental features."""
|
|
2
|
+
|
|
3
|
+
from types import SimpleNamespace
|
|
4
|
+
|
|
5
|
+
from ..utils.console import warn
|
|
6
|
+
from . import hooks as hooks
|
|
7
|
+
|
|
8
|
+
warn(
|
|
9
|
+
"`rx._x` contains experimental features and might be removed at any time in the future .",
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
_x = SimpleNamespace(
|
|
13
|
+
hooks=hooks,
|
|
14
|
+
)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Add standard Hooks wrapper for React."""
|
|
2
|
+
|
|
3
|
+
from reflex.utils.imports import ImportVar
|
|
4
|
+
from reflex.vars import Var, VarData
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _add_react_import(v: Var | None, tags: str | list):
|
|
8
|
+
if v is None:
|
|
9
|
+
return
|
|
10
|
+
|
|
11
|
+
if isinstance(tags, str):
|
|
12
|
+
tags = [tags]
|
|
13
|
+
|
|
14
|
+
v._var_data = VarData( # type: ignore
|
|
15
|
+
imports={"react": [ImportVar(tag=tag) for tag in tags]},
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def const(name, value) -> Var | None:
|
|
20
|
+
"""Create a constant Var.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
name: The name of the constant.
|
|
24
|
+
value: The value of the constant.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
The constant Var.
|
|
28
|
+
"""
|
|
29
|
+
return Var.create(f"const {name} = {value}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def useCallback(func, deps) -> Var | None:
|
|
33
|
+
"""Create a useCallback hook with a function and dependencies.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
func: The function to wrap.
|
|
37
|
+
deps: The dependencies of the function.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The useCallback hook.
|
|
41
|
+
"""
|
|
42
|
+
if deps:
|
|
43
|
+
v = Var.create(f"useCallback({func}, {deps})")
|
|
44
|
+
else:
|
|
45
|
+
v = Var.create(f"useCallback({func})")
|
|
46
|
+
_add_react_import(v, "useCallback")
|
|
47
|
+
return v
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def useContext(context) -> Var | None:
|
|
51
|
+
"""Create a useContext hook with a context.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
context: The context to use.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
The useContext hook.
|
|
58
|
+
"""
|
|
59
|
+
v = Var.create(f"useContext({context})")
|
|
60
|
+
_add_react_import(v, "useContext")
|
|
61
|
+
return v
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def useRef(default) -> Var | None:
|
|
65
|
+
"""Create a useRef hook with a default value.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
default: The default value of the ref.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
The useRef hook.
|
|
72
|
+
"""
|
|
73
|
+
v = Var.create(f"useRef({default})")
|
|
74
|
+
_add_react_import(v, "useRef")
|
|
75
|
+
return v
|
reflex/page.py
CHANGED
|
@@ -30,7 +30,7 @@ def page(
|
|
|
30
30
|
title: The title of the page.
|
|
31
31
|
image: The favicon of the page.
|
|
32
32
|
description: The description of the page.
|
|
33
|
-
meta:
|
|
33
|
+
meta: Additional meta to add to the page.
|
|
34
34
|
on_load: The event handler(s) called when the page load.
|
|
35
35
|
script_tags: scripts to attach to the page
|
|
36
36
|
|
reflex/reflex.py
CHANGED
|
@@ -63,7 +63,7 @@ def main(
|
|
|
63
63
|
|
|
64
64
|
def _init(
|
|
65
65
|
name: str,
|
|
66
|
-
template:
|
|
66
|
+
template: str | None = None,
|
|
67
67
|
loglevel: constants.LogLevel = config.loglevel,
|
|
68
68
|
):
|
|
69
69
|
"""Initialize a new Reflex app in the given directory."""
|
|
@@ -79,31 +79,20 @@ def _init(
|
|
|
79
79
|
app_name = prerequisites.validate_app_name(name)
|
|
80
80
|
console.rule(f"[bold]Initializing {app_name}")
|
|
81
81
|
|
|
82
|
+
# Check prerequisites.
|
|
82
83
|
prerequisites.check_latest_package_version(constants.Reflex.MODULE_NAME)
|
|
83
|
-
|
|
84
84
|
prerequisites.initialize_reflex_user_directory()
|
|
85
|
-
|
|
86
85
|
prerequisites.ensure_reflex_installation_id()
|
|
87
86
|
|
|
88
87
|
# When upgrading to 0.4, show migration instructions.
|
|
89
88
|
if prerequisites.should_show_rx_chakra_migration_instructions():
|
|
90
89
|
prerequisites.show_rx_chakra_migration_instructions()
|
|
91
90
|
|
|
92
|
-
# Set up the app directory, only if the config doesn't exist.
|
|
93
|
-
if not os.path.exists(constants.Config.FILE):
|
|
94
|
-
if template is None:
|
|
95
|
-
template = prerequisites.prompt_for_template()
|
|
96
|
-
prerequisites.create_config(app_name)
|
|
97
|
-
prerequisites.initialize_app_directory(app_name, template)
|
|
98
|
-
telemetry_event = "init"
|
|
99
|
-
else:
|
|
100
|
-
telemetry_event = "reinit"
|
|
101
|
-
|
|
102
91
|
# Set up the web project.
|
|
103
92
|
prerequisites.initialize_frontend_dependencies()
|
|
104
93
|
|
|
105
|
-
#
|
|
106
|
-
|
|
94
|
+
# Initialize the app.
|
|
95
|
+
prerequisites.initialize_app(app_name, template)
|
|
107
96
|
|
|
108
97
|
# Migrate Pynecone projects to Reflex.
|
|
109
98
|
prerequisites.migrate_to_reflex()
|
|
@@ -123,7 +112,7 @@ def init(
|
|
|
123
112
|
name: str = typer.Option(
|
|
124
113
|
None, metavar="APP_NAME", help="The name of the app to initialize."
|
|
125
114
|
),
|
|
126
|
-
template:
|
|
115
|
+
template: str = typer.Option(
|
|
127
116
|
None,
|
|
128
117
|
help="The template to initialize the app with.",
|
|
129
118
|
),
|
|
@@ -165,7 +154,8 @@ def _run(
|
|
|
165
154
|
_skip_compile()
|
|
166
155
|
|
|
167
156
|
# Check that the app is initialized.
|
|
168
|
-
prerequisites.
|
|
157
|
+
if prerequisites.needs_reinit(frontend=frontend):
|
|
158
|
+
_init(name=config.app_name, loglevel=loglevel)
|
|
169
159
|
|
|
170
160
|
# If something is running on the ports, ask the user if they want to kill or change it.
|
|
171
161
|
if frontend and processes.is_process_on_port(frontend_port):
|
|
@@ -234,6 +224,11 @@ def _run(
|
|
|
234
224
|
# In dev mode, run the backend on the main thread.
|
|
235
225
|
if backend and env == constants.Env.DEV:
|
|
236
226
|
backend_cmd(backend_host, int(backend_port))
|
|
227
|
+
# The windows uvicorn bug workaround
|
|
228
|
+
# https://github.com/reflex-dev/reflex/issues/2335
|
|
229
|
+
if constants.IS_WINDOWS and exec.frontend_process:
|
|
230
|
+
# Sends SIGTERM in windows
|
|
231
|
+
exec.kill(exec.frontend_process.pid)
|
|
237
232
|
|
|
238
233
|
|
|
239
234
|
@cli.command()
|
|
@@ -289,6 +284,10 @@ def export(
|
|
|
289
284
|
):
|
|
290
285
|
"""Export the app to a zip file."""
|
|
291
286
|
from reflex.utils import export as export_utils
|
|
287
|
+
from reflex.utils import prerequisites
|
|
288
|
+
|
|
289
|
+
if prerequisites.needs_reinit(frontend=True):
|
|
290
|
+
_init(name=config.app_name, loglevel=loglevel)
|
|
292
291
|
|
|
293
292
|
export_utils.export(
|
|
294
293
|
zipping=zipping,
|
|
@@ -524,7 +523,8 @@ def deploy(
|
|
|
524
523
|
dependency.check_requirements()
|
|
525
524
|
|
|
526
525
|
# Check if we are set up.
|
|
527
|
-
prerequisites.
|
|
526
|
+
if prerequisites.needs_reinit(frontend=True):
|
|
527
|
+
_init(name=config.app_name, loglevel=loglevel)
|
|
528
528
|
prerequisites.check_latest_package_version(constants.ReflexHostingCLI.MODULE_NAME)
|
|
529
529
|
|
|
530
530
|
hosting_cli.deploy(
|
|
@@ -565,20 +565,6 @@ def demo(
|
|
|
565
565
|
# Open the demo app in a terminal.
|
|
566
566
|
webbrowser.open("https://demo.reflex.run")
|
|
567
567
|
|
|
568
|
-
# Later: open the demo app locally.
|
|
569
|
-
# with tempfile.TemporaryDirectory() as tmp_dir:
|
|
570
|
-
# os.chdir(tmp_dir)
|
|
571
|
-
# _init(
|
|
572
|
-
# name="reflex_demo",
|
|
573
|
-
# template=constants.Templates.Kind.DEMO,
|
|
574
|
-
# loglevel=constants.LogLevel.DEBUG,
|
|
575
|
-
# )
|
|
576
|
-
# _run(
|
|
577
|
-
# frontend_port=frontend_port,
|
|
578
|
-
# backend_port=backend_port,
|
|
579
|
-
# loglevel=constants.LogLevel.DEBUG,
|
|
580
|
-
# )
|
|
581
|
-
|
|
582
568
|
|
|
583
569
|
cli.add_typer(db_cli, name="db", help="Subcommands for managing the database schema.")
|
|
584
570
|
cli.add_typer(script_cli, name="script", help="Subcommands running helper scripts.")
|
reflex/style.py
CHANGED
|
@@ -22,7 +22,7 @@ color_mode_var_data = VarData( # type: ignore
|
|
|
22
22
|
"react": {ImportVar(tag="useContext")},
|
|
23
23
|
},
|
|
24
24
|
hooks={
|
|
25
|
-
f"const [ {constants.ColorMode.NAME}, {constants.ColorMode.TOGGLE} ] = useContext(ColorModeContext)",
|
|
25
|
+
f"const [ {constants.ColorMode.NAME}, {constants.ColorMode.TOGGLE} ] = useContext(ColorModeContext)": None,
|
|
26
26
|
},
|
|
27
27
|
)
|
|
28
28
|
# Var resolves to the current color mode for the app ("light" or "dark")
|
|
@@ -240,9 +240,9 @@ def format_as_emotion(style_dict: dict[str, Any]) -> Style | None:
|
|
|
240
240
|
if isinstance(value, list):
|
|
241
241
|
# Apply media queries from responsive value list.
|
|
242
242
|
mbps = {
|
|
243
|
-
media_query(bp):
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
media_query(bp): (
|
|
244
|
+
bp_value if isinstance(bp_value, dict) else {key: bp_value}
|
|
245
|
+
)
|
|
246
246
|
for bp, bp_value in enumerate(value)
|
|
247
247
|
}
|
|
248
248
|
if key.startswith("&:"):
|
reflex/testing.py
CHANGED
|
@@ -223,7 +223,7 @@ class AppHarness:
|
|
|
223
223
|
with chdir(self.app_path):
|
|
224
224
|
reflex.reflex._init(
|
|
225
225
|
name=self.app_name,
|
|
226
|
-
template=reflex.constants.Templates.
|
|
226
|
+
template=reflex.constants.Templates.DEFAULT,
|
|
227
227
|
loglevel=reflex.constants.LogLevel.INFO,
|
|
228
228
|
)
|
|
229
229
|
self.app_module_path.write_text(source_code)
|
reflex/utils/console.py
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import List, Optional
|
|
6
|
-
|
|
7
5
|
from rich.console import Console
|
|
8
6
|
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
|
|
9
7
|
from rich.prompt import Prompt
|
|
@@ -150,7 +148,10 @@ def error(msg: str, **kwargs):
|
|
|
150
148
|
|
|
151
149
|
|
|
152
150
|
def ask(
|
|
153
|
-
question: str,
|
|
151
|
+
question: str,
|
|
152
|
+
choices: list[str] | None = None,
|
|
153
|
+
default: str | None = None,
|
|
154
|
+
show_choices: bool = True,
|
|
154
155
|
) -> str:
|
|
155
156
|
"""Takes a prompt question and optionally a list of choices
|
|
156
157
|
and returns the user input.
|
|
@@ -159,11 +160,12 @@ def ask(
|
|
|
159
160
|
question: The question to ask the user.
|
|
160
161
|
choices: A list of choices to select from.
|
|
161
162
|
default: The default option selected.
|
|
163
|
+
show_choices: Whether to show the choices.
|
|
162
164
|
|
|
163
165
|
Returns:
|
|
164
166
|
A string with the user input.
|
|
165
167
|
"""
|
|
166
|
-
return Prompt.ask(question, choices=choices, default=default) # type: ignore
|
|
168
|
+
return Prompt.ask(question, choices=choices, default=default, show_choices=show_choices) # type: ignore
|
|
167
169
|
|
|
168
170
|
|
|
169
171
|
def progress():
|
reflex/utils/exec.py
CHANGED
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import os
|
|
8
8
|
import platform
|
|
9
9
|
import re
|
|
10
|
+
import subprocess
|
|
10
11
|
import sys
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from urllib.parse import urljoin
|
|
@@ -18,6 +19,9 @@ from reflex.config import get_config
|
|
|
18
19
|
from reflex.utils import console, path_ops
|
|
19
20
|
from reflex.utils.watch import AssetFolderWatch
|
|
20
21
|
|
|
22
|
+
# For uvicorn windows bug fix (#2335)
|
|
23
|
+
frontend_process = None
|
|
24
|
+
|
|
21
25
|
|
|
22
26
|
def start_watching_assets_folder(root):
|
|
23
27
|
"""Start watching assets folder.
|
|
@@ -66,6 +70,9 @@ def kill(proc_pid: int):
|
|
|
66
70
|
process.kill()
|
|
67
71
|
|
|
68
72
|
|
|
73
|
+
# run_process_and_launch_url is assumed to be used
|
|
74
|
+
# only to launch the frontend
|
|
75
|
+
# If this is not the case, might have to change the logic
|
|
69
76
|
def run_process_and_launch_url(run_command: list[str]):
|
|
70
77
|
"""Run the process and launch the URL.
|
|
71
78
|
|
|
@@ -81,9 +88,17 @@ def run_process_and_launch_url(run_command: list[str]):
|
|
|
81
88
|
|
|
82
89
|
while True:
|
|
83
90
|
if process is None:
|
|
91
|
+
kwargs = {}
|
|
92
|
+
if constants.IS_WINDOWS:
|
|
93
|
+
kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore
|
|
84
94
|
process = processes.new_process(
|
|
85
|
-
run_command,
|
|
95
|
+
run_command,
|
|
96
|
+
cwd=constants.Dirs.WEB,
|
|
97
|
+
shell=constants.IS_WINDOWS,
|
|
98
|
+
**kwargs,
|
|
86
99
|
)
|
|
100
|
+
global frontend_process
|
|
101
|
+
frontend_process = process
|
|
87
102
|
if process.stdout:
|
|
88
103
|
for line in processes.stream_logs("Starting frontend", process):
|
|
89
104
|
match = re.search(constants.Next.FRONTEND_LISTENING_REGEX, line)
|
|
@@ -175,6 +190,7 @@ def run_backend(
|
|
|
175
190
|
log_level=loglevel.value,
|
|
176
191
|
reload=True,
|
|
177
192
|
reload_dirs=[config.app_name],
|
|
193
|
+
reload_excludes=[constants.Dirs.WEB],
|
|
178
194
|
)
|
|
179
195
|
|
|
180
196
|
|
reflex/utils/export.py
CHANGED
|
@@ -46,9 +46,6 @@ def export(
|
|
|
46
46
|
# Show system info
|
|
47
47
|
exec.output_system_info()
|
|
48
48
|
|
|
49
|
-
# Check that the app is initialized.
|
|
50
|
-
prerequisites.check_initialized(frontend=frontend)
|
|
51
|
-
|
|
52
49
|
# Compile the app in production mode and export it.
|
|
53
50
|
console.rule("[bold]Compiling production app and preparing for export.")
|
|
54
51
|
|