|
6 | 6 | # Default target - show help |
7 | 7 | .DEFAULT_GOAL := help |
8 | 8 |
|
9 | | -# Toolchain (prefer project venv if present) |
| 9 | +# -------------------------------------------------------------------------- |
| 10 | +# Python interpreter detection |
| 11 | +# -------------------------------------------------------------------------- |
| 12 | +# VENV_BIN: path to local virtualenv bin directory |
10 | 13 | VENV_BIN := $(PWD)/venv/bin |
11 | | -PY_FIND := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null) |
12 | | -PYTHON ?= $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,$(PY_FIND)) |
| 14 | + |
| 15 | +# PY_BEST: scan for newest supported Python (used when creating new venvs) |
| 16 | +# Supports 3.9-3.13 to match CI matrix |
| 17 | +PY_BEST := $(shell for v in 3.13 3.12 3.11 3.10 3.9; do command -v python$$v >/dev/null 2>&1 && { echo python$$v; exit 0; }; done; command -v python3 2>/dev/null || command -v python 2>/dev/null) |
| 18 | + |
| 19 | +# PY_PATH: active python3/python on PATH (respects CI setup-python and activated venvs) |
| 20 | +PY_PATH := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null) |
| 21 | + |
| 22 | +# PYTHON: interpreter used for all commands |
| 23 | +# 1. Use local venv if present |
| 24 | +# 2. Otherwise use active python on PATH (important for CI) |
| 25 | +# 3. Fall back to best available version |
| 26 | +# 4. Final fallback to 'python3' literal for clear error messages |
| 27 | +PYTHON ?= $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,$(if $(PY_PATH),$(PY_PATH),$(if $(PY_BEST),$(PY_BEST),python3))) |
| 28 | + |
| 29 | +# Derived tool commands (always use -m to ensure correct environment) |
13 | 30 | PIP := $(PYTHON) -m pip |
14 | 31 | PYTEST := $(PYTHON) -m pytest |
15 | 32 | RUFF := $(PYTHON) -m ruff |
@@ -50,23 +67,23 @@ help: |
50 | 67 | @echo "Utilities:" |
51 | 68 | @echo " make info - Show project information" |
52 | 69 | @echo " make hooks - Run pre-commit on all files" |
53 | | - @echo " make check-python - Check if venv Python matches system Python" |
| 70 | + @echo " make check-python - Check if venv Python matches best available" |
54 | 71 |
|
55 | 72 | # Setup and Installation |
56 | 73 | dev: |
57 | 74 | @echo "🚀 Setting up development environment..." |
58 | 75 | @if [ ! -x "$(VENV_BIN)/python" ]; then \ |
59 | | - if [ -z "$(PY_FIND)" ]; then \ |
| 76 | + if [ -z "$(PY_BEST)" ]; then \ |
60 | 77 | echo "❌ Error: No Python interpreter found (python3 or python)"; \ |
61 | 78 | exit 1; \ |
62 | 79 | fi; \ |
63 | | - echo "🐍 Creating virtual environment with $(PY_FIND) ..."; \ |
64 | | - $(PY_FIND) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }; \ |
| 80 | + echo "🐍 Creating virtual environment with $(PY_BEST) ..."; \ |
| 81 | + $(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }; \ |
65 | 82 | if [ ! -x "$(VENV_BIN)/python" ]; then \ |
66 | 83 | echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \ |
67 | 84 | exit 1; \ |
68 | 85 | fi; \ |
69 | | - $(VENV_BIN)/python -m pip install -U pip wheel; \ |
| 86 | + $(VENV_BIN)/python -m pip install -U pip setuptools wheel; \ |
70 | 87 | fi |
71 | 88 | @echo "📦 Installing dev dependencies..." |
72 | 89 | @$(VENV_BIN)/python -m pip install -e .'[dev]' |
|
77 | 94 |
|
78 | 95 | venv: |
79 | 96 | @echo "🐍 Creating virtual environment in ./venv ..." |
80 | | - @if [ -z "$(PY_FIND)" ]; then \ |
| 97 | + @if [ -z "$(PY_BEST)" ]; then \ |
81 | 98 | echo "❌ Error: No Python interpreter found (python3 or python)"; \ |
82 | 99 | exit 1; \ |
83 | 100 | fi |
84 | | - @$(PY_FIND) -m venv venv || { echo "❌ Failed to create venv"; exit 1; } |
| 101 | + @$(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; } |
85 | 102 | @if [ ! -x "$(VENV_BIN)/python" ]; then \ |
86 | 103 | echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \ |
87 | 104 | exit 1; \ |
88 | 105 | fi |
89 | | - @$(VENV_BIN)/python -m pip install -U pip wheel |
| 106 | + @$(VENV_BIN)/python -m pip install -U pip setuptools wheel |
90 | 107 | @echo "✅ venv ready. Activate with: source venv/bin/activate" |
91 | 108 |
|
92 | 109 | clean-venv: |
@@ -223,7 +240,7 @@ info: |
223 | 240 | @echo "" |
224 | 241 | @echo "🐍 Python Environment:" |
225 | 242 | @echo " Python (active): $$($(PYTHON) --version)" |
226 | | - @echo " Python (system): $$($(PY_FIND) --version 2>/dev/null || echo 'missing')" |
| 243 | + @echo " Python (best): $$($(PY_BEST) --version 2>/dev/null || echo 'missing')" |
227 | 244 | @$(MAKE) check-python |
228 | 245 | @echo " Package version: $$($(PYTHON) -c 'import importlib.metadata; print(importlib.metadata.version("ngraph"))' 2>/dev/null || echo 'Not installed')" |
229 | 246 | @echo " Virtual environment: $$(echo $$VIRTUAL_ENV | sed 's|.*/||' || echo 'None active')" |
@@ -256,9 +273,9 @@ hooks: |
256 | 273 | check-python: |
257 | 274 | @if [ -x "$(VENV_BIN)/python" ]; then \ |
258 | 275 | VENV_VER=$$($(VENV_BIN)/python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \ |
259 | | - SYS_VER=$$($(PY_FIND) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \ |
260 | | - if [ -n "$$VENV_VER" ] && [ -n "$$SYS_VER" ] && [ "$$VENV_VER" != "$$SYS_VER" ]; then \ |
261 | | - echo "⚠️ WARNING: venv Python ($$VENV_VER) != system Python ($$SYS_VER)"; \ |
262 | | - echo " Run 'make clean-venv && make dev' to recreate venv with system Python"; \ |
| 276 | + BEST_VER=$$($(PY_BEST) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \ |
| 277 | + if [ -n "$$VENV_VER" ] && [ -n "$$BEST_VER" ] && [ "$$VENV_VER" != "$$BEST_VER" ]; then \ |
| 278 | + echo "⚠️ WARNING: venv Python ($$VENV_VER) != best available Python ($$BEST_VER)"; \ |
| 279 | + echo " Run 'make clean-venv && make dev' to recreate venv if desired"; \ |
263 | 280 | fi; \ |
264 | 281 | fi |
0 commit comments