mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-17 10:15:27 -04:00
fix(setup): clear error when setup runs under x86/Rosetta Python (#941)
Add a check_arch() guard that fails fast with actionable guidance when setup runs on Apple Silicon under an Intel (x86_64) Python via Rosetta — otherwise compiled deps (bcrypt, pydantic-core, …) load as the wrong architecture and crash later with a cryptic "incompatible architecture" import error. Also catch that specific error around the bcrypt import and print rebuild steps. Rebased onto current main: the start-macos.sh venv-Python changes that were part of this branch are dropped, since they're already on main via PR #978. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,9 @@ initial admin user. Safe to re-run (skips what already exists).
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
@@ -117,7 +119,16 @@ def create_default_admin():
|
|||||||
print(f" Temporary password: {password}")
|
print(f" Temporary password: {password}")
|
||||||
print(f" ** Change it after first login. Set ODYSSEUS_ADMIN_PASSWORD to choose your own. **")
|
print(f" ** Change it after first login. Set ODYSSEUS_ADMIN_PASSWORD to choose your own. **")
|
||||||
return "created"
|
return "created"
|
||||||
except ImportError:
|
except ImportError as e:
|
||||||
|
if "incompatible architecture" in str(e).lower():
|
||||||
|
# bcrypt is present but built for the wrong CPU architecture — the
|
||||||
|
# same Apple Silicon mismatch check_arch() guards against, caught here
|
||||||
|
# for the rarer case of an x86 wheel inside an arm64 venv.
|
||||||
|
print(" [error] bcrypt loaded with the wrong CPU architecture.")
|
||||||
|
print(" Rebuild the venv with an arm64 Python:")
|
||||||
|
print(" rm -rf venv && /opt/homebrew/bin/python3.11 -m venv venv")
|
||||||
|
print(" ./venv/bin/pip install -r requirements.txt")
|
||||||
|
return "skipped"
|
||||||
print(" [warn] bcrypt not installed — skipping admin user creation")
|
print(" [warn] bcrypt not installed — skipping admin user creation")
|
||||||
print(" Run: pip install bcrypt")
|
print(" Run: pip install bcrypt")
|
||||||
return "skipped"
|
return "skipped"
|
||||||
@@ -167,9 +178,52 @@ def check_deps():
|
|||||||
print(" [ok] tmux installed")
|
print(" [ok] tmux installed")
|
||||||
|
|
||||||
|
|
||||||
|
def check_arch():
|
||||||
|
"""Stop early, with guidance, if we're on Apple Silicon but running an
|
||||||
|
Intel (x86_64) Python through Rosetta.
|
||||||
|
|
||||||
|
A venv built with such an interpreter installs and loads compiled packages
|
||||||
|
(bcrypt, pydantic-core, onnxruntime, …) for the wrong CPU architecture, then
|
||||||
|
dies deep inside an import with a cryptic
|
||||||
|
"(mach-o file, but is an incompatible architecture)" error. Catching it here
|
||||||
|
turns that into one clear, actionable message.
|
||||||
|
"""
|
||||||
|
if sys.platform != "darwin" or platform.machine() == "arm64":
|
||||||
|
return # Not macOS, or already an arm64-native interpreter — nothing to do.
|
||||||
|
|
||||||
|
# platform.machine() == "x86_64": either a genuine Intel Mac (fine) or an x86
|
||||||
|
# interpreter running under Rosetta on Apple Silicon (the case we must catch).
|
||||||
|
try:
|
||||||
|
translated = subprocess.run(
|
||||||
|
["sysctl", "-n", "sysctl.proc_translated"],
|
||||||
|
capture_output=True, text=True, timeout=5,
|
||||||
|
).stdout.strip()
|
||||||
|
except Exception:
|
||||||
|
translated = ""
|
||||||
|
if translated != "1":
|
||||||
|
return # Genuine Intel Mac — carry on.
|
||||||
|
|
||||||
|
print("\n [error] This is an Apple Silicon Mac, but setup is running under an")
|
||||||
|
print(" Intel (x86_64) Python through Rosetta. Compiled packages would")
|
||||||
|
print(' load as the wrong architecture and crash with "incompatible')
|
||||||
|
print(' architecture" later on.')
|
||||||
|
print("\n Rebuild the environment with Homebrew's arm64 Python:")
|
||||||
|
print(" brew install python@3.11 # if you don't have it yet")
|
||||||
|
print(" rm -rf venv")
|
||||||
|
print(" /opt/homebrew/bin/python3.11 -m venv venv")
|
||||||
|
print(" ./venv/bin/pip install -r requirements.txt")
|
||||||
|
print(" ./venv/bin/python setup.py")
|
||||||
|
print("\n Tip: ./start-macos.sh does all of this with the right Python.\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("\n=== Odysseus Setup ===\n")
|
print("\n=== Odysseus Setup ===\n")
|
||||||
|
|
||||||
|
# Fail fast with a clear message if the CPU architecture is wrong (Apple
|
||||||
|
# Silicon under an x86/Rosetta Python) before importing anything native.
|
||||||
|
check_arch()
|
||||||
|
|
||||||
print("1. Creating directories...")
|
print("1. Creating directories...")
|
||||||
create_dirs()
|
create_dirs()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user