Ajoute le TP4 Python

This commit is contained in:
Alexis Fourmaux 2025-09-25 10:47:27 +02:00
parent 9cdc849095
commit 7dc0df2a31
10 changed files with 31311 additions and 7790 deletions

View file

@ -41,9 +41,9 @@ Cette 3e itération a pour objectif de développer la fonctionnalité de génér
- Questions orale et compréhension générale
- Connaissance du cours
- 50% Professionnalisme (10pts)
- Attitude professionnelle durant l'activité (3pts)
- Posture professionnelle durant l'activité (3pts)
- Qualité du rendu (Compte rendu - Documentation - Code) (3pts)
- Respect des délais/horaires (compte rendu et retard en cours) (2pts)
- Respect des délais/horaires (2pts)
- Autonomie dans la progression (2pts)
- Bonus +2pts

View file

@ -0,0 +1,193 @@
# TP4 - Générateur de mots de passe - Fichiers
## Objectifs du TP
### Objectifs pédagogiques
- **Fichiers** : Comprendre comment manipuler des fichiers en Python (lecture et écriture)
- **Dictionnaires** : Manipuler des dictionnaires en Python
### Objectifs techniques
- Écrire des mots de passe générés dans un fichier au lieu de les afficher en console
- Récupérer la liste des mots pour générer des passphrases directement depuis un fichier
## Validation
### Livrables
- Le code final
- Le compte-rendu du TP
Le tout dans un répertoire avec le nom suivant `YYYY-MM-DD_TPX_NOM1_Prenom1_NOM2_Prenom2`.
- Le compte rendu peut-être livré au format Markdown ou PDF.
- Si vous choisissez le Markdown, attention à bien livrer les éventuelles images et à la validité des liens.
### Résultats attendus
- [ ] Le programme se lance sans erreur.
- [ ] Chaque fonction contient une docstring minimale expliquant sa fonctionnalité. Bonus : Doctsrings complètes au format Numpy.
- [ ] Le code est propre, correctement formaté, les variables, fonctions et paramètres sont bien nommés, les conventions sont respectées.
### Critères d'évaluation
- 50% Technique (10pts)
- Code fonctionnel
- Réponses dans le compte-rendu
- Questions orale et compréhension générale
- Connaissance du cours
- 50% Professionnalisme (10pts)
- Posture professionnelle durant l'activité (3pts)
- Qualité du rendu (Compte rendu - Documentation - Code) (3pts)
- Respect des délais/horaires (2pts)
- Autonomie dans la progression (2pts)
- Bonus +2pts
## Documents fournis
- Cours
- Python - 5 - Les fichiers
- Docs
- Listes de mots en anglais
- Listes de mots en français
## Étapes
### 1 - Ouvrir un fichier pour lire la liste des mots
**Objectif :** Créer une fonction qui ira lire les mots dans un fichier et utiliser cette liste pour générer des passphrases en français
```admonish travail
1. Dans votre module `mdp`, créer une nouvelle fonction `get_word_list_from_file`. Cette fonction prendra un paramètre `filename` et la valeur par défaut `"wordlist_fr.txt"`.
1. Ouvrir le fichier à l'aide d'un **gestionnaire de contexte**
1. Lire toutes les lignes du fichier, et les stocker dans la variable `lines` et retourner cette variable
1. Remplacer l'appel à la fonction `get_word_list` dans votre fonction `generer_passphrase` par votre nouvelle fonction.
1. Vérifier que votre programme génère désormais des passphrases en français.
```
```admonish help title="Aide"
Un gestionnaire de contexte est la méthode recommandée par Python pour ouvrir et fermer un fichier en toute sécurité. La syntaxe est la suivante:
~~~python
with open(filename, mode) as file:
# Actions sur le fichier
~~~
Cette syntaxe présente l'avantage de fermer systématiquement votre fichier à la sortie du bloc de contexte, et évite donc de nombreux risques de bugs pour votre application. Elle définit une variable `file` qui sera détruite une fois sorti du bloc de contexte.
```
```admonish note title="Dans le compte rendu"
1. Donnez le code de votre fonction
2. Si nous n'avions pas utilisé de gestionnaire de contexte (`with ... as ...:`), qu'aurait-on dû absolument faire après avoir travaillé avec notre fichier ? Quelle méthode aurions-nous dû utiliser pour ça ?
```
### 2 - Écrire dans un fichier
**Objectif :** Écrire un mot de passe généré dans un fichier au lieu de l'afficher en console
```admonish travail
1. Dans votre module principal (`main.py`), créer une fonction `write_password_in_file` qui prendra en paramètres :
- `password`
- `filename` avec une valeur par défaut `passwords.txt`
2. Dans cette fonction, ouvrir votre fichier en mode "append" avec un gestionnaire de contexte.
3. Écrire le contenu de la variable `password` dans le fichier
4. Créer une nouvelle entrée dans votre menu intitulée `5 - Générer un fichier avec des passphrases`.
- Adapter votre fonction `choix_utilisateur` pour gérer ce nouveau cas.
- Vous ferez appel aux fonctions `generer_passphrase` et `write_password_in_file` pour écrire votre passphrase dans un fichier.
5. Testez votre programme pour vérifier que vos passphrases s'écrivent bien dans le fichier.
```
```admonish note title="Dans le compte rendu"
1. Donnez le code de votre nouvelle fonction
1. Que constatez-vous dans le fichier si vous appelez plusieurs fois votre programme à la suite ?
2. Quelle est la différence entre le mode "write" et le mode "append" ?
3. Quel mode puis-je utiliser si je veux à la fois lire et écrire dans mon fichier ?
```
### 3 - Faire un vrai jet de dés
```admonish warning title="Attention"
Dans la suite, nous allons aller au bout du processus "diceware" décrit par l'EFF dans le document du TP3. C'était déjà l'objet de l'étape 6 du TP précédent.
Les personnes ayant terminé l'étape 6 dans le TP précédent (celle qui vous faisait tirer les dés et manipuler des dictionnaires) :
- Dans votre compte-rendu, aux parties 3 et 4, répondez aux questions et ajoutez votre code déjà réalisé
- Passez ensuite au bonus `Lire le dictionnaire à partir d'un fichier` de ce TP.
- Vous pourrez ensuite réaliser les bonus des TP précédents.
```
**Objectif :** Tirer 5 dés et les assembler en une chaîne de caractères
```admonish travail
1. Créer une nouvelle fonction `tirer_les_des` dans votre module `mdp`.
2. Dans cette fonction, commencer par créer une variable `dice` qui sera une chaîne de caractères vide.
3. Créer une boucle qui fera 5 itérations. Dans cette boucle :
- Tirer au sort un nombre entre 1 et 6. Vous utiliserez pour cela [`secrets.randbelow`](https://docs.python.org/3/library/secrets.html#secrets.randbelow).
- Lisez la documentation de `secrets.randbelow` pour comprendre son fonctionnement
- Ajouter ce nombre sous forme de chaîne de caractères à votre variable `dice`
4. A la fin de la boucle, retourner la valeur de `dice`
5. Vérifiez que votre fonction retourne une chaîne de caractères aléatoire ressemblant à `"12345"`
```
```admonish help title="Aide"
- `secrets.randbelow` retourne un nombre entier. Vous aurez besoin d'une chaine de caractères. Pensez à vos conversions si vous rencontrez l'erreur suivante :
~~~
TypeError: can only concatenate str (not "int") to str
~~~
- `secrets.randbelow(n)` retourne un nombre compris entre `0` et `n-1`. Pour avoir un nombre compris entre `1` et `n`, il vous faudra ajouter 1 au résultat.
```
```admonish note title="Dans le compte rendu"
1. Mettez le code de votre fonction `tirer_les_des`
```
### 4 - Générer une passphrase tirée aux dés
**Objectif :** Utiliser votre tirage de dés pour sélectionner les mots dans un dictionnaire Python
```admonish travail
1. Créer une fonction `generer_dice_passphrase` qui sera une copie de `generer_passphrase` pour commencer
1. Remplacer l'appel à `get_word_list_from_file` par `get_word_dict` du module `eff_words`. Cette fonction retourne un dictionnaire dont les **clés** sont les tirages de dés et les **valeurs** sont les mots.
1. Modifier la boucle de `generer_dice_passphrase` pour
- appeler `tirer_les_des` et récupérer le jet de dés dans une variable `dice`
- utiliser l'une des deux syntaxes possibles permettant de récupérer une valeur dans un dictionnaire à l'aide de la clé. Votre but est de récupérer le mot à partir du tirage de dés
- Ajoutez ce mot à votre liste `passphrase_words`
6. Remplacez l'appel à `generer_passphrase` dans votre menu par un appel à `generer_dice_passphrase` et validez que votre programme fonctionne toujours correctement.
```
```admonish note title="Dans le compte rendu"
1. Donnez le code de votre nouvelle fonction `generer_dice_passphrase`
1. Quelle est la différence entre la syntaxe `mon_dict[key]` et `mon_dict.get(key)`, sachant que `mon_dict` est un dictionnaire python ?
```
## Pour aller plus loin
### Bonus facile - Docstrings au format Numpy
**Objectif**: Documenter votre code en ajoutant des docstrings au format Numpy
### Bonus - Lire les dictionnaires à partir d'un fichier
**Objectif** : Lire le dictionnaire utilisé dans votre fonction `generer_dice_passphrase` depuis le fichier `bonus_wordlist_fr.txt`
```admonish travail
1. Dans votre module `mdp`, créer une nouvelle fonction `get_word_dict_from_file`. Cette fonction prendra un paramètre `filename` et la valeur par défaut `"wordlist_fr.txt"`.
1. Ouvrir le fichier à l'aide d'un **gestionnaire de contexte**
1. Lire toutes les lignes du fichier, et les stocker dans la variable `lines`
1. Il va falloir maintenant construire votre dictionnaire à partir des lignes lues. Chaque ligne est composée de la manière suivante : `12345 mot\n` (5 chiffres représentant le tirage de dés, un espace puis un mot, et enfin un retour à la ligne)
1. Retournez votre dictionnaire
1. Remplacer l'appel à la fonction `get_word_dict` dans votre fonction `generer_dice_passphrase` par votre nouvelle fonction.
1. Vérifier que votre programme génère désormais des passphrases en français.
```
```admonish help title="Aide"
- Pour séparer une chaine de caractères, on peut utiliser la méthode [`split`](https://docs.python.org/3/library/stdtypes.html#str.split) sur la chaîne de caractères.
- Pour retirer les espaces et autres passages à la ligne autour des mots, on peut utiliser la méthode [`strip`](https://docs.python.org/3/library/stdtypes.html#str.strip)
- Pour construire votre dictionnaire, vous devrez boucler sur vos lignes, séparer les deux mots et les nettoyer. Puis vous pourrez les ajouter au dictionnaire avec la syntaxe `mon_dict[key] = value`. N'oubliez pas d'initialiser un dictionnaire vide (`{}`) avant votre boucle.
```
### Ressources
- [Liste de mots diceware en français](https://github.com/mbelivo/diceware-wordlists-fr/tree/master)
- [xkcd - Password Strength](https://xkcd.com/936/)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,3 @@
from pathlib import Path
WORDS = {
"11111": "abacus",
"11112": "abdomen",
@ -7783,12 +7781,4 @@ def get_word_list():
return list(WORDS.values())
def get_word_dict():
return WORDS
def get_words_from_file():
file_path = Path("eff_words_long_list.txt")
with file_path.open('r') as file:
lines = file.readlines()
words = {line.split("\t")[0].strip():line.split("\t")[1].strip() for line in lines}
return words
return WORDS

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,8 @@
import secrets
import string
from pathlib import Path
from eff_words import get_word_list, get_words_from_file
from eff_words import get_word_list
LETTRES = string.ascii_letters
CHIFFRES = string.digits
@ -11,6 +12,14 @@ ALPHABET = LETTRES + CHIFFRES + SPECIAL
DICE_NB = 5
def get_words_from_file():
file_path = Path("wordlist_en.txt")
with file_path.open('r') as file:
lines = file.readlines()
words = {line.split("\t")[0].strip():line.split("\t")[1].strip() for line in lines}
return words
def generer_mdp(password_length = 14):
password = ""
for i in range(password_length):

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
- [TP1 - Générateur de mots de passe - Menu interactif](./CIEL1/01-bases-python/tp/TP_MDP01_menu.md)
- [TP2 - Générateur de mots de passe - Fonctions et Modules](./CIEL1/01-bases-python/tp/TP_MDP02_fonctions.md)
- [TP3 - Générateur de mots de passe - Listes et dictionnaires](./CIEL1/01-bases-python/tp/TP_MDP03_collections.md)
- [TP4 - Générateur de mots de passe - Fichiers](./CIEL1/01-bases-python/tp/TP_MDP04_fichiers.md)
- [TD1 - Bases](./CIEL1/01-bases-python/td/td01-python.md)
- [TD2 - Fonctions ](./CIEL1/01-bases-python/td/td02-fonctions.md)
- [Annexe - Visual Studio Code](./CIEL1/01-bases-python/annexes/vscode.md)