Speed up reflex CLI imports (#2185)

This commit is contained in:
Nikhil Rao 2023-11-17 12:31:07 -08:00 committed by GitHub
parent 1a83f85783
commit c3e652b8c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 55 deletions

View File

@ -16,21 +16,11 @@ from typing import List, Optional
import typer import typer
import typer.core import typer.core
from alembic.util.exc import CommandError
from tabulate import tabulate from tabulate import tabulate
from reflex import constants, model from reflex import constants
from reflex.config import get_config from reflex.config import get_config
from reflex.utils import ( from reflex.utils import console, dependency, telemetry
build,
console,
dependency,
exec,
hosting,
prerequisites,
processes,
telemetry,
)
# Disable typer+rich integration for help panels # Disable typer+rich integration for help panels
typer.core.rich = False # type: ignore typer.core.rich = False # type: ignore
@ -81,6 +71,8 @@ def _init(
loglevel: constants.LogLevel = config.loglevel, loglevel: constants.LogLevel = config.loglevel,
): ):
"""Initialize a new Reflex app in the given directory.""" """Initialize a new Reflex app in the given directory."""
from reflex.utils import exec, prerequisites
# Set the log level. # Set the log level.
console.set_log_level(loglevel) console.set_log_level(loglevel)
@ -138,12 +130,14 @@ def _run(
env: constants.Env = constants.Env.DEV, env: constants.Env = constants.Env.DEV,
frontend: bool = True, frontend: bool = True,
backend: bool = True, backend: bool = True,
frontend_port: str = str(get_config().frontend_port), frontend_port: str = str(config.frontend_port),
backend_port: str = str(get_config().backend_port), backend_port: str = str(config.backend_port),
backend_host: str = config.backend_host, backend_host: str = config.backend_host,
loglevel: constants.LogLevel = config.loglevel, loglevel: constants.LogLevel = config.loglevel,
): ):
"""Run the app in the given directory.""" """Run the app in the given directory."""
from reflex.utils import build, exec, prerequisites, processes
# Set the log level. # Set the log level.
console.set_log_level(loglevel) console.set_log_level(loglevel)
@ -279,10 +273,12 @@ def export(
hidden=True, hidden=True,
), ),
loglevel: constants.LogLevel = typer.Option( loglevel: constants.LogLevel = typer.Option(
console._LOG_LEVEL, help="The log level to use." config.loglevel, help="The log level to use."
), ),
): ):
"""Export the app to a zip file.""" """Export the app to a zip file."""
from reflex.utils import build, exec, prerequisites
# Set the log level. # Set the log level.
console.set_log_level(loglevel) console.set_log_level(loglevel)
@ -324,6 +320,8 @@ def login(
), ),
): ):
"""Authenticate with Reflex hosting service.""" """Authenticate with Reflex hosting service."""
from reflex.utils import hosting
# Set the log level. # Set the log level.
console.set_log_level(loglevel) console.set_log_level(loglevel)
@ -349,6 +347,8 @@ def logout(
), ),
): ):
"""Log out of access to Reflex hosting service.""" """Log out of access to Reflex hosting service."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
hosting.log_out_on_browser() hosting.log_out_on_browser()
@ -367,6 +367,9 @@ def _skip_compile():
@db_cli.command(name="init") @db_cli.command(name="init")
def db_init(): def db_init():
"""Create database schema and migration configuration.""" """Create database schema and migration configuration."""
from reflex import model
from reflex.utils import prerequisites
# Check the database url. # Check the database url.
if config.db_url is None: if config.db_url is None:
console.error("db_url is not configured, cannot initialize.") console.error("db_url is not configured, cannot initialize.")
@ -392,6 +395,9 @@ def db_init():
@db_cli.command() @db_cli.command()
def migrate(): def migrate():
"""Create or update database schema from migration scripts.""" """Create or update database schema from migration scripts."""
from reflex import model
from reflex.utils import prerequisites
_skip_compile() _skip_compile()
prerequisites.get_app() prerequisites.get_app()
if not prerequisites.check_db_initialized(): if not prerequisites.check_db_initialized():
@ -407,6 +413,11 @@ def makemigrations(
), ),
): ):
"""Create autogenerated alembic migration scripts.""" """Create autogenerated alembic migration scripts."""
from alembic.util.exc import CommandError
from reflex import model
from reflex.utils import prerequisites
_skip_compile() _skip_compile()
prerequisites.get_app() prerequisites.get_app()
if not prerequisites.check_db_initialized(): if not prerequisites.check_db_initialized():
@ -493,6 +504,8 @@ def deploy(
), ),
): ):
"""Deploy the app to the Reflex hosting service.""" """Deploy the app to the Reflex hosting service."""
from reflex.utils import hosting, prerequisites
# Set the log level. # Set the log level.
console.set_log_level(loglevel) console.set_log_level(loglevel)
@ -732,6 +745,8 @@ def list_deployments(
), ),
): ):
"""List all the hosted deployments of the authenticated user.""" """List all the hosted deployments of the authenticated user."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
try: try:
deployments = hosting.list_deployments() deployments = hosting.list_deployments()
@ -759,6 +774,8 @@ def delete_deployment(
), ),
): ):
"""Delete a hosted instance.""" """Delete a hosted instance."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
try: try:
hosting.delete_deployment(key) hosting.delete_deployment(key)
@ -776,6 +793,8 @@ def get_deployment_status(
), ),
): ):
"""Check the status of a deployment.""" """Check the status of a deployment."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
try: try:
@ -812,6 +831,8 @@ def get_deployment_logs(
), ),
): ):
"""Get the logs for a deployment.""" """Get the logs for a deployment."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
console.print("Note: there is a few seconds delay for logs to be available.") console.print("Note: there is a few seconds delay for logs to be available.")
try: try:
@ -829,6 +850,8 @@ def get_deployment_build_logs(
), ),
): ):
"""Get the logs for a deployment.""" """Get the logs for a deployment."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
console.print("Note: there is a few seconds delay for logs to be available.") console.print("Note: there is a few seconds delay for logs to be available.")
@ -852,6 +875,8 @@ def get_deployment_regions(
), ),
): ):
"""List all the regions of the hosting service.""" """List all the regions of the hosting service."""
from reflex.utils import hosting
console.set_log_level(loglevel) console.set_log_level(loglevel)
list_regions_info = hosting.get_regions() list_regions_info = hosting.get_regions()
if as_json: if as_json:

View File

@ -12,11 +12,10 @@ from pathlib import Path
from urllib.parse import urljoin from urllib.parse import urljoin
import psutil import psutil
import uvicorn
from reflex import constants from reflex import constants
from reflex.config import get_config from reflex.config import get_config
from reflex.utils import console, path_ops, prerequisites, processes from reflex.utils import console, path_ops
from reflex.utils.watch import AssetFolderWatch from reflex.utils.watch import AssetFolderWatch
@ -73,6 +72,8 @@ def run_process_and_launch_url(run_command: list[str]):
Args: Args:
run_command: The command to run. run_command: The command to run.
""" """
from reflex.utils import processes
json_file_path = os.path.join(constants.Dirs.WEB, "package.json") json_file_path = os.path.join(constants.Dirs.WEB, "package.json")
last_hash = detect_package_change(json_file_path) last_hash = detect_package_change(json_file_path)
process = None process = None
@ -113,6 +114,8 @@ def run_frontend(root: Path, port: str):
root: The root path of the project. root: The root path of the project.
port: The port to run the frontend on. port: The port to run the frontend on.
""" """
from reflex.utils import prerequisites
# Start watching asset folder. # Start watching asset folder.
start_watching_assets_folder(root) start_watching_assets_folder(root)
# validate dependencies before run # validate dependencies before run
@ -131,6 +134,8 @@ def run_frontend_prod(root: Path, port: str):
root: The root path of the project (to keep same API as run_frontend). root: The root path of the project (to keep same API as run_frontend).
port: The port to run the frontend on. port: The port to run the frontend on.
""" """
from reflex.utils import prerequisites
# Set the port. # Set the port.
os.environ["PORT"] = str(get_config().frontend_port if port is None else port) os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
# validate dependencies before run # validate dependencies before run
@ -152,6 +157,8 @@ def run_backend(
port: The app port port: The app port
loglevel: The log level. loglevel: The log level.
""" """
import uvicorn
config = get_config() config = get_config()
app_module = f"{config.app_name}.{config.app_name}:{constants.CompileVars.APP}" app_module = f"{config.app_name}.{config.app_name}:{constants.CompileVars.APP}"
@ -183,6 +190,8 @@ def run_backend_prod(
port: The app port port: The app port
loglevel: The log level. loglevel: The log level.
""" """
from reflex.utils import processes
num_workers = processes.get_num_workers() num_workers = processes.get_num_workers()
config = get_config() config = get_config()
RUN_BACKEND_PROD = f"gunicorn --worker-class {config.gunicorn_worker_class} --preload --timeout {config.timeout} --log-level critical".split() RUN_BACKEND_PROD = f"gunicorn --worker-class {config.gunicorn_worker_class} --preload --timeout {config.timeout} --log-level critical".split()
@ -227,6 +236,8 @@ def output_system_info():
if console._LOG_LEVEL > constants.LogLevel.DEBUG: if console._LOG_LEVEL > constants.LogLevel.DEBUG:
return return
from reflex.utils import prerequisites
config = get_config() config = get_config()
try: try:
config_file = sys.modules[config.__module__].__file__ config_file = sys.modules[config.__module__].__file__

View File

@ -7,12 +7,9 @@ import multiprocessing
import platform import platform
from datetime import datetime from datetime import datetime
import httpx
import psutil import psutil
from reflex import constants from reflex import constants
from reflex.base import Base
from reflex.config import get_config
def get_os() -> str: def get_os() -> str:
@ -60,16 +57,6 @@ def get_memory() -> int:
return psutil.virtual_memory().total >> 20 return psutil.virtual_memory().total >> 20
class Telemetry(Base):
"""Anonymous telemetry for Reflex."""
user_os: str = get_os()
cpu_count: int = get_cpu_count()
memory: int = get_memory()
reflex_version: str = get_reflex_version()
python_version: str = get_python_version()
def send(event: str, telemetry_enabled: bool | None = None) -> bool: def send(event: str, telemetry_enabled: bool | None = None) -> bool:
"""Send anonymous telemetry for Reflex. """Send anonymous telemetry for Reflex.
@ -80,6 +67,10 @@ def send(event: str, telemetry_enabled: bool | None = None) -> bool:
Returns: Returns:
Whether the telemetry was sent successfully. Whether the telemetry was sent successfully.
""" """
import httpx
from reflex.config import get_config
# Get the telemetry_enabled from the config if it is not specified. # Get the telemetry_enabled from the config if it is not specified.
if telemetry_enabled is None: if telemetry_enabled is None:
telemetry_enabled = get_config().telemetry_enabled telemetry_enabled = get_config().telemetry_enabled
@ -89,7 +80,6 @@ def send(event: str, telemetry_enabled: bool | None = None) -> bool:
return False return False
try: try:
telemetry = Telemetry()
with open(constants.Dirs.REFLEX_JSON) as f: with open(constants.Dirs.REFLEX_JSON) as f:
reflex_json = json.load(f) reflex_json = json.load(f)
distinct_id = reflex_json["project_hash"] distinct_id = reflex_json["project_hash"]
@ -98,11 +88,11 @@ def send(event: str, telemetry_enabled: bool | None = None) -> bool:
"event": event, "event": event,
"properties": { "properties": {
"distinct_id": distinct_id, "distinct_id": distinct_id,
"user_os": telemetry.user_os, "user_os": get_os(),
"reflex_version": telemetry.reflex_version, "reflex_version": get_reflex_version(),
"python_version": telemetry.python_version, "python_version": get_python_version(),
"cpu_count": telemetry.cpu_count, "cpu_count": get_cpu_count(),
"memory": telemetry.memory, "memory": get_memory(),
}, },
"timestamp": datetime.utcnow().isoformat(), "timestamp": datetime.utcnow().isoformat(),
} }

View File

@ -1,5 +1,3 @@
import json
from reflex.utils import telemetry from reflex.utils import telemetry
@ -9,32 +7,24 @@ def versiontuple(v):
def test_telemetry(): def test_telemetry():
"""Test that telemetry is sent correctly.""" """Test that telemetry is sent correctly."""
tel = telemetry.Telemetry()
# Check that the user OS is one of the supported operating systems. # Check that the user OS is one of the supported operating systems.
assert tel.user_os is not None user_os = telemetry.get_os()
assert tel.user_os in ["Linux", "Darwin", "Java", "Windows"] assert user_os is not None
assert user_os in ["Linux", "Darwin", "Java", "Windows"]
# Check that the CPU count and memory are greater than 0. # Check that the CPU count and memory are greater than 0.
assert tel.cpu_count > 0 assert telemetry.get_cpu_count() > 0
# Check that the available memory is greater than 0 # Check that the available memory is greater than 0
assert tel.memory > 0 assert telemetry.get_memory() > 0
# Check that the Reflex version is not None. # Check that the Reflex version is not None.
assert tel.reflex_version is not None assert telemetry.get_reflex_version() is not None
# Check that the Python version is greater than 3.7. # Check that the Python version is greater than 3.7.
assert tel.python_version is not None python_version = telemetry.get_python_version()
assert versiontuple(tel.python_version) >= versiontuple("3.7") assert python_version is not None
assert versiontuple(python_version) >= versiontuple("3.7")
# Check the json method.
tel_json = json.loads(tel.json())
assert tel_json["user_os"] == tel.user_os
assert tel_json["cpu_count"] == tel.cpu_count
assert tel_json["memory"] == tel.memory
assert tel_json["reflex_version"] == tel.reflex_version
assert tel_json["python_version"] == tel.python_version
def test_disable(): def test_disable():