|
@@ -2,6 +2,7 @@
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
+import functools
|
|
|
import glob
|
|
|
import importlib
|
|
|
import inspect
|
|
@@ -49,6 +50,14 @@ class Template(Base):
|
|
|
demo_url: str
|
|
|
|
|
|
|
|
|
+class CpuInfo(Base):
|
|
|
+ """Model to save cpu info."""
|
|
|
+
|
|
|
+ manufacturer_id: Optional[str]
|
|
|
+ model_name: Optional[str]
|
|
|
+ address_width: Optional[int]
|
|
|
+
|
|
|
+
|
|
|
def check_latest_package_version(package_name: str):
|
|
|
"""Check if the latest version of the package is installed.
|
|
|
|
|
@@ -172,7 +181,7 @@ def get_install_package_manager() -> str | None:
|
|
|
Returns:
|
|
|
The path to the package manager.
|
|
|
"""
|
|
|
- if constants.IS_WINDOWS and not constants.IS_WINDOWS_BUN_SUPPORTED_MACHINE:
|
|
|
+ if constants.IS_WINDOWS and not is_windows_bun_supported():
|
|
|
return get_package_manager()
|
|
|
return get_config().bun_path
|
|
|
|
|
@@ -728,7 +737,7 @@ def install_bun():
|
|
|
Raises:
|
|
|
FileNotFoundError: If required packages are not found.
|
|
|
"""
|
|
|
- if constants.IS_WINDOWS and not constants.IS_WINDOWS_BUN_SUPPORTED_MACHINE:
|
|
|
+ if constants.IS_WINDOWS and not is_windows_bun_supported():
|
|
|
console.warn(
|
|
|
"Bun for Windows is currently only available for x86 64-bit Windows. Installation will fall back on npm."
|
|
|
)
|
|
@@ -833,7 +842,7 @@ def install_frontend_packages(packages: set[str], config: Config):
|
|
|
get_package_manager()
|
|
|
if not constants.IS_WINDOWS
|
|
|
or constants.IS_WINDOWS
|
|
|
- and constants.IS_WINDOWS_BUN_SUPPORTED_MACHINE
|
|
|
+ and is_windows_bun_supported()
|
|
|
else None
|
|
|
)
|
|
|
processes.run_process_with_fallback(
|
|
@@ -1418,3 +1427,92 @@ def initialize_app(app_name: str, template: str | None = None):
|
|
|
)
|
|
|
|
|
|
telemetry.send("init", template=template)
|
|
|
+
|
|
|
+
|
|
|
+def format_address_width(address_width) -> int | None:
|
|
|
+ """Cast address width to an int.
|
|
|
+
|
|
|
+ Args:
|
|
|
+ address_width: The address width.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ Address width int
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ return int(address_width) if address_width else None
|
|
|
+ except ValueError:
|
|
|
+ return None
|
|
|
+
|
|
|
+
|
|
|
+@functools.lru_cache(maxsize=None)
|
|
|
+def get_cpu_info() -> CpuInfo | None:
|
|
|
+ """Get the CPU info of the underlining host.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ The CPU info.
|
|
|
+ """
|
|
|
+ platform_os = platform.system()
|
|
|
+ cpuinfo = {}
|
|
|
+ try:
|
|
|
+ if platform_os == "Windows":
|
|
|
+ cmd = "wmic cpu get addresswidth,caption,manufacturer /FORMAT:csv"
|
|
|
+ output = processes.execute_command_and_return_output(cmd)
|
|
|
+ if output:
|
|
|
+ val = output.splitlines()[-1].split(",")[1:]
|
|
|
+ cpuinfo["manufacturer_id"] = val[2]
|
|
|
+ cpuinfo["model_name"] = val[1].split("Family")[0].strip()
|
|
|
+ cpuinfo["address_width"] = format_address_width(val[0])
|
|
|
+ elif platform_os == "Linux":
|
|
|
+ output = processes.execute_command_and_return_output("lscpu")
|
|
|
+ if output:
|
|
|
+ lines = output.split("\n")
|
|
|
+ for line in lines:
|
|
|
+ if "Architecture" in line:
|
|
|
+ cpuinfo["address_width"] = (
|
|
|
+ 64 if line.split(":")[1].strip() == "x86_64" else 32
|
|
|
+ )
|
|
|
+ if "Vendor ID:" in line:
|
|
|
+ cpuinfo["manufacturer_id"] = line.split(":")[1].strip()
|
|
|
+ if "Model name" in line:
|
|
|
+ cpuinfo["model_name"] = line.split(":")[1].strip()
|
|
|
+ elif platform_os == "Darwin":
|
|
|
+ cpuinfo["address_width"] = format_address_width(
|
|
|
+ processes.execute_command_and_return_output("getconf LONG_BIT")
|
|
|
+ )
|
|
|
+ cpuinfo["manufacturer_id"] = processes.execute_command_and_return_output(
|
|
|
+ "sysctl -n machdep.cpu.brand_string"
|
|
|
+ )
|
|
|
+ cpuinfo["model_name"] = processes.execute_command_and_return_output(
|
|
|
+ "uname -m"
|
|
|
+ )
|
|
|
+ except Exception as err:
|
|
|
+ console.error(f"Failed to retrieve CPU info. {err}")
|
|
|
+ return None
|
|
|
+
|
|
|
+ return (
|
|
|
+ CpuInfo(
|
|
|
+ manufacturer_id=cpuinfo.get("manufacturer_id"),
|
|
|
+ model_name=cpuinfo.get("model_name"),
|
|
|
+ address_width=cpuinfo.get("address_width"),
|
|
|
+ )
|
|
|
+ if cpuinfo
|
|
|
+ else None
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+@functools.lru_cache(maxsize=None)
|
|
|
+def is_windows_bun_supported() -> bool:
|
|
|
+ """Check whether the underlining host running windows qualifies to run bun.
|
|
|
+ We typically do not run bun on ARM or 32 bit devices that use windows.
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ Whether the host is qualified to use bun.
|
|
|
+ """
|
|
|
+ cpu_info = get_cpu_info()
|
|
|
+ return (
|
|
|
+ constants.IS_WINDOWS
|
|
|
+ and cpu_info is not None
|
|
|
+ and cpu_info.address_width == 64
|
|
|
+ and cpu_info.model_name is not None
|
|
|
+ and "ARM" not in cpu_info.model_name
|
|
|
+ )
|