Je vais créer un guide ultra-détaillé sur la documentation Python, en suivant la même structure exhaustive que le guide Flask. Ce sera LA référence complète pour maîtriser la documentation Python.

---

**Partie 1 : Fondamentaux de la Documentation**

Je vais commencer par créer la première partie qui couvre les bases essentielles de la documentation Python.

---

# ============================================================================
# [LIVRE] PYTHON DOCUMENTATION - GUIDE ULTRA-DÉTAILLÉ POUR DÉBUTANTS
# ============================================================================
#
# [OBJECTIF] GUIDE COMPLET POUR MAÎTRISER LA DOCUMENTATION PYTHON DE ZÉRO À EXPERT
#
# Ce guide est organisé en 4 parties progressives :
#
# PARTIE 1 : FONDAMENTAUX (documentation_partie1.txt)
# - Chapitre 0 : Introduction à la Documentation
# - Chapitre 1 : Docstrings (Documentation des fonctions/classes)
# - Chapitre 2 : Comments vs Docstrings
# - Chapitre 3 : Conventions PEP 257
#
# PARTIE 2 : OUTILS DE DOCUMENTATION (documentation_partie2.txt)
# - Chapitre 4 : Sphinx (Outil principal)
# - Chapitre 5 : Read the Docs
# - Chapitre 6 : MkDocs
# - Chapitre 7 : pdoc3
#
# PARTIE 3 : FORMATS AVANCÉS (documentation_partie3.txt)
# - Chapitre 8 : ReStructuredText (reST)
# - Chapitre 9 : Markdown
# - Chapitre 10 : Type Hints et Documentation
# - Chapitre 11 : Documentation d'API
#
# PARTIE 4 : BONNES PRATIQUES (documentation_partie4.txt)
# - Chapitre 12 : README.md
# - Chapitre 13 : CHANGELOG
# - Chapitre 14 : Documentation de Projet Complet
# - Chapitre 15 : Exemples et Tutoriels
#
# [TEMPS] TEMPS DE LECTURE TOTAL : ~15-20 heures
# [DOCS] PRÉREQUIS : Python de base (variables, fonctions, classes)
#
# [IDEE] COMMENT UTILISER CE GUIDE :
# 1. Lisez les parties dans l'ordre
# 2. Testez TOUS les exemples
# 3. Documentez vos propres projets
# 4. Créez votre portfolio documenté
#
# ============================================================================

"""
[OBJECTIF] PHILOSOPHIE DE CE GUIDE

COMMENT ? -> Explications pas à pas
POURQUOI ? -> Raisons et contexte
QUAND ? -> Cas d'usage concrets
PRATIQUE -> Exemples réels et exercices

Ce guide vise à être VOTRE SEULE RÉFÉRENCE pour la Documentation Python !
"""

# ============================================================================
# [NOTE] CONVENTIONS UTILISÉES DANS CE GUIDE
# ============================================================================

"""
[IDEE] Information importante
[REFLEXION] Question / Réflexion
[OK] Bonne pratique
[X] Mauvaise pratique
[ATTENTION] Attention / Avertissement
[CLE] Point clé à retenir
[COURS] Exercice pratique
[DOCS] Résumé
[OBJECTIF] Objectif
[TEMPS] Temps estimé
[RAPIDE] Prêt pour la suite
"""

# ============================================================================
# [OUTILS] CONFIGURATION DE L'ENVIRONNEMENT
# ============================================================================

"""
AVANT DE COMMENCER

1. INSTALLER PYTHON
   - Version recommandée : Python 3.8+
   - Vérifier : python --version

2. INSTALLER OUTILS DE DOCUMENTATION
"""

# Outils essentiels
pip install sphinx
pip install pdoc3
pip install mkdocs
pip install pydocstyle

# Vérifier installations
sphinx-build --version
pdoc3 --version
mkdocs --version

"""
3. ÉDITEUR RECOMMANDÉ
   
VS Code avec extensions :
- Python (Microsoft)
- Python Docstring Generator
- autoDocstring
- Markdown All in One

PyCharm :
- Intégration Sphinx native
- Génération docstrings automatique
"""


# ============================================================================
# [GUIDE] CHAPITRE 0 : INTRODUCTION À LA DOCUMENTATION
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Pourquoi documenter est crucial
[OK] Types de documentation
[OK] Qui lit votre documentation
[OK] Quand et quoi documenter
[OK] Principes d'une bonne documentation
"""


# ----------------------------------------------------------------------------
# [REFLEXION] POURQUOI DOCUMENTER ?
# ----------------------------------------------------------------------------

"""
PROBLÈME : CODE SANS DOCUMENTATION

Imaginez ce code sans documentation :
"""

# [X] Code non documenté (NE PAS FAIRE)
def p(x, y, z=True):
    if z:
        return x * y
    return x + y

r = p(5, 3)
s = p(5, 3, False)

"""
[X] PROBLÈMES MAJEURS

1. COMPRÉHENSION IMPOSSIBLE
   - Que fait cette fonction ?
   - Que signifient x, y, z ?
   - Pourquoi z=True par défaut ?

2. MAINTENANCE CAUCHEMARDESQUE
   - Dans 6 mois, vous ne comprendrez plus votre propre code
   - Modification = peur de tout casser

3. COLLABORATION IMPOSSIBLE
   - Nouveaux développeurs perdus
   - Pas de transfert de connaissance

4. PAS DE RÉUTILISATION
   - Personne n'ose utiliser ce code
   - Duplication de code

5. BUGS CACHÉS
   - Comportements non documentés
   - Effets de bord inconnus


[OK] AVEC DOCUMENTATION APPROPRIÉE
"""

def calculate_price(
    base_price: float,
    quantity: int,
    apply_discount: bool = True
) -> float:
    """
    Calcule le prix total d'un produit.
    
    Cette fonction calcule le prix en multipliant le prix de base
    par la quantité. Si apply_discount est True, une réduction de 10%
    est appliquée sur le total.
    
    Args:
        base_price (float): Prix unitaire du produit en euros.
            Doit être positif.
        quantity (int): Nombre d'unités à acheter.
            Doit être supérieur à 0.
        apply_discount (bool, optional): Si True, applique une réduction
            de 10% sur le total. Par défaut True.
    
    Returns:
        float: Prix total après calcul, avec ou sans réduction.
    
    Raises:
        ValueError: Si base_price est négatif ou quantity <= 0.
    
    Examples:
        >>> calculate_price(10.0, 5)
        45.0
        
        >>> calculate_price(10.0, 5, apply_discount=False)
        50.0
        
        >>> calculate_price(-10, 5)
        Traceback (most recent call last):
            ...
        ValueError: base_price doit être positif
    
    Note:
        La réduction est fixée à 10% et ne peut pas être modifiée.
        Pour des remises personnalisées, utilisez calculate_custom_discount().
    
    See Also:
        calculate_custom_discount: Pour des remises personnalisées
        get_bulk_discount: Pour des remises sur quantité
    """
    if base_price < 0:
        raise ValueError("base_price doit être positif")
    if quantity <= 0:
        raise ValueError("quantity doit être supérieur à 0")
    
    total = base_price * quantity
    
    if apply_discount:
        total *= 0.9  # Réduction de 10%
    
    return total

"""
[OK] AVANTAGES DOCUMENTATION

1. COMPRÉHENSION IMMÉDIATE
   - Objectif clair
   - Paramètres expliqués
   - Comportement documenté

2. MAINTENANCE FACILE
   - Modifications en confiance
   - Effets de bord connus
   - Evolution sereine

3. COLLABORATION EFFICACE
   - Nouveaux développeurs autonomes
   - API claire
   - Standards partagés

4. RÉUTILISATION
   - Code réutilisable
   - Exemples concrets
   - Tests intégrés

5. QUALITÉ PROFESSIONNELLE
   - Crédibilité
   - Confiance
   - Open-source friendly


[IDEE] DOCUMENTATION = INVESTISSEMENT

Temps passé : 20% de développement
Gain : 80% de temps de maintenance

Ratio : 1h doc -> 4h de debug économisées !
"""


# ----------------------------------------------------------------------------
# [DOCS] TYPES DE DOCUMENTATION
# ----------------------------------------------------------------------------

"""
1. DOCUMENTATION INLINE (DANS LE CODE)
──────────────────────────────────────

A. COMMENTS (#)
   - Explications courtes
   - Pourquoi, pas quoi
   - Contexte spécifique
"""

# Calculer la TVA à 20% (taux français en vigueur)
price_with_tax = price * 1.20

# HACK: API retourne parfois None, on utilise 0 par défaut
value = api_response or 0

# TODO: Optimiser cette boucle (complexité O(n²))
for i in items:
    for j in items:
        process(i, j)

"""
B. DOCSTRINGS (""" """)
   - Documentation fonctions/classes
   - Accessible via help()
   - Générée automatiquement
"""

def factorial(n):
    """Calcule la factorielle de n."""
    return 1 if n <= 1 else n * factorial(n-1)

# Accessible via
help(factorial)
print(factorial.__doc__)

"""
2. DOCUMENTATION EXTERNE
────────────────────────

A. README.md
   - Première impression
   - Installation
   - Quick start
"""

# README.md
"""
# Mon Projet

Description courte du projet.

## Installation

```bash
pip install mon-projet
```

## Utilisation

```python
from mon_projet import calculate
result = calculate(10, 5)
```
"""

"""
B. DOCUMENTATION TECHNIQUE (Sphinx, MkDocs)
   - Reference API complète
   - Tutoriels détaillés
   - Architecture du projet
   - Générée depuis docstrings


C. CHANGELOG.md
   - Historique des versions
   - Changements majeurs
   - Migrations nécessaires


D. CONTRIBUTING.md
   - Guide de contribution
   - Standards de code
   - Process de PR


3. DOCUMENTATION UTILISATEUR
────────────────────────────

A. TUTORIELS
   - Pas à pas débutants
   - Cas d'usage concrets
   - Screenshots/vidéos


B. HOW-TO GUIDES
   - Résoudre problèmes spécifiques
   - Recettes pratiques
   - Best practices


C. REFERENCE API
   - Liste exhaustive fonctions
   - Paramètres détaillés
   - Exemples d'utilisation


D. EXPLICATIONS
   - Concepts architecturaux
   - Choix de design
   - Pourquoi et comment
"""


# ----------------------------------------------------------------------------
# [UTILISATEURS] QUI LIT VOTRE DOCUMENTATION ?
# ----------------------------------------------------------------------------

"""
AUDIENCE CIBLE ET BESOINS


1. VOUS (DANS 6 MOIS) [REFLEXION]
──────────────────────

Besoins :
- Comprendre rapidement votre code
- Savoir pourquoi vous avez fait ce choix
- Retrouver comment utiliser cette fonction

Documentation nécessaire :
[OK] Comments pour décisions non-évidentes
[OK] Docstrings claires et complètes
[OK] README à jour


2. VOS COLLÈGUES [UTILISATEURS]
───────────────────

Besoins :
- Utiliser votre code sans vous déranger
- Comprendre l'architecture
- Contribuer efficacement

Documentation nécessaire :
[OK] Docstrings détaillées
[OK] CONTRIBUTING.md
[OK] Architecture documentation
[OK] Exemples d'utilisation


3. NOUVEAUX DÉVELOPPEURS 🆕
────────────────────────────

Besoins :
- Onboarding rapide
- Comprendre le projet globalement
- Savoir par où commencer

Documentation nécessaire :
[OK] README complet
[OK] Tutoriel Getting Started
[OK] Glossaire des termes
[OK] Architecture overview


4. UTILISATEURS FINAUX [UTILISATEUR]
──────────────────────────

Besoins :
- Installer facilement
- Utiliser sans être développeur
- Résoudre problèmes courants

Documentation nécessaire :
[OK] Installation guide
[OK] Quick start
[OK] FAQ
[OK] Troubleshooting


5. CONTRIBUTEURS OPEN-SOURCE [MONDE]
────────────────────────────────

Besoins :
- Comprendre comment contribuer
- Standards de code
- Process de review

Documentation nécessaire :
[OK] CONTRIBUTING.md
[OK] Code of Conduct
[OK] Development setup
[OK] Testing guide


[IDEE] ADAPTER LA DOCUMENTATION À L'AUDIENCE

Documentation Technique (développeurs) :
- Détails d'implémentation
- Type hints
- Complexité algorithmique
- Edge cases

Documentation Utilisateur :
- Langage simple
- Exemples concrets
- Pas de jargon
- Visuels
"""


# ----------------------------------------------------------------------------
# [NOTE] QUAND DOCUMENTER ?
# ----------------------------------------------------------------------------

"""
RÈGLE D'OR : Documenter AU MOMENT DE L'ÉCRITURE


TIMELINE IDÉALE
───────────────

1. AVANT LE CODE (Design) [MESURE]
   
   Documenter :
   - Objectif de la fonctionnalité
   - Signature de la fonction
   - Comportement attendu
"""

def process_payment(amount: float, currency: str) -> bool:
    """
    Traite un paiement dans la devise spécifiée.
    
    [À IMPLÉMENTER]
    
    Args:
        amount: Montant à payer (positif)
        currency: Code ISO 4217 (EUR, USD, etc.)
    
    Returns:
        True si paiement réussi, False sinon
    """
    pass  # TODO: Implémenter

"""
2. PENDANT LE CODE (Implémentation) [CODE]

   Documenter :
   - Décisions non-évidentes
   - Workarounds
   - Limitations connues
"""

def process_payment(amount: float, currency: str) -> bool:
    # Vérifications de base
    if amount <= 0:
        return False
    
    # HACK: L'API accepte seulement 2 décimales
    # On arrondit pour éviter les erreurs
    amount = round(amount, 2)
    
    # TODO: Ajouter support pour crypto-monnaies
    
    return api.charge(amount, currency)

"""
3. APRÈS LE CODE (Finalisation) [OK]

   Documenter :
   - Exemples d'utilisation
   - Tests en docstring
   - Edge cases découverts
"""

def process_payment(amount: float, currency: str) -> bool:
    """
    [Documentation complète avec exemples]
    
    Examples:
        >>> process_payment(100.50, "EUR")
        True
        
        >>> process_payment(-10, "USD")
        False
        
        >>> process_payment(0.001, "EUR")  # Arrondi à 0.00
        False
    """
    pass


"""
MOMENTS CLÉs POUR DOCUMENTER
─────────────────────────────

[OK] TOUJOURS DOCUMENTER :

1. Fonctions publiques (API)
2. Classes et méthodes
3. Modules
4. Paramètres non-évidents
5. Valeurs de retour complexes
6. Exceptions levées
7. Effets de bord
8. Dépendances externes


[X] PAS BESOIN DE DOCUMENTER :

1. Code trivial évident
"""

# [X] Sur-documentation inutile
def add(a, b):
    """Additionne a et b."""  # Évident !
    return a + b

"""
2. Getters/setters simples
"""

@property
def name(self):
    """Retourne le nom."""  # Évident !
    return self._name

"""
3. Fonctions privées triviales
"""

def _format_date(date):  # Privée, simple, nom explicite
    return date.strftime("%Y-%m-%d")

"""
[ATTENTION] MAIS : Si comportement non-évident, DOCUMENTER !
"""

def _calculate_tax(amount):
    """
    Calcule la taxe avec règles françaises 2024.
    
    Règles :
    - < 1000€ : TVA 20%
    - >= 1000€ : TVA 20% + taxe luxe 5%
    
    Note: Règles mises à jour annuellement
    """
    pass


"""
DOCUMENTER LORS DES CHANGEMENTS
────────────────────────────────

[OK] Mettre à jour documentation SI :

1. Changement de signature
"""

# Avant
def send_email(to, subject, body):
    """Envoie un email simple."""
    pass

# Après (DOCUMENTER LE CHANGEMENT)
def send_email(to, subject, body, cc=None, bcc=None, attachments=None):
    """
    Envoie un email avec options avancées.
    
    Note:
        Version 2.0 : Ajout des paramètres cc, bcc et attachments.
        Pour compatibilité, utilisez les arguments nommés.
    
    Args:
        cc (list, optional): Destinataires en copie. Nouveau en v2.0.
        bcc (list, optional): Copie cachée. Nouveau en v2.0.
        attachments (list, optional): Fichiers joints. Nouveau en v2.0.
    """
    pass

"""
2. Changement de comportement
"""

def calculate_discount(price):
    """
    Calcule la remise sur le prix.
    
    Comportement :
        Version < 2.0 : Remise fixe de 10%
        Version >= 2.0 : Remise progressive selon prix
            - < 100€ : 5%
            - 100-500€ : 10%
            - > 500€ : 15%
    
    Changed:
        Version 2.0 : Passage à remise progressive
    """
    pass

"""
3. Dépréciation
"""

def old_function():
    """
    Ancienne fonction (DÉPRÉCIÉE).
    
    .. deprecated:: 2.0
        Utilisez :func:`new_function` à la place.
        old_function() sera supprimée en version 3.0.
    
    Migration:
        >>> # Ancien code
        >>> result = old_function()
        
        >>> # Nouveau code
        >>> result = new_function()
    """
    import warnings
    warnings.warn(
        "old_function est dépréciée, utilisez new_function",
        DeprecationWarning,
        stacklevel=2
    )
    pass
"""


# ----------------------------------------------------------------------------
# [OBJECTIF] QUOI DOCUMENTER ?
# ----------------------------------------------------------------------------

"""
CHECKLIST : ÉLÉMENTS À DOCUMENTER


1. FONCTIONS
────────────

[OK] À documenter :
"""

def fetch_user_data(
    user_id: int,
    include_posts: bool = False,
    max_posts: int = 10
) -> dict:
    """
    Récupère les données d'un utilisateur depuis l'API.
    
    Description détaillée du comportement, cas particuliers,
    limitations, etc.
    
    Args:
        user_id (int): Identifiant unique de l'utilisateur.
            Doit être positif et exister dans la base.
        include_posts (bool, optional): Si True, inclut les posts
            de l'utilisateur dans la réponse. Défaut False.
        max_posts (int, optional): Nombre maximum de posts à inclure
            si include_posts=True. Défaut 10, max 100.
    
    Returns:
        dict: Dictionnaire contenant les données utilisateur.
            Structure :
            {
                'id': int,
                'username': str,
                'email': str,
                'posts': list[dict] (si include_posts=True)
            }
    
    Raises:
        ValueError: Si user_id <= 0 ou max_posts > 100.
        UserNotFoundError: Si l'utilisateur n'existe pas.
        APIConnectionError: Si connexion API échoue.
    
    Examples:
        >>> data = fetch_user_data(123)
        >>> print(data['username'])
        'john_doe'
        
        >>> data = fetch_user_data(123, include_posts=True, max_posts=5)
        >>> len(data['posts'])
        5
    
    Note:
        L'API a un rate limit de 100 requêtes/minute.
        Utilisez fetch_users_batch() pour récupérer plusieurs
        utilisateurs efficacement.
    
    Warning:
        Le champ 'email' peut être None si utilisateur n'a pas
        vérifié son email.
    
    See Also:
        fetch_users_batch : Récupérer plusieurs utilisateurs
        update_user_data : Mettre à jour un utilisateur
    """
    pass

"""
Éléments documentés :
1. Description (quoi, pourquoi)
2. Chaque paramètre (type, signification, contraintes)
3. Valeur de retour (type, structure)
4. Exceptions possibles
5. Exemples concrets
6. Notes et warnings
7. Fonctions liées


2. CLASSES
──────────

[OK] À documenter :
"""

class UserManager:
    """
    Gestionnaire des opérations sur les utilisateurs.
    
    Cette classe fournit une interface unifiée pour toutes les
    opérations CRUD sur les utilisateurs. Elle gère automatiquement
    la connexion à la base de données et la validation.
    
    Attributes:
        db_connection (Connection): Connexion active à la base de données.
        cache (dict): Cache en mémoire des utilisateurs récemment accédés.
        max_cache_size (int): Taille maximale du cache (défaut 1000).
    
    Examples:
        >>> manager = UserManager(db_connection)
        >>> user = manager.create_user('john', 'john@example.com')
        >>> print(user.username)
        'john'
        
        >>> users = manager.get_users(age_min=18)
        >>> len(users)
        42
    
    Note:
        UserManager n'est pas thread-safe. Utilisez un gestionnaire
        par thread ou verrouillez les accès concurrents.
    
    See Also:
        User : Modèle de données utilisateur
        AdminManager : Gestionnaire pour opérations admin
    """
    
    def __init__(self, db_connection, max_cache_size=1000):
        """
        Initialise le gestionnaire d'utilisateurs.
        
        Args:
            db_connection (Connection): Connexion DB active et valide.
            max_cache_size (int, optional): Taille max du cache.
                Défaut 1000. Min 10, Max 10000.
        
        Raises:
            ValueError: Si max_cache_size hors limites.
            ConnectionError: Si db_connection invalide ou fermée.
        
        Examples:
            >>> conn = create_connection()
            >>> manager = UserManager(conn)
            
            >>> manager = UserManager(conn, max_cache_size=5000)
        """
        pass
    
    def create_user(self, username, email, password):
        """
        Crée un nouvel utilisateur.
        
        Le mot de passe est automatiquement hashé avant stockage.
        Un email de vérification est envoyé à l'adresse fournie.
        
        Args:
            username (str): Nom d'utilisateur unique. 3-20 caractères,
                alphanumériques et underscore uniquement.
            email (str): Adresse email valide et unique.
            password (str): Mot de passe en clair. Min 8 caractères,
                doit contenir majuscule, minuscule, chiffre.
        
        Returns:
            User: Objet utilisateur créé avec id assigné.
        
        Raises:
            ValueError: Si validation échoue (username/email/password).
            DuplicateError: Si username ou email déjà existe.
            EmailError: Si envoi email de vérification échoue.
        
        Examples:
            >>> user = manager.create_user(
            ...     'john_doe',
            ...     'john@example.com',
            ...     'SecurePass123'
            ... )
            >>> user.id
            1
            >>> user.is_verified
            False
        
        Note:
            L'utilisateur doit vérifier son email avant de pouvoir
            se connecter. Vérification expira après 24h.
        
        See Also:
            verify_email : Vérifier l'email d'un utilisateur
            update_password : Changer le mot de passe
        """
        pass

"""
3. MODULES
──────────

[OK] Documenter en haut du fichier :
"""

# users.py
"""
Module de gestion des utilisateurs.

Ce module fournit toutes les fonctionnalités nécessaires pour
gérer les utilisateurs de l'application, incluant :
- Création et suppression
- Authentification
- Gestion des profils
- Permissions et rôles

Usage typique :
    >>> from users import UserManager
    >>> manager = UserManager(db)
    >>> user = manager.create_user('john', 'john@example.com')

Classes:
    UserManager: Gestionnaire principal des utilisateurs
    User: Modèle de données utilisateur
    UserRole: Énumération des rôles possibles

Fonctions:
    authenticate: Authentifie un utilisateur
    hash_password: Hashe un mot de passe
    validate_email: Valide format email

Exceptions:
    UserNotFoundError: Utilisateur introuvable
    DuplicateUserError: Utilisateur déjà existe
    AuthenticationError: Échec d'authentification

Note:
    Ce module nécessite une connexion base de données active.
    Configurez la connexion avant d'utiliser UserManager.

Example:
    Configuration et utilisation complète :
    
    >>> from database import create_connection
    >>> from users import UserManager
    >>> 
    >>> conn = create_connection('postgresql://...')
    >>> manager = UserManager(conn)
    >>> 
    >>> # Créer utilisateur
    >>> user = manager.create_user('alice', 'alice@example.com', 'pass123')
    >>> 
    >>> # Authentifier
    >>> if manager.authenticate('alice', 'pass123'):
    ...     print('Login success')

Author:
    Votre Nom <email@example.com>

Version:
    2.1.0

Since:
    1.0.0

See Also:
    database: Module de connexion base de données
    auth: Module d'authentification avancée
"""

"""
4. CONSTANTES ET VARIABLES GLOBALES
────────────────────────────────────

[OK] Documenter constantes importantes :
"""

# Configuration API
API_BASE_URL = "https://api.example.com/v1"
"""str: URL de base de l'API externe.

Cette URL est utilisée pour toutes les requêtes API.
Peut être surchargée via variable d'environnement API_URL.

Example:
    >>> import os
    >>> os.environ['API_URL'] = 'https://api-dev.example.com/v1'
    >>> # API_BASE_URL sera maintenant l'URL de dev
"""

MAX_RETRIES = 3
"""int: Nombre maximum de tentatives pour requêtes API.

Si une requête échoue, elle sera automatiquement retentée jusqu'à
MAX_RETRIES fois avec délai exponentiel entre chaque tentative.

Warning:
    Valeur trop haute peut causer des timeouts longs.
    Valeur recommandée : 3-5
"""

SUPPORTED_FORMATS = ['json', 'xml', 'csv']
"""list[str]: Formats de données supportés par l'API.

Formats valides pour paramètre 'format' dans les requêtes.
Tout autre format causera une ValueError.

See Also:
    parse_response : Parse la réponse selon le format
"""


"""
5. EXCEPTIONS PERSONNALISÉES
─────────────────────────────

[OK] Documenter exceptions :
"""

class UserNotFoundError(Exception):
    """
    Exception levée quand un utilisateur est introuvable.
    
    Cette exception est levée par UserManager.get_user() et méthodes
    similaires quand l'utilisateur demandé n'existe pas dans la base.
    
    Attributes:
        user_id (int): ID de l'utilisateur recherché.
        message (str): Message d'erreur descriptif.
    
    Example:
        >>> try:
        ...     user = manager.get_user(999)
        ... except UserNotFoundError as e:
        ...     print(f"User {e.user_id} not found: {e.message}")
    """
    
    def __init__(self, user_id, message=None):
        self.user_id = user_id
        self.message = message or f"User with ID {user_id} not found"
        super().__init__(self.message)


class ValidationError(Exception):
    """
    Exception levée lors d'erreur de validation.
    
    Raised when:
        - Format de données invalide
        - Contraintes non respectées
        - Valeurs hors limites
    
    Attributes:
        field (str): Nom du champ en erreur.
        value: Valeur rejetée.
        reason (str): Raison du rejet.
    
    Examples:
        >>> try:
        ...     user.email = "invalid-email"
        ... except ValidationError as e:
        ...     print(f"{e.field}: {e.reason}")
        email: Format email invalide
    """
    pass
"""


# ----------------------------------------------------------------------------
# [OK] PRINCIPES D'UNE BONNE DOCUMENTATION
# ----------------------------------------------------------------------------

"""
10 RÈGLES D'OR


1. CLAIRE ET CONCISE
────────────────────

[X] Mauvais : Verbeux et confus
def process(x):
    \"\"\"
    Cette fonction prend un paramètre x qui peut être de différents types
    et fait des choses avec selon le type mais ça dépend vraiment de ce
    que vous voulez faire et...
    \"\"\"

[OK] Bon : Direct et précis
def process_data(data: dict) -> dict:
    \"\"\"
    Valide et normalise les données d'entrée.
    
    Args:
        data: Dictionnaire de données brutes.
    
    Returns:
        Dictionnaire de données validées et normalisées.
    \"\"\"


2. COMPLÈTE MAIS PAS EXHAUSTIVE
────────────────────────────────

[OK] Documenter :
- Ce qui n'est PAS évident
- Comportements surprenants
- Limitations
- Cas particuliers

[X] Ne pas documenter :
- Chaque ligne de code
- Détails d'implémentation évidents
- Code qui se lit naturellement


3. EXEMPLES CONCRETS
─────────────────────

[OK] Toujours inclure exemples :
\"\"\"
Examples:
    >>> calculate_discount(100, 0.1)
    90.0
    
    >>> calculate_discount(100, 0)
    100.0
\"\"\"


4. ACCESSIBLE À L'AUDIENCE
───────────────────────────

Pour débutants :
\"\"\"
Calcule la moyenne d'une liste de nombres.

Example:
    >>> moyenne([1, 2, 3, 4, 5])
    3.0
\"\"\"

Pour experts :
\"\"\"
Calcule la moyenne arithmétique pondérée.

Complexité : O(n)
Thread-safe : Non

Args:
    values: Séquence de valeurs numériques.
    weights: Poids optionnels (même longueur que values).

Returns:
    float: Moyenne pondérée ou None si values vide.

Raises:
    ValueError: Si len(values) != len(weights).
\"\"\"


5. À JOUR
─────────

[OK] Mettre à jour documentation AVANT le commit
[X] Documentation obsolète pire que pas de documentation


6. CORRECTE GRAMMATICALEMENT
─────────────────────────────

[OK] Orthographe et grammaire soignées
[OK] Phrases complètes
[OK] Ponctuation correcte

[X] "calcul prix avec remise si actif"
[OK] "Calcule le prix avec remise si l'utilisateur est actif."


7. FORMATS STANDARDS
────────────────────

[OK] Suivre PEP 257 pour docstrings
[OK] Utiliser formats reconnus (Google, NumPy, Sphinx)
[OK] Cohérence dans tout le projet


8. LIENS ET RÉFÉRENCES
───────────────────────

[OK] Lier vers documentation connexe
\"\"\"
See Also:
    calculate_total : Calcule le total sans remise
    get_discount_rate : Obtient le taux de remise
\"\"\"


9. VERSIONNING
──────────────

[OK] Documenter changements de version
\"\"\"
.. versionadded:: 2.0
   Support des remises personnalisées

.. versionchanged:: 2.1
   Ajout paramètre max_discount

.. deprecated:: 3.0
   Utilisez calculate_custom_discount() à la place
\"\"\"


10. TESTABLE
────────────

[OK] Exemples dans docstrings = tests
\"\"\"
>>> add(2, 3)
5
>>> add(-1, 1)
0
\"\"\"

# Test avec doctest
python -m doctest module.py -v
"""


# ============================================================================
# [DOCS] RÉCAPITULATIF CHAPITRE 0
# ============================================================================

"""
CE QUE VOUS AVEZ APPRIS

[OK] Pourquoi documenter est crucial
[OK] Types de documentation (inline, externe, utilisateur)
[OK] Audiences cibles et leurs besoins
[OK] Quand documenter (timeline idéale)
[OK] Quoi documenter (fonctions, classes, modules, exceptions)
[OK] Principes d'une bonne documentation


[CLE] POINTS CLÉS

1. Documentation = Investissement rentable
2. Documenter AU MOMENT de l'écriture
3. Adapter à l'audience
4. Être clair, concis, complet
5. Exemples > Descriptions abstraites
6. Mettre à jour = Responsabilité


[OBJECTIF] AVANT DE CONTINUER

Assurez-vous de comprendre :
[OK] Différence comments / docstrings
[OK] Types de documentation
[OK] Quand documenter quoi
[OK] Éléments à documenter


-> PROCHAINE ÉTAPE : Chapitre 1 - Docstrings !

Vous allez apprendre :
- Syntaxe complète des docstrings
- Formats (Google, NumPy, Sphinx)
- Docstrings pour fonctions, classes, modules
- Génération automatique
- Doctest

Prêt ? C'est parti ! [RAPIDE]
"""

# ============================================================================
# FIN DU CHAPITRE 0
# CONTINUEZ AVEC LE CHAPITRE 1 CI-DESSOUS
# ============================================================================

J'ai créé le début du guide ultra-détaillé sur la documentation Python. Le Chapitre 0 couvre les fondamentaux essentiels sur environ 1000 lignes.

**Ce qui est inclus dans ce premier artifact :**

### [OK] Chapitre 0 : Introduction à la Documentation
1. **Pourquoi documenter** - Comparaison code non documenté vs documenté
2. **Types de documentation** - Inline, externe, utilisateur
3. **Audiences** - Qui lit votre documentation et leurs besoins
4. **Quand documenter** - Timeline idéale (avant/pendant/après)
5. **Quoi documenter** - Fonctions, classes, modules, exceptions
6. **Principes** - 10 règles d'or

Voulez-vous que je continue avec :
- **Chapitre 1 : Docstrings** (syntaxe, formats, exemples détaillés)
- **Chapitre 2 : Comments vs Docstrings**
- **Chapitre 3 : Conventions PEP 257**

Pour compléter la **Partie 1** ?

# ============================================================================
# [GUIDE] CHAPITRE 1 : DOCSTRINGS (DOCUMENTATION DES FONCTIONS/CLASSES)
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Qu'est-ce qu'une docstring et comment ça marche
[OK] Syntaxe de base et règles
[OK] Docstrings pour fonctions simples et complexes
[OK] Docstrings pour classes et méthodes
[OK] Docstrings pour modules et packages
[OK] Formats standards (Google, NumPy, Sphinx)
[OK] Accéder aux docstrings programmatiquement
[OK] Doctest : tests dans les docstrings
"""


# ----------------------------------------------------------------------------
# [REFLEXION] QU'EST-CE QU'UNE DOCSTRING ?
# ----------------------------------------------------------------------------

"""
DÉFINITION

Docstring = "Documentation String"
- Chaîne de caractères littérale
- Première instruction d'un module, fonction, classe ou méthode
- Délimitée par triple quotes (''' ou \"\"\")
- Accessible via attribut __doc__


[IDEE] DIFFÉRENCE AVEC COMMENT

Comment (#) :
- Pour les développeurs lisant le code
- Explique POURQUOI et COMMENT
- Pas accessible programmatiquement
- Ne figure pas dans documentation générée

Docstring (\"\"\" \"\"\") :
- Pour les utilisateurs du code
- Explique QUOI et COMMENT UTILISER
- Accessible via help() et __doc__
- Utilisée pour générer documentation
"""

# Exemple de différence
def calculate_tax(amount):
    """
    Calcule la TVA sur un montant donné.
    
    Cette docstring explique quoi fait la fonction
    et comment l'utiliser.
    """
    
    # Ce commentaire explique POURQUOI on utilise 0.20
    # (taux de TVA français en 2024)
    tax_rate = 0.20
    
    # HACK: Arrondir pour éviter problèmes float
    return round(amount * tax_rate, 2)


"""
[IDEE] ACCÈS AUX DOCSTRINGS

3 façons d'accéder :
"""

# 1. Avec help()
help(calculate_tax)
"""
Output:
Help on function calculate_tax in module __main__:

calculate_tax(amount)
    Calcule la TVA sur un montant donné.
    
    Cette docstring explique quoi fait la fonction
    et comment l'utiliser.
"""

# 2. Avec __doc__
print(calculate_tax.__doc__)
"""
Output:
    Calcule la TVA sur un montant donné.
    
    Cette docstring explique quoi fait la fonction
    et comment l'utiliser.
"""

# 3. Avec inspect
import inspect
print(inspect.getdoc(calculate_tax))


# ----------------------------------------------------------------------------
# [NOTE] SYNTAXE DE BASE
# ----------------------------------------------------------------------------

"""
RÈGLES FONDAMENTALES


1. POSITION
───────────

Docstring = PREMIÈRE instruction après la définition
"""

# [OK] BON
def good_example():
    """Ceci est une docstring."""
    return True

# [X] MAUVAIS
def bad_example():
    x = 1  # <- Code avant docstring
    """Ceci n'est PAS une docstring."""  # <- Juste une string
    return x

"""
2. DÉLIMITEURS
──────────────

Triple quotes : ''' ou \"\"\"
Recommandé : \"\"\" (plus courant)
"""

# [OK] Acceptable
def example1():
    '''Docstring avec simple quotes.'''
    pass

# [OK] Recommandé
def example2():
    """Docstring avec double quotes."""
    pass

"""
3. FORMAT ONE-LINE
──────────────────

Pour fonctions simples : tout sur une ligne
"""

def add(a, b):
    """Additionne deux nombres."""
    return a + b

def get_name():
    """Retourne le nom de l'utilisateur."""
    return self.name

"""
Règles one-line :
- Commencer et finir sur la même ligne
- Triple quotes au début ET à la fin
- Phrase complète avec point final
- Pas de ligne vide avant ou après
"""

# [OK] BON
def square(n):
    """Retourne le carré de n."""
    return n ** 2

# [X] MAUVAIS : Multi-lignes inutile
def square(n):
    """
    Retourne le carré de n.
    """
    return n ** 2

# [X] MAUVAIS : Pas de point final
def square(n):
    """Retourne le carré de n"""
    return n ** 2

"""
4. FORMAT MULTI-LINE
────────────────────

Pour fonctions complexes : plusieurs lignes
"""

def complex_function(param1, param2):
    """
    Ligne de résumé (impérative, se termine par un point).
    
    Description détaillée sur plusieurs paragraphes si nécessaire.
    Expliquez le comportement, les cas particuliers, etc.
    
    Args:
        param1: Description du premier paramètre.
        param2: Description du second paramètre.
    
    Returns:
        Description de la valeur de retour.
    """
    pass

"""
Règles multi-line :
1. Ligne de résumé (< 80 caractères)
2. Ligne vide
3. Description détaillée
4. Sections (Args, Returns, etc.)
5. """ sur ligne séparée à la fin
"""


# ----------------------------------------------------------------------------
# [LISTE] DOCSTRINGS POUR FONCTIONS
# ----------------------------------------------------------------------------

"""
FONCTION SIMPLE
───────────────

Une ligne suffit si comportement évident
"""

def is_even(n):
    """Retourne True si n est pair."""
    return n % 2 == 0

def capitalize(text):
    """Met la première lettre en majuscule."""
    return text.capitalize()

def get_current_time():
    """Retourne l'heure actuelle."""
    from datetime import datetime
    return datetime.now()


"""
FONCTION AVEC PARAMÈTRES
─────────────────────────

Documenter chaque paramètre
"""

def greet(name, title=None):
    """
    Génère un message de salutation personnalisé.
    
    Args:
        name (str): Nom de la personne à saluer.
        title (str, optional): Titre de civilité (M., Mme, Dr, etc.).
            Si None, pas de titre utilisé. Défaut à None.
    
    Returns:
        str: Message de salutation complet.
    
    Examples:
        >>> greet("Alice")
        'Bonjour Alice !'
        
        >>> greet("Smith", title="Dr")
        'Bonjour Dr Smith !'
    """
    if title:
        return f"Bonjour {title} {name} !"
    return f"Bonjour {name} !"


"""
FONCTION AVEC VALEUR DE RETOUR COMPLEXE
────────────────────────────────────────

Détailler la structure retournée
"""

def get_user_info(user_id):
    """
    Récupère les informations complètes d'un utilisateur.
    
    Args:
        user_id (int): Identifiant unique de l'utilisateur.
    
    Returns:
        dict: Informations utilisateur avec les clés suivantes :
            - 'id' (int): Identifiant de l'utilisateur
            - 'username' (str): Nom d'utilisateur
            - 'email' (str): Adresse email
            - 'created_at' (datetime): Date de création du compte
            - 'is_active' (bool): Statut actif/inactif
            - 'roles' (list[str]): Liste des rôles assignés
        
        Retourne None si utilisateur introuvable.
    
    Examples:
        >>> info = get_user_info(123)
        >>> print(info['username'])
        'john_doe'
        >>> print(info['roles'])
        ['user', 'moderator']
    """
    pass


"""
FONCTION AVEC EXCEPTIONS
─────────────────────────

Documenter toutes les exceptions levées
"""

def divide(a, b):
    """
    Divise a par b.
    
    Args:
        a (float): Numérateur.
        b (float): Dénominateur.
    
    Returns:
        float: Résultat de la division a/b.
    
    Raises:
        ZeroDivisionError: Si b est égal à 0.
        TypeError: Si a ou b ne sont pas numériques.
    
    Examples:
        >>> divide(10, 2)
        5.0
        
        >>> divide(10, 0)
        Traceback (most recent call last):
            ...
        ZeroDivisionError: division by zero
    
    Note:
        Le résultat est toujours retourné en float, même si
        les arguments sont des entiers.
    """
    if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
        raise TypeError("Arguments doivent être numériques")
    if b == 0:
        raise ZeroDivisionError("division by zero")
    return a / b


"""
FONCTION AVEC EFFETS DE BORD
─────────────────────────────

Documenter les modifications externes
"""

def save_user(user, db_connection):
    """
    Sauvegarde un utilisateur dans la base de données.
    
    Cette fonction modifie directement la base de données et met à jour
    l'attribut user.id avec l'ID assigné par la base.
    
    Args:
        user (User): Objet utilisateur à sauvegarder.
        db_connection (Connection): Connexion active à la base de données.
    
    Returns:
        int: ID de l'utilisateur sauvegardé.
    
    Side Effects:
        - Insert une nouvelle ligne dans la table 'users'
        - Modifie user.id avec l'ID généré
        - Commit la transaction si auto-commit activé
    
    Raises:
        DatabaseError: Si erreur lors de l'insertion.
        ValidationError: Si user contient des données invalides.
    
    Warning:
        Cette fonction commit automatiquement si db_connection.auto_commit
        est True. Assurez-vous de gérer les transactions manuellement
        si nécessaire.
    
    Examples:
        >>> user = User(username='alice', email='alice@example.com')
        >>> user_id = save_user(user, db)
        >>> print(user.id)  # ID a été modifié
        1
    """
    pass


"""
FONCTION AVEC TYPE HINTS
─────────────────────────

Les type hints complètent la docstring
"""

from typing import List, Optional, Dict, Union

def filter_users(
    users: List[Dict[str, any]],
    role: Optional[str] = None,
    active_only: bool = True
) -> List[Dict[str, any]]:
    """
    Filtre une liste d'utilisateurs selon critères.
    
    Args:
        users: Liste de dictionnaires représentant les utilisateurs.
            Chaque dict doit contenir au minimum les clés 'role' et 'is_active'.
        role: Si spécifié, ne garde que les utilisateurs avec ce rôle.
            Si None, tous les rôles sont inclus.
        active_only: Si True, exclut les utilisateurs inactifs.
    
    Returns:
        Liste filtrée d'utilisateurs répondant aux critères.
        Liste vide si aucun utilisateur ne correspond.
    
    Examples:
        >>> users = [
        ...     {'name': 'Alice', 'role': 'admin', 'is_active': True},
        ...     {'name': 'Bob', 'role': 'user', 'is_active': False},
        ...     {'name': 'Charlie', 'role': 'admin', 'is_active': True}
        ... ]
        >>> filter_users(users, role='admin')
        [{'name': 'Alice', 'role': 'admin', 'is_active': True},
         {'name': 'Charlie', 'role': 'admin', 'is_active': True}]
        
        >>> filter_users(users, active_only=False)
        [{'name': 'Alice', ...}, {'name': 'Bob', ...}, {'name': 'Charlie', ...}]
    """
    pass


# ----------------------------------------------------------------------------
# [CLASSICAL_BUILDING] DOCSTRINGS POUR CLASSES
# ----------------------------------------------------------------------------

"""
CLASSE SIMPLE
─────────────

Docstring de classe + docstring __init__
"""

class User:
    """
    Représente un utilisateur de l'application.
    
    Cette classe encapsule toutes les données et comportements
    relatifs à un utilisateur : profil, authentification, permissions.
    
    Attributes:
        username (str): Nom d'utilisateur unique.
        email (str): Adresse email de l'utilisateur.
        is_active (bool): Statut actif/inactif du compte.
        created_at (datetime): Date de création du compte.
    
    Examples:
        >>> user = User('alice', 'alice@example.com')
        >>> print(user.username)
        'alice'
        >>> user.activate()
        >>> print(user.is_active)
        True
    """
    
    def __init__(self, username, email):
        """
        Initialise un nouvel utilisateur.
        
        Args:
            username (str): Nom d'utilisateur (3-20 caractères).
            email (str): Adresse email valide.
        
        Raises:
            ValueError: Si username ou email invalide.
        
        Examples:
            >>> user = User('alice', 'alice@example.com')
            >>> user.username
            'alice'
        """
        self.username = username
        self.email = email
        self.is_active = False
        from datetime import datetime
        self.created_at = datetime.now()
    
    def activate(self):
        """
        Active le compte utilisateur.
        
        Passe is_active à True et envoie un email de confirmation.
        
        Returns:
            bool: True si activation réussie, False si déjà actif.
        
        Side Effects:
            - Modifie self.is_active
            - Envoie email de confirmation
        
        Examples:
            >>> user = User('alice', 'alice@example.com')
            >>> user.activate()
            True
            >>> user.is_active
            True
        """
        if self.is_active:
            return False
        self.is_active = True
        return True


"""
CLASSE AVEC PROPERTIES
──────────────────────

Documenter les properties
"""

class Temperature:
    """
    Représente une température avec conversion automatique.
    
    Cette classe stocke la température en Celsius et fournit
    des conversions automatiques vers Fahrenheit et Kelvin.
    
    Attributes:
        celsius (float): Température en degrés Celsius.
    
    Examples:
        >>> temp = Temperature(25)
        >>> temp.celsius
        25.0
        >>> temp.fahrenheit
        77.0
        >>> temp.kelvin
        298.15
    """
    
    def __init__(self, celsius):
        """
        Initialise une température.
        
        Args:
            celsius (float): Température en degrés Celsius.
        """
        self._celsius = float(celsius)
    
    @property
    def celsius(self):
        """
        float: Température en degrés Celsius.
        
        Examples:
            >>> temp = Temperature(25)
            >>> temp.celsius
            25.0
        """
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """
        Définit la température en Celsius.
        
        Args:
            value (float): Nouvelle température en Celsius.
        
        Raises:
            ValueError: Si température < -273.15 (zéro absolu).
        
        Examples:
            >>> temp = Temperature(0)
            >>> temp.celsius = 25
            >>> temp.celsius
            25.0
        """
        if value < -273.15:
            raise ValueError("Température sous le zéro absolu")
        self._celsius = float(value)
    
    @property
    def fahrenheit(self):
        """
        float: Température en degrés Fahrenheit (lecture seule).
        
        Formule : F = C × 9/5 + 32
        
        Examples:
            >>> temp = Temperature(0)
            >>> temp.fahrenheit
            32.0
            >>> temp = Temperature(100)
            >>> temp.fahrenheit
            212.0
        """
        return self._celsius * 9/5 + 32
    
    @property
    def kelvin(self):
        """
        float: Température en Kelvin (lecture seule).
        
        Formule : K = C + 273.15
        
        Examples:
            >>> temp = Temperature(0)
            >>> temp.kelvin
            273.15
        """
        return self._celsius + 273.15


"""
CLASSE AVEC MÉTHODES STATIQUES/CLASSE
──────────────────────────────────────

Documenter @staticmethod et @classmethod
"""

class MathUtils:
    """
    Utilitaires mathématiques.
    
    Cette classe fournit des méthodes statiques pour opérations
    mathématiques courantes.
    """
    
    @staticmethod
    def is_prime(n):
        """
        Vérifie si un nombre est premier.
        
        Un nombre premier est divisible uniquement par 1 et lui-même.
        Par convention, 1 n'est pas considéré comme premier.
        
        Args:
            n (int): Nombre à tester.
        
        Returns:
            bool: True si n est premier, False sinon.
        
        Examples:
            >>> MathUtils.is_prime(2)
            True
            >>> MathUtils.is_prime(4)
            False
            >>> MathUtils.is_prime(17)
            True
            >>> MathUtils.is_prime(1)
            False
        
        Note:
            Cette implémentation a une complexité O(√n).
            Pour de très grands nombres, utilisez des algorithmes
            probabilistes comme Miller-Rabin.
        """
        if n < 2:
            return False
        for i in range(2, int(n ** 0.5) + 1):
            if n % i == 0:
                return False
        return True
    
    @classmethod
    def from_config(cls, config_dict):
        """
        Crée une instance depuis un dictionnaire de configuration.
        
        Args:
            config_dict (dict): Configuration contenant les paramètres.
        
        Returns:
            MathUtils: Nouvelle instance configurée.
        
        Examples:
            >>> config = {'precision': 2}
            >>> math = MathUtils.from_config(config)
        """
        pass


"""
CLASSE ABSTRAITE
────────────────

Documenter les classes abstraites et leurs méthodes
"""

from abc import ABC, abstractmethod

class Shape(ABC):
    """
    Classe abstraite de base pour toutes les formes géométriques.
    
    Cette classe définit l'interface commune pour toutes les formes.
    Les sous-classes DOIVENT implémenter les méthodes area() et perimeter().
    
    Note:
        Cette classe ne peut pas être instanciée directement.
        Utilisez les sous-classes concrètes (Circle, Rectangle, etc.).
    
    Examples:
        >>> class Circle(Shape):
        ...     def __init__(self, radius):
        ...         self.radius = radius
        ...     def area(self):
        ...         return 3.14159 * self.radius ** 2
        ...     def perimeter(self):
        ...         return 2 * 3.14159 * self.radius
        >>> circle = Circle(5)
        >>> circle.area()
        78.53975
    """
    
    @abstractmethod
    def area(self):
        """
        Calcule l'aire de la forme.
        
        Returns:
            float: Aire de la forme en unités carrées.
        
        Note:
            Cette méthode DOIT être implémentée par les sous-classes.
        """
        pass
    
    @abstractmethod
    def perimeter(self):
        """
        Calcule le périmètre de la forme.
        
        Returns:
            float: Périmètre de la forme en unités.
        
        Note:
            Cette méthode DOIT être implémentée par les sous-classes.
        """
        pass


# ----------------------------------------------------------------------------
# [PACKAGE] DOCSTRINGS POUR MODULES
# ----------------------------------------------------------------------------

"""
MODULE SIMPLE
─────────────

Docstring en haut du fichier
"""

# math_utils.py
"""
Utilitaires mathématiques pour l'application.

Ce module fournit des fonctions et classes pour opérations
mathématiques courantes non couvertes par le module math standard.

Fonctions disponibles :
    - is_prime(n): Teste si n est premier
    - gcd(a, b): PGCD de a et b
    - lcm(a, b): PPCM de a et b
    - fibonacci(n): N-ième nombre de Fibonacci

Classes :
    - Matrix: Opérations sur matrices
    - Vector: Opérations sur vecteurs

Constantes :
    - GOLDEN_RATIO: Nombre d'or (≈1.618)
    - EULER: Constante d'Euler (≈2.718)

Examples:
    Utilisation typique :
    
    >>> from math_utils import is_prime, fibonacci
    >>> is_prime(17)
    True
    >>> fibonacci(10)
    55

Note:
    Pour opérations matricielles avancées, considérez NumPy.

Author:
    Votre Nom <email@example.com>

Version:
    1.2.0

License:
    MIT
"""

# Constantes
GOLDEN_RATIO = 1.618033988749895
"""float: Le nombre d'or (φ = (1 + √5) / 2)."""

EULER = 2.718281828459045
"""float: La constante d'Euler (e)."""

# Fonctions...


"""
MODULE AVEC STRUCTURE COMPLEXE
───────────────────────────────

Décrire l'organisation du module
"""

# database/__init__.py
"""
Package de gestion de la base de données.

Ce package fournit une abstraction complète pour interagir avec
la base de données, incluant connexion, modèles, migrations et queries.

Structure :
    database/
        __init__.py         - Ce fichier
        connection.py       - Gestion des connexions
        models.py          - Modèles de données
        migrations.py      - Système de migrations
        query_builder.py   - Constructeur de requêtes

Modules :
    connection
        Classes : Connection, ConnectionPool
        Fonctions : create_connection(), close_all()
    
    models
        Classes : Model, User, Post, Comment
        Fonctions : create_table(), drop_table()
    
    migrations
        Classes : Migration, MigrationManager
        Fonctions : run_migrations(), rollback()
    
    query_builder
        Classes : QueryBuilder, SelectQuery, InsertQuery
        Fonctions : select(), insert(), update(), delete()

Usage :
    Configuration initiale :
    
    >>> from database import create_connection, User
    >>> conn = create_connection('sqlite:///app.db')
    >>> user = User(username='alice', email='alice@example.com')
    >>> user.save(conn)
    
    Requêtes avancées :
    
    >>> from database.query_builder import select
    >>> query = select('users').where('age', '>', 18).limit(10)
    >>> results = query.execute(conn)

Configuration :
    Variables d'environnement requises :
    - DATABASE_URL: URL de connexion à la base
    - DB_POOL_SIZE: Taille du pool de connexions (défaut: 10)
    - DB_TIMEOUT: Timeout des requêtes en secondes (défaut: 30)

Dépendances :
    - sqlalchemy >= 1.4.0
    - psycopg2-binary >= 2.9.0 (pour PostgreSQL)

Note:
    Ce package supporte SQLite, PostgreSQL et MySQL.
    Pour MongoDB, utilisez le package database.nosql.

See Also:
    database.nosql : Support pour bases de données NoSQL
    cache : Système de cache pour requêtes fréquentes

Author:
    Équipe Database <db-team@example.com>

Maintainers:
    - Alice Developer <alice@example.com>
    - Bob Engineer <bob@example.com>

Version:
    2.1.0

Since:
    1.0.0

License:
    MIT License - voir LICENSE file

Changes:
    Version 2.1.0 (2024-01-15):
        - Ajout support MySQL
        - Amélioration performance ConnectionPool
        - Correction bug migrations concurrentes
    
    Version 2.0.0 (2023-12-01):
        - BREAKING: Nouveau système de migrations
        - Ajout QueryBuilder
        - Support PostgreSQL

Examples:
    Exemple complet d'utilisation :
    
    >>> # Configuration
    >>> import os
    >>> os.environ['DATABASE_URL'] = 'postgresql://user:pass@localhost/db'
    >>> 
    >>> # Connexion
    >>> from database import create_connection, User, Post
    >>> conn = create_connection()
    >>> 
    >>> # Créer utilisateur
    >>> user = User(username='alice', email='alice@example.com')
    >>> user.save(conn)
    >>> 
    >>> # Créer post
    >>> post = Post(title='Hello', content='World', author=user)
    >>> post.save(conn)
    >>> 
    >>> # Requête
    >>> from database.query_builder import select
    >>> posts = select('posts').where('author_id', '=', user.id).execute(conn)
    >>> 
    >>> # Fermeture
    >>> conn.close()
"""


# ----------------------------------------------------------------------------
# [DESIGN] FORMATS STANDARDS DE DOCSTRINGS
# ----------------------------------------------------------------------------

"""
Il existe plusieurs formats standardisés pour les docstrings.
Les 3 principaux : Google, NumPy, Sphinx


1. FORMAT GOOGLE STYLE
───────────────────────

[OK] Avantages :
- Lisible en texte brut
- Compact
- Populaire

[X] Inconvénients :
- Moins structuré que reST
"""

def google_style_example(param1, param2, param3=None):
    """
    Résumé de la fonction sur une ligne.
    
    Description détaillée de la fonction sur plusieurs paragraphes
    si nécessaire. Expliquez le comportement, les algorithmes utilisés,
    les cas particuliers, etc.
    
    Args:
        param1 (int): Description du premier paramètre.
            Peut s'étendre sur plusieurs lignes si nécessaire.
        param2 (str): Description du second paramètre.
        param3 (list, optional): Description du paramètre optionnel.
            Defaults to None.
    
    Returns:
        bool: Description de la valeur de retour.
            Peut aussi s'étendre sur plusieurs lignes.
    
    Raises:
        ValueError: Description de quand cette erreur est levée.
        TypeError: Description d'une autre erreur possible.
    
    Yields:
        int: Si c'est un générateur, décrire ce qui est généré.
    
    Examples:
        Exemples d'utilisation :
        
        >>> google_style_example(1, "hello")
        True
        
        >>> google_style_example(2, "world", [1, 2, 3])
        False
    
    Note:
        Notes supplémentaires sur la fonction.
        Avertissements, limitations, etc.
    
    See Also:
        other_function : Fonction liée
        SomeClass : Classe liée
    
    References:
        .. [1] Auteur, "Titre", Journal, 2023
    
    Todo:
        * Amélioration 1
        * Amélioration 2
    """
    pass


"""
2. FORMAT NUMPY STYLE
─────────────────────

[OK] Avantages :
- Très structuré
- Excellent pour code scientifique
- Sections bien séparées

[X] Inconvénients :
- Plus verbeux
- Moins compact
"""

def numpy_style_example(param1, param2, param3=None):
    """
    Résumé de la fonction sur une ligne.
    
    Description détaillée de la fonction sur plusieurs paragraphes
    si nécessaire. Expliquez le comportement, les algorithmes utilisés,
    les cas particuliers, etc.
    
    Parameters
    ----------
    param1 : int
        Description du premier paramètre.
        Peut s'étendre sur plusieurs lignes si nécessaire.
    param2 : str
        Description du second paramètre.
    param3 : list, optional
        Description du paramètre optionnel.
        Default is None.
    
    Returns
    -------
    bool
        Description de la valeur de retour.
        Peut aussi s'étendre sur plusieurs lignes.
    
    Raises
    ------
    ValueError
        Description de quand cette erreur est levée.
    TypeError
        Description d'une autre erreur possible.
    
    Yields
    ------
    int
        Si c'est un générateur, décrire ce qui est généré.
    
    See Also
    --------
    other_function : Fonction liée
    SomeClass : Classe liée
    
    Notes
    -----
    Notes supplémentaires sur la fonction.
    Avertissements, limitations, etc.
    
    References
    ----------
    .. [1] Auteur, "Titre", Journal, 2023
    
    Examples
    --------
    Exemples d'utilisation :
    
    >>> numpy_style_example(1, "hello")
    True
    
    >>> numpy_style_example(2, "world", [1, 2, 3])
    False
    """
    pass


"""
3. FORMAT SPHINX (reStructuredText)
───────────────────────────────────

[OK] Avantages :
- Très puissant et extensible
- Standard pour Sphinx
- Nombreuses directives

[X] Inconvénients :
- Syntaxe moins lisible
- Plus complexe
"""

def sphinx_style_example(param1, param2, param3=None):
    """
    Résumé de la fonction sur une ligne.
    
    Description détaillée de la fonction sur plusieurs paragraphes
    si nécessaire. Expliquez le comportement, les algorithmes utilisés,
    les cas particuliers, etc.
    
    :param param1: Description du premier paramètre.
        Peut s'étendre sur plusieurs lignes si nécessaire.
    :type param1: int
    :param param2: Description du second paramètre.
    :type param2: str
    :param param3: Description du paramètre optionnel.
    :type param3: list, optional
    
    :return: Description de la valeur de retour.
    :rtype: bool
    
    :raises ValueError: Description de quand cette erreur est levée.
    :raises TypeError: Description d'une autre erreur possible.
    
    :yields: Si c'est un générateur, décrire ce qui est généré.
    :ytype: int
    
    .. seealso::
       :func:`other_function`
       :class:`SomeClass`
    
    .. note::
       Notes supplémentaires sur la fonction.
       Avertissements, limitations, etc.
    
    .. warning::
       Avertissement important.
    
    .. todo::
       * Amélioration 1
       * Amélioration 2
    
    .. versionadded:: 1.0
       Fonction ajoutée en version 1.0
    
    .. versionchanged:: 1.1
       Ajout du paramètre param3
    
    .. deprecated:: 2.0
       Utilisez :func:`new_function` à la place
    
    **Examples:**
    
    Exemples d'utilisation :
    
    >>> sphinx_style_example(1, "hello")
    True
    
    >>> sphinx_style_example(2, "world", [1, 2, 3])
    False
    """
    pass


"""
[IDEE] QUEL FORMAT CHOISIR ?

GOOGLE STYLE
    [OK] Projets généraux Python
    [OK] Startups, petites équipes
    [OK] Code orienté web/backend
    
NUMPY STYLE
    [OK] Code scientifique
    [OK] Data science / Machine Learning
    [OK] Projets académiques
    
SPHINX STYLE
    [OK] Projets avec documentation Sphinx complexe
    [OK] Bibliothèques Python publiques
    [OK] Besoin de directives avancées


[CLE] RÈGLE D'OR : Choisir UN format et rester COHÉRENT !

Ne JAMAIS mélanger les formats dans un même projet.
"""


# ----------------------------------------------------------------------------
# [RECHERCHE] ACCÉDER AUX DOCSTRINGS PROGRAMMATIQUEMENT
# ----------------------------------------------------------------------------

"""
PLUSIEURS MÉTHODES POUR ACCÉDER AUX DOCSTRINGS


1. ATTRIBUT __doc__
───────────────────
"""

def example():
    """Ceci est une docstring."""
    pass

# Accès direct
print(example.__doc__)
# Output: Ceci est une docstring.

# Pour classes
class MyClass:
    """Docstring de classe."""
    pass

print(MyClass.__doc__)
# Output: Docstring de classe.


"""
2. FONCTION help()
──────────────────

Affiche documentation formatée
"""

help(example)
"""
Output:
Help on function example in module __main__:

example()
    Ceci est une docstring.
"""


"""
3. MODULE inspect
─────────────────

Plus de contrôle et d'informations
"""

import inspect

def advanced_example(a, b=10):
    """
    Fonction exemple.
    
    Args:
        a: Premier argument
        b: Second argument (défaut 10)
    """
    return a + b

# Obtenir docstring
doc = inspect.getdoc(advanced_example)
print(doc)

# Obtenir signature
sig = inspect.signature(advanced_example)
print(sig)
# Output: (a, b=10)

# Obtenir code source
source = inspect.getsource(advanced_example)
print(source)

# Obtenir infos sur paramètres
params = sig.parameters
for name, param in params.items():
    print(f"{name}: default={param.default}")
# Output:
# a: default=<class 'inspect._empty'>
# b: default=10


"""
4. MODULE pydoc
───────────────

Générer documentation en texte ou HTML
"""

import pydoc

# Documentation texte
text_doc = pydoc.render_doc(advanced_example, "Documentation de %s")
print(text_doc)

# Générer HTML
html_doc = pydoc.HTMLDoc().document(advanced_example)

# Sauvegarder en fichier
with open('doc.html', 'w') as f:
    f.write(html_doc)


"""
5. PARSER PERSONNALISÉ
──────────────────────

Extraire sections spécifiques
"""

def parse_docstring(func):
    """
    Parse une docstring Google Style.
    
    Returns:
        dict: Dictionnaire avec sections de la docstring
    """
    doc = inspect.getdoc(func)
    if not doc:
        return {}
    
    sections = {}
    current_section = 'description'
    sections[current_section] = []
    
    for line in doc.split('\n'):
        line = line.strip()
        
        if line.endswith(':') and line[:-1] in ['Args', 'Returns', 'Raises', 'Examples']:
            current_section = line[:-1].lower()
            sections[current_section] = []
        else:
            sections[current_section].append(line)
    
    # Nettoyer
    for key in sections:
        sections[key] = '\n'.join(sections[key]).strip()
    
    return sections

# Utilisation
def example(a, b):
    """
    Additionne deux nombres.
    
    Args:
        a: Premier nombre
        b: Second nombre
    
    Returns:
        Somme de a et b
    """
    return a + b

parsed = parse_docstring(example)
print(parsed['description'])  # Additionne deux nombres.
print(parsed['args'])         # a: Premier nombre...
print(parsed['returns'])      # Somme de a et b


# ============================================================================
# CE FICHIER CONTINUE...
# ============================================================================

Excellent ! J'ai créé la suite avec le **Chapitre 1 complet sur les Docstrings**. 

Voulez-vous que je continue avec :
- **Chapitre 2 : Comments vs Docstrings** (différences détaillées, quand utiliser quoi)
- **Chapitre 3 : Conventions PEP 257** (standards officiels Python)

Pour compléter la **Partie 1 : Fondamentaux** ?

# ============================================================================
# [GUIDE] CHAPITRE 1 (SUITE) : DOCTEST - TESTS DANS LES DOCSTRINGS
# ============================================================================

"""
[OBJECTIF] DOCTEST : TESTER VIA LES DOCSTRINGS

Doctest = Module Python pour exécuter les exemples dans les docstrings
comme des tests automatisés.
"""

# ----------------------------------------------------------------------------
# [TEST] INTRODUCTION AU DOCTEST
# ----------------------------------------------------------------------------

"""
QU'EST-CE QUE DOCTEST ?

Doctest lit les docstrings, trouve les exemples qui ressemblent à
des sessions interactives Python (>>>), les exécute et vérifie que
les résultats correspondent.
"""

def factorial(n):
    """
    Calcule la factorielle de n.
    
    Args:
        n (int): Nombre entier positif ou nul.
    
    Returns:
        int: Factorielle de n.
    
    Examples:
        >>> factorial(0)
        1
        >>> factorial(1)
        1
        >>> factorial(5)
        120
        >>> factorial(10)
        3628800
    """
    if n == 0:
        return 1
    return n * factorial(n - 1)

# Exécuter les doctests
if __name__ == "__main__":
    import doctest
    doctest.testmod()

"""
[IDEE] COMMENT EXÉCUTER ?

Méthode 1 : Dans le code
    if __name__ == "__main__":
        import doctest
        doctest.testmod()
    
    python module.py

Méthode 2 : Ligne de commande
    python -m doctest module.py
    
    # Avec verbose pour voir tous les tests
    python -m doctest -v module.py


OUTPUT (si tests passent) :
    (aucun output)

OUTPUT (avec -v) :
    Trying:
        factorial(0)
    Expecting:
        1
    ok
    Trying:
        factorial(5)
    Expecting:
        120
    ok
    2 items had no tests:
        __main__
    1 items passed all tests:
       4 tests in __main__.factorial
    4 tests in 2 items.
    4 passed and 0 failed.
"""


"""
SYNTAXE DOCTEST
───────────────

Format EXACT d'une session interactive Python
"""

def add(a, b):
    """
    Additionne deux nombres.
    
    Examples:
        >>> add(2, 3)      # <- Ligne commence par >>>
        5                   # <- Résultat attendu (pas de >>>)
        
        >>> add(10, 20)
        30
        
        >>> # On peut mettre des commentaires
        >>> result = add(5, 7)
        >>> result
        12
        
        >>> # Test sur plusieurs lignes
        >>> x = add(1, 2)
        >>> y = add(3, 4)
        >>> x + y
        10
    """
    return a + b


"""
RÈGLES IMPORTANTES
──────────────────

1. >>> INDIQUE UNE COMMANDE
2. Résultat attendu = ligne(s) suivante(s) sans >>>
3. Indentation EXACTE requise
4. Espaces blancs importants
5. Output doit correspondre EXACTEMENT
"""

# [OK] BON
def good_example():
    """
    >>> 1 + 1
    2
    """
    pass

# [X] MAUVAIS : Espace après 2
def bad_example1():
    """
    >>> 1 + 1
    2 
    """
    # Échec ! Output attendu "2 " mais obtenu "2"
    pass

# [X] MAUVAIS : Indentation incorrecte
def bad_example2():
    """
    >>> 1 + 1
        2
    """
    # Échec ! Indentation ne correspond pas
    pass


"""
TESTS AVEC EXCEPTIONS
─────────────────────

Tester que les exceptions sont bien levées
"""

def divide(a, b):
    """
    Divise a par b.
    
    Examples:
        >>> divide(10, 2)
        5.0
        
        >>> divide(10, 0)
        Traceback (most recent call last):
            ...
        ZeroDivisionError: division by zero
    """
    if b == 0:
        raise ZeroDivisionError("division by zero")
    return a / b

"""
[IDEE] FORMAT EXCEPTION

    >>> fonction_qui_leve_erreur()
    Traceback (most recent call last):
        ...
    TypeErreur: Message de l'erreur

- Traceback (most recent call last): obligatoire
- ... = remplace le traceback complet
- Nom de l'exception : Message (doit correspondre)
"""


"""
TESTS AVEC SORTIES MULTIPLES
─────────────────────────────

Pour listes, dicts, etc.
"""

def get_user_data():
    """
    Retourne données utilisateur.
    
    Examples:
        >>> data = get_user_data()
        >>> data['name']
        'Alice'
        >>> data['age']
        30
        >>> sorted(data.keys())
        ['age', 'name']
    """
    return {'name': 'Alice', 'age': 30}


"""
TESTS AVEC OUTPUT LONG OU VARIABLE
───────────────────────────────────

Utiliser ... pour parties variables
"""

def get_timestamp():
    """
    Retourne timestamp actuel.
    
    Examples:
        >>> import re
        >>> ts = get_timestamp()
        >>> bool(re.match(r'\d{4}-\d{2}-\d{2}', ts))
        True
    """
    from datetime import datetime
    return datetime.now().strftime('%Y-%m-%d %H:%M:%S')


"""
DIRECTIVES DOCTEST
──────────────────

Contrôler comportement des tests
"""

def example_with_directives():
    """
    Exemples avec directives.
    
    # ELLIPSIS : Accepter ... pour parties variables
    >>> print(list(range(20)))  # doctest: +ELLIPSIS
    [0, 1, 2, ..., 19]
    
    # NORMALIZE_WHITESPACE : Ignorer différences espaces
    >>> print("hello    world")  # doctest: +NORMALIZE_WHITESPACE
    hello world
    
    # SKIP : Ignorer ce test
    >>> print("Not executed")  # doctest: +SKIP
    anything here
    
    # IGNORE_EXCEPTION_DETAIL : Ignorer détails exception
    >>> int('invalid')  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ValueError: ...
    """
    pass

"""
DIRECTIVES DISPONIBLES

+ELLIPSIS
    Accepter ... dans output pour parties variables
    >>> print([1, 2, 3, 4, 5])  # doctest: +ELLIPSIS
    [1, ..., 5]

+NORMALIZE_WHITESPACE
    Ignorer différences d'espaces blancs
    >>> print("a  b    c")  # doctest: +NORMALIZE_WHITESPACE
    a b c

+SKIP
    Sauter ce test
    >>> raise Exception()  # doctest: +SKIP

+IGNORE_EXCEPTION_DETAIL
    Ignorer message d'erreur détaillé
    >>> 1/0  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ZeroDivisionError: ...

+DONT_ACCEPT_TRUE_FOR_1
    Ne pas considérer True == 1

+REPORT_UDIFF, +REPORT_CDIFF, +REPORT_NDIFF
    Format de rapport pour différences
"""


"""
CONFIGURATION GLOBALE
─────────────────────

Appliquer directives à tous les tests
"""

import doctest

def run_tests():
    """Exécute tous les doctests avec options."""
    doctest.testmod(
        verbose=True,              # Afficher tous les tests
        optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE
    )

if __name__ == "__main__":
    run_tests()


"""
DOCTEST DANS FICHIERS TEXTE
────────────────────────────

On peut aussi mettre des doctests dans des fichiers .txt
"""

# test_examples.txt
"""
Test d'addition
===============

>>> from calculator import add
>>> add(2, 3)
5

>>> add(10, -5)
5

Test de soustraction
====================

>>> from calculator import subtract
>>> subtract(10, 3)
7
"""

# Exécuter
# python -m doctest test_examples.txt


"""
BONNES PRATIQUES DOCTEST
─────────────────────────

[OK] À FAIRE

1. TESTS SIMPLES ET COURTS
   >>> add(2, 3)
   5

2. COUVRIR CAS NORMAUX
   >>> factorial(5)
   120

3. COUVRIR CAS LIMITES
   >>> factorial(0)
   1

4. TESTER EXCEPTIONS
   >>> factorial(-1)
   Traceback (most recent call last):
       ...
   ValueError: n doit être positif

5. UTILISER COMME DOCUMENTATION
   Les exemples montrent comment utiliser la fonction


[X] À ÉVITER

1. TESTS TROP COMPLEXES
   # [X] Trop long, difficile à maintenir
   >>> # Setup complexe sur 20 lignes...

2. TESTS DÉPENDANTS DE L'ENVIRONNEMENT
   # [X] Dépend du système
   >>> import os
   >>> os.listdir('.')  # Résultat variable

3. OUTPUT TROP LONG
   # [X] Difficile à lire
   >>> print(list(range(1000)))
   [0, 1, 2, ..., 999]  # Mieux

4. TESTS NON DÉTERMINISTES
   # [X] Résultat change à chaque fois
   >>> import random
   >>> random.randint(1, 10)
   7  # Peut échouer

5. REMPLACER VRAIE SUITE DE TESTS
   # Doctest = complément, pas remplacement
   # Utilisez pytest/unittest pour tests complets
"""


# ============================================================================
# [GUIDE] CHAPITRE 2 : COMMENTS VS DOCSTRINGS
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Différence fondamentale entre comments et docstrings
[OK] Quand utiliser un comment (#)
[OK] Quand utiliser une docstring (''' ''')
[OK] Types de comments et leurs usages
[OK] Anti-patterns à éviter
[OK] Équilibre entre comments et code lisible
"""


# ----------------------------------------------------------------------------
# [REFLEXION] DIFFÉRENCE FONDAMENTALE
# ----------------------------------------------------------------------------

"""
COMMENTS (#)
────────────

Définition :
- Ligne commençant par #
- Ignorée par l'interpréteur Python
- Pour les développeurs lisant le CODE SOURCE
- Explique POURQUOI et COMMENT (implémentation)

Caractéristiques :
- Pas accessible programmatiquement
- Pas dans help()
- Pas dans documentation générée
- Peut être mise à jour librement sans casser l'API


DOCSTRINGS (''' ''')
────────────────────

Définition :
- String littérale, première instruction d'un objet
- Stockée dans __doc__
- Pour les utilisateurs du CODE (API)
- Explique QUOI fait le code et COMMENT L'UTILISER

Caractéristiques :
- Accessible via help() et __doc__
- Utilisée pour documentation générée
- Partie de l'API publique
- Doit rester à jour avec le code


[IDEE] RÈGLE D'OR

Comment  -> Pour VOUS et autres développeurs
Docstring -> Pour UTILISATEURS de votre code
"""


# ----------------------------------------------------------------------------
# [NOTE] QUAND UTILISER DES COMMENTS
# ----------------------------------------------------------------------------

"""
1. EXPLIQUER LE POURQUOI
────────────────────────

[OK] Expliquer décisions non-évidentes
"""

def calculate_discount(price, customer_type):
    # On applique 15% de remise pour clients premium
    # car c'est plus rentable de fidéliser que d'acquérir
    if customer_type == 'premium':
        return price * 0.85
    
    # Remise standard de 5% selon politique commerciale 2024
    return price * 0.95


"""
2. CLARIFIER CODE COMPLEXE
───────────────────────────

[OK] Expliquer algorithme ou logique compliquée
"""

def quicksort(arr):
    if len(arr) <= 1:
        return arr
    
    # Choisir pivot (élément du milieu pour éviter worst-case sur listes triées)
    pivot = arr[len(arr) // 2]
    
    # Partitionner en trois groupes
    left = [x for x in arr if x < pivot]    # Éléments < pivot
    middle = [x for x in arr if x == pivot]  # Éléments = pivot
    right = [x for x in arr if x > pivot]    # Éléments > pivot
    
    # Récursion sur sous-listes et concaténation
    return quicksort(left) + middle + quicksort(right)


"""
3. DOCUMENTER WORKAROUNDS ET HACKS
───────────────────────────────────

[OK] Expliquer solutions temporaires ou non-optimales
"""

def process_data(data):
    # HACK: L'API retourne parfois None au lieu de liste vide
    # TODO: Corriger côté API (ticket #1234)
    if data is None:
        data = []
    
    # WORKAROUND: Bug dans lib v1.2.3 avec unicode
    # Sera corrigé dans v1.3.0 (sortie prévue février 2024)
    data = [str(item) for item in data]
    
    return process(data)


"""
4. MARQUER TODO ET FIXME
────────────────────────

[OK] Signaler code à améliorer
"""

def calculate_tax(amount):
    # TODO: Ajouter support pour taxes locales
    # TODO: Gérer cas des zones franches
    # FIXME: Ne gère pas les montants négatifs
    # FIXME: Arrondis incorrects pour gros montants (> 1M€)
    
    return amount * 0.20

"""
Conventions courantes :
- TODO: Fonctionnalité à ajouter
- FIXME: Bug à corriger
- HACK: Solution temporaire non-idéale
- NOTE: Information importante
- WARNING: Attention particulière requise
- XXX: Code problématique mais fonctionnel
- OPTIMIZE: Amélioration performance possible
"""


"""
5. DÉSACTIVER CODE TEMPORAIREMENT
──────────────────────────────────

[OK] Pour debug ou test
"""

def process():
    result = step1()
    # result = step2(result)  # Temporairement désactivé pour debug
    result = step3(result)
    return result


"""
6. EXPLIQUER MAGIE ET EDGE CASES
─────────────────────────────────

[OK] Clarifier nombres magiques, constantes, cas limites
"""

def validate_age(age):
    # 18 = âge minimum légal en France pour voter
    if age < 18:
        return False
    
    # 120 = âge maximum réaliste (record mondial: 122 ans)
    if age > 120:
        return False
    
    return True


# Constantes avec comments explicatifs
MAX_RETRY = 3  # Basé sur analyse statistique: 99% requêtes OK en 3 tentatives
TIMEOUT = 30   # 30s = compromis entre UX et coût serveur
CACHE_TTL = 3600  # 1h = fréquence mise à jour des données upstream


"""
7. EXPLIQUER DÉPENDANCES ET IMPORTS
────────────────────────────────────

[OK] Clarifier imports non-évidents
"""

# Importation conditionnelle pour compatibilité Python 2/3
try:
    from urllib.parse import urlencode  # Python 3
except ImportError:
    from urllib import urlencode  # Python 2

# Import renommé pour éviter conflit avec variable locale 'date'
from datetime import date as datetime_date

# Import spécifique pour réduire empreinte mémoire
from collections import defaultdict  # Seulement ce dont on a besoin


"""
8. DOCUMENTER REGEX ET FORMATS
───────────────────────────────

[OK] Expliquer expressions régulières complexes
"""

import re

# Regex email (RFC 5322 simplifié)
# Format: local@domaine.tld
# local: 1+ caractères alphanumériques, ., _, -, +
# domaine: 1+ segments alphanumériques séparés par .
# tld: 2+ lettres
EMAIL_PATTERN = re.compile(
    r'^[a-zA-Z0-9._%+-]+'  # Local part
    r'@'                    # @
    r'[a-zA-Z0-9.-]+'      # Domain
    r'\.'                   # .
    r'[a-zA-Z]{2,}$'       # TLD
)


# ----------------------------------------------------------------------------
# [DOCS] QUAND UTILISER DES DOCSTRINGS
# ----------------------------------------------------------------------------

"""
1. DOCUMENTATION API PUBLIQUE
──────────────────────────────

[OK] Toute fonction/classe accessible de l'extérieur
"""

def public_function(param):
    """
    Fonction publique de l'API.
    
    Cette docstring explique comment UTILISER la fonction,
    pas comment elle est IMPLÉMENTÉE.
    
    Args:
        param: Description du paramètre
    
    Returns:
        Description du retour
    """
    # Comments ici pour implémentation
    result = internal_process(param)
    return result


"""
2. INTERFACES ET CONTRATS
──────────────────────────

[OK] Définir comportement attendu
"""

class DataProcessor:
    """
    Interface pour processeurs de données.
    
    Toute classe implémentant cette interface DOIT :
    - Implémenter process()
    - Lever ProcessingError en cas d'échec
    - Retourner données dans format standardisé
    """
    
    def process(self, data):
        """
        Traite les données d'entrée.
        
        Args:
            data (dict): Données brutes à traiter
        
        Returns:
            dict: Données traitées au format standard
        
        Raises:
            ProcessingError: Si traitement échoue
        """
        raise NotImplementedError


"""
3. MODULES ET PACKAGES
──────────────────────

[OK] Vue d'ensemble et guide d'utilisation
"""

# module.py
"""
Module de traitement de texte.

Fournit fonctions pour nettoyer, analyser et transformer du texte.

Usage:
    >>> from text_processing import clean, analyze
    >>> text = "  Hello World!  "
    >>> clean(text)
    'Hello World!'

Available functions:
    - clean(text): Nettoie espaces et ponctuation
    - analyze(text): Analyse statistiques du texte
    - transform(text, mode): Transforme selon mode
"""


"""
4. EXEMPLES D'UTILISATION
──────────────────────────

[OK] Montrer comment utiliser le code
"""

def complex_api_function(config):
    """
    Configure le système selon paramètres.
    
    Args:
        config (dict): Configuration complète
    
    Examples:
        Configuration minimale :
        
        >>> config = {'mode': 'production'}
        >>> complex_api_function(config)
        
        Configuration complète :
        
        >>> config = {
        ...     'mode': 'production',
        ...     'database': {
        ...         'host': 'localhost',
        ...         'port': 5432
        ...     },
        ...     'cache': {
        ...         'enabled': True,
        ...         'ttl': 3600
        ...     }
        ... }
        >>> complex_api_function(config)
    """
    pass


# ----------------------------------------------------------------------------
# [SCALES] ÉQUILIBRE COMMENTS VS CODE LISIBLE
# ----------------------------------------------------------------------------

"""
LE MEILLEUR COMMENT EST... PAS DE COMMENT !

Code auto-documenté > Comments


[X] CODE QUI NÉCESSITE COMMENTS
"""

def calc(x, y, z):
    # Calculer le prix avec taxe et remise
    t = x * 1.2  # Ajouter 20% taxe
    if z:  # Si remise
        t = t * 0.9  # Appliquer 10% remise
    return t


"""
[OK] CODE AUTO-DOCUMENTÉ (Sans comments nécessaires)
"""

def calculate_final_price(base_price, quantity, apply_discount):
    """Calcule prix final avec taxe et remise optionnelle."""
    TAX_RATE = 1.20
    DISCOUNT_RATE = 0.90
    
    price_with_tax = base_price * TAX_RATE
    
    if apply_discount:
        final_price = price_with_tax * DISCOUNT_RATE
    else:
        final_price = price_with_tax
    
    return final_price


"""
PRINCIPES CODE AUTO-DOCUMENTÉ
──────────────────────────────

1. NOMS DESCRIPTIFS
"""

# [X] Mauvais
def f(x):
    return x * 0.2

# [OK] Bon
def calculate_vat(amount):
    VAT_RATE = 0.20
    return amount * VAT_RATE


"""
2. FONCTIONS COURTES ET FOCALISÉES
"""

# [X] Mauvais : Fonction longue nécessitant comments
def process(data):
    # Valider données
    if not data:
        return None
    # Nettoyer
    data = data.strip()
    # Transformer
    data = data.upper()
    # Encoder
    data = data.encode('utf-8')
    # Compresser
    import zlib
    data = zlib.compress(data)
    return data


# [OK] Bon : Fonctions séparées auto-documentées
def process(data):
    """Pipeline de traitement complet."""
    validated_data = validate(data)
    cleaned_data = clean(validated_data)
    transformed_data = transform(cleaned_data)
    encoded_data = encode(transformed_data)
    compressed_data = compress(encoded_data)
    return compressed_data

def validate(data):
    """Valide que data est non-vide."""
    if not data:
        raise ValueError("Data cannot be empty")
    return data

def clean(data):
    """Retire espaces inutiles."""
    return data.strip()

# etc.


"""
3. CONSTANTES NOMMÉES
"""

# [X] Mauvais : Nombres magiques
def is_adult(age):
    return age >= 18

def is_senior(age):
    return age >= 65


# [OK] Bon : Constantes explicites
ADULT_AGE = 18
SENIOR_AGE = 65

def is_adult(age):
    return age >= ADULT_AGE

def is_senior(age):
    return age >= SENIOR_AGE


"""
4. EXTRACTION DE VARIABLES
"""

# [X] Mauvais : Expression complexe
if user.age >= 18 and user.is_verified and user.balance > 0:
    process_payment()


# [OK] Bon : Variables intermédiaires
is_adult = user.age >= 18
is_verified = user.is_verified
has_balance = user.balance > 0

if is_adult and is_verified and has_balance:
    process_payment()


"""
QUAND LES COMMENTS SONT NÉCESSAIRES
────────────────────────────────────

Même avec code propre, comments utiles pour :

1. CONTEXTE MÉTIER
   # Règle comptable française : TVA non applicable sur livres
   
2. ALGORITHMES COMPLEXES
   # Algorithme de Dijkstra pour plus court chemin
   
3. OPTIMISATIONS NON-ÉVIDENTES
   # Utiliser set() ici réduit complexité de O(n²) à O(n)
   
4. LIMITATIONS ET BUGS CONNUS
   # FIXME: Race condition possible avec threading
   
5. RÉFÉRENCES EXTERNES
   # Implémentation basée sur RFC 3986 section 3.2
"""


# ----------------------------------------------------------------------------
# [INTERDIT] ANTI-PATTERNS À ÉVITER
# ----------------------------------------------------------------------------

"""
1. COMMENTS ÉVIDENTS
────────────────────
"""

# [X] MAUVAIS : Comment répète le code
# Incrémenter i
i += 1

# Définir x à 10
x = 10

# Boucler sur la liste
for item in items:
    process(item)


"""
2. COMMENTS OBSOLÈTES
─────────────────────
"""

# [X] MAUVAIS : Comment ne correspond plus au code
# Calculer la moyenne
result = sum(numbers) / len(numbers)  # Calcule médiane maintenant !


"""
3. CODE COMMENTÉ (MORT)
───────────────────────
"""

# [X] MAUVAIS : Vieux code commenté
def process():
    result = new_method()
    # old_result = old_method()  # Ancienne version
    # if old_result:
    #     return old_result
    # else:
    #     return default
    return result

# [OK] BON : Supprimer (Git garde l'historique !)
def process():
    return new_method()


"""
4. TROP DE COMMENTS
───────────────────
"""

# [X] MAUVAIS : Sur-commenté
def calculate_total(items):
    # Initialiser total à 0
    total = 0
    
    # Boucler sur chaque item
    for item in items:
        # Obtenir prix de l'item
        price = item.price
        
        # Obtenir quantité
        quantity = item.quantity
        
        # Multiplier prix par quantité
        subtotal = price * quantity
        
        # Ajouter au total
        total += subtotal
    
    # Retourner le total
    return total


# [OK] BON : Code clair sans comments excessifs
def calculate_total(items):
    """Calcule le total de tous les items."""
    total = 0
    for item in items:
        subtotal = item.price * item.quantity
        total += subtotal
    return total

# Ou encore mieux
def calculate_total(items):
    """Calcule le total de tous les items."""
    return sum(item.price * item.quantity for item in items)


"""
5. COMMENTS POUR CODE MAL ÉCRIT
────────────────────────────────
"""

# [X] MAUVAIS : Comment compense code illisible
# Obtenir premier élément de x si x pas vide sinon None
r = x[0] if x else None

# [OK] BON : Fonction explicite
def get_first_or_none(items):
    """Retourne premier élément ou None si liste vide."""
    return items[0] if items else None

result = get_first_or_none(x)


"""
6. DOCSTRINGS VIDES OU INUTILES
────────────────────────────────
"""

# [X] MAUVAIS : Docstring n'ajoute rien
def add(a, b):
    """Ajoute a et b."""
    return a + b

# [OK] BON : Pas de docstring si évident
def add(a, b):
    return a + b

# OU docstring utile si complexité
def add_with_overflow_check(a, b, max_value=None):
    """
    Additionne a et b avec vérification débordement.
    
    Args:
        a (int): Premier nombre
        b (int): Second nombre
        max_value (int, optional): Valeur max autorisée
    
    Returns:
        int: Somme de a et b
    
    Raises:
        OverflowError: Si résultat > max_value
    """
    result = a + b
    if max_value and result > max_value:
        raise OverflowError(f"Result {result} exceeds {max_value}")
    return result


# ============================================================================
# [GUIDE] CHAPITRE 3 : CONVENTIONS PEP 257
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Qu'est-ce que PEP 257
[OK] Conventions officielles Python pour docstrings
[OK] Format one-line vs multi-line
[OK] Docstrings pour différents objets
[OK] Vérifier conformité PEP 257
[OK] Outils de validation automatique
"""


# ----------------------------------------------------------------------------
# [DOC] QU'EST-CE QUE PEP 257 ?
# ----------------------------------------------------------------------------

"""
PEP 257 = Python Enhancement Proposal 257
"Docstring Conventions"

Document officiel définissant :
- Comment écrire des docstrings
- Format et style recommandés
- Bonnes pratiques

URL : https://peps.python.org/pep-0257/

[IDEE] POURQUOI C'EST IMPORTANT ?

[OK] Standard officiel Python
[OK] Cohérence entre projets
[OK] Outils automatiques (Sphinx, pydoc)
[OK] Meilleure collaboration
[OK] Documentation professionnelle
"""


# ----------------------------------------------------------------------------
# [MESURE] RÈGLES GÉNÉRALES PEP 257
# ----------------------------------------------------------------------------

"""
RÈGLE 1 : TRIPLE QUOTES
───────────────────────

Toujours utiliser triple double-quotes : \"\"\"
"""

# [OK] BON
def example():
    """Docstring avec triple double-quotes."""
    pass

# [X] ÉVITER (mais techniquement valide)
def example():
    '''Docstring avec triple simple-quotes.'''
    pass

# [X] MAUVAIS
def example():
    "Docstring avec double-quotes simple."
    pass


"""
RÈGLE 2 : PHRASES COMPLÈTES
────────────────────────────

Docstrings = phrases complètes, impératives, avec ponctuation
"""

# [OK] BON
def calculate():
    """Calcule le résultat."""
    pass

# [X] MAUVAIS
def calculate():
    """calcul du resultat"""  # Pas de majuscule, pas de point
    pass

# [X] MAUVAIS
def calculate():
    """Cette fonction calcule le résultat."""  # Pas impératif
    pass


"""
RÈGLE 3 : POSITION
──────────────────

Docstring = première instruction, juste après définition
"""

# [OK] BON
def example():
    """Docstring immédiatement après def."""
    x = 1
    return x

# [X] MAUVAIS
def example():
    x = 1  # Code avant docstring
    """Ceci n'est pas une docstring valide."""
    return x


"""
RÈGLE 4 : LIGNE VIDE APRÈS
───────────────────────────

Ligne vide après docstring (sauf one-line)
"""

# [OK] BON (one-line)
def simple():
    """Fonction simple."""
    return True

# [OK] BON (multi-line)
def complex():
    """
    Fonction complexe.
    
    Description détaillée.
    """
    
    # Ligne vide après docstring
    return True

# [X] MAUVAIS
def example():
    """Docstring."""
    return True  # Pas de ligne vide pour one-line = OK


# ----------------------------------------------------------------------------
# [NOTE] FORMAT ONE-LINE
# ----------------------------------------------------------------------------

"""
RÈGLES ONE-LINE DOCSTRINGS
───────────────────────────

1. Tout sur une seule ligne
2. Triple quotes début ET fin sur même ligne
3. Phrase impérative
4. Point final
5. Décrit l'action, pas l'implémentation
"""

# [OK] PARFAIT
def get_name():
    """Retourne le nom de l'utilisateur."""
    return self.name

def is_valid():
    """Vérifie si les données sont valides."""
    return check_validation()

def send_email():
    """Envoie un email de confirmation."""
    smtp.send(message)


# [X] VIOLATIONS COURANTES

def bad1():
    """
    Retourne le nom.
    """  # Multi-ligne inutile
    pass

def bad2():
    """Retourne le nom"""  # Pas de point final
    pass

def bad3():
    """retourne le nom."""  # Pas de majuscule
    pass

def bad4():
    """Cette fonction retourne le nom."""  # Pas impératif
    pass

def bad5():
    """Retourne le nom en appelant self.name."""  # Trop de détails
    pass


"""
QUAND UTILISER ONE-LINE
───────────────────────

[OK] Fonctions simples et évidentes
[OK] Getters/Setters basiques
[OK] Fonctions utilitaires claires
[OK] Méthodes avec comportement simple

[X] Fonctions avec paramètres complexes
[X] Plusieurs valeurs de retour
[X] Exceptions possibles
[X] Comportements non-évidents
"""


# ----------------------------------------------------------------------------
# [FICHIER] FORMAT MULTI-LINE
# ----------------------------------------------------------------------------

"""
RÈGLES MULTI-LINE DOCSTRINGS
─────────────────────────────

1. Ligne de résumé (comme one-line)
2. Ligne vide
3. Description détaillée
4. Triple quotes de fin sur ligne séparée
"""

# [OK] FORMAT CORRECT
def complex_function(param1, param2):
    """
    Ligne de résumé (impérative, < 80 caractères).
    
    Description détaillée sur plusieurs paragraphes si nécessaire.
    Expliquez le comportement, les détails importants, etc.
    
    Le texte ici peut être aussi long que nécessaire. Divisez
    en paragraphes pour clarté. Chaque paragraphe séparé par
    une ligne vide.
    
    Args:
        param1: Description du premier paramètre.
        param2: Description du second paramètre.
    
    Returns:
        Description de ce qui est retourné.
    
    Raises:
        ValueError: Quand et pourquoi cette exception.
    """
    pass


"""
STRUCTURE DÉTAILLÉE
───────────────────
"""

def detailed_example(arg1, arg2, option=None):
    """
    [1] Ligne de résumé impérative se terminant par un point.
    
    [2] Ligne vide obligatoire
    
    [3] Description étendue (optionnelle)
    Cette section peut contenir plusieurs paragraphes expliquant
    en détail ce que fait la fonction, pourquoi elle existe,
    comment l'utiliser efficacement.
    
    [4] Sections structurées
    
    Args:
        arg1 (type): Description de arg1.
            Peut continuer sur plusieurs lignes si indentées.
        arg2 (type): Description de arg2.
        option (type, optional): Description de option.
            Defaults to None.
    
    Returns:
        type: Description de la valeur retournée.
            Détails sur la structure si nécessaire.
    
    Raises:
        ExceptionType: Quand cette exception est levée.
        AnotherException: Autre exception possible.
    
    Yields:
        type: Si générateur, ce qui est généré.
    
    Examples:
        Exemples d'utilisation :
        
        >>> detailed_example(1, 2)
        3
        
        >>> detailed_example(10, 20, option='special')
        'special result'
    
    Note:
        Notes supplémentaires, avertissements, limitations.
    
    See Also:
        related_function : Fonction liée
        AnotherClass : Classe liée
    
    References:
        .. [1] Author, "Title", Journal, Year
    
    Todo:
        * Amélioration prévue 1
        * Amélioration prévue 2
    """  # [5] Triple quotes sur ligne séparée
    pass


# ----------------------------------------------------------------------------
# [CLASSICAL_BUILDING] DOCSTRINGS SPÉCIFIQUES PAR TYPE
# ----------------------------------------------------------------------------

"""
1. MODULES
──────────

Docstring en haut du fichier, avant imports
"""

# my_module.py
"""
Résumé d'une ligne du module.

Description détaillée du module. Expliquez son rôle dans l'application,
ce qu'il fournit, comment l'utiliser.

This module provides:
    - Function1: Description courte
    - Function2: Description courte
    - Class1: Description courte

Typical usage example:
    from my_module import Function1, Class1
    
    result = Function1(arg)
    obj = Class1()
    obj.method()
"""

import sys
import os


"""
2. CLASSES
──────────

Docstring après class, avant __init__
"""

class MyClass:
    """
    Résumé de la classe sur une ligne.
    
    Description détaillée de la classe. Expliquez son rôle,
    ses responsabilités, comment l'utiliser.
    
    Attributes:
        public_attr (type): Description de l'attribut public.
        another_attr (type): Autre attribut.
    
    Examples:
        >>> obj = MyClass(param)
        >>> obj.method()
        result
    """
    
    def __init__(self, param):
        """
        Initialise une instance de MyClass.
        
        Args:
            param: Description du paramètre.
        """
        self.public_attr = param


"""
3. FONCTIONS ET MÉTHODES
────────────────────────

Selon PEP 257
"""

def function(arg1, arg2):
    """
    Résumé de ce que fait la fonction.
    
    Description détaillée si nécessaire.
    
    Args:
        arg1: Description
        arg2: Description
    
    Returns:
        Description du retour
    """
    pass


"""
4. MÉTHODES SPÉCIALES
─────────────────────

__init__, __str__, __repr__, etc.
"""

class Example:
    def __init__(self, value):
        """
        Initialise Example avec value.
        
        Args:
            value: Valeur initiale.
        """
        self.value = value
    
    def __str__(self):
        """Retourne représentation string lisible."""
        return f"Example({self.value})"
    
    def __repr__(self):
        """Retourne représentation string technique."""
        return f"Example(value={self.value!r})"
    
    def __len__(self):
        """Retourne la longueur."""
        return len(self.value)


"""
5. PROPERTIES
─────────────

Documenter getters, setters, deleters
"""

class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        """
        float: Température en Celsius.
        
        Getter retourne température en degrés Celsius.
        Setter permet de définir température avec validation.
        """
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        """
        Définit température en Celsius.
        
        Args:
            value (float): Température en Celsius.
        
        Raises:
            ValueError: Si temperature < -273.15.
        """
        if value < -273.15:
            raise ValueError("Below absolute zero")
        self._celsius = value


"""
6. GÉNÉRATEURS
──────────────

Utiliser Yields au lieu de Returns
"""

def count_up_to(n):
    """
    Génère nombres de 1 à n.
    
    Args:
        n (int): Nombre maximum.
    
    Yields:
        int: Nombres successifs de 1 à n.
    
    Examples:
        >>> list(count_up_to(5))
        [1, 2, 3, 4, 5]
    """
    for i in range(1, n + 1):
        yield i


# ----------------------------------------------------------------------------
# [RECHERCHE] VÉRIFIER CONFORMITÉ PEP 257
# ----------------------------------------------------------------------------

"""
OUTILS DE VALIDATION
────────────────────


1. PYDOCSTYLE
─────────────

Vérificateur dédié PEP 257
"""

# Installation
pip install pydocstyle

# Vérifier fichier
pydocstyle my_module.py

# Vérifier dossier
pydocstyle my_package/

# Output exemple
"""
my_module.py:1 at module level:
        D100: Missing docstring in public module
        
my_module.py:5 in public function `calculate`:
        D103: Missing docstring in public function
        
my_module.py:10 in public function `process`:
        D200: One-line docstring should fit on one line with quotes
"""


"""
2. PYLINT
─────────

Linter général incluant vérifications docstrings
"""

pip install pylint

# Vérifier
pylint my_module.py

# Configurer dans .pylintrc
"""
[MASTER]
docstring-min-length=10

[MESSAGES CONTROL]
enable=missing-docstring,
       empty-docstring
"""


"""
3. FLAKE8 + PLUGINS
───────────────────

Linter avec extensions docstrings
"""

pip install flake8 flake8-docstrings

# Vérifier
flake8 my_module.py


"""
4. PRÉ-COMMIT HOOKS
───────────────────

Vérification automatique avant commit
"""

# .pre-commit-config.yaml
"""
repos:
  - repo: https://github.com/PyCQA/pydocstyle
    rev: 6.3.0
    hooks:
      - id: pydocstyle
        args: [--convention=pep257]
"""


"""
CONFIGURATION PYDOCSTYLE
────────────────────────

Fichier .pydocstyle ou setup.cfg
"""

# .pydocstyle
"""
[pydocstyle]
convention = pep257
add-ignore = D100,D104  # Ignorer certaines erreurs
match = .*\.py          # Fichiers à vérifier
match-dir = ^(?!tests)  # Exclure dossier tests
"""


"""
CODES D'ERREUR PYDOCSTYLE
──────────────────────────

Erreurs courantes :

D100: Missing docstring in public module
D101: Missing docstring in public class
D102: Missing docstring in public method
D103: Missing docstring in public function
D104: Missing docstring in public package

D200: One-line docstring should fit on one line
D201: No blank lines allowed before function docstring
D202: No blank lines allowed after function docstring
D203: 1 blank line required before class docstring
D204: 1 blank line required after class docstring

D300: Use triple double quotes
D301: Use r""" if any backslashes in docstring
D302: Use u""" for Unicode docstrings (Python 2)

D400: First line should end with a period
D401: First line should be in imperative mood
D402: First line should not be function's signature

D403: First word of first line should be capitalized
D404: First word of docstring should not be "This"
"""


# ============================================================================
# [DOCS] RÉCAPITULATIF PARTIE 1 COMPLÈTE
# ============================================================================

"""
[BRAVO] FÉLICITATIONS ! PARTIE 1 TERMINÉE !

VOUS MAÎTRISEZ MAINTENANT :

Chapitre 0 : Introduction
[OK] Pourquoi documenter est crucial
[OK] Types de documentation
[OK] Audiences et leurs besoins
[OK] Quand et quoi documenter
[OK] Principes d'une bonne documentation

Chapitre 1 : Docstrings
[OK] Syntaxe et règles de base
[OK] Docstrings pour fonctions, classes, modules
[OK] Formats standards (Google, NumPy, Sphinx)
[OK] Accès programmatique aux docstrings
[OK] Doctest : tests dans docstrings

Chapitre 2 : Comments vs Docstrings
[OK] Différence fondamentale
[OK] Quand utiliser comments
[OK] Quand utiliser docstrings
[OK] Code auto-documenté
[OK] Anti-patterns à éviter

Chapitre 3 : Conventions PEP 257
[OK] Standard officiel Python
[OK] Règles générales
[OK] Format one-line et multi-line
[OK] Docstrings par type d'objet
[OK] Outils de validation


[CLE] POINTS CLÉS

1. Docstring = API publique, Comment = Implémentation
2. Triple double-quotes toujours
3. Phrases impératives avec point final
4. PEP 257 = standard à suivre
5. Doctest = documentation + tests
6. Code lisible > Comments excessifs


[OBJECTIF] VOUS POUVEZ MAINTENANT

[OK] Écrire docstrings professionnelles
[OK] Distinguer comments et docstrings
[OK] Suivre conventions PEP 257
[OK] Valider vos docstrings automatiquement
[OK] Intégrer doctests


-> PROCHAINE ÉTAPE : PARTIE 2

La Partie 2 couvrira :
- Sphinx (génération documentation)
- Read the Docs (hébergement)
- MkDocs (alternative moderne)
- pdoc3 (simple et rapide)

Vous allez apprendre à :
- Générer documentation HTML/PDF
- Héberger documentation en ligne
- Créer sites de documentation
- Automatiser génération docs


[GUIDE] FICHIER SUIVANT : documentation_partie2.txt

Excellente progression ! Prêt pour les outils ? [RAPIDE]
"""

# ============================================================================
# FIN DE LA PARTIE 1
# ============================================================================

Parfait ! J'ai complété la **Partie 1** avec :

### [OK] Chapitre 1 (fin) : Doctest
- Tests intégrés dans docstrings
- Syntaxe et règles
- Directives doctest
- Configuration et exécution
- Bonnes pratiques

### [OK] Chapitre 2 : Comments vs Docstrings
- Différences fondamentales
- Quand utiliser chacun
- 8 cas d'usage pour comments
- Code auto-documenté
- Anti-patterns détaillés

### [OK] Chapitre 3 : Conventions PEP 257
- Standard officiel Python
- Règles générales (quotes, phrases, position)
- Format one-line vs multi-line
- Docstrings par type (modules, classes, fonctions)
- Outils de validation (pydocstyle, pylint)
- Codes d'erreur et configuration

**La Partie 1 est maintenant complète (~2500 lignes) !**

Voulez-vous que je continue avec la **Partie 2 : Outils de Documentation** ?
- Chapitre 4 : Sphinx
- Chapitre 5 : Read the Docs
- Chapitre 6 : MkDocs
- Chapitre 7 : pdoc3

# ============================================================================
# [LIVRE] PYTHON DOCUMENTATION - PARTIE 2 : OUTILS DE DOCUMENTATION
# ============================================================================
#
# [OBJECTIF] CETTE PARTIE COUVRE :
# - Chapitre 4 : Sphinx (Outil principal de documentation)
# - Chapitre 5 : Read the Docs (Hébergement documentation)
# - Chapitre 6 : MkDocs (Alternative moderne)
# - Chapitre 7 : pdoc3 (Simple et rapide)
#
# [TEMPS] TEMPS : ~6-8 heures
# [DOCS] PRÉREQUIS : Partie 1 complétée (Docstrings, PEP 257)
# ============================================================================


# ============================================================================
# [GUIDE] CHAPITRE 4 : SPHINX - LE STANDARD PYTHON
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Installer et configurer Sphinx
[OK] Générer documentation depuis docstrings
[OK] Utiliser reStructuredText (reST)
[OK] Personnaliser thèmes et apparence
[OK] Ajouter extensions utiles
[OK] Générer HTML, PDF, ePub
[OK] Automatiser avec autodoc
[OK] Déployer votre documentation
"""


# ----------------------------------------------------------------------------
# [REFLEXION] QU'EST-CE QUE SPHINX ?
# ----------------------------------------------------------------------------

"""
DÉFINITION

Sphinx = Générateur de documentation Python
- Créé pour documenter Python lui-même
- Standard de facto pour projets Python
- Transforme reST -> HTML, PDF, ePub...
- Autodoc : Génère doc depuis docstrings


[IDEE] POURQUOI SPHINX ?

[OK] STANDARD PYTHON
   - Utilisé par Python, Django, Flask, NumPy, etc.
   - Reconnu et attendu par la communauté

[OK] PUISSANT ET EXTENSIBLE
   - Nombreuses extensions
   - Thèmes personnalisables
   - Formats multiples (HTML, PDF, ePub)

[OK] AUTODOC
   - Extraction automatique des docstrings
   - Moins de duplication
   - Documentation toujours à jour

[OK] CROSS-REFERENCES
   - Liens automatiques entre pages
   - Index et glossaire
   - Recherche intégrée

[OK] SUPPORT MATH ET CODE
   - Formules mathématiques (LaTeX)
   - Coloration syntaxique code
   - Diagrammes et graphiques


[X] INCONVÉNIENTS

- Courbe d'apprentissage (reST)
- Configuration initiale
- Plus lourd que MkDocs/pdoc
- Syntaxe moins intuitive que Markdown


[TROPHEE] PROJETS UTILISANT SPHINX

- Python Documentation officielle
- Django, Flask, Requests
- NumPy, SciPy, Pandas
- SQLAlchemy, Celery
- Read the Docs (plateforme)
"""


# ----------------------------------------------------------------------------
# [OUTILS] INSTALLATION ET SETUP
# ----------------------------------------------------------------------------

"""
INSTALLATION
────────────
"""

# Installation de base
pip install sphinx

# Avec extensions courantes
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints

# Vérifier installation
sphinx-build --version


"""
INITIALISER PROJET SPHINX
──────────────────────────

Structure de projet recommandée :
"""

# Structure avant Sphinx
mon_projet/
├── mon_package/
│   ├── __init__.py
│   ├── module1.py
│   └── module2.py
├── tests/
├── README.md
└── setup.py

# Créer dossier docs et initialiser
mkdir docs
cd docs
sphinx-quickstart

"""
[IDEE] SPHINX-QUICKSTART

Wizard interactif qui pose des questions :

> Separate source and build directories (y/n) [n]: y
  [OK] Recommandé : Sépare source (reST) et build (HTML)

> Project name: Mon Projet
> Author name(s): Votre Nom
> Project release []: 1.0.0

> Project language [en]: fr  (optionnel)

> autodoc: automatically insert docstrings (y/n) [n]: y
  [OK] IMPORTANT : Active autodoc

> intersphinx: link between Sphinx docs (y/n) [n]: y
  [OK] Liens vers autres docs (Python, etc.)

> viewcode: include links to source code (y/n) [n]: y
  [OK] Liens vers code source

Autres : accepter défauts (n)
"""


"""
STRUCTURE APRÈS INITIALISATION
───────────────────────────────
"""

mon_projet/
├── mon_package/
│   ├── __init__.py
│   ├── module1.py
│   └── module2.py
├── docs/
│   ├── source/              # <- Fichiers source (.rst)
│   │   ├── conf.py         # <- Configuration Sphinx
│   │   ├── index.rst       # <- Page d'accueil
│   │   └── _static/        # Fichiers statiques (CSS, images)
│   │   └── _templates/     # Templates personnalisés
│   ├── build/              # <- Documentation générée (Git ignore)
│   │   └── html/           # HTML généré
│   └── Makefile            # <- Commandes build (Linux/Mac)
│   └── make.bat            # <- Commandes build (Windows)
├── tests/
└── setup.py


"""
FICHIER CONF.PY
───────────────

Configuration principale Sphinx
"""

# docs/source/conf.py

# -- Path setup --------------------------------------------------------------
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))  # <- Accès à mon_package


# -- Project information -----------------------------------------------------
project = 'Mon Projet'
copyright = '2024, Votre Nom'
author = 'Votre Nom'
release = '1.0.0'


# -- General configuration ---------------------------------------------------
extensions = [
    'sphinx.ext.autodoc',      # Documentation automatique
    'sphinx.ext.napoleon',     # Support Google/NumPy docstrings
    'sphinx.ext.viewcode',     # Liens vers code source
    'sphinx.ext.intersphinx',  # Liens vers autres docs
    'sphinx.ext.todo',         # Support TODOs
    'sphinx.ext.coverage',     # Vérifier couverture doc
]

templates_path = ['_templates']
exclude_patterns = []

language = 'fr'  # Langue de la doc


# -- Options for HTML output -------------------------------------------------
html_theme = 'sphinx_rtd_theme'  # Thème Read the Docs
html_static_path = ['_static']


# -- Extension configuration -------------------------------------------------
# autodoc
autodoc_default_options = {
    'members': True,           # Documenter tous les membres
    'undoc-members': True,     # Inclure membres sans docstring
    'show-inheritance': True,  # Montrer héritage classes
}

# napoleon (pour Google/NumPy style)
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = True

# intersphinx (liens vers Python docs)
intersphinx_mapping = {
    'python': ('https://docs.python.org/3', None),
}


# ----------------------------------------------------------------------------
# [NOTE] PREMIERS PAS AVEC RESTRUCTUREDTEXT (reST)
# ----------------------------------------------------------------------------

"""
SYNTAXE DE BASE reST
────────────────────

reStructuredText = Langage de markup pour Sphinx
Plus puissant mais plus complexe que Markdown


1. TITRES
─────────

Soulignement avec caractères spéciaux
Hiérarchie : = > - > ^ > "
"""

# index.rst
"""
======================
Titre Principal (H1)
======================

Sous-titre (H2)
===============

Section (H3)
------------

Sous-section (H4)
^^^^^^^^^^^^^^^^^

Paragraphe (H5)
"""""""""""""""
"""


"""
2. PARAGRAPHES ET TEXTE
───────────────────────
"""

# exemple.rst
"""
Un paragraphe normal. Les lignes sont automatiquement
fusionnées si pas de ligne vide.

Un nouveau paragraphe nécessite une ligne vide.

*Italique* ou **Gras** ou ``code``

Lien : `Python <https://python.org>`_

Lien interne : :ref:`ma-section`
"""


"""
3. LISTES
─────────
"""

# listes.rst
"""
Liste à puces :

* Item 1
* Item 2
  
  * Sous-item 2.1
  * Sous-item 2.2
  
* Item 3

Liste numérotée :

1. Premier
2. Deuxième
3. Troisième

#. Auto-numérotation
#. Continue automatiquement
"""


"""
4. BLOCS DE CODE
────────────────
"""

# code.rst
"""
Code inline : ``variable = 10``

Bloc de code :

.. code-block:: python

   def hello():
       '''Fonction exemple.'''
       print("Hello World")
       return True

Avec numéros de ligne :

.. code-block:: python
   :linenos:
   :emphasize-lines: 2,3

   def calculate(a, b):
       result = a + b  # Ligne mise en évidence
       return result   # Ligne mise en évidence
"""


"""
5. NOTES ET AVERTISSEMENTS
──────────────────────────
"""

# notes.rst
"""
.. note::
   Ceci est une note informative.

.. warning::
   Ceci est un avertissement important.

.. tip::
   Ceci est un conseil utile.

.. important::
   Information importante.

.. seealso::
   Voir aussi cette autre section.

.. danger::
   Attention ! Danger potentiel.
"""


"""
6. TABLEAUX
───────────
"""

# tableaux.rst
"""
Tableau simple :

+--------+--------+--------+
| Header | Header | Header |
+========+========+========+
| Cell   | Cell   | Cell   |
+--------+--------+--------+
| Cell   | Cell   | Cell   |
+--------+--------+--------+

Tableau CSV :

.. csv-table:: Mon Tableau
   :header: "Nom", "Âge", "Ville"
   :widths: 20, 10, 20

   "Alice", 30, "Paris"
   "Bob", 25, "Lyon"
   "Charlie", 35, "Marseille"

Liste de tableau :

.. list-table:: Comparaison
   :widths: 25 25 50
   :header-rows: 1

   * - Feature
     - Python
     - JavaScript
   * - Typage
     - Dynamique
     - Dynamique
   * - Performance
     - Moyenne
     - Haute
"""


"""
7. IMAGES ET FIGURES
────────────────────
"""

# images.rst
"""
Image simple :

.. image:: _static/logo.png
   :width: 200px
   :alt: Logo du projet

Figure avec légende :

.. figure:: _static/architecture.png
   :scale: 50%
   :align: center
   :alt: Architecture du système

   Diagramme de l'architecture système
"""


"""
8. LIENS ET RÉFÉRENCES
──────────────────────
"""

# liens.rst
"""
Lien externe :
`Python <https://python.org>`_

Lien externe avec texte :
Visitez le `site Python`_.

.. _site Python: https://python.org

Référence interne :

.. _ma-section:

Ma Section
==========

Contenu...

Pour référencer : voir :ref:`ma-section`

Référence vers autre fichier :
:doc:`autre-page`
"""


# ----------------------------------------------------------------------------
# [BOT] AUTODOC : DOCUMENTATION AUTOMATIQUE
# ----------------------------------------------------------------------------

"""
AUTODOC = Extension pour générer doc depuis docstrings


PRÉREQUIS
─────────

1. Extension activée dans conf.py
"""

# conf.py
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.napoleon',  # Pour Google/NumPy style
]


"""
2. Package accessible (sys.path configuré)
"""

import sys
import os
sys.path.insert(0, os.path.abspath('../..'))


"""
DIRECTIVES AUTODOC
──────────────────

.. automodule::   - Documenter module complet
.. autoclass::    - Documenter classe
.. autofunction:: - Documenter fonction
.. automethod::   - Documenter méthode
.. autodata::     - Documenter variable/constante
.. autoattribute:: - Documenter attribut


EXEMPLE COMPLET
───────────────
"""

# mon_package/calculator.py
"""
Module de calcul mathématique.

Ce module fournit des fonctions de calcul de base.
"""

class Calculator:
    """
    Calculatrice simple.
    
    Cette classe fournit des opérations arithmétiques de base.
    
    Attributes:
        result (float): Résultat de la dernière opération.
        history (list): Historique des opérations.
    
    Examples:
        >>> calc = Calculator()
        >>> calc.add(5, 3)
        8
    """
    
    def __init__(self):
        """Initialise la calculatrice."""
        self.result = 0
        self.history = []
    
    def add(self, a, b):
        """
        Additionne deux nombres.
        
        Args:
            a (float): Premier nombre.
            b (float): Second nombre.
        
        Returns:
            float: Somme de a et b.
        
        Examples:
            >>> calc = Calculator()
            >>> calc.add(2, 3)
            5
        """
        self.result = a + b
        self.history.append(f"{a} + {b} = {self.result}")
        return self.result
    
    def multiply(self, a, b):
        """
        Multiplie deux nombres.
        
        Args:
            a (float): Premier nombre.
            b (float): Second nombre.
        
        Returns:
            float: Produit de a et b.
        """
        self.result = a * b
        self.history.append(f"{a} × {b} = {self.result}")
        return self.result


def factorial(n):
    """
    Calcule la factorielle de n.
    
    Args:
        n (int): Nombre entier positif.
    
    Returns:
        int: Factorielle de n.
    
    Raises:
        ValueError: Si n est négatif.
    
    Examples:
        >>> factorial(5)
        120
        >>> factorial(0)
        1
    """
    if n < 0:
        raise ValueError("n doit être positif")
    if n == 0:
        return 1
    return n * factorial(n - 1)


# Documentation Sphinx
# docs/source/api.rst
"""
API Reference
=============

Module calculator
-----------------

.. automodule:: mon_package.calculator
   :members:
   :undoc-members:
   :show-inheritance:

Classes
-------

Calculator
^^^^^^^^^^

.. autoclass:: mon_package.calculator.Calculator
   :members:
   :undoc-members:
   :show-inheritance:
   :special-members: __init__

Functions
---------

factorial
^^^^^^^^^

.. autofunction:: mon_package.calculator.factorial
"""


"""
OPTIONS AUTODOC
───────────────

:members:              Documenter tous les membres
:undoc-members:        Inclure membres sans docstring
:private-members:      Inclure membres privés (_xxx)
:special-members:      Inclure méthodes spéciales (__xxx__)
:show-inheritance:     Montrer classes parentes
:inherited-members:    Inclure membres hérités
:exclude-members:      Exclure certains membres

:member-order:         Ordre des membres
                       - alphabetical
                       - bysource (ordre dans code)
                       - groupwise (par type)
"""


"""
EXEMPLE AVEC OPTIONS
────────────────────
"""

# api.rst
"""
.. autoclass:: mon_package.User
   :members:
   :undoc-members:
   :show-inheritance:
   :member-order: bysource
   :exclude-members: _internal_method
   :special-members: __init__, __str__, __repr__
"""


"""
AUTODOC AVEC TYPE HINTS
───────────────────────

Extension pour meilleure intégration type hints
"""

# Installation
pip install sphinx-autodoc-typehints

# conf.py
extensions = [
    'sphinx.ext.autodoc',
    'sphinx_autodoc_typehints',
]

# Code avec type hints
from typing import List, Optional, Dict

def process_data(
    data: List[Dict[str, any]],
    filter_key: Optional[str] = None
) -> List[Dict[str, any]]:
    """
    Traite et filtre les données.
    
    Args:
        data: Liste de dictionnaires à traiter.
        filter_key: Clé optionnelle pour filtrage.
    
    Returns:
        Données traitées et filtrées.
    """
    # Type hints apparaîtront automatiquement dans la doc
    pass


# ----------------------------------------------------------------------------
# [DESIGN] THÈMES ET PERSONNALISATION
# ----------------------------------------------------------------------------

"""
THÈMES POPULAIRES
─────────────────


1. SPHINX_RTD_THEME (Read the Docs)
────────────────────────────────────

Thème le plus populaire
"""

pip install sphinx-rtd-theme

# conf.py
html_theme = 'sphinx_rtd_theme'

html_theme_options = {
    'canonical_url': '',
    'analytics_id': '',
    'logo_only': False,
    'display_version': True,
    'prev_next_buttons_location': 'bottom',
    'style_external_links': False,
    'collapse_navigation': True,
    'sticky_navigation': True,
    'navigation_depth': 4,
    'includehidden': True,
    'titles_only': False
}


"""
2. FURO (Moderne et épuré)
──────────────────────────
"""

pip install furo

# conf.py
html_theme = 'furo'

html_theme_options = {
    "light_css_variables": {
        "color-brand-primary": "#2962ff",
        "color-brand-content": "#2962ff",
    },
}


"""
3. PYDATA_SPHINX_THEME (Pour data science)
───────────────────────────────────────────
"""

pip install pydata-sphinx-theme

# conf.py
html_theme = 'pydata_sphinx_theme'


"""
4. BOOK THEME (Style livre)
───────────────────────────
"""

pip install sphinx-book-theme

# conf.py
html_theme = 'sphinx_book_theme'


"""
PERSONNALISATION HTML
─────────────────────
"""

# conf.py

# Logo
html_logo = '_static/logo.png'

# Favicon
html_favicon = '_static/favicon.ico'

# CSS personnalisé
html_static_path = ['_static']
html_css_files = [
    'custom.css',
]

# JavaScript personnalisé
html_js_files = [
    'custom.js',
]

# Titre du navigateur
html_title = 'Mon Projet Documentation'

# Footer personnalisé
html_show_sphinx = False  # Cacher "Built with Sphinx"
html_show_copyright = True

# Sidebar
html_sidebars = {
    '**': [
        'about.html',
        'navigation.html',
        'relations.html',
        'searchbox.html',
    ]
}


"""
CSS PERSONNALISÉ
────────────────
"""

# docs/source/_static/custom.css
"""
/* Couleurs personnalisées */
:root {
    --primary-color: #2962ff;
    --secondary-color: #00bfa5;
}

/* Style des titres */
h1 {
    color: var(--primary-color);
    border-bottom: 2px solid var(--primary-color);
    padding-bottom: 0.5rem;
}

/* Style des blocs de code */
.highlight {
    background-color: #f5f5f5;
    border-left: 3px solid var(--primary-color);
    padding: 1rem;
}

/* Style des notes */
.admonition.note {
    border-left: 4px solid var(--secondary-color);
}
"""


# ----------------------------------------------------------------------------
# [PACKAGE] EXTENSIONS UTILES
# ----------------------------------------------------------------------------

"""
EXTENSIONS ESSENTIELLES
───────────────────────


1. NAPOLEON
───────────

Support Google et NumPy docstring styles
"""

# conf.py
extensions = ['sphinx.ext.napoleon']

napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = True
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True


"""
2. VIEWCODE
───────────

Liens vers code source
"""

extensions = ['sphinx.ext.viewcode']


"""
3. INTERSPHINX
──────────────

Liens vers autres documentations Sphinx
"""

extensions = ['sphinx.ext.intersphinx']

intersphinx_mapping = {
    'python': ('https://docs.python.org/3', None),
    'numpy': ('https://numpy.org/doc/stable/', None),
    'pandas': ('https://pandas.pydata.org/docs/', None),
    'django': ('https://docs.djangoproject.com/en/stable/', None),
}

# Utilisation dans .rst
"""
Voir :class:`python:list` pour plus d'infos.
Référence à :func:`numpy:numpy.array`.
"""


"""
4. TODO
───────

Gérer les TODOs dans la documentation
"""

extensions = ['sphinx.ext.todo']

todo_include_todos = True  # Afficher TODOs

# Utilisation
"""
.. todo::
   Ajouter exemples supplémentaires
   
.. todo::
   Corriger typos dans cette section
"""


"""
5. AUTOSUMMARY
──────────────

Générer automatiquement tables de résumé
"""

extensions = ['sphinx.ext.autosummary']

autosummary_generate = True

# Utilisation
"""
.. autosummary::
   :toctree: _autosummary
   
   mon_package.module1
   mon_package.module2
   mon_package.module3
"""


"""
6. DOCTEST
──────────

Tester les exemples dans la doc
"""

extensions = ['sphinx.ext.doctest']

# Tester
make doctest


"""
7. COVERAGE
───────────

Vérifier couverture documentation
"""

extensions = ['sphinx.ext.coverage']

# Générer rapport
make coverage


"""
EXTENSIONS TIERCES POPULAIRES
──────────────────────────────


1. SPHINX-COPYBUTTON
────────────────────

Bouton copier pour blocs de code
"""

pip install sphinx-copybutton

# conf.py
extensions = ['sphinx_copybutton']


"""
2. SPHINX-TABS
──────────────

Onglets dans la documentation
"""

pip install sphinx-tabs

# conf.py
extensions = ['sphinx_tabs.tabs']

# Utilisation
"""
.. tabs::

   .. tab:: Python
   
      .. code-block:: python
      
         print("Hello Python")
   
   .. tab:: JavaScript
   
      .. code-block:: javascript
      
         console.log("Hello JS");
"""


"""
3. MYST-PARSER
──────────────

Support Markdown dans Sphinx
"""

pip install myst-parser

# conf.py
extensions = ['myst_parser']

source_suffix = {
    '.rst': 'restructuredtext',
    '.md': 'markdown',
}


"""
4. SPHINX-DESIGN
────────────────

Composants UI modernes (cards, grids, etc.)
"""

pip install sphinx-design

# conf.py
extensions = ['sphinx_design']

# Utilisation
"""
.. card:: Titre de la carte

   Contenu de la carte avec **Markdown**

.. grid:: 2

   .. grid-item-card:: Card 1
   
      Contenu
   
   .. grid-item-card:: Card 2
   
      Contenu
"""


"""
5. SPHINXCONTRIB-MERMAID
────────────────────────

Diagrammes Mermaid
"""

pip install sphinxcontrib-mermaid

# conf.py
extensions = ['sphinxcontrib.mermaid']

# Utilisation
"""
.. mermaid::

   graph TD
       A[Start] --> B{Is it?}
       B -->|Yes| C[OK]
       B -->|No| D[End]
"""


# ----------------------------------------------------------------------------
# [CONSTRUCTION] GÉNÉRER LA DOCUMENTATION
# ----------------------------------------------------------------------------

"""
COMMANDES DE BUILD
──────────────────


BUILD HTML
──────────
"""

# Linux/Mac
make html

# Windows
make.bat html

# Ou directement
sphinx-build -b html source build/html


"""
OUTPUT
──────

Documentation générée dans :
docs/build/html/index.html

Ouvrir dans navigateur :
"""

# Linux/Mac
open docs/build/html/index.html

# Windows
start docs/build/html/index.html


"""
BUILD PDF
─────────

Nécessite LaTeX installé
"""

# Linux
sudo apt-get install texlive-full

# Mac
brew install mactex

# Build
make latexpdf

# Output
# docs/build/latex/monprojet.pdf


"""
BUILD EPUB
──────────

Pour liseuses électroniques
"""

make epub

# Output
# docs/build/epub/monprojet.epub


"""
AUTRES FORMATS
──────────────
"""

make man        # Pages man Unix
make texinfo    # Format Texinfo
make text       # Texte brut
make xml        # XML
make json       # JSON


"""
CLEAN BUILD
───────────

Nettoyer avant rebuild
"""

make clean
make html


"""
BUILD AUTO (WATCH)
──────────────────

Rebuild automatique à chaque modification
"""

pip install sphinx-autobuild

# Lancer serveur avec auto-rebuild
sphinx-autobuild source build/html

# Ouvrir http://127.0.0.1:8000
# Documentation se recharge automatiquement !


# ----------------------------------------------------------------------------
# [GUIDE] STRUCTURE DOCUMENTATION COMPLÈTE
# ----------------------------------------------------------------------------

"""
ORGANISATION RECOMMANDÉE
────────────────────────
"""

docs/
├── source/
│   ├── conf.py              # Configuration
│   ├── index.rst            # Page d'accueil
│   │
│   ├── getting_started.rst  # Guide démarrage
│   ├── installation.rst     # Installation
│   ├── quickstart.rst       # Quick start
│   │
│   ├── user_guide/          # Guide utilisateur
│   │   ├── index.rst
│   │   ├── basic_usage.rst
│   │   ├── advanced.rst
│   │   └── examples.rst
│   │
│   ├── api/                 # API Reference
│   │   ├── index.rst
│   │   ├── module1.rst
│   │   ├── module2.rst
│   │   └── exceptions.rst
│   │
│   ├── tutorials/           # Tutoriels
│   │   ├── index.rst
│   │   ├── tutorial1.rst
│   │   └── tutorial2.rst
│   │
│   ├── howto/              # How-to guides
│   │   ├── index.rst
│   │   ├── deployment.rst
│   │   └── testing.rst
│   │
│   ├── reference/          # Références
│   │   ├── index.rst
│   │   ├── config.rst
│   │   └── cli.rst
│   │
│   ├── development/        # Dev docs
│   │   ├── index.rst
│   │   ├── contributing.rst
│   │   ├── architecture.rst
│   │   └── changelog.rst
│   │
│   ├── _static/            # Fichiers statiques
│   │   ├── logo.png
│   │   ├── custom.css
│   │   └── custom.js
│   │
│   └── _templates/         # Templates custom
│       └── layout.html
│
└── build/                  # Documentation générée
    └── html/


"""
EXEMPLE index.rst
─────────────────
"""

# docs/source/index.rst
"""
=============================
Documentation de Mon Projet
=============================

.. image:: _static/logo.png
   :alt: Logo Mon Projet
   :width: 200px

Bienvenue dans la documentation de Mon Projet !

Mon Projet est une bibliothèque Python pour [description courte].

Features
========

* Feature 1 : Description
* Feature 2 : Description
* Feature 3 : Description

Quick Example
=============

.. code-block:: python

   from mon_projet import MyClass
   
   obj = MyClass()
   result = obj.process()
   print(result)

Table of Contents
=================

.. toctree::
   :maxdepth: 2
   :caption: Getting Started
   
   installation
   quickstart

.. toctree::
   :maxdepth: 2
   :caption: User Guide
   
   user_guide/index
   user_guide/basic_usage
   user_guide/advanced

.. toctree::
   :maxdepth: 2
   :caption: API Reference
   
   api/index

.. toctree::
   :maxdepth: 1
   :caption: Development
   
   development/contributing
   development/changelog

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
"""


"""
EXEMPLE installation.rst
────────────────────────
"""

# docs/source/installation.rst
"""
============
Installation
============

Requirements
============

* Python 3.8+
* pip

Install from PyPI
=================

.. code-block:: bash

   pip install mon-projet

Install from Source
===================

.. code-block:: bash

   git clone https://github.com/user/mon-projet.git
   cd mon-projet
   pip install -e .

Verify Installation
===================

.. code-block:: python

   import mon_projet
   print(mon_projet.__version__)

Next Steps
==========

Continue to :doc:`quickstart` to get started!
"""


# ============================================================================
# [COURS] EXERCICE PRATIQUE : DOCUMENTATION SPHINX COMPLÈTE
# ============================================================================

"""
OBJECTIF
────────

Créer documentation Sphinx complète pour un projet Python


PROJET EXEMPLE : CALCULATRICE
──────────────────────────────
"""

# calculator/__init__.py
"""
Bibliothèque de calcul mathématique.

Ce package fournit des calculatrices pour différents besoins.
"""

__version__ = '1.0.0'

from .basic import BasicCalculator
from .scientific import ScientificCalculator

__all__ = ['BasicCalculator', 'ScientificCalculator']


# calculator/basic.py
"""
Module de calcul de base.

Fournit calculatrice avec opérations arithmétiques simples.
"""

class BasicCalculator:
    """
    Calculatrice pour opérations de base.
    
    Cette calculatrice supporte addition, soustraction,
    multiplication et division.
    
    Attributes:
        result (float): Résultat de la dernière opération.
        history (list): Historique des opérations.
    
    Examples:
        >>> calc = BasicCalculator()
        >>> calc.add(5, 3)
        8
        >>> calc.multiply(4, 2)
        8
    """
    
    def __init__(self):
        """Initialise la calculatrice."""
        self.result = 0
        self.history = []
    
    def add(self, a, b):
        """
        Additionne deux nombres.
        
        Args:
            a (float): Premier nombre.
            b (float): Second nombre.
        
        Returns:
            float: Somme de a et b.
        
        Examples:
            >>> calc = BasicCalculator()
            >>> calc.add(2, 3)
            5
        """
        self.result = a + b
        self._record(f"{a} + {b} = {self.result}")
        return self.result
    
    def subtract(self, a, b):
        """
        Soustrait b de a.
        
        Args:
            a (float): Nombre de départ.
            b (float): Nombre à soustraire.
        
        Returns:
            float: Différence a - b.
        """
        self.result = a - b
        self._record(f"{a} - {b} = {self.result}")
        return self.result
    
    def multiply(self, a, b):
        """Multiplie deux nombres."""
        self.result = a * b
        self._record(f"{a} × {b} = {self.result}")
        return self.result
    
    def divide(self, a, b):
        """
        Divise a par b.
        
        Args:
            a (float): Numérateur.
            b (float): Dénominateur.
        
        Returns:
            float: Quotient a / b.
        
        Raises:
            ZeroDivisionError: Si b est 0.
        """
        if b == 0:
            raise ZeroDivisionError("Division par zéro")
        self.result = a / b
        self._record(f"{a} ÷ {b} = {self.result}")
        return self.result
    
    def _record(self, operation):
        """Enregistre opération dans historique."""
        self.history.append(operation)


"""
ÉTAPES
──────

1. Initialiser Sphinx
2. Configurer conf.py
3. Créer structure pages
4. Générer doc API
5. Personnaliser thème
6. Ajouter exemples
7. Compiler et tester


SOLUTION DISPONIBLE DANS EXERCICE GUIDÉ
────────────────────────────────────────
(Voir documentation_partie2_exercices.txt)
"""


# ============================================================================
# [DOCS] RÉCAPITULATIF CHAPITRE 4
# ============================================================================

"""
CE QUE VOUS AVEZ APPRIS

[OK] Qu'est-ce que Sphinx et pourquoi l'utiliser
[OK] Installation et configuration (sphinx-quickstart)
[OK] Structure projet Sphinx (source/, build/, conf.py)
[OK] Syntaxe reStructuredText (titres, listes, code, liens)
[OK] Autodoc (documentation automatique depuis docstrings)
[OK] Thèmes populaires (RTD, Furo, PyData)
[OK] Personnalisation (CSS, JS, logo, favicon)
[OK] Extensions essentielles (napoleon, viewcode, intersphinx)
[OK] Génération documentation (HTML, PDF, ePub)
[OK] Organisation documentation complète


[CLE] POINTS CLÉS

1. Sphinx = Standard Python pour documentation
2. reStructuredText plus puissant que Markdown
3. Autodoc extrait docstrings automatiquement
4. Extensions étendent fonctionnalités
5. Thèmes personnalisent apparence
6. make html génère documentation
7. Organisation claire = doc utilisable


[OBJECTIF] VOUS POUVEZ MAINTENANT

[OK] Initialiser projet Sphinx
[OK] Écrire documentation en reST
[OK] Générer doc depuis docstrings
[OK] Personnaliser thème et apparence
[OK] Compiler documentation professionnelle


-> PROCHAINE ÉTAPE : Chapitre 5 - Read the Docs !

Vous allez apprendre :
- Héberger documentation gratuitement
- Builds automatiques depuis Git
- Versions multiples
- Domaine personnalisé

Prêt à publier votre doc en ligne ? [RAPIDE]
"""

# ============================================================================
# CE FICHIER CONTINUE...
# ============================================================================

Excellent ! J'ai créé le **Chapitre 4 complet sur Sphinx** (~1800 lignes).

**Ce qui est inclus :**

### [OK] Chapitre 4 : Sphinx
1. **Introduction** - Qu'est-ce que Sphinx, pourquoi l'utiliser
2. **Installation** - Setup complet avec sphinx-quickstart
3. **ReStructuredText** - Syntaxe complète (titres, listes, code, tableaux, images)
4. **Autodoc** - Documentation automatique depuis docstrings
5. **Thèmes** - RTD, Furo, PyData, personnalisation CSS/JS
6. **Extensions** - Napoleon, Viewcode, Intersphinx, TODO, etc.
7. **Build** - Génération HTML, PDF, ePub
8. **Structure** - Organisation documentation complète
9. **Exercice pratique** - Projet calculatrice documenté

Voulez-vous que je continue avec :
- **Chapitre 5 : Read the Docs** (hébergement gratuit, builds auto)
- **Chapitre 6 : MkDocs** (alternative Markdown moderne)
- **Chapitre 7 : pdoc3** (documentation simple et rapide)

Pour compléter la **Partie 2 : Outils de Documentation** ?

# ============================================================================
# [GUIDE] CHAPITRE 5 : READ THE DOCS - HÉBERGEMENT DOCUMENTATION
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Qu'est-ce que Read the Docs et ses avantages
[OK] Créer un compte et connecter GitHub/GitLab
[OK] Configurer projet pour Read the Docs
[OK] Builds automatiques depuis Git
[OK] Gérer versions multiples de documentation
[OK] Personnaliser domaine et sous-domaine
[OK] Variables d'environnement et dépendances
[OK] Webhooks et intégrations CI/CD
[OK] Analytics et monitoring
"""


# ----------------------------------------------------------------------------
# [REFLEXION] QU'EST-CE QUE READ THE DOCS ?
# ----------------------------------------------------------------------------

"""
DÉFINITION

Read the Docs (RTD) = Plateforme d'hébergement documentation
- Gratuit pour projets open-source
- Builds automatiques depuis Git
- Versions multiples (latest, stable, v1.0, etc.)
- HTTPS inclus
- Recherche intégrée
- Support Sphinx, MkDocs, autres


[IDEE] POURQUOI READ THE DOCS ?

[OK] GRATUIT
   - Hébergement illimité projets open-source
   - Bande passante illimitée
   - Builds automatiques

[OK] AUTOMATISATION COMPLÈTE
   - Push Git -> Build automatique
   - Pas de déploiement manuel
   - Toujours à jour

[OK] VERSIONS MULTIPLES
   - Documentation par version (v1.0, v2.0)
   - latest vs stable
   - Branches et tags Git

[OK] RECHERCHE INTÉGRÉE
   - Index automatique
   - Recherche rapide
   - Pas de configuration

[OK] ANALYTICS
   - Statistiques de visites
   - Pages populaires
   - Recherches courantes

[OK] DOMAINE PERSONNALISÉ
   - docs.monprojet.com
   - HTTPS automatique
   - Certificat SSL gratuit

[OK] INTÉGRATIONS
   - GitHub, GitLab, Bitbucket
   - Webhooks
   - Status badges


[X] LIMITATIONS

- Projets privés payants ($5/mois)
- Builds limités en temps (max 15min)
- Pas de contrôle serveur
- Moins flexible qu'auto-hébergement


[TROPHEE] PROJETS SUR READ THE DOCS

- Requests, Django, Flask
- Sphinx, MkDocs
- NumPy, SciPy, Pandas
- Pytest, Tox
- Et des milliers d'autres !

URL : https://readthedocs.org
"""


# ----------------------------------------------------------------------------
# [RAPIDE] PREMIERS PAS
# ----------------------------------------------------------------------------

"""
ÉTAPE 1 : CRÉER UN COMPTE
──────────────────────────

1. Aller sur https://readthedocs.org
2. Sign Up
3. Connecter avec GitHub/GitLab/Bitbucket (recommandé)
   OU créer compte email


ÉTAPE 2 : PRÉPARER VOTRE PROJET
────────────────────────────────

Prérequis :
[OK] Code sur GitHub/GitLab/Bitbucket
[OK] Documentation Sphinx configurée
[OK] Fichier requirements.txt ou docs/requirements.txt
[OK] Fichier .readthedocs.yaml (optionnel mais recommandé)


STRUCTURE PROJET TYPIQUE
─────────────────────────
"""

mon_projet/
├── .readthedocs.yaml        # <- Configuration RTD
├── README.md
├── setup.py
├── requirements.txt         # Dépendances projet
│
├── mon_package/
│   ├── __init__.py
│   └── module.py
│
├── docs/
│   ├── requirements.txt     # <- Dépendances doc
│   ├── source/
│   │   ├── conf.py
│   │   └── index.rst
│   └── Makefile
│
└── tests/


"""
ÉTAPE 3 : FICHIER .readthedocs.yaml
────────────────────────────────────

Configuration projet Read the Docs (v2)
"""

# .readthedocs.yaml
version: 2

# Build documentation dans docs/
build:
  os: ubuntu-22.04
  tools:
    python: "3.11"

# Configuration Sphinx
sphinx:
  builder: html
  configuration: docs/source/conf.py
  fail_on_warning: true

# Formats de sortie
formats:
  - pdf
  - epub

# Dépendances Python
python:
  install:
    - requirements: docs/requirements.txt
    - method: pip
      path: .

"""
[IDEE] SECTIONS .readthedocs.yaml

version: 2
    Version du fichier config (toujours 2)

build:
    OS et outils de build
    - os: ubuntu-20.04 ou ubuntu-22.04
    - tools.python: version Python

sphinx:
    Configuration Sphinx
    - builder: html, dirhtml, htmldir
    - configuration: chemin vers conf.py
    - fail_on_warning: échouer si warnings

formats:
    Formats supplémentaires à générer
    - pdf (nécessite LaTeX)
    - epub
    - htmlzip

python:
    Installation dépendances Python
    - requirements: fichier requirements.txt
    - method: pip ou setuptools
    - path: chemin vers setup.py
"""


"""
EXEMPLE COMPLET .readthedocs.yaml
──────────────────────────────────
"""

# .readthedocs.yaml
version: 2

build:
  os: ubuntu-22.04
  tools:
    python: "3.11"
  jobs:
    post_checkout:
      # Commandes après checkout Git
      - git fetch --unshallow || true
    pre_build:
      # Commandes avant build doc
      - echo "Starting documentation build"
    post_build:
      # Commandes après build doc
      - echo "Documentation built successfully"

sphinx:
  builder: html
  configuration: docs/source/conf.py
  fail_on_warning: false

formats:
  - pdf
  - epub

python:
  install:
    # Installer dépendances doc
    - requirements: docs/requirements.txt
    # Installer package en mode éditable
    - method: pip
      path: .
      extra_requirements:
        - docs

# Redirections
# (pour migration URLs)
# redirects:
#   "/old-page.html": "/new-page.html"


"""
FICHIER docs/requirements.txt
──────────────────────────────

Dépendances pour build documentation
"""

# docs/requirements.txt
sphinx>=5.0
sphinx-rtd-theme>=1.0
sphinx-autodoc-typehints>=1.18
myst-parser>=0.18  # Si utilisation Markdown

# Extensions supplémentaires
sphinxcontrib-mermaid>=0.7
sphinx-copybutton>=0.5
sphinx-tabs>=3.4


"""
ÉTAPE 4 : IMPORTER PROJET SUR RTD
──────────────────────────────────

1. Connexion à https://readthedocs.org
2. Cliquer "Import a Project"
3. Sélectionner repository depuis GitHub/GitLab
4. Ou importer manuellement :
   - Nom du projet
   - URL du repository
   - Branche par défaut (main/master)
5. Cliquer "Next"
6. Configuration auto-détectée
7. Cliquer "Build version"


ÉTAPE 5 : PREMIER BUILD
────────────────────────

Read the Docs :
1. Clone le repository
2. Détecte .readthedocs.yaml
3. Installe dépendances
4. Exécute sphinx-build
5. Publie documentation

URL de votre doc :
https://nom-projet.readthedocs.io


VÉRIFIER LE BUILD
─────────────────

Admin -> Builds -> Voir derniers builds
- Success [OK] (vert)
- Failed [X] (rouge)
- Cancelled (gris)

Cliquer sur build pour voir logs détaillés
"""


# ----------------------------------------------------------------------------
# [OUTIL] CONFIGURATION AVANCÉE
# ----------------------------------------------------------------------------

"""
CONFIGURATION DANS INTERFACE RTD
─────────────────────────────────


ADMIN -> SETTINGS
────────────────

General Settings:
- Name: Nom affiché
- Repository URL: URL Git
- Repository type: Git
- Default branch: main
- Default version: latest
- Privacy level: Public/Private
- Analytics code: Google Analytics

Advanced Settings:
- Install Project: pip install .
- Requirements file: docs/requirements.txt
- Python configuration file: docs/source/conf.py
- Build with docker: Non (recommandé)
- Default Python version: 3.11


ADMIN -> VERSIONS
────────────────

Activer/désactiver versions :
- latest (branche par défaut)
- stable (dernier tag)
- Tags (v1.0, v2.0, etc.)
- Branches (develop, feature-x, etc.)

Pour chaque version :
- Active: Oui/Non
- Privacy level: Public/Private
- Hidden: Masquer de liste versions


ADMIN -> DOMAINS
───────────────

Domaine personnalisé :
1. Ajouter domaine : docs.monprojet.com
2. Créer enregistrement DNS CNAME :
   docs.monprojet.com -> nom-projet.readthedocs.io
3. Activer HTTPS (automatique)

Canonical URL:
URL préférée pour SEO
"""


"""
VARIABLES D'ENVIRONNEMENT
──────────────────────────

Admin -> Environment Variables

Ajouter variables pour build :
"""

# Exemple variables
DJANGO_SETTINGS_MODULE=docs.settings
API_KEY=xxx  # Pour tests dans docstrings
SPHINXOPTS=-W  # Options Sphinx supplémentaires

"""
Utilisation dans conf.py :
"""

# docs/source/conf.py
import os

# Lire variable d'environnement
if os.environ.get('READTHEDOCS') == 'True':
    # Configuration spécifique RTD
    html_theme = 'sphinx_rtd_theme'
else:
    # Configuration locale
    html_theme = 'alabaster'


"""
WEBHOOKS
────────

Admin -> Integrations -> Add integration

Webhooks disponibles :
- GitHub
- GitLab
- Bitbucket
- Generic webhook

Configuration automatique :
1. Sélectionner GitHub
2. RTD crée webhook automatiquement
3. Push -> Build automatique

Webhook manuel :
URL : https://readthedocs.org/api/v2/webhook/...
Events : push, pull_request


NOTIFICATIONS
─────────────

Admin -> Notifications

Email notifications pour :
- Build failures
- Build successes (optionnel)
- New builds

Webhook notifications :
- Slack
- Custom URL
"""


# ----------------------------------------------------------------------------
# [IMPORTANT] GESTION DES VERSIONS
# ----------------------------------------------------------------------------

"""
STRATÉGIE DE VERSIONING
───────────────────────


VERSIONS SPÉCIALES RTD
──────────────────────

latest
    Branche par défaut (main/master)
    Toujours la dernière version dev
    URL : /en/latest/

stable
    Dernier tag/release
    Version stable recommandée
    URL : /en/stable/


VERSIONS DEPUIS TAGS GIT
────────────────────────

Créer release Git :
"""

# Créer tag
git tag -a v1.0.0 -m "Release 1.0.0"
git push origin v1.0.0

# RTD détecte automatiquement et crée version
# URL : /en/v1.0.0/

"""
Activer dans Admin -> Versions


VERSIONS DEPUIS BRANCHES
────────────────────────

Toute branche Git peut être version :
"""

# Créer branche feature
git checkout -b docs-redesign
git push origin docs-redesign

# Activer dans Admin -> Versions
# URL : /en/docs-redesign/


"""
CONFIGURATION PAR VERSION
─────────────────────────

Différentes configs selon version :
"""

# docs/source/conf.py
import os

# Détecter version RTD
rtd_version = os.environ.get('READTHEDOCS_VERSION', 'latest')

if rtd_version == 'latest':
    # Config pour latest
    version = 'dev'
    release = 'development'
else:
    # Config pour versions stables
    version = rtd_version
    release = rtd_version


"""
BANNIÈRE DE VERSION
───────────────────

RTD ajoute automatiquement bannière :
"Vous lisez la version X. Voir version stable."

Personnaliser dans conf.py :
"""

html_context = {
    'display_github': True,
    'github_user': 'username',
    'github_repo': 'project',
    'github_version': 'main',
    'conf_py_path': '/docs/source/',
}


"""
REDIRECTION DE VERSION
──────────────────────

Rediriger ancienne version :
Admin -> Redirects -> Add redirect

Exemple :
/en/v0.9/ -> /en/stable/
/old-page.html -> /new-page.html
"""


# ----------------------------------------------------------------------------
# [RECHERCHE] RECHERCHE
# ----------------------------------------------------------------------------

"""
RECHERCHE INTÉGRÉE
──────────────────

RTD indexe automatiquement :
[OK] Tous les fichiers HTML générés
[OK] Titres et headers
[OK] Contenu texte
[OK] Code examples


PERSONNALISER RECHERCHE
───────────────────────

Exclure du search :
"""

# docs/source/conf.py

# Ne pas indexer ces patterns
html_search_options = {
    'exclude': [
        'search.html',
        'genindex.html',
        'py-modindex.html',
    ]
}


"""
ANALYTICS RECHERCHE
───────────────────

Admin -> Search Analytics

Voir :
- Termes les plus recherchés
- Recherches sans résultats
- Améliorer contenu basé sur recherches
"""


# ----------------------------------------------------------------------------
# [GRAPHIQUE] ANALYTICS ET MONITORING
# ----------------------------------------------------------------------------

"""
TRAFFIC ANALYTICS
─────────────────

Admin -> Traffic Analytics

Statistiques disponibles :
- Vues pages par jour/semaine/mois
- Pages les plus visitées
- Versions les plus consultées
- Pays des visiteurs
- Devices (desktop/mobile)


GOOGLE ANALYTICS
────────────────

Ajouter tracking ID :
Admin -> Settings -> Advanced -> Analytics code
"""

# Ajouter ID : UA-XXXXXXXXX-X ou G-XXXXXXXXXX

# Ou dans conf.py
html_theme_options = {
    'analytics_id': 'G-XXXXXXXXXX',
}


"""
STATUS BADGES
─────────────

Afficher statut build dans README :
"""

# README.md
"""
# Mon Projet

[![Documentation Status](https://readthedocs.org/projects/mon-projet/badge/?version=latest)](https://mon-projet.readthedocs.io/en/latest/?badge=latest)

Documentation complète : https://mon-projet.readthedocs.io
"""


"""
MONITORING UPTIME
─────────────────

RTD fournit :
- Status page : https://status.readthedocs.org
- 99.9% uptime SLA
- Incident reports
"""


# ----------------------------------------------------------------------------
# [SECURISE] DOCUMENTATION PRIVÉE
# ----------------------------------------------------------------------------

"""
PROJETS PRIVÉS
──────────────

Read the Docs for Business (payant)
- $5/mois par projet
- Documentation privée
- Authentification requise
- Teams et permissions


CONFIGURATION PRIVACY
─────────────────────

Admin -> Settings -> Privacy level

Options :
- Public : Accessible à tous
- Private : Authentification requise
- Protected : Lien direct seulement (pas d'index)


AUTHENTIFICATION
────────────────

RTD Business :
- GitHub OAuth
- GitLab OAuth
- SAML/SSO
- Teams et groupes
"""


# ----------------------------------------------------------------------------
# [RAPIDE] INTÉGRATION CI/CD
# ----------------------------------------------------------------------------

"""
GITHUB ACTIONS
──────────────

Build et test doc avant merge
"""

# .github/workflows/docs.yml
name: Documentation

on:
  pull_request:
    paths:
      - 'docs/**'
      - '.readthedocs.yaml'

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'
    
    - name: Install dependencies
      run: |
        pip install -r docs/requirements.txt
        pip install -e .
    
    - name: Build documentation
      run: |
        cd docs
        make html
    
    - name: Check for broken links
      run: |
        cd docs
        make linkcheck


"""
GITLAB CI
─────────
"""

# .gitlab-ci.yml
pages:
  stage: deploy
  image: python:3.11
  
  script:
    - pip install -r docs/requirements.txt
    - pip install -e .
    - cd docs && make html
    - mv build/html/ ../public/
  
  artifacts:
    paths:
      - public
  
  only:
    - main


"""
PRE-COMMIT HOOK
───────────────

Vérifier docs avant commit
"""

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: sphinx-build
        name: Build Sphinx docs
        entry: sphinx-build
        language: system
        args: ['-W', '-b', 'html', 'docs/source', 'docs/build/html']
        pass_filenames: false
        files: '\.rst$|conf\.py'


# ----------------------------------------------------------------------------
# [DESIGN] PERSONNALISATION AVANCÉE
# ----------------------------------------------------------------------------

"""
THÈME PERSONNALISÉ
──────────────────

Utiliser thème custom avec RTD
"""

# docs/source/conf.py

import sphinx_rtd_theme

html_theme = 'sphinx_rtd_theme'

html_theme_options = {
    'logo_only': False,
    'display_version': True,
    'prev_next_buttons_location': 'bottom',
    'style_external_links': True,
    'vcs_pageview_mode': 'blob',
    
    # TOC options
    'collapse_navigation': False,
    'sticky_navigation': True,
    'navigation_depth': 4,
    'includehidden': True,
    'titles_only': False,
    
    # Colors
    'style_nav_header_background': '#2980B9',
}

# CSS personnalisé
html_static_path = ['_static']
html_css_files = [
    'custom.css',
]


"""
docs/source/_static/custom.css
"""

# custom.css
"""
/* Couleurs personnalisées */
.wy-side-nav-search {
    background-color: #2c3e50 !important;
}

.wy-nav-top {
    background-color: #2c3e50 !important;
}

/* Liens */
a {
    color: #2980b9 !important;
}

a:hover {
    color: #1abc9c !important;
}

/* Code blocks */
.highlight {
    background: #f8f9fa;
}
"""


"""
LOGO ET FAVICON
───────────────
"""

# conf.py
html_logo = '_static/logo.png'
html_favicon = '_static/favicon.ico'


"""
FOOTER PERSONNALISÉ
───────────────────
"""

# conf.py
html_show_sphinx = False
html_show_copyright = True

html_context = {
    'display_github': True,
    'github_user': 'username',
    'github_repo': 'project',
    'github_version': 'main',
    'conf_py_path': '/docs/source/',
}


# ----------------------------------------------------------------------------
# [BUG] DÉPANNAGE ET PROBLÈMES COURANTS
# ----------------------------------------------------------------------------

"""
PROBLÈME 1 : BUILD ÉCHOUE
──────────────────────────

Cause : Dépendances manquantes

Solution :
"""

# docs/requirements.txt (vérifier toutes les dépendances)
sphinx>=5.0
sphinx-rtd-theme
# Ajouter TOUTES les extensions utilisées

# .readthedocs.yaml (vérifier installation)
python:
  install:
    - requirements: docs/requirements.txt
    - method: pip
      path: .


"""
PROBLÈME 2 : MODULE NOT FOUND
──────────────────────────────

Cause : sys.path incorrect dans conf.py

Solution :
"""

# docs/source/conf.py
import os
import sys

# Ajouter path vers package
sys.path.insert(0, os.path.abspath('../..'))

# Ou chemin absolu
sys.path.insert(0, '/home/docs/checkouts/readthedocs.org/user_builds/project/checkouts/latest')


"""
PROBLÈME 3 : WARNINGS CASSENT BUILD
────────────────────────────────────

Cause : fail_on_warning: true

Solution :
"""

# Option 1 : Désactiver fail_on_warning
# .readthedocs.yaml
sphinx:
  fail_on_warning: false

# Option 2 : Corriger tous les warnings
# Voir logs de build pour détails


"""
PROBLÈME 4 : THÈME PAS APPLIQUÉ
────────────────────────────────

Cause : Thème non installé

Solution :
"""

# Ajouter dans docs/requirements.txt
sphinx-rtd-theme>=1.0

# Vérifier dans conf.py
html_theme = 'sphinx_rtd_theme'


"""
PROBLÈME 5 : PDF BUILD ÉCHOUE
──────────────────────────────

Cause : LaTeX non disponible ou erreurs

Solution :
"""

# Option 1 : Désactiver PDF
# .readthedocs.yaml
formats: []  # Pas de PDF/ePub

# Option 2 : Corriger erreurs LaTeX
# Voir logs build pour erreurs spécifiques


"""
PROBLÈME 6 : RECHERCHE NE FONCTIONNE PAS
─────────────────────────────────────────

Cause : Index search pas généré

Solution :
Vérifier dans conf.py que search est activé (par défaut)
Rebuild documentation
Attendre réindexation (peut prendre quelques minutes)


PROBLÈME 7 : VERSIONS MULTIPLES CASSÉES
────────────────────────────────────────

Cause : Tags Git mal configurés

Solution :
"""

# Vérifier tags
git tag -l

# Créer tag correct
git tag -a v1.0.0 -m "Version 1.0.0"
git push origin v1.0.0

# Activer dans Admin -> Versions


"""
DEBUG BUILDS
────────────

Voir logs détaillés :
Admin -> Builds -> Cliquer sur build failed

Logs contiennent :
1. Checkout du repository
2. Installation dépendances
3. Build Sphinx
4. Erreurs exactes

Reproduire localement :
"""

# Même environnement que RTD
docker run -it --rm \
  -v $(pwd):/docs \
  readthedocs/build:latest \
  /bin/bash

# Dans container
cd /docs/docs
pip install -r requirements.txt
make html


# ----------------------------------------------------------------------------
# [IDEE] BONNES PRATIQUES READ THE DOCS
# ----------------------------------------------------------------------------

"""
CHECKLIST CONFIGURATION
───────────────────────

[OK] Fichier .readthedocs.yaml à la racine
[OK] Version Python spécifiée (3.11 recommandé)
[OK] docs/requirements.txt complet
[OK] conf.py avec sys.path correct
[OK] Webhook GitHub/GitLab configuré
[OK] Versions activées (latest, stable, tags)
[OK] Domaine personnalisé configuré (optionnel)
[OK] Analytics activé (optionnel)
[OK] Status badge dans README


VERSIONING
──────────

[OK] Utiliser semantic versioning (v1.0.0, v2.0.0)
[OK] Tagger releases importantes
[OK] Maintenir stable = dernière version stable
[OK] latest = développement
[OK] Nettoyer anciennes versions (> 1 an)


DOCUMENTATION
─────────────

[OK] Index clair avec table of contents
[OK] Quick start accessible
[OK] Exemples de code testés (doctest)
[OK] API reference complète (autodoc)
[OK] Changelog maintenu à jour
[OK] Contributing guide
[OK] Liens externes vérifiés (linkcheck)


PERFORMANCE
───────────

[OK] Images optimisées (< 500KB)
[OK] Pas de fichiers énormes (> 10MB)
[OK] Build time < 10 minutes
[OK] Caching activé (.doctrees/)
[OK] Parallel builds si possible


SÉCURITÉ
────────

[OK] Pas de secrets dans code/docs
[OK] Variables d'environnement pour clés
[OK] Documentation privée si nécessaire
[OK] HTTPS activé (automatique)
[OK] Dépendances à jour


MAINTENANCE
───────────

[OK] Surveiller builds (webhooks)
[OK] Vérifier analytics régulièrement
[OK] Répondre issues documentation
[OK] Mettre à jour dépendances
[OK] Tester docs localement avant push
"""


# ============================================================================
# [GUIDE] CHAPITRE 6 : MKDOCS - ALTERNATIVE MODERNE
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Qu'est-ce que MkDocs et ses avantages
[OK] Installer et configurer MkDocs
[OK] Écrire documentation en Markdown
[OK] Utiliser thèmes Material et autres
[OK] Plugins essentiels et extensions
[OK] Déployer sur GitHub Pages, GitLab, Netlify
[OK] Générer documentation depuis docstrings
[OK] Comparer MkDocs vs Sphinx
"""


# ----------------------------------------------------------------------------
# [REFLEXION] QU'EST-CE QUE MKDOCS ?
# ----------------------------------------------------------------------------

"""
DÉFINITION

MkDocs = Générateur de documentation statique
- Écrit en Python
- Utilise Markdown (pas reST)
- Plus simple que Sphinx
- Thèmes modernes (Material Design)
- Preview temps réel


[IDEE] POURQUOI MKDOCS ?

[OK] SIMPLICITÉ
   - Markdown facile à apprendre
   - Configuration YAML simple
   - Setup rapide (< 5 minutes)

[OK] MODERNE
   - Thème Material magnifique
   - Design responsive natif
   - Dark mode intégré

[OK] PREVIEW LIVE
   - mkdocs serve
   - Rechargement auto
   - Développement rapide

[OK] DÉPLOIEMENT FACILE
   - GitHub Pages en 1 commande
   - Netlify, Vercel compatibles
   - Static files simples

[OK] EXTENSIBLE
   - Plugins nombreux
   - Hooks personnalisés
   - Thèmes personnalisables


[X] LIMITATIONS

- Moins puissant que Sphinx
- Pas d'autodoc natif (plugin requis)
- Moins de formats output (HTML seulement)
- Communauté plus petite
- Pas standard pour Python (Sphinx l'est)


[TROPHEE] PROJETS UTILISANT MKDOCS

- FastAPI (documentation officielle)
- Pydantic
- Typer
- Strawberry GraphQL
- Material for MkDocs lui-même


MKDOCS VS SPHINX
─────────────────

┌──────────────────┬───────────────┬──────────────┐
│                  │    MkDocs     │    Sphinx    │
├──────────────────┼───────────────┼──────────────┤
│ Syntaxe          │ Markdown      │ reST         │
│ Courbe           │ Facile        │ Moyenne      │
│ Setup            │ < 5 min       │ 10-15 min    │
│ Autodoc          │ Plugin        │ Natif        │
│ Thèmes           │ Material++    │ RTD++        │
│ Preview          │ Live reload   │ Manual       │
│ Formats          │ HTML          │ HTML/PDF/..  │
│ Standard Python  │ Non           │ Oui          │
│ Use case         │ Doc moderne   │ Doc tech     │
└──────────────────┴───────────────┴──────────────┘
"""


# ----------------------------------------------------------------------------
# [OUTILS] INSTALLATION ET SETUP
# ----------------------------------------------------------------------------

"""
INSTALLATION
────────────
"""

# MkDocs de base
pip install mkdocs

# Avec Material theme (recommandé)
pip install mkdocs-material

# Vérifier installation
mkdocs --version


"""
CRÉER NOUVEAU PROJET
────────────────────
"""

# Créer structure
mkdocs new mon-projet
cd mon-projet

# Structure générée
"""
mon-projet/
├── docs/
│   └── index.md      # Page d'accueil
└── mkdocs.yml        # Configuration
"""


"""
FICHIER mkdocs.yml
──────────────────

Configuration principale
"""

# mkdocs.yml
site_name: Mon Projet
site_url: https://exemple.com
site_author: Votre Nom
site_description: Description courte du projet

# Repository
repo_name: username/projet
repo_url: https://github.com/username/projet

# Navigation
nav:
  - Accueil: index.md
  - Guide utilisateur:
    - Installation: user-guide/installation.md
    - Quick Start: user-guide/quickstart.md
  - API Reference: api/index.md
  - À propos: about.md

# Thème
theme:
  name: material

# Extensions Markdown
markdown_extensions:
  - admonition
  - codehilite
  - toc:
      permalink: true


"""
PREVIEW EN TEMPS RÉEL
─────────────────────
"""

# Lancer serveur dev
mkdocs serve

# Output:
"""
INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  Documentation built in 0.23 seconds
INFO     -  [15:30:00] Serving on http://127.0.0.1:8000/
"""

# Ouvrir http://127.0.0.1:8000
# Modifications = rechargement auto !


"""
BUILD DOCUMENTATION
───────────────────
"""

# Générer HTML statique
mkdocs build

# Output dans site/
"""
site/
├── index.html
├── user-guide/
│   ├── installation/
│   └── quickstart/
├── api/
├── css/
├── js/
└── search/
"""

# Déployer fichiers site/ n'importe où


# ----------------------------------------------------------------------------
# [NOTE] ÉCRIRE EN MARKDOWN
# ----------------------------------------------------------------------------

"""
SYNTAXE MARKDOWN POUR MKDOCS
─────────────────────────────


1. TITRES
─────────
"""

# index.md
"""
# Titre Principal (H1)

## Sous-titre (H2)

### Section (H3)

#### Sous-section (H4)

##### Paragraphe (H5)

###### Note (H6)
"""


"""
2. TEXTE ET FORMATAGE
─────────────────────
"""

"""
Paragraphe normal avec **gras**, *italique*, et `code inline`.

Nouveau paragraphe.

~~Texte barré~~

[Lien vers Python](https://python.org)

[Lien interne](user-guide/installation.md)

![Image](images/logo.png)
"""


"""
3. LISTES
─────────
"""

"""
Liste à puces :

* Item 1
* Item 2
  * Sous-item 2.1
  * Sous-item 2.2
* Item 3

Liste numérotée :

1. Premier
2. Deuxième
3. Troisième

Liste de tâches :

- [x] Tâche terminée
- [ ] Tâche en cours
- [ ] Tâche à faire
"""


"""
4. CODE
───────
"""

"""
Code inline : `variable = 10`

Bloc de code :

```python
def hello():
    '''Fonction exemple.'''
    print("Hello World")
    return True
```

Avec titre :

```python title="example.py"
def calculate(a, b):
    return a + b
```

Avec numéros de ligne :

```python linenums="1"
def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)
```

Highlighting lignes :

```python hl_lines="2 3"
def process():
    result = calculate()  # Ligne mise en évidence
    return result         # Ligne mise en évidence
```
"""


"""
5. ADMONITIONS (NOTES)
──────────────────────

Nécessite extension admonition
"""

"""
!!! note "Titre optionnel"
    Ceci est une note informative.

!!! warning
    Ceci est un avertissement.

!!! danger "Attention !"
    Danger potentiel ici.

!!! tip
    Conseil utile.

!!! info
    Information supplémentaire.

!!! success
    Opération réussie.

!!! question
    Question fréquente ?

!!! example
    Exemple de code.

Admonition collapsible :

??? note "Cliquer pour voir"
    Contenu masqué par défaut.

???+ warning "Ouvert par défaut"
    Contenu visible par défaut.
"""


"""
6. TABLEAUX
───────────
"""

"""
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1   | Cell 2   | Cell 3   |
| Cell 4   | Cell 5   | Cell 6   |

Alignement :

| Gauche | Centre | Droite |
|:-------|:------:|-------:|
| A      |   B    |      C |
"""


"""
7. ONGLETS
──────────

Nécessite extension tabbed
"""

"""
=== "Python"
    ```python
    print("Hello Python")
    ```

=== "JavaScript"
    ```javascript
    console.log("Hello JS");
    ```

=== "Rust"
    ```rust
    println!("Hello Rust");
    ```
"""


"""
8. FOOTNOTES
────────────
"""

"""
Texte avec footnote[^1].

Autre footnote[^2].

[^1]: Première note de bas de page.
[^2]: Deuxième note.
"""


# ----------------------------------------------------------------------------
# [DESIGN] THÈME MATERIAL
# ----------------------------------------------------------------------------

"""
CONFIGURATION MATERIAL
──────────────────────

Thème le plus populaire pour MkDocs
"""

# mkdocs.yml
theme:
  name: material
  
  # Palette de couleurs
  palette:
    # Mode clair
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-7
        name: Passer en mode sombre
    
    # Mode sombre
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-4
        name: Passer en mode clair
  
  # Fonctionnalités
  features:
    - navigation.instant      # Navigation SPA
    - navigation.tracking     # Ancre dans URL
    - navigation.tabs         # Tabs navigation
    - navigation.sections     # Sections dans sidebar
    - navigation.expand       # Expand automatique
    - navigation.indexes      # Index pages
    - navigation.top          # Bouton retour haut
    - search.suggest          # Suggestions recherche
    - search.highlight        # Highlight résultats
    - search.share            # Partager recherche
    - header.autohide         # Cacher header au scroll
    - content.code.copy       # Bouton copier code
    - content.tabs.link       # Lier onglets
  
  # Langue
  language: fr
  
  # Fonts
  font:
    text: Roboto
    code: Roboto Mono
  
  # Icône
  icon:
    repo: fontawesome/brands/github
  
  # Logo et favicon
  logo: assets/logo.png
  favicon: assets/favicon.ico


"""
COULEURS DISPONIBLES
────────────────────

primary (couleur principale) :
- red, pink, purple, deep purple
- indigo, blue, light blue, cyan
- teal, green, light green, lime
- yellow, amber, orange, deep orange
- brown, grey, blue grey, black, white

accent (couleur accentuation) :
Mêmes options que primary


FEATURES MATERIAL
─────────────────

Navigation :
- navigation.instant : SPA-like
- navigation.tabs : Tabs top-level
- navigation.sections : Sections sidebar
- navigation.expand : Auto-expand sidebar
- navigation.indexes : Section index pages
- navigation.top : Back to top button

Search :
- search.suggest : Suggestions
- search.highlight : Highlight résultats
- search.share : Partager recherche

Content :
- content.code.copy : Bouton copier
- content.code.annotate : Annotations code
- content.tabs.link : Lier onglets
- content.tooltips : Tooltips liens
"""


"""
PERSONNALISATION CSS
────────────────────
"""

# mkdocs.yml
extra_css:
  - stylesheets/extra.css

# docs/stylesheets/extra.css
"""
:root {
  --md-primary-fg-color: #2962ff;
  --md-primary-fg-color--light: #448aff;
  --md-primary-fg-color--dark: #0039cb;
}

.md-header {
  background-color: linear-gradient(90deg, #2962ff, #448aff);
}

.md-typeset h1 {
  color: var(--md-primary-fg-color);
}
"""


"""
JAVASCRIPT PERSONNALISÉ
───────────────────────
"""

# mkdocs.yml
extra_javascript:
  - javascripts/extra.js

# docs/javascripts/extra.js
"""
// Ajouter analytics
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
"""


# ----------------------------------------------------------------------------
# [PLUGIN] PLUGINS ESSENTIELS
# ----------------------------------------------------------------------------

"""
PLUGINS POPULAIRES
──────────────────


1. SEARCH (Intégré)
───────────────────
"""

# mkdocs.yml
plugins:
  - search:
      lang: fr
      separator: '[\s\-\.]+'


"""
2. MKDOCSTRINGS (Autodoc)
─────────────────────────

Génération doc depuis docstrings
"""

pip install mkdocstrings[python]

# mkdocs.yml
plugins:
  - search
  - mkdocstrings:
      handlers:
        python:
          options:
            show_source: true
            show_root_heading: true
            show_root_toc_entry: true
            heading_level: 2

# Utilisation dans .md
"""
# API Reference

::: mon_package.module
    options:
      show_root_heading: true
      show_source: true

::: mon_package.Calculator
    options:
      members:
        - add
        - subtract
"""


"""
3. GIT-REVISION-DATE-LOCALIZED
───────────────────────────────

Dates de modification depuis Git
"""

pip install mkdocs-git-revision-date-localized-plugin

# mkdocs.yml
plugins:
  - git-revision-date-localized:
      enable_creation_date: true
      type: timeago


"""
4. MINIFY
─────────

Minifier HTML/CSS/JS
"""

pip install mkdocs-minify-plugin

# mkdocs.yml
plugins:
  - minify:
      minify_html: true
      minify_js: true
      minify_css: true


"""
5. AWESOME-PAGES
────────────────

Organisation pages simplifiée
"""

pip install mkdocs-awesome-pages-plugin

# mkdocs.yml
plugins:
  - awesome-pages

# docs/.pages
"""
title: Documentation
nav:
  - index.md
  - Guide: user-guide
  - API: api
  - ...
"""


"""
6. MACROS
─────────

Variables et macros dans Markdown
"""

pip install mkdocs-macros-plugin

# mkdocs.yml
plugins:
  - macros

extra:
  version: "1.0.0"
  author: "Votre Nom"

# Dans .md
"""
Version actuelle : {{ version }}
Auteur : {{ author }}

{% if version >= "2.0" %}
Fonctionnalité disponible en v2+
{% endif %}
"""


"""
7. PDF-EXPORT
─────────────

Générer PDF depuis documentation
"""

pip install mkdocs-pdf-export-plugin

# mkdocs.yml
plugins:
  - pdf-export:
      verbose: true
      media_type: print
      combined: true


# ----------------------------------------------------------------------------
# [PACKAGE] EXTENSIONS MARKDOWN
# ----------------------------------------------------------------------------

"""
EXTENSIONS COURANTES
────────────────────
"""

# mkdocs.yml
markdown_extensions:
  # Basics
  - meta                    # Métadonnées YAML
  - tables                  # Tables
  - toc:                    # Table of contents
      permalink: true
      toc_depth: 3
  
  # Admonitions
  - admonition              # Notes, warnings, etc.
  - pymdownx.details        # Collapsible admonitions
  
  # Code
  - codehilite:             # Highlighting code
      linenums: true
  - pymdownx.superfences:   # Fenced code blocks avancés
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.highlight:     # Highlighting avancé
      anchor_linenums: true
  - pymdownx.inlinehilite   # Inline code highlighting
  - pymdownx.snippets       # Inclure fichiers externes
  
  # Formatting
  - pymdownx.betterem:      # Emphasis amélioré
      smart_enable: all
  - pymdownx.caret          # Exposant ^text^
  - pymdownx.mark           # Surligner ==text==
  - pymdownx.tilde          # Barré ~~text~~
  - pymdownx.keys           # Touches clavier ++ctrl+alt+del++
  - pymdownx.smartsymbols   # Symboles (C) (R) (TM) -->
  
  # Lists
  - def_list                # Listes de définitions
  - pymdownx.tasklist:      # Task lists
      custom_checkbox: true
  
  # Links
  - attr_list               # Attributs HTML
  - pymdownx.magiclink      # Liens auto-convertis
  
  # Math
  - pymdownx.arithmatex:    # Math LaTeX
      generic: true
  
  # Tabs
  - pymdownx.tabbed:        # Onglets
      alternate_style: true
  
  # Emoji
  - pymdownx.emoji:
      emoji_index: !!python/name:materialx.emoji.twemoji
      emoji_generator: !!python/name:materialx.emoji.to_svg


"""
EXEMPLES EXTENSIONS
───────────────────

Keys :
++ctrl+alt+del++

Mark :
==texte surligné==

Caret (exposant) :
H~2~O
x^2^

SmartSymbols :
(c) (r) (tm) --> <-- <-->

Task list :
- [x] Terminé
- [ ] À faire

Definition list :
Term 1
:   Définition 1

Term 2
:   Définition 2

Math (avec arithmatex) :
$E = mc^2$

Block math :
$$
\frac{n!}{k!(n-k)!} = \binom{n}{k}
$$
"""


# ============================================================================
# CE FICHIER CONTINUE...
# ============================================================================

Excellent ! J'ai créé une partie substantielle du **Chapitre 5 (Read the Docs)** et du **Chapitre 6 (MkDocs)**.

**Ce qui est inclus jusqu'ici :**

### [OK] Chapitre 5 : Read the Docs (complet)
1. Introduction et avantages
2. Premiers pas (compte, setup)
3. Configuration .readthedocs.yaml
4. Configuration avancée (versions, domaines, webhooks)
5. Gestion des versions multiples
6. Recherche et analytics
7. Documentation privée
8. Intégration CI/CD
9. Personnalisation avancée
10. Dépannage et bonnes pratiques

### [OK] Chapitre 6 : MkDocs (en cours)
1. Introduction et comparaison avec Sphinx
2. Installation et setup
3. Écrire en Markdown
4. Thème Material (configuration complète)
5. Plugins essentiels (mkdocstrings, git-revision-date, etc.)
6. Extensions Markdown

Voulez-vous que je continue avec :
- **Fin du Chapitre 6** (déploiement, exemple complet)
- **Chapitre 7 : pdoc3** (outil simple et rapide)

Pour compléter la **Partie 2** ?

# ============================================================================
# [GUIDE] CHAPITRE 6 (SUITE) : MKDOCS - DÉPLOIEMENT ET EXEMPLES
# ============================================================================

"""
[OBJECTIF] SUITE DU CHAPITRE 6
"""


# ----------------------------------------------------------------------------
# [RAPIDE] DÉPLOIEMENT
# ----------------------------------------------------------------------------

"""
1. GITHUB PAGES
───────────────

Déploiement le plus simple avec MkDocs
"""

# Prérequis
# - Repository GitHub public
# - MkDocs configuré localement

# Déploiement en 1 commande
mkdocs gh-deploy

"""
[IDEE] QUE FAIT gh-deploy ?

1. Build documentation (mkdocs build)
2. Crée branche gh-pages (ou utilise existante)
3. Push fichiers site/ vers gh-pages
4. GitHub Pages sert automatiquement

Documentation disponible à :
https://username.github.io/nom-repo/
"""

# Configuration dans mkdocs.yml
site_url: https://username.github.io/nom-repo/

# Forcer HTTPS
use_directory_urls: true

# Message de commit personnalisé
# mkdocs gh-deploy -m "Update documentation [skip ci]"


"""
AUTOMATISATION AVEC GITHUB ACTIONS
───────────────────────────────────
"""

# .github/workflows/docs.yml
name: Deploy Documentation

on:
  push:
    branches:
      - main
    paths:
      - 'docs/**'
      - 'mkdocs.yml'
      - '.github/workflows/docs.yml'

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install mkdocs-material
          pip install mkdocstrings[python]
          pip install mkdocs-git-revision-date-localized-plugin
      
      - name: Deploy to GitHub Pages
        run: |
          git config user.name github-actions
          git config user.email github-actions@github.com
          mkdocs gh-deploy --force

"""
[IDEE] PERMISSIONS REQUISES

Settings -> Actions -> General -> Workflow permissions
-> Sélectionner "Read and write permissions"
"""


"""
2. GITLAB PAGES
───────────────
"""

# .gitlab-ci.yml
pages:
  stage: deploy
  image: python:3.11-alpine
  
  before_script:
    - pip install mkdocs-material
    - pip install mkdocstrings[python]
  
  script:
    - mkdocs build --strict --verbose --site-dir public
  
  artifacts:
    paths:
      - public
  
  only:
    - main

"""
Documentation disponible à :
https://username.gitlab.io/nom-repo/
"""


"""
3. NETLIFY
──────────

Déploiement continu avec preview branches
"""

# netlify.toml
[build]
  command = "pip install -r requirements.txt && mkdocs build"
  publish = "site"

[build.environment]
  PYTHON_VERSION = "3.11"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

# requirements.txt
"""
mkdocs-material>=9.0
mkdocstrings[python]>=0.20
mkdocs-git-revision-date-localized-plugin
"""

"""
Configuration Netlify :
1. Connecter repository GitHub/GitLab
2. Build command : mkdocs build
3. Publish directory : site
4. Deploy automatique sur chaque push

AVANTAGES :
- Preview pour pull requests
- Rollback facile
- CDN global
- Domaine personnalisé gratuit
- HTTPS automatique
"""


"""
4. VERCEL
─────────
"""

# vercel.json
{
  "buildCommand": "pip install -r requirements.txt && mkdocs build",
  "outputDirectory": "site",
  "installCommand": "pip install --upgrade pip"
}

"""
Similar à Netlify :
- Deploy automatique
- Preview branches
- CDN rapide
"""


"""
5. READ THE DOCS (avec MkDocs)
───────────────────────────────
"""

# .readthedocs.yaml
version: 2

build:
  os: ubuntu-22.04
  tools:
    python: "3.11"

mkdocs:
  configuration: mkdocs.yml
  fail_on_warning: false

python:
  install:
    - requirements: requirements.txt


"""
6. DOCKER
─────────

Container pour documentation
"""

# Dockerfile
FROM python:3.11-alpine

WORKDIR /docs

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN mkdocs build

# Servir avec serveur HTTP simple
FROM nginx:alpine
COPY --from=0 /docs/site /usr/share/nginx/html

EXPOSE 80

# Build et run
"""
docker build -t mon-projet-docs .
docker run -p 8080:80 mon-projet-docs
"""

# Ou servir directement avec Python
"""
FROM python:3.11-alpine
WORKDIR /docs
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"]
"""


# ----------------------------------------------------------------------------
# [DOCS] EXEMPLE COMPLET DE PROJET
# ----------------------------------------------------------------------------

"""
PROJET : BIBLIOTHÈQUE DE CALCUL
────────────────────────────────

Structure complète avec MkDocs
"""

mon_projet/
├── .github/
│   └── workflows/
│       └── docs.yml          # CI/CD docs
├── calculator/
│   ├── __init__.py
│   ├── basic.py
│   └── scientific.py
├── docs/
│   ├── assets/
│   │   ├── logo.png
│   │   └── favicon.ico
│   ├── stylesheets/
│   │   └── extra.css
│   ├── javascripts/
│   │   └── extra.js
│   ├── index.md              # Accueil
│   ├── getting-started.md
│   ├── installation.md
│   ├── user-guide/
│   │   ├── index.md
│   │   ├── basic-usage.md
│   │   └── advanced.md
│   ├── api/
│   │   ├── index.md
│   │   ├── basic.md
│   │   └── scientific.md
│   ├── examples/
│   │   ├── index.md
│   │   └── examples.md
│   └── about.md
├── tests/
├── mkdocs.yml
├── requirements.txt
└── README.md


"""
CONFIGURATION mkdocs.yml
────────────────────────
"""

# mkdocs.yml
site_name: Calculator Library
site_description: A comprehensive calculator library for Python
site_author: Votre Nom
site_url: https://username.github.io/calculator/

# Repository
repo_name: username/calculator
repo_url: https://github.com/username/calculator
edit_uri: edit/main/docs/

# Copyright
copyright: Copyright &copy; 2024 Votre Nom

# Navigation
nav:
  - Home: index.md
  - Getting Started:
    - Installation: installation.md
    - Quick Start: getting-started.md
  - User Guide:
    - Overview: user-guide/index.md
    - Basic Usage: user-guide/basic-usage.md
    - Advanced Features: user-guide/advanced.md
  - API Reference:
    - Overview: api/index.md
    - Basic Calculator: api/basic.md
    - Scientific Calculator: api/scientific.md
  - Examples: examples/index.md
  - About: about.md

# Theme
theme:
  name: material
  palette:
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-4
        name: Switch to light mode
  
  features:
    - navigation.instant
    - navigation.tracking
    - navigation.tabs
    - navigation.sections
    - navigation.expand
    - navigation.top
    - search.suggest
    - search.highlight
    - search.share
    - content.code.copy
    - content.code.annotate
  
  language: en
  
  font:
    text: Roboto
    code: Roboto Mono
  
  icon:
    repo: fontawesome/brands/github
  
  logo: assets/logo.png
  favicon: assets/favicon.ico

# Plugins
plugins:
  - search:
      lang: en
  - mkdocstrings:
      handlers:
        python:
          options:
            docstring_style: google
            show_source: true
            show_root_heading: true
            show_root_toc_entry: true
            heading_level: 2
            members_order: source
            show_signature_annotations: true
  - git-revision-date-localized:
      enable_creation_date: true
      type: timeago
  - minify:
      minify_html: true

# Markdown Extensions
markdown_extensions:
  - admonition
  - pymdownx.details
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.highlight:
      anchor_linenums: true
  - pymdownx.inlinehilite
  - pymdownx.snippets
  - pymdownx.tabbed:
      alternate_style: true
  - pymdownx.tasklist:
      custom_checkbox: true
  - pymdownx.emoji:
      emoji_index: !!python/name:materialx.emoji.twemoji
      emoji_generator: !!python/name:materialx.emoji.to_svg
  - attr_list
  - md_in_html
  - tables
  - toc:
      permalink: true

# Extra
extra:
  version:
    provider: mike
  social:
    - icon: fontawesome/brands/github
      link: https://github.com/username
    - icon: fontawesome/brands/twitter
      link: https://twitter.com/username
  analytics:
    provider: google
    property: G-XXXXXXXXXX

# Custom CSS/JS
extra_css:
  - stylesheets/extra.css

extra_javascript:
  - javascripts/extra.js


"""
EXEMPLE PAGES
─────────────
"""

# docs/index.md
"""
# Calculator Library

![Calculator Logo](assets/logo.png){ width="200" }

A powerful and easy-to-use calculator library for Python.

## Features

- :material-calculator: **Basic operations** - Addition, subtraction, multiplication, division
- :material-function: **Scientific functions** - Trigonometry, logarithms, exponentials
- :material-history: **Operation history** - Track all calculations
- :material-speedometer: **High performance** - Optimized algorithms
- :material-shield-check: **Type safe** - Full type hints support

## Quick Example

```python
from calculator import BasicCalculator

calc = BasicCalculator()
result = calc.add(5, 3)
print(result)  # 8
```

## Installation

Install using pip:

```bash
pip install calculator-lib
```

## Next Steps

- [Installation Guide](installation.md)
- [Quick Start Tutorial](getting-started.md)
- [User Guide](user-guide/index.md)
- [API Reference](api/index.md)
"""


# docs/installation.md
"""
# Installation

## Requirements

- Python 3.8 or higher
- pip (usually comes with Python)

## Install from PyPI

=== "pip"
    ```bash
    pip install calculator-lib
    ```

=== "pipenv"
    ```bash
    pipenv install calculator-lib
    ```

=== "poetry"
    ```bash
    poetry add calculator-lib
    ```

## Install from Source

```bash
git clone https://github.com/username/calculator.git
cd calculator
pip install -e .
```

## Verify Installation

```python
import calculator
print(calculator.__version__)
```

Expected output:
```
1.0.0
```

## Optional Dependencies

For scientific calculations:

```bash
pip install calculator-lib[scientific]
```

For all features:

```bash
pip install calculator-lib[all]
```

## Troubleshooting

!!! warning "Common Issues"
    If you encounter import errors, make sure you're using Python 3.8+
    
    ```bash
    python --version
    ```

!!! tip "Virtual Environment"
    We recommend using a virtual environment:
    
    ```bash
    python -m venv venv
    source venv/bin/activate  # Linux/Mac
    venv\\Scripts\\activate     # Windows
    ```

## Next Steps

Continue to the [Quick Start Guide](getting-started.md) to learn how to use the library.
"""


# docs/user-guide/basic-usage.md
"""
# Basic Usage

This guide covers the fundamental operations of the Calculator library.

## Creating a Calculator

```python
from calculator import BasicCalculator

calc = BasicCalculator()
```

## Basic Operations

### Addition

```python
result = calc.add(5, 3)
print(result)  # 8
```

### Subtraction

```python
result = calc.subtract(10, 4)
print(result)  # 6
```

### Multiplication

```python
result = calc.multiply(6, 7)
print(result)  # 42
```

### Division

```python
result = calc.divide(20, 4)
print(result)  # 5.0
```

!!! warning "Division by Zero"
    Division by zero will raise a `ZeroDivisionError`:
    
    ```python
    calc.divide(10, 0)  # Raises ZeroDivisionError
    ```

## Operation History

Track your calculations:

```python
calc = BasicCalculator()
calc.add(5, 3)
calc.multiply(4, 2)

print(calc.history)
# ['5 + 3 = 8', '4 × 2 = 8']
```

Clear history:

```python
calc.clear_history()
```

## Chaining Operations

```python
calc = BasicCalculator()
result = calc.add(5, 3)        # 8
result = calc.multiply(result, 2)  # 16
result = calc.subtract(result, 6)  # 10
```

## Complete Example

```python
from calculator import BasicCalculator

def calculate_total_price(base_price, quantity, tax_rate):
    '''Calculate total price with tax.'''
    calc = BasicCalculator()
    
    # Subtotal
    subtotal = calc.multiply(base_price, quantity)
    
    # Tax
    tax = calc.multiply(subtotal, tax_rate)
    
    # Total
    total = calc.add(subtotal, tax)
    
    return total

# Usage
total = calculate_total_price(10.0, 5, 0.2)
print(f"Total: ${total}")  # Total: $60.0
```
"""


# docs/api/basic.md
"""
# Basic Calculator API

## BasicCalculator

::: calculator.basic.BasicCalculator
    options:
      show_root_heading: true
      show_source: true
      members:
        - __init__
        - add
        - subtract
        - multiply
        - divide
        - clear_history

## Examples

### Creating Instance

```python
from calculator import BasicCalculator

calc = BasicCalculator()
```

### Using Methods

=== "Addition"
    ```python
    result = calc.add(10, 5)
    # Returns: 15
    ```

=== "Subtraction"
    ```python
    result = calc.subtract(10, 5)
    # Returns: 5
    ```

=== "Multiplication"
    ```python
    result = calc.multiply(10, 5)
    # Returns: 50
    ```

=== "Division"
    ```python
    result = calc.divide(10, 5)
    # Returns: 2.0
    ```

## Type Signatures

```python
def add(self, a: float, b: float) -> float: ...
def subtract(self, a: float, b: float) -> float: ...
def multiply(self, a: float, b: float) -> float: ...
def divide(self, a: float, b: float) -> float: ...
```

## Exceptions

| Exception | When Raised |
|-----------|-------------|
| `ZeroDivisionError` | When dividing by zero |
| `TypeError` | When arguments are not numeric |

## See Also

- [Scientific Calculator](scientific.md)
- [User Guide](../user-guide/basic-usage.md)
"""


# ----------------------------------------------------------------------------
# 🆚 MKDOCS VS SPHINX : QUAND UTILISER QUOI ?
# ----------------------------------------------------------------------------

"""
TABLEAU DE DÉCISION
───────────────────

UTILISEZ MKDOCS SI :
[OK] Documentation utilisateur (pas technique)
[OK] Préférence pour Markdown
[OK] Design moderne important
[OK] Setup rapide nécessaire
[OK] Preview live essentiel
[OK] GitHub Pages simple

UTILISEZ SPHINX SI :
[OK] Documentation technique Python
[OK] Autodoc intensif requis
[OK] PDF/ePub nécessaires
[OK] Projet Python standard
[OK] Read the Docs hébergement
[OK] Références croisées complexes


CAS D'USAGE CONCRETS
─────────────────────

MKDOCS :
- Documentation produit/SaaS
- Guides utilisateur
- API REST documentation
- Tutoriels et how-tos
- Projets non-Python

Exemples : FastAPI, Pydantic, Typer

SPHINX :
- Bibliothèques Python
- Documentation technique
- Références API complètes
- Projets scientifiques
- Documentation académique

Exemples : Django, NumPy, Sphinx


MIGRATION SPHINX -> MKDOCS
──────────────────────────

Possible mais nécessite :
1. Convertir .rst -> .md (pandoc)
2. Reconfigurer (conf.py -> mkdocs.yml)
3. Adapter directives Sphinx
4. Tester autodoc avec mkdocstrings

Outil : rst2md, pandoc
"""


# ============================================================================
# [GUIDE] CHAPITRE 7 : PDOC3 - DOCUMENTATION SIMPLE ET RAPIDE
# ============================================================================

"""
[OBJECTIF] OBJECTIFS D'APPRENTISSAGE

À la fin de ce chapitre, vous saurez :
[OK] Qu'est-ce que pdoc3 et ses avantages
[OK] Installer et utiliser pdoc3
[OK] Générer documentation automatiquement
[OK] Personnaliser l'apparence
[OK] Déployer documentation pdoc3
[OK] Comparer pdoc3 avec Sphinx et MkDocs
"""


# ----------------------------------------------------------------------------
# [REFLEXION] QU'EST-CE QUE PDOC3 ?
# ----------------------------------------------------------------------------

"""
DÉFINITION

pdoc3 = Générateur documentation ultra-simple
- Auto-documentation UNIQUEMENT depuis docstrings
- Zéro configuration requise
- Interface web moderne
- Support Markdown dans docstrings
- Génération HTML statique


[IDEE] POURQUOI PDOC3 ?

[OK] EXTRÊME SIMPLICITÉ
   - 1 commande = documentation complète
   - Pas de fichier config
   - Pas de setup

[OK] AUTOMATIQUE
   - Lit docstrings directement
   - Détecte structure automatiquement
   - Liens automatiques

[OK] RAPIDE
   - Setup en 30 secondes
   - Génération instantanée
   - Idéal pour prototypes

[OK] MARKDOWN NATIF
   - Markdown dans docstrings
   - GitHub-flavored Markdown
   - Syntaxe familière

[OK] MODERN UI
   - Interface propre
   - Responsive
   - Dark mode


[X] LIMITATIONS

- Pas de pages personnalisées
- Seulement documentation API
- Pas de tutoriels/guides
- Moins de personnalisation
- Pas de support reST


[OBJECTIF] CAS D'USAGE IDÉAL

[OK] Prototypes rapides
[OK] Bibliothèques internes
[OK] Projets personnels
[OK] Documentation API pure
[OK] Besoin zéro config


PDOC VS PDOC3
─────────────

pdoc (original) : Ancien, moins maintenu
pdoc3 : Fork actif, amélioré, Python 3+

-> Utilisez TOUJOURS pdoc3
"""


# ----------------------------------------------------------------------------
# [OUTILS] INSTALLATION ET UTILISATION
# ----------------------------------------------------------------------------

"""
INSTALLATION
────────────
"""

pip install pdoc3


"""
GÉNÉRATION INSTANTANÉE
──────────────────────

Un seul module :
"""

pdoc --html mon_module.py

# Output dans html/mon_module.html


"""
Package complet :
"""

pdoc --html mon_package

# Output dans html/mon_package/


"""
Avec serveur live :
"""

pdoc --http localhost:8080 mon_package

# Ouvre navigateur à http://localhost:8080
# Rechargement auto lors modifications !


"""
Options courantes :
"""

# Forcer écrasement
pdoc --html --force mon_package

# Output personnalisé
pdoc --html --output-dir docs mon_package

# Inclure modules privés
pdoc --html --force mon_package --filter ".*"

# Format texte (terminal)
pdoc --pdf mon_package  # Nécessite wkhtmltopdf


"""
EXEMPLE COMPLET
───────────────
"""

# Structure projet
"""
calculator/
├── calculator/
│   ├── __init__.py
│   ├── basic.py
│   └── scientific.py
└── README.md
"""

# Générer documentation
pdoc --html --output-dir docs calculator

# Structure générée
"""
docs/
└── calculator/
    ├── index.html
    ├── basic.html
    └── scientific.html
"""

# Servir localement
pdoc --http : calculator

# Auto-ouvre http://localhost:8080/calculator


"""
INTÉGRATION DANS PROJET
────────────────────────

Script de génération
"""

# scripts/build_docs.py
import subprocess
import sys

def build_docs():
    """Generate documentation with pdoc3."""
    try:
        subprocess.run([
            'pdoc',
            '--html',
            '--force',
            '--output-dir', 'docs',
            'calculator'
        ], check=True)
        print("[OK] Documentation generated in docs/")
    except subprocess.CalledProcessError as e:
        print(f"[X] Error: {e}")
        sys.exit(1)

if __name__ == '__main__':
    build_docs()

# Utilisation
# python scripts/build_docs.py


"""
Makefile
"""

# Makefile
.PHONY: docs docs-serve docs-clean

docs:
	pdoc --html --force --output-dir docs calculator

docs-serve:
	pdoc --http localhost:8080 calculator

docs-clean:
	rm -rf docs/calculator

# Usage
# make docs
# make docs-serve


# ----------------------------------------------------------------------------
# [DESIGN] PERSONNALISATION
# ----------------------------------------------------------------------------

"""
TEMPLATE PERSONNALISÉ
─────────────────────

pdoc3 utilise Jinja2 templates
"""

# Copier templates par défaut
pdoc --template-dir my_templates --html calculator

# Structure templates
"""
my_templates/
├── html.html.jinja2        # Template principal
├── module.html.jinja2      # Template module
└── css.html.jinja2         # Styles CSS
"""


"""
CSS PERSONNALISÉ
────────────────
"""

# my_templates/css.html.jinja2
"""
<style>
/* Personnalisation couleurs */
:root {
    --primary: #2962ff;
    --background: #ffffff;
    --text: #333333;
}

body {
    font-family: 'Segoe UI', sans-serif;
}

header {
    background: var(--primary) !important;
}

a {
    color: var(--primary);
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
    :root {
        --background: #1e1e1e;
        --text: #e0e0e0;
    }
    
    body {
        background: var(--background);
        color: var(--text);
    }
}
</style>
"""

# Utiliser template
pdoc --html --template-dir my_templates calculator


"""
MARKDOWN DANS DOCSTRINGS
─────────────────────────

pdoc3 supporte Markdown nativement
"""

def example_function(param):
    """
    Calculate something **important**.
    
    This function uses *advanced* algorithms.
    
    Args:
        param (int): The input value
    
    Returns:
        int: The result
    
    Example:
        ```python
        result = example_function(42)
        print(result)
        ```
    
    !!! note
        This is a special note.
    
    See also:
        - [Python Docs](https://docs.python.org)
        - `other_function()`
    """
    pass


"""
CONFIGURATION VIA __pdoc__
──────────────────────────

Contrôler ce qui est documenté
"""

# calculator/__init__.py
"""
Calculator package.

This package provides basic and scientific calculators.
"""

# Cacher modules privés
__pdoc__ = {
    '_internal': False,
    'BasicCalculator._private_method': False,
}

# Documentation custom pour attributs
__pdoc__['BasicCalculator.result'] = """
Current result of the last operation.

This is automatically updated after each calculation.
"""


"""
ORDRE DES MEMBRES
─────────────────

Contrôler ordre d'affichage
"""

__all__ = ['BasicCalculator', 'ScientificCalculator']

# L'ordre dans __all__ = ordre dans doc


# ----------------------------------------------------------------------------
# [RAPIDE] DÉPLOIEMENT
# ----------------------------------------------------------------------------

"""
GITHUB PAGES
────────────

Script de déploiement
"""

#!/bin/bash
# deploy_docs.sh

# Générer documentation
pdoc --html --force --output-dir docs calculator

# Créer branche gh-pages
git checkout -b gh-pages

# Copier docs
cp -r docs/calculator/* .

# Commit et push
git add .
git commit -m "Update documentation"
git push origin gh-pages --force

# Retour à main
git checkout main

# URL : https://username.github.io/calculator/


"""
GITHUB ACTIONS
──────────────
"""

# .github/workflows/pdoc.yml
name: Generate API Docs

on:
  push:
    branches: [ main ]
    paths:
      - 'calculator/**'

jobs:
  docs:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'
    
    - name: Install pdoc3
      run: pip install pdoc3
    
    - name: Generate docs
      run: pdoc --html --force --output-dir docs calculator
    
    - name: Deploy to GitHub Pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./docs/calculator


"""
NETLIFY
───────
"""

# netlify.toml
[build]
  command = "pip install pdoc3 && pdoc --html --force --output-dir site calculator"
  publish = "site/calculator"

[build.environment]
  PYTHON_VERSION = "3.11"


"""
SERVEUR STATIQUE
────────────────

N'importe quel serveur HTTP
"""

# Générer HTML statique
pdoc --html --force --output-dir dist calculator

# Servir avec Python
cd dist/calculator
python -m http.server 8000

# Ou avec nginx
# cp -r dist/calculator/* /var/www/html/docs/


# ----------------------------------------------------------------------------
# 🆚 COMPARAISON FINALE DES OUTILS
# ----------------------------------------------------------------------------

"""
TABLEAU COMPARATIF COMPLET
──────────────────────────

┌────────────────┬─────────┬─────────┬─────────┐
│                │ Sphinx  │ MkDocs  │ pdoc3   │
├────────────────┼─────────┼─────────┼─────────┤
│ Setup Time     │ 15 min  │ 5 min   │ 30 sec  │
│ Config File    │ conf.py │ .yml    │ Aucun   │
│ Syntax         │ reST    │ MD      │ MD      │
│ Autodoc        │ Natif   │ Plugin  │ Natif   │
│ Custom Pages   │ [OK][OK][OK]     │ [OK][OK][OK]     │ [X]       │
│ API Docs       │ [OK][OK][OK]     │ [OK][OK]      │ [OK][OK][OK]     │
│ Themes         │ [OK][OK]      │ [OK][OK][OK]     │ [OK]       │
│ Output         │ Multi   │ HTML    │ HTML    │
│ Search         │ [OK][OK][OK]     │ [OK][OK][OK]     │ [OK]       │
│ Versioning     │ [OK][OK][OK]     │ [OK][OK]      │ [X]       │
│ Learning       │ Moyen   │ Facile  │ Instant │
│ Customization  │ [OK][OK][OK]     │ [OK][OK]      │ [OK]       │
│ Standard Python│ Oui     │ Non     │ Non     │
└────────────────┴─────────┴─────────┴─────────┘


QUAND UTILISER CHACUN ?
───────────────────────

SPHINX
------
[OK] Bibliothèque Python officielle
[OK] Documentation technique complète
[OK] PDF/ePub requis
[OK] Références croisées complexes
[OK] Standard communauté Python

Exemples : Django, NumPy, Requests


MKDOCS
------
[OK] Documentation moderne utilisateur
[OK] Préférence Markdown
[OK] Design important
[OK] Tutoriels et guides
[OK] Projet non-Python aussi

Exemples : FastAPI, Material for MkDocs


PDOC3
-----
[OK] Prototype rapide
[OK] API documentation pure
[OK] Zéro configuration
[OK] Projet interne
[OK] Documentation minimale

Exemples : Petites bibliothèques, outils internes


COMBINAISON POSSIBLE
────────────────────

Utilisez PLUSIEURS outils :

1. pdoc3 pour développement rapide
2. MkDocs pour guide utilisateur
3. Sphinx pour API reference complète

Exemple structure :
"""

projet/
├── docs-mkdocs/          # Guide utilisateur (MkDocs)
│   └── mkdocs.yml
├── docs-api/             # API reference (pdoc3)
│   └── generated/
└── docs-sphinx/          # Tout combiné (Sphinx)
    └── source/

# Liens entre docs
# MkDocs -> API pdoc3 : [API Docs](https://api.projet.com)
# Sphinx <- Include MkDocs pages


# ============================================================================
# [DOCS] RÉCAPITULATIF PARTIE 2 COMPLÈTE
# ============================================================================

"""
[BRAVO] FÉLICITATIONS ! PARTIE 2 TERMINÉE !

VOUS MAÎTRISEZ MAINTENANT :

Chapitre 4 : Sphinx
[OK] Installation et configuration complète
[OK] Syntaxe reStructuredText
[OK] Autodoc et génération depuis docstrings
[OK] Thèmes et personnalisation
[OK] Extensions essentielles
[OK] Build HTML/PDF/ePub
[OK] Organisation documentation

Chapitre 5 : Read the Docs
[OK] Configuration .readthedocs.yaml
[OK] Builds automatiques depuis Git
[OK] Gestion versions multiples
[OK] Domaines personnalisés
[OK] Analytics et monitoring
[OK] Intégration CI/CD
[OK] Dépannage et bonnes pratiques

Chapitre 6 : MkDocs
[OK] Installation et setup
[OK] Syntaxe Markdown complète
[OK] Thème Material (config avancée)
[OK] Plugins essentiels (mkdocstrings, etc.)
[OK] Extensions Markdown
[OK] Déploiement multi-plateforme
[OK] Exemple projet complet

Chapitre 7 : pdoc3
[OK] Installation et utilisation immédiate
[OK] Génération automatique
[OK] Personnalisation templates
[OK] Markdown dans docstrings
[OK] Déploiement simple
[OK] Comparaison outils


[CLE] POINTS CLÉS

1. Sphinx = Standard Python, le plus puissant
2. MkDocs = Moderne, Markdown, facile
3. pdoc3 = Ultra-simple, zéro config
4. Read the Docs = Hébergement gratuit référence
5. Choisir selon besoins : technique vs utilisateur
6. Possible de combiner plusieurs outils


[OBJECTIF] VOUS POUVEZ MAINTENANT

[OK] Choisir bon outil selon projet
[OK] Configurer Sphinx professionnellement
[OK] Créer doc moderne avec MkDocs
[OK] Générer doc rapide avec pdoc3
[OK] Héberger sur Read the Docs
[OK] Automatiser génération avec CI/CD
[OK] Déployer sur GitHub Pages, Netlify, etc.


-> PROCHAINE ÉTAPE : PARTIE 3

La Partie 3 couvrira :
- ReStructuredText avancé
- Markdown avancé
- Type Hints et documentation
- Documentation d'API REST

Vous allez apprendre :
- Maîtriser reST et Markdown
- Intégrer type hints
- Documenter APIs
- Formats avancés


[GUIDE] FICHIER SUIVANT : documentation_partie3.txt

Excellent travail ! Prêt pour les formats avancés ? [RAPIDE]
"""

# ============================================================================
# FIN DE LA PARTIE 2
# ============================================================================

Parfait ! J'ai complété la **Partie 2 complète** avec :

### [OK] Chapitre 6 (fin) : MkDocs
- Déploiement (GitHub Pages, GitLab, Netlify, Vercel, Docker)
- Exemple complet de projet (structure, configuration, pages)
- Comparaison MkDocs vs Sphinx

### [OK] Chapitre 7 : pdoc3
- Introduction et avantages
- Installation et utilisation immédiate
- Génération automatique
- Personnalisation (templates, CSS)
- Markdown dans docstrings
- Déploiement (GitHub Pages, Netlify, serveur statique)
- Comparaison finale des 3 outils (Sphinx/MkDocs/pdoc3)

**La Partie 2 est maintenant complète (~3000 lignes) !**

Voulez-vous que je continue avec la **Partie 3 : Formats Avancés** ?
- Chapitre 8 : ReStructuredText (reST) avancé
- Chapitre 9 : Markdown avancé
- Chapitre 10 : Type Hints et Documentation
- Chapitre 11 : Documentation d'API REST