reflex 0.8.6a0__py3-none-any.whl → 0.8.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/jinja/web/vite.config.js.jinja2 +4 -1
- reflex/.templates/web/app/routes.js +0 -1
- reflex/.templates/web/utils/state.js +1 -11
- reflex/app.py +27 -23
- reflex/components/base/error_boundary.py +2 -0
- reflex/components/component.py +6 -4
- reflex/components/lucide/icon.py +4 -1
- reflex/components/lucide/icon.pyi +4 -1
- reflex/components/plotly/plotly.py +9 -9
- reflex/components/recharts/recharts.py +2 -2
- reflex/components/sonner/toast.py +7 -7
- reflex/components/sonner/toast.pyi +8 -8
- reflex/config.py +9 -2
- reflex/constants/base.py +2 -0
- reflex/constants/installer.py +6 -6
- reflex/constants/state.py +1 -0
- reflex/custom_components/custom_components.py +3 -3
- reflex/istate/manager.py +2 -1
- reflex/plugins/__init__.py +2 -0
- reflex/plugins/_screenshot.py +144 -0
- reflex/plugins/base.py +14 -1
- reflex/reflex.py +7 -6
- reflex/route.py +4 -0
- reflex/state.py +2 -2
- reflex/testing.py +3 -5
- reflex/utils/build.py +21 -3
- reflex/utils/exec.py +11 -11
- reflex/utils/frontend_skeleton.py +254 -0
- reflex/utils/js_runtimes.py +411 -0
- reflex/utils/prerequisites.py +17 -1383
- reflex/utils/rename.py +170 -0
- reflex/utils/telemetry.py +101 -10
- reflex/utils/templates.py +443 -0
- reflex/vars/base.py +3 -3
- {reflex-0.8.6a0.dist-info → reflex-0.8.7a1.dist-info}/METADATA +2 -2
- {reflex-0.8.6a0.dist-info → reflex-0.8.7a1.dist-info}/RECORD +39 -36
- reflex/.templates/web/utils/client_side_routing.js +0 -45
- reflex/components/core/client_side_routing.py +0 -70
- {reflex-0.8.6a0.dist-info → reflex-0.8.7a1.dist-info}/WHEEL +0 -0
- {reflex-0.8.6a0.dist-info → reflex-0.8.7a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.6a0.dist-info → reflex-0.8.7a1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"""This module provides utilities for managing Reflex app templates."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import re
|
|
5
|
+
import shutil
|
|
6
|
+
import tempfile
|
|
7
|
+
import zipfile
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from urllib.parse import urlparse
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
|
|
13
|
+
from reflex import constants
|
|
14
|
+
from reflex.config import get_config
|
|
15
|
+
from reflex.utils import console, net, path_ops, redir
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclasses.dataclass(frozen=True)
|
|
19
|
+
class Template:
|
|
20
|
+
"""A template for a Reflex app."""
|
|
21
|
+
|
|
22
|
+
name: str
|
|
23
|
+
description: str
|
|
24
|
+
code_url: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_config(app_name: str):
|
|
28
|
+
"""Create a new rxconfig file.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
app_name: The name of the app.
|
|
32
|
+
"""
|
|
33
|
+
# Import here to avoid circular imports.
|
|
34
|
+
from reflex.compiler import templates
|
|
35
|
+
|
|
36
|
+
config_name = f"{re.sub(r'[^a-zA-Z]', '', app_name).capitalize()}Config"
|
|
37
|
+
|
|
38
|
+
console.debug(f"Creating {constants.Config.FILE}")
|
|
39
|
+
constants.Config.FILE.write_text(
|
|
40
|
+
templates.RXCONFIG.render(app_name=app_name, config_name=config_name)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def initialize_app_directory(
|
|
45
|
+
app_name: str,
|
|
46
|
+
template_name: str = constants.Templates.DEFAULT,
|
|
47
|
+
template_code_dir_name: str | None = None,
|
|
48
|
+
template_dir: Path | None = None,
|
|
49
|
+
):
|
|
50
|
+
"""Initialize the app directory on reflex init.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
app_name: The name of the app.
|
|
54
|
+
template_name: The name of the template to use.
|
|
55
|
+
template_code_dir_name: The name of the code directory in the template.
|
|
56
|
+
template_dir: The directory of the template source files.
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
Exit: If template_name, template_code_dir_name, template_dir combination is not supported.
|
|
60
|
+
"""
|
|
61
|
+
console.log("Initializing the app directory.")
|
|
62
|
+
|
|
63
|
+
# By default, use the blank template from local assets.
|
|
64
|
+
if template_name == constants.Templates.DEFAULT:
|
|
65
|
+
if template_code_dir_name is not None or template_dir is not None:
|
|
66
|
+
console.error(
|
|
67
|
+
f"Only {template_name=} should be provided, got {template_code_dir_name=}, {template_dir=}."
|
|
68
|
+
)
|
|
69
|
+
raise click.exceptions.Exit(1)
|
|
70
|
+
template_code_dir_name = constants.Templates.Dirs.CODE
|
|
71
|
+
template_dir = Path(constants.Templates.Dirs.BASE, "apps", template_name)
|
|
72
|
+
else:
|
|
73
|
+
if template_code_dir_name is None or template_dir is None:
|
|
74
|
+
console.error(
|
|
75
|
+
f"For `{template_name}` template, `template_code_dir_name` and `template_dir` should both be provided."
|
|
76
|
+
)
|
|
77
|
+
raise click.exceptions.Exit(1)
|
|
78
|
+
|
|
79
|
+
console.debug(f"Using {template_name=} {template_dir=} {template_code_dir_name=}.")
|
|
80
|
+
|
|
81
|
+
# Remove __pycache__ dirs in template directory and current directory.
|
|
82
|
+
for pycache_dir in [
|
|
83
|
+
*template_dir.glob("**/__pycache__"),
|
|
84
|
+
*Path.cwd().glob("**/__pycache__"),
|
|
85
|
+
]:
|
|
86
|
+
shutil.rmtree(pycache_dir, ignore_errors=True)
|
|
87
|
+
|
|
88
|
+
for file in template_dir.iterdir():
|
|
89
|
+
# Copy the file to current directory but keep the name the same.
|
|
90
|
+
path_ops.cp(str(file), file.name)
|
|
91
|
+
|
|
92
|
+
# Rename the template app to the app name.
|
|
93
|
+
path_ops.mv(template_code_dir_name, app_name)
|
|
94
|
+
path_ops.mv(
|
|
95
|
+
Path(app_name) / (template_name + constants.Ext.PY),
|
|
96
|
+
Path(app_name) / (app_name + constants.Ext.PY),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Fix up the imports.
|
|
100
|
+
path_ops.find_replace(
|
|
101
|
+
app_name,
|
|
102
|
+
f"from {template_name}",
|
|
103
|
+
f"from {app_name}",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def initialize_default_app(app_name: str):
|
|
108
|
+
"""Initialize the default app.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
app_name: The name of the app.
|
|
112
|
+
"""
|
|
113
|
+
create_config(app_name)
|
|
114
|
+
initialize_app_directory(app_name)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def create_config_init_app_from_remote_template(app_name: str, template_url: str):
|
|
118
|
+
"""Create new rxconfig and initialize app using a remote template.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
app_name: The name of the app.
|
|
122
|
+
template_url: The path to the template source code as a zip file.
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
Exit: If any download, file operations fail or unexpected zip file format.
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
import httpx
|
|
129
|
+
|
|
130
|
+
# Create a temp directory for the zip download.
|
|
131
|
+
try:
|
|
132
|
+
temp_dir = tempfile.mkdtemp()
|
|
133
|
+
except OSError as ose:
|
|
134
|
+
console.error(f"Failed to create temp directory for download: {ose}")
|
|
135
|
+
raise click.exceptions.Exit(1) from ose
|
|
136
|
+
|
|
137
|
+
# Use httpx GET with redirects to download the zip file.
|
|
138
|
+
zip_file_path: Path = Path(temp_dir) / "template.zip"
|
|
139
|
+
try:
|
|
140
|
+
# Note: following redirects can be risky. We only allow this for reflex built templates at the moment.
|
|
141
|
+
response = net.get(template_url, follow_redirects=True)
|
|
142
|
+
console.debug(f"Server responded download request: {response}")
|
|
143
|
+
response.raise_for_status()
|
|
144
|
+
except httpx.HTTPError as he:
|
|
145
|
+
console.error(f"Failed to download the template: {he}")
|
|
146
|
+
raise click.exceptions.Exit(1) from he
|
|
147
|
+
try:
|
|
148
|
+
zip_file_path.write_bytes(response.content)
|
|
149
|
+
console.debug(f"Downloaded the zip to {zip_file_path}")
|
|
150
|
+
except OSError as ose:
|
|
151
|
+
console.error(f"Unable to write the downloaded zip to disk {ose}")
|
|
152
|
+
raise click.exceptions.Exit(1) from ose
|
|
153
|
+
|
|
154
|
+
# Create a temp directory for the zip extraction.
|
|
155
|
+
try:
|
|
156
|
+
unzip_dir = Path(tempfile.mkdtemp())
|
|
157
|
+
except OSError as ose:
|
|
158
|
+
console.error(f"Failed to create temp directory for extracting zip: {ose}")
|
|
159
|
+
raise click.exceptions.Exit(1) from ose
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
zipfile.ZipFile(zip_file_path).extractall(path=unzip_dir)
|
|
163
|
+
# The zip file downloaded from github looks like:
|
|
164
|
+
# repo-name-branch/**/*, so we need to remove the top level directory.
|
|
165
|
+
except Exception as uze:
|
|
166
|
+
console.error(f"Failed to unzip the template: {uze}")
|
|
167
|
+
raise click.exceptions.Exit(1) from uze
|
|
168
|
+
|
|
169
|
+
if len(subdirs := list(unzip_dir.iterdir())) != 1:
|
|
170
|
+
console.error(f"Expected one directory in the zip, found {subdirs}")
|
|
171
|
+
raise click.exceptions.Exit(1)
|
|
172
|
+
|
|
173
|
+
template_dir = unzip_dir / subdirs[0]
|
|
174
|
+
console.debug(f"Template folder is located at {template_dir}")
|
|
175
|
+
|
|
176
|
+
# Move the rxconfig file here first.
|
|
177
|
+
path_ops.mv(str(template_dir / constants.Config.FILE), constants.Config.FILE)
|
|
178
|
+
new_config = get_config(reload=True)
|
|
179
|
+
|
|
180
|
+
# Get the template app's name from rxconfig in case it is different than
|
|
181
|
+
# the source code repo name on github.
|
|
182
|
+
template_name = new_config.app_name
|
|
183
|
+
|
|
184
|
+
create_config(app_name)
|
|
185
|
+
initialize_app_directory(
|
|
186
|
+
app_name,
|
|
187
|
+
template_name=template_name,
|
|
188
|
+
template_code_dir_name=template_name,
|
|
189
|
+
template_dir=template_dir,
|
|
190
|
+
)
|
|
191
|
+
req_file = Path("requirements.txt")
|
|
192
|
+
if req_file.exists() and len(req_file.read_text().splitlines()) > 1:
|
|
193
|
+
console.info(
|
|
194
|
+
"Run `pip install -r requirements.txt` to install the required python packages for this template."
|
|
195
|
+
)
|
|
196
|
+
# Clean up the temp directories.
|
|
197
|
+
shutil.rmtree(temp_dir)
|
|
198
|
+
shutil.rmtree(unzip_dir)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def validate_and_create_app_using_remote_template(
|
|
202
|
+
app_name: str, template: str, templates: dict[str, Template]
|
|
203
|
+
):
|
|
204
|
+
"""Validate and create an app using a remote template.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
app_name: The name of the app.
|
|
208
|
+
template: The name of the template.
|
|
209
|
+
templates: The available templates.
|
|
210
|
+
|
|
211
|
+
Raises:
|
|
212
|
+
Exit: If the template is not found.
|
|
213
|
+
"""
|
|
214
|
+
# If user selects a template, it needs to exist.
|
|
215
|
+
if template in templates:
|
|
216
|
+
from reflex_cli.v2.utils import hosting
|
|
217
|
+
|
|
218
|
+
authenticated_token = hosting.authenticated_token()
|
|
219
|
+
if not authenticated_token or not authenticated_token[0]:
|
|
220
|
+
console.print(
|
|
221
|
+
f"Please use `reflex login` to access the '{template}' template."
|
|
222
|
+
)
|
|
223
|
+
raise click.exceptions.Exit(3)
|
|
224
|
+
|
|
225
|
+
template_url = templates[template].code_url
|
|
226
|
+
else:
|
|
227
|
+
template_parsed_url = urlparse(template)
|
|
228
|
+
# Check if the template is a github repo.
|
|
229
|
+
if template_parsed_url.hostname == "github.com":
|
|
230
|
+
path = template_parsed_url.path.strip("/").removesuffix(".git")
|
|
231
|
+
template_url = f"https://github.com/{path}/archive/main.zip"
|
|
232
|
+
else:
|
|
233
|
+
console.error(f"Template `{template}` not found or invalid.")
|
|
234
|
+
raise click.exceptions.Exit(1)
|
|
235
|
+
|
|
236
|
+
if template_url is None:
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
create_config_init_app_from_remote_template(
|
|
240
|
+
app_name=app_name, template_url=template_url
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def fetch_app_templates(version: str) -> dict[str, Template]:
|
|
245
|
+
"""Fetch a dict of templates from the templates repo using github API.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
version: The version of the templates to fetch.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
The dict of templates.
|
|
252
|
+
"""
|
|
253
|
+
|
|
254
|
+
def get_release_by_tag(tag: str) -> dict | None:
|
|
255
|
+
response = net.get(constants.Reflex.RELEASES_URL)
|
|
256
|
+
response.raise_for_status()
|
|
257
|
+
releases = response.json()
|
|
258
|
+
for release in releases:
|
|
259
|
+
if release["tag_name"] == f"v{tag}":
|
|
260
|
+
return release
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
release = get_release_by_tag(version)
|
|
264
|
+
if release is None:
|
|
265
|
+
console.warn(f"No templates known for version {version}")
|
|
266
|
+
return {}
|
|
267
|
+
|
|
268
|
+
assets = release.get("assets", [])
|
|
269
|
+
asset = next((a for a in assets if a["name"] == "templates.json"), None)
|
|
270
|
+
if asset is None:
|
|
271
|
+
console.warn(f"Templates metadata not found for version {version}")
|
|
272
|
+
return {}
|
|
273
|
+
templates_url = asset["browser_download_url"]
|
|
274
|
+
|
|
275
|
+
templates_data = net.get(templates_url, follow_redirects=True).json()["templates"]
|
|
276
|
+
|
|
277
|
+
for template in templates_data:
|
|
278
|
+
if template["name"] == "blank":
|
|
279
|
+
template["code_url"] = ""
|
|
280
|
+
continue
|
|
281
|
+
template["code_url"] = next(
|
|
282
|
+
(
|
|
283
|
+
a["browser_download_url"]
|
|
284
|
+
for a in assets
|
|
285
|
+
if a["name"] == f"{template['name']}.zip"
|
|
286
|
+
),
|
|
287
|
+
None,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
filtered_templates = {}
|
|
291
|
+
for tp in templates_data:
|
|
292
|
+
if tp["hidden"] or tp["code_url"] is None:
|
|
293
|
+
continue
|
|
294
|
+
known_fields = {f.name for f in dataclasses.fields(Template)}
|
|
295
|
+
filtered_templates[tp["name"]] = Template(
|
|
296
|
+
**{k: v for k, v in tp.items() if k in known_fields}
|
|
297
|
+
)
|
|
298
|
+
return filtered_templates
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def fetch_remote_templates(
|
|
302
|
+
template: str,
|
|
303
|
+
) -> tuple[str, dict[str, Template]]:
|
|
304
|
+
"""Fetch the available remote templates.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
template: The name of the template.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
The selected template and the available templates.
|
|
311
|
+
"""
|
|
312
|
+
available_templates = {}
|
|
313
|
+
|
|
314
|
+
try:
|
|
315
|
+
# Get the available templates
|
|
316
|
+
available_templates = fetch_app_templates(constants.Reflex.VERSION)
|
|
317
|
+
except Exception as e:
|
|
318
|
+
console.warn("Failed to fetch templates. Falling back to default template.")
|
|
319
|
+
console.debug(f"Error while fetching templates: {e}")
|
|
320
|
+
template = constants.Templates.DEFAULT
|
|
321
|
+
|
|
322
|
+
return template, available_templates
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def prompt_for_template_options(templates: list[Template]) -> str:
|
|
326
|
+
"""Prompt the user to specify a template.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
templates: The templates to choose from.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
The template name the user selects.
|
|
333
|
+
|
|
334
|
+
Raises:
|
|
335
|
+
Exit: If the user does not select a template.
|
|
336
|
+
"""
|
|
337
|
+
# Show the user the URLs of each template to preview.
|
|
338
|
+
console.print("\nGet started with a template:")
|
|
339
|
+
|
|
340
|
+
# Prompt the user to select a template.
|
|
341
|
+
for index, template in enumerate(templates):
|
|
342
|
+
console.print(f"({index}) {template.description}")
|
|
343
|
+
|
|
344
|
+
template = console.ask(
|
|
345
|
+
"Which template would you like to use?",
|
|
346
|
+
choices=[str(i) for i in range(len(templates))],
|
|
347
|
+
show_choices=False,
|
|
348
|
+
default="0",
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
if not template:
|
|
352
|
+
console.error("No template selected.")
|
|
353
|
+
raise click.exceptions.Exit(1)
|
|
354
|
+
|
|
355
|
+
try:
|
|
356
|
+
template_index = int(template)
|
|
357
|
+
except ValueError:
|
|
358
|
+
console.error("Invalid template selected.")
|
|
359
|
+
raise click.exceptions.Exit(1) from None
|
|
360
|
+
|
|
361
|
+
if template_index < 0 or template_index >= len(templates):
|
|
362
|
+
console.error("Invalid template selected.")
|
|
363
|
+
raise click.exceptions.Exit(1)
|
|
364
|
+
|
|
365
|
+
# Return the template.
|
|
366
|
+
return templates[template_index].name
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def initialize_app(app_name: str, template: str | None = None) -> str | None:
|
|
370
|
+
"""Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
app_name: The name of the app.
|
|
374
|
+
template: The name of the template to use.
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
The name of the template.
|
|
378
|
+
|
|
379
|
+
Raises:
|
|
380
|
+
Exit: If the template is not valid or unspecified.
|
|
381
|
+
"""
|
|
382
|
+
# Local imports to avoid circular imports.
|
|
383
|
+
from reflex.utils import telemetry
|
|
384
|
+
|
|
385
|
+
# Check if the app is already initialized.
|
|
386
|
+
if constants.Config.FILE.exists():
|
|
387
|
+
telemetry.send("reinit")
|
|
388
|
+
return None
|
|
389
|
+
|
|
390
|
+
templates: dict[str, Template] = {}
|
|
391
|
+
|
|
392
|
+
# Don't fetch app templates if the user directly asked for DEFAULT.
|
|
393
|
+
if template is not None and (template not in (constants.Templates.DEFAULT,)):
|
|
394
|
+
template, templates = fetch_remote_templates(template)
|
|
395
|
+
|
|
396
|
+
if template is None:
|
|
397
|
+
template = prompt_for_template_options(get_init_cli_prompt_options())
|
|
398
|
+
|
|
399
|
+
if template == constants.Templates.CHOOSE_TEMPLATES:
|
|
400
|
+
redir.reflex_templates()
|
|
401
|
+
raise click.exceptions.Exit(0)
|
|
402
|
+
|
|
403
|
+
if template == constants.Templates.AI:
|
|
404
|
+
redir.reflex_build_redirect()
|
|
405
|
+
raise click.exceptions.Exit(0)
|
|
406
|
+
|
|
407
|
+
# If the blank template is selected, create a blank app.
|
|
408
|
+
if template == constants.Templates.DEFAULT:
|
|
409
|
+
# Default app creation behavior: a blank app.
|
|
410
|
+
initialize_default_app(app_name)
|
|
411
|
+
else:
|
|
412
|
+
validate_and_create_app_using_remote_template(
|
|
413
|
+
app_name=app_name, template=template, templates=templates
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
telemetry.send("init", template=template)
|
|
417
|
+
|
|
418
|
+
return template
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def get_init_cli_prompt_options() -> list[Template]:
|
|
422
|
+
"""Get the CLI options for initializing a Reflex app.
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
The CLI options.
|
|
426
|
+
"""
|
|
427
|
+
return [
|
|
428
|
+
Template(
|
|
429
|
+
name=constants.Templates.DEFAULT,
|
|
430
|
+
description="A blank Reflex app.",
|
|
431
|
+
code_url="",
|
|
432
|
+
),
|
|
433
|
+
Template(
|
|
434
|
+
name=constants.Templates.AI,
|
|
435
|
+
description="[bold]Try our free AI builder.",
|
|
436
|
+
code_url="",
|
|
437
|
+
),
|
|
438
|
+
Template(
|
|
439
|
+
name=constants.Templates.CHOOSE_TEMPLATES,
|
|
440
|
+
description="Premade templates built by the Reflex team.",
|
|
441
|
+
code_url="",
|
|
442
|
+
),
|
|
443
|
+
]
|
reflex/vars/base.py
CHANGED
|
@@ -717,7 +717,7 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
|
|
|
717
717
|
return f"{constants.REFLEX_VAR_OPENING_TAG}{hashed_var}{constants.REFLEX_VAR_CLOSING_TAG}{self._js_expr}"
|
|
718
718
|
|
|
719
719
|
@overload
|
|
720
|
-
def to(self, output: type[str]) -> StringVar: ...
|
|
720
|
+
def to(self, output: type[str]) -> StringVar: ... # pyright: ignore[reportOverlappingOverload]
|
|
721
721
|
|
|
722
722
|
@overload
|
|
723
723
|
def to(self, output: type[bool]) -> BooleanVar: ...
|
|
@@ -734,8 +734,8 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
|
|
|
734
734
|
@overload
|
|
735
735
|
def to(
|
|
736
736
|
self,
|
|
737
|
-
output: type[
|
|
738
|
-
) -> ArrayVar: ...
|
|
737
|
+
output: type[SEQUENCE_TYPE],
|
|
738
|
+
) -> ArrayVar[SEQUENCE_TYPE]: ...
|
|
739
739
|
|
|
740
740
|
@overload
|
|
741
741
|
def to(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.7a1
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Project-URL: homepage, https://reflex.dev
|
|
6
6
|
Project-URL: repository, https://github.com/reflex-dev/reflex
|
|
@@ -30,7 +30,7 @@ Requires-Dist: pydantic<3.0,>=1.10.21
|
|
|
30
30
|
Requires-Dist: python-multipart<1.0,>=0.0.20
|
|
31
31
|
Requires-Dist: python-socketio<6.0,>=5.12.0
|
|
32
32
|
Requires-Dist: redis<7.0,>=5.2.1
|
|
33
|
-
Requires-Dist: reflex-hosting-cli>=0.1.
|
|
33
|
+
Requires-Dist: reflex-hosting-cli>=0.1.54
|
|
34
34
|
Requires-Dist: rich<15,>=13
|
|
35
35
|
Requires-Dist: sqlmodel<0.1,>=0.0.24
|
|
36
36
|
Requires-Dist: starlette>=0.47.0
|