Merge pull request #222 from svnlto/fix/pip-detection-clean

fix: pip detection inconsistency in non-interactive shells
This commit is contained in:
Beehive Innovations
2025-08-09 12:09:50 -07:00
committed by GitHub
3 changed files with 292 additions and 169 deletions

View File

@@ -39,6 +39,7 @@ extend-exclude = '''
| \.mypy_cache
| \.tox
| \.venv
| \.zen_venv
| venv
| _build
| buck-out

View File

@@ -82,11 +82,15 @@ clear_python_cache() {
get_venv_python_path() {
local venv_path="$1"
# Convert to absolute path for consistent behavior across shell environments
local abs_venv_path
abs_venv_path=$(cd "$(dirname "$venv_path")" && pwd)/$(basename "$venv_path")
# Check for both Unix and Windows Python executable paths
if [[ -f "$venv_path/bin/python" ]]; then
echo "$venv_path/bin/python"
elif [[ -f "$venv_path/Scripts/python.exe" ]]; then
echo "$venv_path/Scripts/python.exe"
if [[ -f "$abs_venv_path/bin/python" ]]; then
echo "$abs_venv_path/bin/python"
elif [[ -f "$abs_venv_path/Scripts/python.exe" ]]; then
echo "$abs_venv_path/Scripts/python.exe"
else
return 1 # No Python executable found
fi
@@ -881,7 +885,15 @@ install_dependencies() {
# If pip is still not available after retries, try to bootstrap it
if [[ "$pip_available" == false ]]; then
print_warning "pip is not available in the Python environment after $max_attempts attempts"
print_info "Python command: $python_cmd"
# Enhanced diagnostic information for debugging
print_info "Diagnostic information:"
print_info " Python executable: $python_cmd"
print_info " Python executable exists: $(if [[ -f "$python_cmd" ]]; then echo "Yes"; else echo "No"; fi)"
print_info " Python executable permissions: $(ls -la "$python_cmd" 2>/dev/null || echo "Cannot check")"
print_info " Virtual environment path: $VENV_PATH"
print_info " Virtual environment exists: $(if [[ -d "$VENV_PATH" ]]; then echo "Yes"; else echo "No"; fi)"
print_info "Attempting to bootstrap pip..."
# Extract the base python command for bootstrap (fallback to python3)
@@ -911,10 +923,16 @@ install_dependencies() {
echo ""
echo "This indicates an incomplete Python installation or a problem with the virtual environment."
echo ""
echo "Final diagnostic information:"
echo " Python executable: $python_cmd"
echo " Python version: $($python_cmd --version 2>&1 || echo "Cannot determine")"
echo " pip module check: $($python_cmd -c "import pip; print('Available')" 2>&1 || echo "Not available")"
echo ""
echo "Troubleshooting steps:"
echo "1. Delete the virtual environment: rm -rf $VENV_PATH"
echo "2. Run this script again: ./run-server.sh"
echo "3. If the problem persists, check your Python installation"
echo "4. For Git Bash on Windows, try running from a regular Command Prompt or PowerShell"
echo ""
return 1
fi

View File

@@ -0,0 +1,104 @@
"""Tests for pip detection fix in run-server.sh script.
This test file ensures our pip detection improvements work correctly
and don't break existing functionality.
"""
import subprocess
import tempfile
from pathlib import Path
import pytest
class TestPipDetectionFix:
"""Test cases for issue #188: PIP is available but not recognized."""
def test_run_server_script_syntax_valid(self):
"""Test that run-server.sh has valid bash syntax."""
result = subprocess.run(["bash", "-n", "./run-server.sh"], capture_output=True, text=True)
assert result.returncode == 0, f"Syntax error in run-server.sh: {result.stderr}"
def test_run_server_has_proper_shebang(self):
"""Test that run-server.sh starts with proper shebang."""
content = Path("./run-server.sh").read_text()
assert content.startswith("#!/bin/bash"), "Script missing proper bash shebang"
def test_critical_functions_exist(self):
"""Test that all critical functions are defined in the script."""
content = Path("./run-server.sh").read_text()
critical_functions = ["find_python", "setup_environment", "setup_venv", "install_dependencies", "bootstrap_pip"]
for func in critical_functions:
assert f"{func}()" in content, f"Critical function {func}() not found in script"
def test_pip_detection_consistency_issue(self):
"""Test the specific issue: pip works in setup_venv but fails in install_dependencies.
This test verifies that our fix ensures consistent Python executable paths.
"""
# Test that the get_venv_python_path function now returns absolute paths
content = Path("./run-server.sh").read_text()
# Check that get_venv_python_path includes our absolute path conversion logic
assert "abs_venv_path" in content, "get_venv_python_path should use absolute paths"
assert 'cd "$(dirname' in content, "Should convert to absolute path"
# Test successful completion - our fix should make the script more robust
result = subprocess.run(["bash", "-n", "./run-server.sh"], capture_output=True, text=True)
assert result.returncode == 0, "Script should have valid syntax after our fix"
def test_pip_detection_with_non_interactive_shell(self):
"""Test pip detection works in non-interactive shell environments.
This addresses the contributor's suggestion about non-interactive shells
not sourcing ~/.bashrc where pip PATH might be defined.
"""
# Test case for Git Bash on Windows and non-interactive Linux shells
with tempfile.TemporaryDirectory() as temp_dir:
# Create mock virtual environment structure
venv_path = Path(temp_dir) / ".zen_venv"
bin_path = venv_path / "bin"
bin_path.mkdir(parents=True)
# Create mock python executable
python_exe = bin_path / "python"
python_exe.write_text("#!/bin/bash\necho 'Python 3.12.3'\n")
python_exe.chmod(0o755)
# Create mock pip executable
pip_exe = bin_path / "pip"
pip_exe.write_text("#!/bin/bash\necho 'pip 23.0.1'\n")
pip_exe.chmod(0o755)
# Test that we can detect pip using explicit paths (not PATH)
assert python_exe.exists(), "Mock python executable should exist"
assert pip_exe.exists(), "Mock pip executable should exist"
assert python_exe.is_file(), "Python should be a file"
assert pip_exe.is_file(), "Pip should be a file"
def test_enhanced_diagnostic_messages_included(self):
"""Test that our enhanced diagnostic messages are included in the script.
Verify that the script contains the enhanced error diagnostics we added.
"""
content = Path("./run-server.sh").read_text()
# Check that enhanced diagnostic information is present in the script
expected_diagnostic_patterns = [
"Enhanced diagnostic information for debugging",
"Diagnostic information:",
"Python executable:",
"Python executable exists:",
"Python executable permissions:",
"Virtual environment path:",
"Virtual environment exists:",
"Final diagnostic information:",
]
for pattern in expected_diagnostic_patterns:
assert pattern in content, f"Enhanced diagnostic pattern '{pattern}' should be in script"
if __name__ == "__main__":
pytest.main([__file__, "-v"])