Browse Source

Unify the launch of child processes (#1250)

Sergei Ozeranskii 1 year ago
parent
commit
1dfe76c4a3
3 changed files with 31 additions and 14 deletions
  1. 3 8
      reflex/utils/build.py
  2. 3 6
      reflex/utils/exec.py
  3. 25 0
      reflex/utils/processes.py

+ 3 - 8
reflex/utils/build.py

@@ -14,6 +14,7 @@ from rich.progress import Progress
 from reflex import constants
 from reflex.config import get_config
 from reflex.utils import path_ops, prerequisites
+from reflex.utils.processes import new_process
 
 
 def update_json_file(file_path: str, update_dict: dict[str, Union[int, str]]):
@@ -115,13 +116,9 @@ def export_app(
     task = progress.add_task("Building app... ", total=500)
 
     # Start the subprocess with the progress bar.
-    with progress, subprocess.Popen(
+    with progress, new_process(
         [prerequisites.get_package_manager(), "run", "export"],
         cwd=constants.WEB_DIR,
-        env=os.environ,
-        stderr=subprocess.STDOUT,
-        stdout=subprocess.PIPE,  # Redirect stdout to a pipe
-        universal_newlines=True,  # Set universal_newlines to True for text mode
     ) as export_process:
         assert export_process.stdout is not None, "No stdout for export process."
         for line in export_process.stdout:
@@ -216,7 +213,7 @@ def setup_frontend(
 
     # Disable the Next telemetry.
     if disable_telemetry:
-        subprocess.Popen(
+        new_process(
             [
                 prerequisites.get_package_manager(),
                 "run",
@@ -225,9 +222,7 @@ def setup_frontend(
                 "disable",
             ],
             cwd=constants.WEB_DIR,
-            env=os.environ,
             stdout=subprocess.DEVNULL,
-            stderr=subprocess.STDOUT,
         )
 
 

+ 3 - 6
reflex/utils/exec.py

@@ -13,6 +13,7 @@ from rich import print
 from reflex import constants
 from reflex.config import get_config
 from reflex.utils import console, prerequisites, processes
+from reflex.utils.processes import new_process
 from reflex.utils.watch import AssetFolderWatch
 
 
@@ -36,13 +37,9 @@ def run_process_and_launch_url(
         run_command: The command to run.
         loglevel: The log level to use.
     """
-    process = subprocess.Popen(
+    process = new_process(
         run_command,
         cwd=constants.WEB_DIR,
-        env=os.environ,
-        stderr=subprocess.STDOUT,
-        stdout=None if platform.system() == "Windows" else subprocess.PIPE,
-        universal_newlines=None if platform.system() == "Windows" else True,
     )
 
     current_time = datetime.now()
@@ -134,7 +131,7 @@ def run_backend(
         loglevel,
         "--reload",
     ]
-    process = subprocess.Popen(cmd)
+    process = new_process(cmd)
 
     try:
         process.wait()

+ 25 - 0
reflex/utils/processes.py

@@ -5,6 +5,7 @@ from __future__ import annotations
 import contextlib
 import os
 import signal
+import subprocess
 import sys
 from typing import Optional
 from urllib.parse import urlparse
@@ -120,3 +121,27 @@ def change_or_terminate_port(port, _type) -> str:
     else:
         console.print("Exiting...")
         sys.exit()
+
+
+def new_process(args, **kwargs):
+    """Wrapper over subprocess.Popen to unify the launch of child processes.
+
+    Args:
+        args: A string, or a sequence of program arguments.
+        **kwargs: Kwargs to override default wrap values to pass to subprocess.Popen as arguments.
+
+    Returns:
+        Execute a child program in a new process.
+    """
+    kwargs = {
+        "env": os.environ,
+        "stderr": subprocess.STDOUT,
+        "stdout": subprocess.PIPE,  # Redirect stdout to a pipe
+        "universal_newlines": True,  # Set universal_newlines to True for text mode
+        "encoding": "UTF-8",
+        **kwargs,
+    }
+    return subprocess.Popen(
+        args,
+        **kwargs,
+    )