""" Report Generator Module - Generate HTML and JSON reports. This module handles: - HTML dashboard generation - JSON report output - Console summary formatting - Report history management """ import json import logging from pathlib import Path from typing import Dict, Any from datetime import datetime logger = logging.getLogger(__name__) class ReportGenerator: """Generate quality reports in multiple formats.""" def __init__(self, config: Dict[str, Any], project_root: str): """ Initialize the report generator. Args: config: Configuration dictionary for report generator project_root: Root directory of the project """ self.config = config self.project_root = Path(project_root) self.output_dir = self.project_root / config.get("output_dir", "quality_reports") self.output_dir.mkdir(exist_ok=True) def generate_reports(self, results: Dict[str, Any]): """ Generate all configured reports. Args: results: Combined results from all modules """ logger.info("Generating reports...") # Generate JSON report if self.config.get("generate_json", True): self._generate_json_report(results) # Generate HTML report if self.config.get("generate_html", True): self._generate_html_report(results) # Generate console summary if self.config.get("generate_console_summary", True): self._print_console_summary(results) # Save to history if self.config.get("save_history", True): self._save_to_history(results) logger.info(f"Reports generated in: {self.output_dir}") def _generate_json_report(self, results: Dict[str, Any]): """Generate JSON report.""" logger.info("Generating JSON report...") report_file = self.output_dir / "latest_report.json" report_data = { "timestamp": datetime.now().isoformat(), "project_name": self.config.get("project_name", "Unknown"), "results": results } with open(report_file, 'w') as f: json.dump(report_data, f, indent=2) logger.info(f"JSON report saved to: {report_file}") def _generate_html_report(self, results: Dict[str, Any]): """Generate HTML dashboard report.""" logger.info("Generating HTML report...") report_file = self.output_dir / "latest_report.html" # Extract results cleaner = results.get("code_cleaner", {}) vuln = results.get("vulnerability_checker", {}) conn = results.get("connection_tester", {}) tester = results.get("code_tester", {}) # Build HTML html = f""" Code Quality Report - {self.config.get('project_name', 'Project')}

šŸ” Code Quality Report

Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}

Project: {self.config.get('project_name', 'Unknown')}

šŸ“ Code Cleaning

Files Processed {cleaner.get('total_files_processed', 0)}
Formatted {len(cleaner.get('formatted_files', []))}
Errors {len(cleaner.get('errors', []))}

šŸ”’ Security

Total Issues {vuln.get('total_issues', 0)}
Critical {vuln.get('severity_counts', {}).get('CRITICAL', 0)}
High {vuln.get('severity_counts', {}).get('HIGH', 0)}

šŸ”Œ Connections

Total Tests {conn.get('total_tests', 0)}
Passed {conn.get('passed_tests', 0)}
Failed {conn.get('failed_tests', 0)}

āœ… Tests

Total Tests {tester.get('total_tests', 0)}
Coverage {tester.get('coverage_percentage', 0):.1f}%
Pylint Score {tester.get('pylint_results', {}).get('score', 'N/A')}/10

šŸ”’ Security Vulnerabilities

{self._generate_vulnerability_html(vuln)}

šŸ”Œ Connection Tests

{self._generate_connection_html(conn)}
""" with open(report_file, 'w', encoding='utf-8') as f: f.write(html) logger.info(f"HTML report saved to: {report_file}") def _generate_vulnerability_html(self, vuln: Dict[str, Any]) -> str: """Generate HTML for vulnerability section.""" if vuln.get('total_issues', 0) == 0: return '

āœ“ No security issues found!

' html = '' return html def _generate_connection_html(self, conn: Dict[str, Any]) -> str: """Generate HTML for connection tests section.""" if conn.get('total_tests', 0) == 0: return '

No connection tests were run.

' html = '' # Database tests for test in conn.get('database_tests', []): status = test.get('status', 'FAILED').lower() html += f'''
{test.get('test', 'Database Test')} {test.get('status', 'UNKNOWN')}
''' # API tests for test in conn.get('api_tests', [])[:5]: # Limit to 5 status = test.get('status', 'FAILED').lower() html += f'''
{test.get('test', 'API Test')} {test.get('status', 'UNKNOWN')}
''' return html def _print_console_summary(self, results: Dict[str, Any]): """Print a summary to console.""" print("\n" + "="*70) print("CODE QUALITY REPORT SUMMARY") print("="*70) # Code Cleaner cleaner = results.get("code_cleaner", {}) print(f"\nšŸ“ CODE CLEANING:") print(f" Files processed: {cleaner.get('total_files_processed', 0)}") print(f" Formatted: {len(cleaner.get('formatted_files', []))}") # Vulnerabilities vuln = results.get("vulnerability_checker", {}) print(f"\nšŸ”’ SECURITY:") print(f" Total issues: {vuln.get('total_issues', 0)}") print(f" Critical: {vuln.get('severity_counts', {}).get('CRITICAL', 0)}") print(f" High: {vuln.get('severity_counts', {}).get('HIGH', 0)}") # Connections conn = results.get("connection_tester", {}) print(f"\nšŸ”Œ CONNECTIONS:") print(f" Tests run: {conn.get('total_tests', 0)}") print(f" Passed: {conn.get('passed_tests', 0)}") print(f" Failed: {conn.get('failed_tests', 0)}") # Tests tester = results.get("code_tester", {}) print(f"\nāœ… CODE TESTS:") print(f" Total tests: {tester.get('total_tests', 0)}") print(f" Coverage: {tester.get('coverage_percentage', 0):.1f}%") print(f" Pylint score: {tester.get('pylint_results', {}).get('score', 'N/A')}/10") print("\n" + "="*70) print(f"Full reports available in: {self.output_dir}") print("="*70 + "\n") def _save_to_history(self, results: Dict[str, Any]): """Save report to history.""" history_dir = self.output_dir / "history" history_dir.mkdir(exist_ok=True) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") history_file = history_dir / f"report_{timestamp}.json" with open(history_file, 'w') as f: json.dump(results, f, indent=2) # Clean old history files max_history = self.config.get("max_history_reports", 10) history_files = sorted(history_dir.glob("report_*.json")) if len(history_files) > max_history: for old_file in history_files[:-max_history]: old_file.unlink()