187 lines
4.7 KiB
Python
187 lines
4.7 KiB
Python
"""Everything regarding execution of the built app."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from rich import print
|
|
|
|
from pynecone import constants
|
|
from pynecone.config import get_config
|
|
from pynecone.utils import console, prerequisites, processes
|
|
from pynecone.utils.watch import AssetFolderWatch
|
|
|
|
|
|
def start_watching_assets_folder(root):
|
|
"""Start watching assets folder.
|
|
|
|
Args:
|
|
root: root path of the project.
|
|
"""
|
|
asset_watch = AssetFolderWatch(root)
|
|
asset_watch.start()
|
|
|
|
|
|
def run_process_and_launch_url(
|
|
run_command: list[str],
|
|
loglevel: constants.LogLevel = constants.LogLevel.ERROR,
|
|
):
|
|
"""Run the process and launch the URL.
|
|
|
|
Args:
|
|
run_command: The command to run.
|
|
loglevel: The log level to use.
|
|
"""
|
|
process = subprocess.Popen(
|
|
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()
|
|
if process.stdout:
|
|
for line in process.stdout:
|
|
if "ready started server on" in line:
|
|
url = line.split("url: ")[-1].strip()
|
|
print(f"App running at: [bold green]{url}")
|
|
if (
|
|
"Fast Refresh" in line
|
|
or "compiling..." in line
|
|
and (datetime.now() - current_time).total_seconds() > 1
|
|
):
|
|
current_time = datetime.now()
|
|
print(
|
|
f"[yellow][Updating App][/yellow] Applying changes and refreshing. Time: {current_time}"
|
|
)
|
|
elif loglevel == constants.LogLevel.DEBUG:
|
|
print(line, end="")
|
|
|
|
|
|
def run_frontend(
|
|
root: Path,
|
|
port: str,
|
|
loglevel: constants.LogLevel = constants.LogLevel.ERROR,
|
|
):
|
|
"""Run the frontend.
|
|
|
|
Args:
|
|
root: The root path of the project.
|
|
port: The port to run the frontend on.
|
|
loglevel: The log level to use.
|
|
"""
|
|
# Start watching asset folder.
|
|
start_watching_assets_folder(root)
|
|
|
|
# Run the frontend in development mode.
|
|
console.rule("[bold green]App Running")
|
|
os.environ["PORT"] = get_config().frontend_port if port is None else port
|
|
run_process_and_launch_url(
|
|
[prerequisites.get_package_manager(), "run", "dev"], loglevel
|
|
)
|
|
|
|
|
|
def run_frontend_prod(
|
|
root: Path,
|
|
port: str,
|
|
loglevel: constants.LogLevel = constants.LogLevel.ERROR,
|
|
):
|
|
"""Run the frontend.
|
|
|
|
Args:
|
|
root: The root path of the project (to keep same API as run_frontend).
|
|
port: The port to run the frontend on.
|
|
loglevel: The log level to use.
|
|
"""
|
|
# Set the port.
|
|
os.environ["PORT"] = get_config().frontend_port if port is None else port
|
|
|
|
# Run the frontend in production mode.
|
|
console.rule("[bold green]App Running")
|
|
run_process_and_launch_url(
|
|
[prerequisites.get_package_manager(), "run", "prod"], loglevel
|
|
)
|
|
|
|
|
|
def run_backend(
|
|
app_name: str,
|
|
host: str,
|
|
port: int,
|
|
loglevel: constants.LogLevel = constants.LogLevel.ERROR,
|
|
):
|
|
"""Run the backend.
|
|
|
|
Args:
|
|
host: The app host
|
|
app_name: The app name.
|
|
port: The app port
|
|
loglevel: The log level.
|
|
"""
|
|
cmd = [
|
|
"uvicorn",
|
|
f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}",
|
|
"--host",
|
|
host,
|
|
"--port",
|
|
str(port),
|
|
"--log-level",
|
|
loglevel,
|
|
"--reload",
|
|
]
|
|
process = subprocess.Popen(cmd)
|
|
|
|
try:
|
|
process.wait()
|
|
except KeyboardInterrupt:
|
|
process.terminate()
|
|
|
|
|
|
def run_backend_prod(
|
|
app_name: str,
|
|
host: str,
|
|
port: int,
|
|
loglevel: constants.LogLevel = constants.LogLevel.ERROR,
|
|
):
|
|
"""Run the backend.
|
|
|
|
Args:
|
|
host: The app host
|
|
app_name: The app name.
|
|
port: The app port
|
|
loglevel: The log level.
|
|
"""
|
|
num_workers = processes.get_num_workers()
|
|
command = (
|
|
[
|
|
*constants.RUN_BACKEND_PROD_WINDOWS,
|
|
"--host",
|
|
host,
|
|
"--port",
|
|
str(port),
|
|
f"{app_name}:{constants.APP_VAR}",
|
|
]
|
|
if platform.system() == "Windows"
|
|
else [
|
|
*constants.RUN_BACKEND_PROD,
|
|
"--bind",
|
|
f"{host}:{port}",
|
|
"--threads",
|
|
str(num_workers),
|
|
f"{app_name}:{constants.APP_VAR}()",
|
|
]
|
|
)
|
|
|
|
command += [
|
|
"--log-level",
|
|
loglevel.value,
|
|
"--workers",
|
|
str(num_workers),
|
|
]
|
|
subprocess.run(command)
|