Spaces:
Sleeping
Sleeping
Download RodSizer_Launcher_MacOS.command from Caesium135/RodSizer_web: direct link, hf CLI and curl.
- Browser
- Download file 11.9 kB
-
https://huggingface.co/spaces/Caesium135/RodSizer_web/resolve/main/RodSizer_Launcher_MacOS.command
- Command line
-
hf download hf://spaces/Caesium135/RodSizer_web/RodSizer_Launcher_MacOS.command
-
curl -L -o RodSizer_Launcher_MacOS.command https://huggingface.co/spaces/Caesium135/RodSizer_web/resolve/main/RodSizer_Launcher_MacOS.command
11.9 kB
| #!/bin/bash | |
| # ============================================================================= | |
| # RodSizer β Mac Launcher | |
| # Double-click this file in Finder to start the app. | |
| # ============================================================================= | |
| # ββ Navigate to the project root (same folder as this script) ββββββββββββββββ | |
| cd "$(dirname "$0")" | |
| PROJECT_DIR="$(pwd)" | |
| BACKEND_DIR="$PROJECT_DIR/backend" | |
| VENV_DIR="$BACKEND_DIR/.venv" | |
| CACHE_DIR="$BACKEND_DIR/.cache" | |
| MPL_CACHE_DIR="$CACHE_DIR/matplotlib" | |
| # ββ Terminal colours ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' | |
| info() { echo -e "${GREEN}[β]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[!]${NC} $*"; } | |
| error() { echo -e "${RED}[β]${NC} $*"; } | |
| step() { echo -e "\n${CYAN}ββββββββββββββββββββββββββββββββββββββββββ${NC}"; echo -e "${CYAN} $*${NC}"; echo -e "${CYAN}ββββββββββββββββββββββββββββββββββββββββββ${NC}"; } | |
| step "RodSizer β Starting up" | |
| # ββ Detect CPU architecture βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ARCH=$(uname -m) | |
| if [ "$ARCH" = "arm64" ]; then | |
| IS_APPLE_SILICON=true | |
| info "Apple Silicon (M-series) Mac detected" | |
| else | |
| IS_APPLE_SILICON=false | |
| info "Intel Mac detected" | |
| fi | |
| # ============================================================================= | |
| # STEP 1 β Homebrew | |
| # ============================================================================= | |
| step "Step 1/5: Checking Homebrew" | |
| # Ensure brew is on PATH (Apple Silicon installs to /opt/homebrew) | |
| if [ "$IS_APPLE_SILICON" = true ] && [ -f /opt/homebrew/bin/brew ]; then | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| elif [ -f /usr/local/bin/brew ]; then | |
| eval "$(/usr/local/bin/brew shellenv)" | |
| fi | |
| if ! command -v brew &>/dev/null; then | |
| warn "Homebrew not found. Installing now (this requires an internet connection)..." | |
| /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| # Re-source brew after install | |
| if [ "$IS_APPLE_SILICON" = true ] && [ -f /opt/homebrew/bin/brew ]; then | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| elif [ -f /usr/local/bin/brew ]; then | |
| eval "$(/usr/local/bin/brew shellenv)" | |
| fi | |
| fi | |
| if ! command -v brew &>/dev/null; then | |
| error "Homebrew installation failed." | |
| error "Please install it manually from https://brew.sh, then re-run this launcher." | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| info "Homebrew: $(brew --version | head -1)" | |
| # ============================================================================= | |
| # STEP 2 β Python 3.11 | |
| # | |
| # TensorFlow 2.x officially supports Python 3.8β3.11. | |
| # Python 3.12+ does NOT have stable TensorFlow wheels yet. | |
| # We therefore require Python 3.11 specifically. | |
| # ============================================================================= | |
| step "Step 2/4: Checking Python 3.11" | |
| PYTHON_CMD="" | |
| # Helper: find python3.11 by checking all known locations | |
| find_python311() { | |
| # 1. Homebrew-managed path (most reliable β works regardless of PATH) | |
| local brew_prefix | |
| brew_prefix="$(brew --prefix python@3.11 2>/dev/null)" | |
| if [ -n "$brew_prefix" ] && [ -x "$brew_prefix/bin/python3.11" ]; then | |
| echo "$brew_prefix/bin/python3.11"; return | |
| fi | |
| # 2. Direct binary in PATH | |
| if command -v python3.11 &>/dev/null; then | |
| command -v python3.11; return | |
| fi | |
| # 3. Common Homebrew Cellar fallback (Apple Silicon) | |
| local cellar_py | |
| cellar_py=$(ls /opt/homebrew/Cellar/python@3.11/*/bin/python3.11 2>/dev/null | sort -V | tail -1) | |
| if [ -x "$cellar_py" ]; then | |
| echo "$cellar_py"; return | |
| fi | |
| # Intel | |
| cellar_py=$(ls /usr/local/Cellar/python@3.11/*/bin/python3.11 2>/dev/null | sort -V | tail -1) | |
| if [ -x "$cellar_py" ]; then | |
| echo "$cellar_py"; return | |
| fi | |
| # 4. pyenv | |
| if command -v pyenv &>/dev/null; then | |
| local pyenv_ver | |
| pyenv_ver=$(pyenv versions --bare 2>/dev/null | grep "^3\.11\." | sort -V | tail -1) | |
| if [ -n "$pyenv_ver" ]; then | |
| local pyenv_py="$(pyenv root)/versions/$pyenv_ver/bin/python3.11" | |
| [ -x "$pyenv_py" ] && echo "$pyenv_py"; return | |
| fi | |
| fi | |
| } | |
| PYTHON_CMD="$(find_python311)" | |
| # If still not found, install via Homebrew then retry | |
| if [ -z "$PYTHON_CMD" ]; then | |
| warn "Python 3.11 not found. Installing via Homebrew (needed for TensorFlow)..." | |
| brew install python@3.11 | |
| PYTHON_CMD="$(find_python311)" | |
| fi | |
| if [ -z "$PYTHON_CMD" ] || [ ! -x "$PYTHON_CMD" ]; then | |
| error "Could not find or install Python 3.11." | |
| error "Please install it manually: brew install python@3.11" | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| PYTHON_VER=$("$PYTHON_CMD" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')") | |
| info "Using Python $PYTHON_VER at: $PYTHON_CMD" | |
| PYTHON_MINOR=$("$PYTHON_CMD" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") | |
| # ============================================================================= | |
| # STEP 3 β Virtual environment & Python dependencies | |
| # ============================================================================= | |
| step "Step 3/4: Setting up Python environment" | |
| # Create venv if it does not exist | |
| if [ ! -d "$VENV_DIR" ]; then | |
| info "Creating virtual environment..." | |
| "$PYTHON_CMD" -m venv "$VENV_DIR" | |
| fi | |
| # Activate | |
| source "$VENV_DIR/bin/activate" | |
| info "Virtual environment activated" | |
| # Ensure Python/matplotlib/fontconfig can cache into writable project-local paths. | |
| mkdir -p "$MPL_CACHE_DIR" | |
| export XDG_CACHE_HOME="$CACHE_DIR" | |
| export MPLCONFIGDIR="$MPL_CACHE_DIR" | |
| install_tensorflow_with_fallback() { | |
| local tf_wheel_url="" | |
| info "Installing TensorFlow..." | |
| if pip install tensorflow; then | |
| return 0 | |
| fi | |
| warn "pip could not resolve tensorflow from the package index." | |
| if [ "$IS_APPLE_SILICON" = true ]; then | |
| case "$PYTHON_MINOR" in | |
| "3.11") | |
| tf_wheel_url="https://files.pythonhosted.org/packages/ec/76/b649b02a243c09f0348199dbd81408c1558cfbec2b6d77d820c428a95254/tensorflow-2.21.0-cp311-cp311-macosx_12_0_arm64.whl" | |
| ;; | |
| esac | |
| fi | |
| if [ -n "$tf_wheel_url" ]; then | |
| warn "Retrying TensorFlow install using the official macOS wheel URL..." | |
| pip install "$tf_wheel_url" && return 0 | |
| fi | |
| return 1 | |
| } | |
| # Check whether a first-time install is needed | |
| if ! python -c "import fastapi" &>/dev/null 2>&1; then | |
| info "Installing Python packages β this may take 5β10 minutes on first run." | |
| info "Please do NOT close this window." | |
| # Upgrade pip / setuptools silently | |
| pip install --upgrade pip setuptools wheel --quiet | |
| # ββ TensorFlow first (sets numpy version constraint everything else must follow) ββ | |
| # | |
| # tensorflow-macos was deprecated at 2.13 and forces numpy<2, which conflicts | |
| # with opencv-python-headless >=4.9 and ncempy >=1.15 (both require numpy>=2). | |
| # | |
| # tensorflow >= 2.16 ships a universal wheel that runs natively on Apple | |
| # Silicon (M-series) without a separate macos fork, and is compatible with | |
| # numpy 2.x. tensorflow-metal is still the GPU-acceleration plugin for M-chips. | |
| if ! install_tensorflow_with_fallback; then | |
| error "TensorFlow installation failed." | |
| error "This is usually a package-index or network issue, not a RodSizer code issue." | |
| if [ "$IS_APPLE_SILICON" = true ]; then | |
| error "If needed, try this manually inside backend/.venv:" | |
| error " pip install https://files.pythonhosted.org/packages/ec/76/b649b02a243c09f0348199dbd81408c1558cfbec2b6d77d820c428a95254/tensorflow-2.21.0-cp311-cp311-macosx_12_0_arm64.whl" | |
| else | |
| error "Try rerunning later, or install TensorFlow manually inside backend/.venv." | |
| fi | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| # Note: tensorflow-metal is NOT installed because v1.2.0 is incompatible | |
| # with tensorflow >=2.16 (dlopen fails on _pywrap_tensorflow_internal.so). | |
| # Modern TensorFlow already runs natively on Apple Silicon without it. | |
| if ! python -c "import tensorflow" &>/dev/null 2>&1; then | |
| error "TensorFlow import failed after installation." | |
| error "Try deleting backend/.venv and relaunching, or check network connectivity." | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| # ββ Remaining packages (numpy version is now fixed by TF above) βββββββββββββ | |
| TMP_REQ=$(mktemp /tmp/rodsizer_req_XXXX.txt) | |
| grep -v "^tensorflow" "$BACKEND_DIR/requirements.txt" > "$TMP_REQ" | |
| if ! pip install -r "$TMP_REQ" --quiet; then | |
| error "Failed to install some packages. Check the output above." | |
| rm -f "$TMP_REQ" | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| rm -f "$TMP_REQ" | |
| # ββ Verify tensorflow is importable βββββββββββββββββββββββββββββββββββββββ | |
| if ! python -c "import tensorflow" &>/dev/null 2>&1; then | |
| error "TensorFlow installation failed." | |
| error "Try running this manually inside the venv:" | |
| if [ "$IS_APPLE_SILICON" = true ]; then | |
| error " pip install tensorflow-macos tensorflow-metal" | |
| else | |
| error " pip install tensorflow" | |
| fi | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| info "All packages installed successfully." | |
| else | |
| info "Python packages already installed β skipping." | |
| fi | |
| # ============================================================================= | |
| # STEP 4 β Launch server & open browser | |
| # ============================================================================= | |
| step "Step 4/4: Starting server" | |
| # Kill any leftover process on port 8000 | |
| if lsof -ti:8000 &>/dev/null; then | |
| warn "Port 8000 is already in use β stopping the existing process..." | |
| lsof -ti:8000 | xargs kill -9 2>/dev/null | |
| sleep 1 | |
| fi | |
| # Start uvicorn (log goes to backend/server.log) | |
| cd "$BACKEND_DIR" | |
| "$VENV_DIR/bin/uvicorn" main:app --host 127.0.0.1 --port 8000 > server.log 2>&1 & | |
| SERVER_PID=$! | |
| # Wait until the server responds (allow extra time on first run while caches build) | |
| echo -n " Waiting for server to be ready" | |
| MAX_WAIT=90 | |
| for ((i=1; i<=MAX_WAIT; i++)); do | |
| if curl -s http://127.0.0.1:8000 &>/dev/null; then | |
| break | |
| fi | |
| echo -n "." | |
| sleep 1 | |
| if [ $i -eq $MAX_WAIT ]; then | |
| echo "" | |
| error "Server did not start within ${MAX_WAIT} seconds." | |
| error "Check $BACKEND_DIR/server.log for details." | |
| kill "$SERVER_PID" 2>/dev/null | |
| echo "Press Enter to close..."; read -r; exit 1 | |
| fi | |
| done | |
| echo "" | |
| info "Server is running at http://127.0.0.1:8000" | |
| open http://127.0.0.1:8000 | |
| echo "" | |
| echo -e "${GREEN}ββββββββββββββββββββββββββββββββββββββββββββ${NC}" | |
| echo -e "${GREEN} RodSizer is ready!${NC}" | |
| echo -e "${GREEN} URL: http://127.0.0.1:8000${NC}" | |
| echo -e "${GREEN}ββββββββββββββββββββββββββββββββββββββββββββ${NC}" | |
| echo "" | |
| echo " Press Ctrl+C or close this window to stop the server." | |
| echo "" | |
| # Keep the terminal open (closing it stops the server) | |
| wait "$SERVER_PID" | |