""" Dependency management Handles package installation and verification """ import sys import subprocess import importlib.util from config_settings import REQUIRED_PACKAGES, REPOSITORY_PATH def install_package_from_wheel(wheel_path, package_name): """Install a Python package from a wheel file""" try: print(f"Installing {package_name} from {wheel_path}...") result = subprocess.run([ sys.executable, "-m", "pip", "install", wheel_path, "--no-index", "--no-deps", "--break-system-packages", "--no-warn-script-location", "--force-reinstall" ], capture_output=True, text=True, timeout=60) if result.returncode == 0: print(f"✓ {package_name} installed successfully") return True else: print(f"✗ Failed to install {package_name}: {result.stderr}") return False except Exception as e: print(f"✗ Error installing {package_name}: {e}") return False def check_and_install_dependencies(): """Check if required packages are installed and install them from local repository if needed""" print("Checking and installing dependencies...") repository_path = str(REPOSITORY_PATH) missing_packages = [] # Check each required package for package_name, wheel_file in REQUIRED_PACKAGES.items(): try: spec = importlib.util.find_spec(package_name) if spec is not None: print(f"✓ {package_name} is already installed") else: raise ImportError(f"Package {package_name} not found") except ImportError: print(f"✗ {package_name} is not installed") missing_packages.append((package_name, wheel_file)) except Exception as e: print(f"✗ Error checking {package_name}: {e}") missing_packages.append((package_name, wheel_file)) # Install missing packages if missing_packages: print(f"\nInstalling {len(missing_packages)} missing packages...") for package_name, wheel_file in missing_packages: if wheel_file is None: # Try to install via pip from internet or system packages try: print(f"Attempting to install {package_name} via pip...") result = subprocess.run([ sys.executable, "-m", "pip", "install", package_name, "--break-system-packages", "--no-warn-script-location" ], capture_output=True, text=True, timeout=120) if result.returncode == 0: print(f"✓ {package_name} installed via pip") else: print(f"✗ Could not install {package_name} via pip: {result.stderr}") if package_name in ['flask', 'gpiozero']: try: print(f"Trying to install {package_name} via apt...") result = subprocess.run([ 'sudo', 'apt', 'install', '-y', f'python3-{package_name}', '--no-install-recommends' ], capture_output=True, text=True, timeout=120) if result.returncode == 0: print(f"✓ {package_name} installed via apt") else: print(f"✗ Could not install {package_name} via apt") except Exception as apt_e: print(f"✗ apt install failed: {apt_e}") except Exception as pip_e: print(f"✗ pip install failed: {pip_e}") else: # Try to install from wheel file wheel_path = f"{repository_path}/{wheel_file}" install_package_from_wheel(wheel_path, package_name) def verify_dependencies(): """Verify that all required dependencies are available""" print("Verifying dependencies...") available = True for package_name in REQUIRED_PACKAGES.keys(): try: spec = importlib.util.find_spec(package_name) if spec is not None: print(f"✓ {package_name} verified") else: print(f"✗ {package_name} not available") available = False except Exception as e: print(f"✗ Error verifying {package_name}: {e}") available = False return available