Si vous avez utilisé `break` dans votre structure conditionnelle, cela ne fonctionnera plus : il se trouve dans une sous-fonction, et donc il n'est plus directement dans la boucle.
Il faudra donc gérer la pause avec une condition sur `choix`.
1. Dans le module `mdp`, tout en haut du fichier, importer les modules `secrets` et `string` qui sont livrés avec Python
1. En haut du fichier, après les imports, créer quatre **constantes** comme ci-dessous. Elles vont nous aider à définir l'ensemble des caractères autorisés dans les mots de passe
~~~python
LETTRES = string.ascii_letters # Définit toutes les lettres autorisées
CHIFFRES = string.digits # Définit tous les chiffres autorisés
SPECIAL = string.punctuation # Définit les caractères spéciaux autorisés
ALPHABET = LETTRES + CHIFFRES + SPECIAL # Ensemble complet des caractères autorisés
~~~
1. Modifier la fonction `generer_mdp` pour générer un mot de passe de 14 caractères. Pour cela :
1. Ajouter une boucle qui bouclera 14 fois, grâce à la fonction `range`
2. Dans cette boucle, nous allons ajouter un nouveau caractère à la variable `password`. Ce caractère sera tiré aléatoirement dans la constante `ALPHABET`.
Pour ça, nous allons utiliser la fonction `choice` du module `secrets` :
~~~python
password += secrets.choice(ALPHABET)
~~~
3. A la fin, une fois sorti de la boucle, nous retournons la variable `password`
1. Vérifier que votre fonction marche en essayant de générer un mot de passe (via l'option 1)
1. Les constantes en Python sont comme des variables. La différence est qu'on ne voudra jamais changer leur valeur. Mais rien ne permet de l'empêcher. Alors pour savoir qu'il s'agit d'une constante et qu'elle ne devrait pas être modifiée, on lui donne un nom en majuscules. Il s'agit d'une convention courante en programmation.
1. Les constantes `string.ascii_letters`, `string.digits`, `string.punctuation` sont des chaînes de caractères avec l'ensemble des caractères de chaque catégorie. Elles sont définies dans le module string pour nous faire gagner du temps et éviter d'en oublier.
1. Pour ajouter un caractère à une chaîne, il suffit d'utiliser `+`
1. Donner le nouveau code du module `mdp`**complet**
1. Aller voir la [documentation du module `random` de python](https://docs.python.org/3/library/random.html).
1. Expliquer en quelques mots le rôle de la bibliothèque `random`
1. Il y a un avertissement important sur la page, dans l'introduction. À la lecture de cet avertissement, expliquer en quelques mots pourquoi nous avons choisi la bibliothèque `secrets` plutôt que `random` pour générer un mot de passe **sécurisé**.
1. À l'aide de la section "Bonnes pratiques" du cours, ajoutez des docstrings aux fonctions de votre TP pour les documenter en respectant la syntaxe Numpy fournie
**Objectif** : Créer une fonction `generer_mdp_avec_contraintes` pour ajouter des contraintes sur le nombre de caractères spéciaux et de chiffres
```admonish travail
1. Créer une nouvelle fonction `generer_mdp_avec_contraintes` dans le module `mdp`. Cette fonction appellera `generer_mdp` et retournera le mot de passe généré. Elle prendra trois paramètres :
-`password_length` pour la longueur du mot de passe. Cette valeur sera passée à `generer_mdp` telle quelle et aura 14 en valeur par défaut.
-`special` pour le nombre minimum de caractères spéciaux. Sa valeur par défaut sera de 1.
-`digits` pour le nombre minimum de chiffres. Sa valeur par défaut sera de 1.
2. Ajouter une boucle qui permettra de re-générer le mot de passe tant qu'il ne comportera pas au moins `special` caractères spéciaux et `digits` chiffres. Il faudra pour cela :
- Compter les caractères spéciaux (et les chiffres) dans votre mot de passe
- Vérifier ensuite que ce nombre soit supérieur au paramètre correspondant (`digits` ou `special`)
- Arrêter la boucle si ces deux conditions sont réunies (donc la continuer tant que les deux conditions ne sont pas réunies)
3. Remplacer la fonction `generer_mdp` dans l'option 2 du menu pour utiliser votre nouvelle fonction.
4. Vérfiez que les mots de passe générés respectent la contrainte par défaut
5. Sur le modèle de la longueur du mot de passe, demander à l'utilisateurice de choisir les contraintes voulues.
6. Documenter votre/vos nouvelles fonctions avec une docstring complète.
```
```admonish help title="Aide"
1. Pour compter les caractères spéciaux (ou les chiffres) dans votre mot de passe, vous pouvez
- faire une boucle 'for' sur votre mot de passe
- vérifier si le caractère se trouve dans votre constante `SPECIAL` avec la syntaxe `caractere in SPECIAL`
- et incrémenter une variable à chaque fois que la condition précédente est à `True`
2. Vous pouvez extraire le comptage et la validation de la contrainte dans une sous-fonction pour rendre votre code plus lisible.
```
```admonish note title="Dans le compte rendu"
1. Donner le code de la fonction `generer_mdp_avec_contraintes` et des éventuelles sous-fonctions créées.