Module demo_api.reports.html_reports

Générateur de rapports HTML pour demo_api

Classes

class HTMLReportGenerator (output_directory: str = 'outputs')
Expand source code
class HTMLReportGenerator(BaseReportGenerator):
    """Générateur de rapports au format HTML avec templates Jinja2"""

    def __init__(self, output_directory: str = "outputs"):
        """
        Initialise le générateur de rapports HTML

        Args:
            output_directory: Dossier de sortie pour les rapports HTML
        """
        super().__init__(output_directory)
        self.html_directory = os.path.join(output_directory, "html")
        self._ensure_html_directory()

        # Configuration de Jinja2
        template_dir = os.path.join(
            os.path.dirname(__file__), "..", "templates", "html"
        )
        self.jinja_env = Environment(
            loader=FileSystemLoader(template_dir),
            autoescape=select_autoescape(["html", "xml"]),
            trim_blocks=True,
            lstrip_blocks=True,
        )

        # Ajout de filtres personnalisés
        self.jinja_env.filters["pad"] = self._pad_filter

    def _ensure_html_directory(self) -> None:
        """Crée le dossier HTML s'il n'existe pas"""
        if not os.path.exists(self.html_directory):
            os.makedirs(self.html_directory, exist_ok=True)
            logger.info(f"Dossier HTML créé: {self.html_directory}")

    def _pad_filter(self, text: str, width: int) -> str:
        """Filtre Jinja2 pour padding de texte"""
        return text.ljust(width)

    def get_extension(self) -> str:
        """Retourne l'extension des fichiers HTML"""
        return "html"

    def generate(
        self,
        data: Any,
        filename: Optional[str] = None,
        template_name: str = "default.html.j2",
    ) -> str:
        """
        Génère un rapport HTML

        Args:
            data: Données à inclure dans le rapport HTML
            filename: Nom de fichier personnalisé (optionnel)
            template_name: Nom du template Jinja2 à utiliser

        Returns:
            str: Chemin vers le fichier HTML généré
        """
        if filename is None:
            filename = self._generate_filename("report", self.get_extension())
        else:
            # S'assurer que le fichier a la bonne extension
            if not filename.endswith(f".{self.get_extension()}"):
                filename = f"{filename}.{self.get_extension()}"
            filename = os.path.join(self.html_directory, filename)

        # Préparer les données avec métadonnées
        report_data = {"metadata": self._get_metadata(), "data": data}

        # Générer le fichier HTML
        try:
            template = self.jinja_env.get_template(template_name)
            content = template.render(**report_data)

            with open(filename, "w", encoding="utf-8") as f:
                f.write(content)

            logger.info(
                "Rapport HTML généré avec succès",
                filename=filename,
                template=template_name,
            )

            return filename

        except Exception as e:
            logger.error(
                "Erreur lors de la génération du rapport HTML",
                filename=filename,
                error=str(e),
            )
            raise

    def generate_users_vms_report(
        self, users: List[Dict[str, Any]], filename: str = "vm_users.html"
    ) -> str:
        """
        Génère un rapport spécifique pour les utilisateurs et VMs

        Args:
            users: Liste des utilisateurs avec leurs VMs associées
            filename: Nom du fichier de sortie

        Returns:
            str: Chemin vers le fichier généré
        """
        logger.info(
            "Génération du rapport utilisateurs/VMs HTML",
            users_count=len(users),
            filename=filename,
        )

        # Statistiques supplémentaires
        stats = self._calculate_users_vms_stats(users)

        report_data = {
            "summary": {
                "total_users": len(users),
                "total_vms": stats["total_vms"],
                "vms_by_status": stats["vms_by_status"],
                "users_with_vms": stats["users_with_vms"],
                "users_without_vms": stats["users_without_vms"],
            },
            "users": users,
        }

        return self.generate(report_data, filename, "users_vms_report.html.j2")

    def generate_status_report(
        self, status_data: Dict[str, Any], filename: str = "vm_status_report.html"
    ) -> str:
        """
        Génère un rapport de statut des VMs

        Args:
            status_data: Données de statut des VMs
            filename: Nom du fichier de sortie

        Returns:
            str: Chemin vers le fichier généré
        """
        logger.info("Génération du rapport de statut HTML", filename=filename)

        return self.generate(status_data, filename, "vm_status_report.html.j2")

    def _calculate_users_vms_stats(self, users: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Calcule les statistiques des utilisateurs et VMs"""
        total_vms: int = 0
        vms_by_status: Dict[str, int] = {}
        users_with_vms: int = 0
        users_without_vms: int = 0

        for user in users:
            user_vms = user.get("vms", [])
            if user_vms:
                users_with_vms += 1
                total_vms += len(user_vms)

                # Compter les VMs par statut
                for vm in user_vms:
                    status = vm.get("status", "unknown")
                    vms_by_status[status] = vms_by_status.get(status, 0) + 1
            else:
                users_without_vms += 1

        return {
            "total_vms": total_vms,
            "vms_by_status": vms_by_status,
            "users_with_vms": users_with_vms,
            "users_without_vms": users_without_vms,
        }

Générateur de rapports au format HTML avec templates Jinja2

Initialise le générateur de rapports HTML

Args

output_directory
Dossier de sortie pour les rapports HTML

Ancestors

Methods

def generate(self,
data: Any,
filename: str | None = None,
template_name: str = 'default.html.j2') ‑> str
Expand source code
def generate(
    self,
    data: Any,
    filename: Optional[str] = None,
    template_name: str = "default.html.j2",
) -> str:
    """
    Génère un rapport HTML

    Args:
        data: Données à inclure dans le rapport HTML
        filename: Nom de fichier personnalisé (optionnel)
        template_name: Nom du template Jinja2 à utiliser

    Returns:
        str: Chemin vers le fichier HTML généré
    """
    if filename is None:
        filename = self._generate_filename("report", self.get_extension())
    else:
        # S'assurer que le fichier a la bonne extension
        if not filename.endswith(f".{self.get_extension()}"):
            filename = f"{filename}.{self.get_extension()}"
        filename = os.path.join(self.html_directory, filename)

    # Préparer les données avec métadonnées
    report_data = {"metadata": self._get_metadata(), "data": data}

    # Générer le fichier HTML
    try:
        template = self.jinja_env.get_template(template_name)
        content = template.render(**report_data)

        with open(filename, "w", encoding="utf-8") as f:
            f.write(content)

        logger.info(
            "Rapport HTML généré avec succès",
            filename=filename,
            template=template_name,
        )

        return filename

    except Exception as e:
        logger.error(
            "Erreur lors de la génération du rapport HTML",
            filename=filename,
            error=str(e),
        )
        raise

Génère un rapport HTML

Args

data
Données à inclure dans le rapport HTML
filename
Nom de fichier personnalisé (optionnel)
template_name
Nom du template Jinja2 à utiliser

Returns

str
Chemin vers le fichier HTML généré
def generate_status_report(self, status_data: Dict[str, Any], filename: str = 'vm_status_report.html') ‑> str
Expand source code
def generate_status_report(
    self, status_data: Dict[str, Any], filename: str = "vm_status_report.html"
) -> str:
    """
    Génère un rapport de statut des VMs

    Args:
        status_data: Données de statut des VMs
        filename: Nom du fichier de sortie

    Returns:
        str: Chemin vers le fichier généré
    """
    logger.info("Génération du rapport de statut HTML", filename=filename)

    return self.generate(status_data, filename, "vm_status_report.html.j2")

Génère un rapport de statut des VMs

Args

status_data
Données de statut des VMs
filename
Nom du fichier de sortie

Returns

str
Chemin vers le fichier généré
def generate_users_vms_report(self, users: List[Dict[str, Any]], filename: str = 'vm_users.html') ‑> str
Expand source code
def generate_users_vms_report(
    self, users: List[Dict[str, Any]], filename: str = "vm_users.html"
) -> str:
    """
    Génère un rapport spécifique pour les utilisateurs et VMs

    Args:
        users: Liste des utilisateurs avec leurs VMs associées
        filename: Nom du fichier de sortie

    Returns:
        str: Chemin vers le fichier généré
    """
    logger.info(
        "Génération du rapport utilisateurs/VMs HTML",
        users_count=len(users),
        filename=filename,
    )

    # Statistiques supplémentaires
    stats = self._calculate_users_vms_stats(users)

    report_data = {
        "summary": {
            "total_users": len(users),
            "total_vms": stats["total_vms"],
            "vms_by_status": stats["vms_by_status"],
            "users_with_vms": stats["users_with_vms"],
            "users_without_vms": stats["users_without_vms"],
        },
        "users": users,
    }

    return self.generate(report_data, filename, "users_vms_report.html.j2")

Génère un rapport spécifique pour les utilisateurs et VMs

Args

users
Liste des utilisateurs avec leurs VMs associées
filename
Nom du fichier de sortie

Returns

str
Chemin vers le fichier généré
def get_extension(self) ‑> str
Expand source code
def get_extension(self) -> str:
    """Retourne l'extension des fichiers HTML"""
    return "html"

Retourne l'extension des fichiers HTML