reflex 0.2.2a1__py3-none-any.whl → 0.2.3__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/utils/build.py CHANGED
@@ -9,12 +9,9 @@ import subprocess
9
9
  from pathlib import Path
10
10
  from typing import Optional, Union
11
11
 
12
- from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
13
-
14
12
  from reflex import constants
15
13
  from reflex.config import get_config
16
- from reflex.utils import console, path_ops, prerequisites
17
- from reflex.utils.processes import new_process
14
+ from reflex.utils import console, path_ops, prerequisites, processes
18
15
 
19
16
 
20
17
  def update_json_file(file_path: str, update_dict: dict[str, Union[int, str]]):
@@ -39,7 +36,9 @@ def update_json_file(file_path: str, update_dict: dict[str, Union[int, str]]):
39
36
 
40
37
  def set_reflex_project_hash():
41
38
  """Write the hash of the Reflex project to a REFLEX_JSON."""
42
- update_json_file(constants.REFLEX_JSON, {"project_hash": random.getrandbits(128)})
39
+ project_hash = random.getrandbits(128)
40
+ console.debug(f"Setting project hash to {project_hash}.")
41
+ update_json_file(constants.REFLEX_JSON, {"project_hash": project_hash})
43
42
 
44
43
 
45
44
  def set_environment_variables():
@@ -86,21 +85,19 @@ def generate_sitemap_config(deploy_url: str):
86
85
  f.write(templates.SITEMAP_CONFIG(config=config))
87
86
 
88
87
 
89
- def export_app(
88
+ def export(
90
89
  backend: bool = True,
91
90
  frontend: bool = True,
92
91
  zip: bool = False,
93
92
  deploy_url: Optional[str] = None,
94
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
95
93
  ):
96
- """Zip up the app for deployment.
94
+ """Export the app for deployment.
97
95
 
98
96
  Args:
99
97
  backend: Whether to zip up the backend app.
100
98
  frontend: Whether to zip up the frontend app.
101
99
  zip: Whether to zip the app.
102
100
  deploy_url: The URL of the deployed app.
103
- loglevel: The log level to use.
104
101
  """
105
102
  # Remove the static folder.
106
103
  path_ops.rm(constants.WEB_STATIC_DIR)
@@ -111,13 +108,6 @@ def export_app(
111
108
  generate_sitemap_config(deploy_url)
112
109
  command = "export-sitemap"
113
110
 
114
- # Create a progress object
115
- progress = Progress(
116
- *Progress.get_default_columns()[:-1],
117
- MofNCompleteColumn(),
118
- TimeElapsedColumn(),
119
- )
120
-
121
111
  checkpoints = [
122
112
  "Linting and checking ",
123
113
  "Compiled successfully",
@@ -130,36 +120,12 @@ def export_app(
130
120
  "Export successful",
131
121
  ]
132
122
 
133
- # Add a single task to the progress object
134
- task = progress.add_task("Creating Production Build: ", total=len(checkpoints))
135
-
136
123
  # Start the subprocess with the progress bar.
137
- try:
138
- with progress, new_process(
139
- [prerequisites.get_package_manager(), "run", command],
140
- cwd=constants.WEB_DIR,
141
- ) as export_process:
142
- assert export_process.stdout is not None, "No stdout for export process."
143
- for line in export_process.stdout:
144
- if loglevel == constants.LogLevel.DEBUG:
145
- print(line, end="")
146
-
147
- # Check for special strings and update the progress bar.
148
- for special_string in checkpoints:
149
- if special_string in line:
150
- if special_string == "Export successful":
151
- progress.update(task, completed=len(checkpoints))
152
- break # Exit the loop if the completion message is found
153
- else:
154
- progress.update(task, advance=1)
155
- break
156
-
157
- except Exception as e:
158
- console.print(f"[red]Export process errored: {e}")
159
- console.print(
160
- "[red]Run in with [bold]--loglevel debug[/bold] to see the full error."
161
- )
162
- os._exit(1)
124
+ process = processes.new_process(
125
+ [prerequisites.get_package_manager(), "run", command],
126
+ cwd=constants.WEB_DIR,
127
+ )
128
+ processes.show_progress("Creating Production Build", process, checkpoints)
163
129
 
164
130
  # Zip up the app.
165
131
  if zip:
@@ -203,24 +169,16 @@ def posix_export(backend: bool = True, frontend: bool = True):
203
169
 
204
170
  def setup_frontend(
205
171
  root: Path,
206
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
207
172
  disable_telemetry: bool = True,
208
173
  ):
209
- """Set up the frontend.
174
+ """Set up the frontend to run the app.
210
175
 
211
176
  Args:
212
177
  root: The root path of the project.
213
- loglevel: The log level to use.
214
178
  disable_telemetry: Whether to disable the Next telemetry.
215
179
  """
216
- # Validate bun version.
217
- prerequisites.validate_and_install_bun(initialize=False)
218
-
219
- # Initialize the web directory if it doesn't exist.
220
- web_dir = prerequisites.create_web_directory(root)
221
-
222
180
  # Install frontend packages.
223
- prerequisites.install_frontend_packages(web_dir)
181
+ prerequisites.install_frontend_packages()
224
182
 
225
183
  # Copy asset files to public folder.
226
184
  path_ops.cp(
@@ -228,12 +186,12 @@ def setup_frontend(
228
186
  dest=str(root / constants.WEB_ASSETS_DIR),
229
187
  )
230
188
 
231
- # set the environment variables in client(env.json)
189
+ # Set the environment variables in client (env.json).
232
190
  set_environment_variables()
233
191
 
234
192
  # Disable the Next telemetry.
235
193
  if disable_telemetry:
236
- new_process(
194
+ processes.new_process(
237
195
  [
238
196
  prerequisites.get_package_manager(),
239
197
  "run",
@@ -248,15 +206,13 @@ def setup_frontend(
248
206
 
249
207
  def setup_frontend_prod(
250
208
  root: Path,
251
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
252
209
  disable_telemetry: bool = True,
253
210
  ):
254
211
  """Set up the frontend for prod mode.
255
212
 
256
213
  Args:
257
214
  root: The root path of the project.
258
- loglevel: The log level to use.
259
215
  disable_telemetry: Whether to disable the Next telemetry.
260
216
  """
261
- setup_frontend(root, loglevel, disable_telemetry)
262
- export_app(loglevel=loglevel, deploy_url=get_config().deploy_url)
217
+ setup_frontend(root, disable_telemetry)
218
+ export(deploy_url=get_config().deploy_url)
reflex/utils/console.py CHANGED
@@ -5,47 +5,123 @@ from __future__ import annotations
5
5
  from typing import List, Optional
6
6
 
7
7
  from rich.console import Console
8
+ from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
8
9
  from rich.prompt import Prompt
9
- from rich.status import Status
10
+
11
+ from reflex.constants import LogLevel
10
12
 
11
13
  # Console for pretty printing.
12
14
  _console = Console()
13
15
 
16
+ # The current log level.
17
+ LOG_LEVEL = LogLevel.INFO
14
18
 
15
- def deprecate(msg: str) -> None:
16
- """Print a deprecation warning.
19
+
20
+ def set_log_level(log_level: LogLevel):
21
+ """Set the log level.
17
22
 
18
23
  Args:
19
- msg: The deprecation message.
24
+ log_level: The log level to set.
20
25
  """
21
- _console.print(f"[yellow]DeprecationWarning: {msg}[/yellow]")
26
+ global LOG_LEVEL
27
+ LOG_LEVEL = log_level
22
28
 
23
29
 
24
- def log(msg: str) -> None:
25
- """Takes a string and logs it to the console.
30
+ def print(msg: str, **kwargs):
31
+ """Print a message.
26
32
 
27
33
  Args:
28
- msg: The message to log.
34
+ msg: The message to print.
35
+ kwargs: Keyword arguments to pass to the print function.
29
36
  """
30
- _console.log(msg)
37
+ _console.print(msg, **kwargs)
31
38
 
32
39
 
33
- def print(msg: str) -> None:
34
- """Prints the given message to the console.
40
+ def debug(msg: str, **kwargs):
41
+ """Print a debug message.
35
42
 
36
43
  Args:
37
- msg: The message to print to the console.
44
+ msg: The debug message.
45
+ kwargs: Keyword arguments to pass to the print function.
46
+ """
47
+ if LOG_LEVEL <= LogLevel.DEBUG:
48
+ print(f"[blue]Debug: {msg}[/blue]", **kwargs)
49
+
50
+
51
+ def info(msg: str, **kwargs):
52
+ """Print an info message.
53
+
54
+ Args:
55
+ msg: The info message.
56
+ kwargs: Keyword arguments to pass to the print function.
57
+ """
58
+ if LOG_LEVEL <= LogLevel.INFO:
59
+ print(f"[cyan]Info: {msg}[/cyan]", **kwargs)
60
+
61
+
62
+ def success(msg: str, **kwargs):
63
+ """Print a success message.
64
+
65
+ Args:
66
+ msg: The success message.
67
+ kwargs: Keyword arguments to pass to the print function.
68
+ """
69
+ if LOG_LEVEL <= LogLevel.INFO:
70
+ print(f"[green]Success: {msg}[/green]", **kwargs)
71
+
72
+
73
+ def log(msg: str, **kwargs):
74
+ """Takes a string and logs it to the console.
75
+
76
+ Args:
77
+ msg: The message to log.
78
+ kwargs: Keyword arguments to pass to the print function.
38
79
  """
39
- _console.print(msg)
80
+ if LOG_LEVEL <= LogLevel.INFO:
81
+ _console.log(msg, **kwargs)
40
82
 
41
83
 
42
- def rule(title: str) -> None:
84
+ def rule(title: str, **kwargs):
43
85
  """Prints a horizontal rule with a title.
44
86
 
45
87
  Args:
46
88
  title: The title of the rule.
89
+ kwargs: Keyword arguments to pass to the print function.
47
90
  """
48
- _console.rule(title)
91
+ _console.rule(title, **kwargs)
92
+
93
+
94
+ def warn(msg: str, **kwargs):
95
+ """Print a warning message.
96
+
97
+ Args:
98
+ msg: The warning message.
99
+ kwargs: Keyword arguments to pass to the print function.
100
+ """
101
+ if LOG_LEVEL <= LogLevel.WARNING:
102
+ print(f"[orange1]Warning: {msg}[/orange1]", **kwargs)
103
+
104
+
105
+ def deprecate(msg: str, **kwargs):
106
+ """Print a deprecation warning.
107
+
108
+ Args:
109
+ msg: The deprecation message.
110
+ kwargs: Keyword arguments to pass to the print function.
111
+ """
112
+ if LOG_LEVEL <= LogLevel.WARNING:
113
+ print(f"[yellow]DeprecationWarning: {msg}[/yellow]", **kwargs)
114
+
115
+
116
+ def error(msg: str, **kwargs):
117
+ """Print an error message.
118
+
119
+ Args:
120
+ msg: The error message.
121
+ kwargs: Keyword arguments to pass to the print function.
122
+ """
123
+ if LOG_LEVEL <= LogLevel.ERROR:
124
+ print(f"[red]Error: {msg}[/red]", **kwargs)
49
125
 
50
126
 
51
127
  def ask(
@@ -60,19 +136,33 @@ def ask(
60
136
  default: The default option selected.
61
137
 
62
138
  Returns:
63
- A string
139
+ A string with the user input.
64
140
  """
65
141
  return Prompt.ask(question, choices=choices, default=default) # type: ignore
66
142
 
67
143
 
68
- def status(msg: str) -> Status:
69
- """Returns a status,
70
- which can be used as a context manager.
144
+ def progress():
145
+ """Create a new progress bar.
146
+
147
+
148
+ Returns:
149
+ A new progress bar.
150
+ """
151
+ return Progress(
152
+ *Progress.get_default_columns()[:-1],
153
+ MofNCompleteColumn(),
154
+ TimeElapsedColumn(),
155
+ )
156
+
157
+
158
+ def status(*args, **kwargs):
159
+ """Create a status with a spinner.
71
160
 
72
161
  Args:
73
- msg: The message to be used as status title.
162
+ *args: Args to pass to the status.
163
+ **kwargs: Kwargs to pass to the status.
74
164
 
75
165
  Returns:
76
- The status of the console.
166
+ A new status.
77
167
  """
78
- return _console.status(msg)
168
+ return _console.status(*args, **kwargs)
reflex/utils/exec.py CHANGED
@@ -3,16 +3,11 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
- import platform
7
- import subprocess
8
6
  from pathlib import Path
9
7
 
10
- from rich import print
11
-
12
8
  from reflex import constants
13
9
  from reflex.config import get_config
14
10
  from reflex.utils import console, prerequisites, processes
15
- from reflex.utils.processes import new_process
16
11
  from reflex.utils.watch import AssetFolderWatch
17
12
 
18
13
 
@@ -28,15 +23,13 @@ def start_watching_assets_folder(root):
28
23
 
29
24
  def run_process_and_launch_url(
30
25
  run_command: list[str],
31
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
32
26
  ):
33
27
  """Run the process and launch the URL.
34
28
 
35
29
  Args:
36
30
  run_command: The command to run.
37
- loglevel: The log level to use.
38
31
  """
39
- process = new_process(
32
+ process = processes.new_process(
40
33
  run_command,
41
34
  cwd=constants.WEB_DIR,
42
35
  )
@@ -45,22 +38,20 @@ def run_process_and_launch_url(
45
38
  for line in process.stdout:
46
39
  if "ready started server on" in line:
47
40
  url = line.split("url: ")[-1].strip()
48
- print(f"App running at: [bold green]{url}")
49
- if loglevel == constants.LogLevel.DEBUG:
50
- print(line, end="")
41
+ console.print(f"App running at: [bold green]{url}")
42
+ else:
43
+ console.debug(line)
51
44
 
52
45
 
53
46
  def run_frontend(
54
47
  root: Path,
55
48
  port: str,
56
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
57
49
  ):
58
50
  """Run the frontend.
59
51
 
60
52
  Args:
61
53
  root: The root path of the project.
62
54
  port: The port to run the frontend on.
63
- loglevel: The log level to use.
64
55
  """
65
56
  # Start watching asset folder.
66
57
  start_watching_assets_folder(root)
@@ -68,31 +59,25 @@ def run_frontend(
68
59
  # Run the frontend in development mode.
69
60
  console.rule("[bold green]App Running")
70
61
  os.environ["PORT"] = get_config().frontend_port if port is None else port
71
- run_process_and_launch_url(
72
- [prerequisites.get_package_manager(), "run", "dev"], loglevel
73
- )
62
+ run_process_and_launch_url([prerequisites.get_package_manager(), "run", "dev"])
74
63
 
75
64
 
76
65
  def run_frontend_prod(
77
66
  root: Path,
78
67
  port: str,
79
- loglevel: constants.LogLevel = constants.LogLevel.ERROR,
80
68
  ):
81
69
  """Run the frontend.
82
70
 
83
71
  Args:
84
72
  root: The root path of the project (to keep same API as run_frontend).
85
73
  port: The port to run the frontend on.
86
- loglevel: The log level to use.
87
74
  """
88
75
  # Set the port.
89
76
  os.environ["PORT"] = get_config().frontend_port if port is None else port
90
77
 
91
78
  # Run the frontend in production mode.
92
79
  console.rule("[bold green]App Running")
93
- run_process_and_launch_url(
94
- [prerequisites.get_package_manager(), "run", "prod"], loglevel
95
- )
80
+ run_process_and_launch_url([constants.NPM_PATH, "run", "prod"])
96
81
 
97
82
 
98
83
  def run_backend(
@@ -109,25 +94,23 @@ def run_backend(
109
94
  port: The app port
110
95
  loglevel: The log level.
111
96
  """
112
- cmd = [
113
- "uvicorn",
114
- f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}",
115
- "--host",
116
- host,
117
- "--port",
118
- str(port),
119
- "--log-level",
120
- loglevel,
121
- "--reload",
122
- "--reload-dir",
123
- app_name.split(".")[0],
124
- ]
125
- process = subprocess.Popen(cmd)
126
-
127
- try:
128
- process.wait()
129
- except KeyboardInterrupt:
130
- process.terminate()
97
+ processes.new_process(
98
+ [
99
+ "uvicorn",
100
+ f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}",
101
+ "--host",
102
+ host,
103
+ "--port",
104
+ str(port),
105
+ "--log-level",
106
+ loglevel,
107
+ "--reload",
108
+ "--reload-dir",
109
+ app_name.split(".")[0],
110
+ ],
111
+ run=True,
112
+ show_logs=True,
113
+ )
131
114
 
132
115
 
133
116
  def run_backend_prod(
@@ -154,7 +137,7 @@ def run_backend_prod(
154
137
  str(port),
155
138
  f"{app_name}:{constants.APP_VAR}",
156
139
  ]
157
- if platform.system() == "Windows"
140
+ if prerequisites.IS_WINDOWS
158
141
  else [
159
142
  *constants.RUN_BACKEND_PROD,
160
143
  "--bind",
@@ -171,4 +154,4 @@ def run_backend_prod(
171
154
  "--workers",
172
155
  str(num_workers),
173
156
  ]
174
- subprocess.run(command)
157
+ processes.new_process(command, run=True, show_logs=True)
reflex/utils/format.py CHANGED
@@ -6,6 +6,7 @@ import base64
6
6
  import io
7
7
  import json
8
8
  import os
9
+ import os.path as op
9
10
  import re
10
11
  import sys
11
12
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type
@@ -460,6 +461,24 @@ def format_dict(prop: ComponentStyle) -> str:
460
461
  return fprop
461
462
 
462
463
 
464
+ def format_breadcrumbs(route: str) -> list[tuple[str, str]]:
465
+ """Take a route and return a list of tuple for use in breadcrumb.
466
+
467
+ Args:
468
+ route: The route to transform.
469
+
470
+ Returns:
471
+ list[tuple[str, str]]: the list of tuples for the breadcrumb.
472
+ """
473
+ route_parts = route.lstrip("/").split("/")
474
+
475
+ # create and return breadcrumbs
476
+ return [
477
+ (part, op.join("/", *route_parts[: i + 1]))
478
+ for i, part in enumerate(route_parts)
479
+ ]
480
+
481
+
463
482
  def json_dumps(obj: Any) -> str:
464
483
  """Takes an object and returns a jsonified string.
465
484
 
reflex/utils/imports.py CHANGED
@@ -9,7 +9,7 @@ ImportDict = Dict[str, Set[ImportVar]]
9
9
 
10
10
 
11
11
  def merge_imports(*imports) -> ImportDict:
12
- """Merge two import dicts together.
12
+ """Merge multiple import dicts together.
13
13
 
14
14
  Args:
15
15
  *imports: The list of import dicts to merge.