#!/usr/bin/env python3 """ Local coverage runner script. Runs test and documentation coverage locally and generates badges. """ import subprocess import os def run_command(cmd, description): """Run a command and handle errors.""" print(f"\n{'='*50}") print(f"Running: {description}") print(f"Command: {cmd}") print(f"{'='*50}") try: result = subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True) print(result.stdout) if result.stderr: print("STDERR:", result.stderr) return True except subprocess.CalledProcessError as e: print(f"Error running {description}:") print(f"Return code: {e.returncode}") print(f"STDOUT: {e.stdout}") print(f"STDERR: {e.stderr}") return False def main(): """Run full coverage analysis locally.""" print("Local Coverage Analysis for pyWebLayout") print("=" * 60) # Change to project root if running from scripts directory if os.path.basename(os.getcwd()) == "scripts": os.chdir("..") # Install required packages print("\n1. Installing required packages...") packages = [ "pytest pytest-cov", "coverage-badge", "interrogate" ] for package in packages: if not run_command(f"pip install {package}", f"Installing {package}"): print(f"Failed to install {package}, continuing...") # Run tests with coverage print("\n2. Running tests with coverage...") test_cmd = ( "python -m pytest tests/ -v --cov=pyWebLayout " "--cov-report=term-missing --cov-report=json --cov-report=html --cov-report=xml" ) run_command(test_cmd, "Running tests with coverage") # Generate test coverage badge print("\n3. Generating test coverage badge...") run_command("coverage-badge -o coverage.svg -f", "Generating test coverage badge") # Check documentation coverage print("\n4. Checking documentation coverage...") docs_cmd = ( "interrogate -v --ignore-init-method --ignore-init-module --ignore-magic " "--ignore-private --ignore-property-decorators --ignore-semiprivate " "--fail-under=80 --generate-badge coverage-docs.svg pyWebLayout/" ) run_command(docs_cmd, "Checking documentation coverage") # Generate coverage summary print("\n5. Generating coverage summary...") # Write a temporary script to avoid shell quoting issues summary_script_content = '''import json import os if os.path.exists("coverage.json"): with open("coverage.json", "r") as f: coverage_data = json.load(f) total_coverage = round(coverage_data["totals"]["percent_covered"], 1) covered_lines = coverage_data["totals"]["covered_lines"] total_lines = coverage_data["totals"]["num_statements"] with open("coverage-summary.txt", "w") as f: f.write(f"{total_coverage}%") print(f"Test Coverage: {total_coverage}%") print(f"Lines Covered: {covered_lines}/{total_lines}") else: print("No coverage data found") ''' # Write and execute temporary script with open('temp_coverage_summary.py', 'w') as f: f.write(summary_script_content) run_command("python temp_coverage_summary.py", "Generating coverage summary") # Clean up temporary script if os.path.exists('temp_coverage_summary.py'): os.remove('temp_coverage_summary.py') # List generated files print("\n6. Generated files:") files = ["coverage.svg", "coverage-docs.svg", "coverage-summary.txt", "htmlcov/", "coverage.json", "coverage.xml"] for file in files: if os.path.exists(file): print(f" ✓ {file}") else: print(f" ✗ {file} (not found)") print("\n" + "="*60) print("Coverage analysis complete!") print("To update your README with badges, run:") print(" python scripts/update_coverage_badges.py") print("\nTo view detailed HTML coverage report:") print(" open htmlcov/index.html") if __name__ == "__main__": main()