Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fnm and node for POSIX #1606

Merged
merged 34 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
14b260f
refactor to use PlaftormDirs for windows
ElijahAhianyo Aug 14, 2023
25a61f8
lint
ElijahAhianyo Aug 14, 2023
b408e30
fix imports
ElijahAhianyo Aug 14, 2023
8b81568
Fnm and Node for Posix
ElijahAhianyo Aug 16, 2023
e064d3b
fix tests
ElijahAhianyo Aug 17, 2023
7723e79
Take out nvm
ElijahAhianyo Aug 17, 2023
2c234ae
Testing docker
ElijahAhianyo Aug 18, 2023
41f6867
debugging CI
ElijahAhianyo Aug 21, 2023
76e139e
rebase
ElijahAhianyo Aug 21, 2023
efd191c
rebase
ElijahAhianyo Aug 21, 2023
23cc9f9
Revert "rebase"
ElijahAhianyo Aug 21, 2023
e8b9dd0
Revert "rebase"
ElijahAhianyo Aug 21, 2023
c87faea
refactor
ElijahAhianyo Aug 21, 2023
4392e66
fix tests
ElijahAhianyo Aug 21, 2023
ced65d0
fix tests
ElijahAhianyo Aug 21, 2023
7a7b3b8
add comments
ElijahAhianyo Aug 21, 2023
0bb51df
make bun directory visible for consistency
ElijahAhianyo Aug 21, 2023
d4b507d
fix race condition
ElijahAhianyo Aug 22, 2023
261eeef
fix tests
ElijahAhianyo Aug 22, 2023
41b97ba
debugging ci
ElijahAhianyo Aug 22, 2023
d95802e
removed debug lines
ElijahAhianyo Aug 22, 2023
27226fb
punctuation
ElijahAhianyo Aug 22, 2023
7cdd515
punctuation
ElijahAhianyo Aug 22, 2023
cb3e7a2
punctuation
ElijahAhianyo Aug 22, 2023
11eb6bd
punctuation
ElijahAhianyo Aug 22, 2023
1da0a5f
punctuation
ElijahAhianyo Aug 22, 2023
3c9b81e
resolve pr comments
ElijahAhianyo Aug 24, 2023
bcca4d0
use node on host system for platforms outside macOS, Linux, Windows
ElijahAhianyo Aug 24, 2023
898864c
fix based on comments
ElijahAhianyo Aug 24, 2023
89e0c92
Merge branch 'main' into elijah/posix_fnm
ElijahAhianyo Aug 24, 2023
3618f53
refactor
ElijahAhianyo Aug 24, 2023
b71c9a3
set None path values to ""
ElijahAhianyo Aug 24, 2023
ac5b662
handle exception
ElijahAhianyo Aug 24, 2023
78584be
add annotaions
ElijahAhianyo Aug 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions reflex/utils/exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import sys
from pathlib import Path

import typer

from reflex import constants
from reflex.config import get_config
from reflex.utils import console, path_ops, prerequisites, processes
Expand Down Expand Up @@ -53,14 +55,31 @@ def run_frontend(
Args:
root: The root path of the project.
port: The port to run the frontend on.

Raises:
Exit: If the package manager is invalid.
"""
# Start watching asset folder.
start_watching_assets_folder(root)
package_manager = prerequisites.get_package_manager()

if not package_manager:
console.error(
"Could not find NPM package manager. Make sure you have node installed."
)
raise typer.Exit(1)

if not prerequisites.check_node_version():
node_version = prerequisites.get_node_version()
console.error(
f"Reflex requires node version {constants.NODE_VERSION_MIN} or higher to run, but the detected version is {node_version}",
)
raise typer.Exit(1)

# Run the frontend in development mode.
console.rule("[bold green]App Running")
os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
run_process_and_launch_url([prerequisites.get_package_manager(), "run", "dev"])
run_process_and_launch_url([package_manager, "run", "dev"])


def run_frontend_prod(
Expand All @@ -72,13 +91,28 @@ def run_frontend_prod(
Args:
root: The root path of the project (to keep same API as run_frontend).
port: The port to run the frontend on.

Raises:
Exit: If the package manager is invalid.
"""
# Set the port.
os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
package_manager = prerequisites.get_package_manager()
if not package_manager:
console.error(
"Could not find NPM package manager. Make sure you have node installed."
)
raise typer.Exit(1)

if not prerequisites.check_node_version():
node_version = prerequisites.get_node_version()
console.error(
f"Reflex requires node version {constants.NODE_VERSION_MIN} or higher to run, but the detected version is {node_version}",
)
raise typer.Exit(1)
ElijahAhianyo marked this conversation as resolved.
Show resolved Hide resolved
# Run the frontend in production mode.
console.rule("[bold green]App Running")
run_process_and_launch_url([prerequisites.get_package_manager(), "run", "prod"])
run_process_and_launch_url([package_manager, "run", "prod"])


def run_backend(
Expand Down Expand Up @@ -178,7 +212,7 @@ def output_system_info():

dependencies = [
f"[Reflex {constants.VERSION} with Python {platform.python_version()} (PATH: {sys.executable})]",
f"[Node {prerequisites.get_node_version()} (Expected: {constants.NODE_VERSION}) (PATH:{constants.NODE_PATH})]",
f"[Node {prerequisites.get_node_version()} (Expected: {constants.NODE_VERSION}) (PATH:{path_ops.get_node_path()})]",
]

system = platform.system()
Expand Down Expand Up @@ -208,8 +242,8 @@ def output_system_info():
console.debug(f"{dep}")

console.debug(
f"Using package installer at: {prerequisites.get_install_package_manager()}"
f"Using package installer at: {prerequisites.get_install_package_manager()}" # type: ignore
)
console.debug(f"Using package executer at: {prerequisites.get_package_manager()}")
console.debug(f"Using package executer at: {prerequisites.get_package_manager()}") # type: ignore
if system != "Windows":
console.debug(f"Unzip path: {path_ops.which('unzip')}")
37 changes: 37 additions & 0 deletions reflex/utils/path_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

import os
import shutil
from pathlib import Path
from typing import Optional

from reflex import constants

# Shorthand for join.
join = os.linesep.join

Expand Down Expand Up @@ -107,3 +110,37 @@ def which(program: str) -> Optional[str]:
The path to the executable.
"""
return shutil.which(program)


def get_node_bin_path() -> Optional[str]:
"""Get the node binary dir path.

Returns:
The path to the node bin folder.
"""
if not os.path.exists(constants.NODE_BIN_PATH):
str_path = which("node")
return str(Path(str_path).parent) if str_path else str_path
return constants.NODE_BIN_PATH


def get_node_path():
"""Get the node binary path.

Returns:
The path to the node binary file.
"""
if not os.path.exists(constants.NODE_PATH):
return which("node")
return constants.NODE_PATH


def get_npm_path():
"""Get npm binary path.

Returns:
The path to the npm binary file.
"""
if not os.path.exists(constants.NODE_PATH):
return which("npm")
return constants.NPM_PATH
12 changes: 6 additions & 6 deletions reflex/utils/prerequisites.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get_node_version() -> Optional[version.Version]:
The version of node.
"""
try:
result = processes.new_process([constants.NODE_PATH, "-v"], run=True)
result = processes.new_process([path_ops.get_node_path(), "-v"], run=True)
# The output will be in the form "vX.Y.Z", but version.parse() can handle it
return version.parse(result.stdout) # type: ignore
except FileNotFoundError:
Expand All @@ -71,7 +71,7 @@ def get_bun_version() -> Optional[version.Version]:
return None


def get_install_package_manager() -> str:
def get_install_package_manager() -> Optional[str]:
"""Get the package manager executable for installation.
Currently on unix systems, bun is used for installation only.

Expand All @@ -80,20 +80,20 @@ def get_install_package_manager() -> str:
"""
# On Windows, we use npm instead of bun.
if constants.IS_WINDOWS:
return constants.NPM_PATH
return path_ops.get_npm_path()

# On other platforms, we use bun.
return get_config().bun_path


def get_package_manager() -> str:
def get_package_manager() -> Optional[str]:
"""Get the package manager executable for running app.
Currently on unix systems, npm is used for running the app only.

Returns:
The path to the package manager.
"""
return constants.NPM_PATH
return path_ops.get_npm_path()


def get_app() -> ModuleType:
Expand Down Expand Up @@ -275,7 +275,7 @@ def download_and_extract_fnm_zip():
# Download the zip file
url = constants.FNM_INSTALL_URL
console.debug(f"Downloading {url}")
fnm_zip_file = os.sep.join([constants.FNM_DIR, f"{constants.FNM_FILENAME}.zip"])
fnm_zip_file = os.path.join(constants.FNM_DIR, f"{constants.FNM_FILENAME}.zip")
# Function to download and extract the FNM zip release.
try:
# Download the FNM zip release.
Expand Down
11 changes: 8 additions & 3 deletions reflex/utils/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
import psutil
import typer

from reflex import constants
from reflex.utils import console, prerequisites
from reflex.utils import console, path_ops, prerequisites


def kill(pid):
Expand Down Expand Up @@ -126,10 +125,16 @@ def new_process(args, run: bool = False, show_logs: bool = False, **kwargs):
Returns:
Execute a child program in a new process.
"""
node_bin_path = path_ops.get_node_bin_path()
if not node_bin_path:
console.warn(
"The path to the Node binary could not be found. Please ensure that Node is properly "
"installed and added to your system's PATH environment variable."
)
# Add the node bin path to the PATH environment variable.
env = {
**os.environ,
"PATH": os.pathsep.join([constants.NODE_BIN_PATH, os.environ["PATH"]]),
"PATH": os.pathsep.join([node_bin_path, os.environ["PATH"]]), # type: ignore
**kwargs.pop("env", {}),
}
kwargs = {
Expand Down