#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # SPDX-License-Identifier: Apache-2.0 # Copyright Pionix GmbH and Contributors to EVerest # """ author: andreas.heinrich@pionix.de This script checks whether the packages in a requirements.txt are satisfied. If run inside a virtual environment, it can optionally fix unmet requirements by running pip install -r. """ import argparse import sys from importlib.metadata import version, PackageNotFoundError import re import subprocess def parse_requirement(req_line: str): req_line = req_line.strip() if not req_line or req_line.startswith("#"): return None match = re.match(r"([a-zA-Z0-9_\-]+)==([0-9\.]+)", req_line) if match: return match.groups() return (req_line, None) def check_requirements(file_path: str, fix_in_venv: bool = False): errors = [] with open(file_path, "r") as f: for line in f: parsed = parse_requirement(line) if not parsed: continue pkg, req_version = parsed try: installed_version = version(pkg) if req_version and installed_version != req_version: errors.append(f"{pkg}=={req_version} (installed: {installed_version})") except PackageNotFoundError: errors.append(f"{pkg}=={req_version or 'any version'} (not installed)") if fix_in_venv and errors: if sys.prefix != sys.base_prefix: print(f"Attempting to fix requirements in the current venv: {sys.prefix}") subprocess.run([sys.executable, "-m", "pip", "install", "-r", file_path], check=True) return check_requirements(file_path, fix_in_venv=False) else: print("Not in a virtual environment. Cannot fix requirements automatically.") if not errors: print("✅ All requirements are met.") else: print("❌ There are unmet requirements:") for e in errors: print(" ", e) sys.exit(1) def main(): parser = argparse.ArgumentParser(description="Checks if the packages in a requirements.txt are satisfied.") parser.add_argument("requirements_file", type=str, help="Path to the requirements.txt") parser.add_argument("--fix-in-venv", action="store_true", help="Run pip install -r in the current venv if there are unmet requirements") args = parser.parse_args() check_requirements(args.requirements_file, args.fix_in_venv) if __name__ == "__main__": try: main() except Exception as e: print(f"Error: {e}") exit(1)