| Question | Réponse |
|---|---|
| Entrées | password (une chaîne de caractères) et is_admin (True ou False, False par défaut) |
| Sortie | un tuple : True ou False, puis la liste des messages d'erreur |
| Exemple valide | check_password("Tr0ub4dour&Co") renvoie (True, []) |
| Exemple refusé | check_password("azerty") renvoie False et 5 messages. Il ne respecte presque aucune règle |
créer une liste d'erreurs vide
si le mot de passe est trop court : ajouter une erreur
regarder chaque caractère du mot de passe :
noter les catégories vues : majuscule, minuscule, chiffre, spécial
pour chaque catégorie jamais rencontrée : ajouter une erreur
si le mot de passe est un mot de passe courant : ajouter une erreur
renvoyer (la liste est-elle vide ?, la liste des erreurs)
Chaque ligne du plan deviendra quelques lignes de Python. Le plus dur est fait. Il ne reste qu'à traduire.
def check_password(password, is_admin=False):
"""Vérifie un mot de passe."""
errors = []
# … les règles viendront ici …
return len(errors) == 0, errors
print(check_password("azerty")) # (True, [])
len(errors) == 0 vaut True quand la liste est videreturn a, b renvoie un tuple
MIN_LENGTH = 12
ADMIN_MIN_LENGTH = 16
def check_password(password, is_admin=False):
errors = []
if is_admin:
min_length = ADMIN_MIN_LENGTH
else:
min_length = MIN_LENGTH
if len(password) < min_length:
errors.append(f"au moins {min_length} caractères")
return len(errors) == 0, errors
check_password("azerty") renvoie maintenant (False, ['au moins 12 caractères'])
has_upper = False
has_lower = False
has_digit = False
has_special = False
for char in password:
if char.isupper():
has_upper = True
elif char.islower():
has_lower = True
elif char.isdigit():
has_digit = True
elif not char.isalnum():
has_special = True
False : « je n'ai encore rien vu »True dès qu'elle rencontre la catégorieisalnum() est vrai pour une lettre ou un chiffre. not char.isalnum() repère donc un caractère spécial
if not has_upper:
errors.append("au moins une majuscule")
if not has_lower:
errors.append("au moins une minuscule")
if not has_digit:
errors.append("au moins un chiffre")
if not has_special:
errors.append("au moins un caractère spécial")
common = [p.lower() for p in COMMON_PASSWORDS]
if password.lower() in common:
errors.append("ne doit pas être un mot de passe courant")
return len(errors) == 0, errors
if indépendants (et non des elif). Plusieurs règles peuvent échouer en même tempsreturn reste à la fin, après toutes les vérifications
print(check_password("Tr0ub4dour&Co"))
# (True, [])
print(check_password("Azerty123456!"))
# (False, ['ne doit pas être un mot de passe courant'])
print(check_password("azerty"))
# (False, ['au moins 12 caractères', 'au moins une majuscule', 'au moins un chiffre',
# 'au moins un caractère spécial', 'ne doit pas être un mot de passe courant'])
print(check_password("Tr0ub4dour&Co", is_admin=True))
# (False, ['au moins 16 caractères'])
Si un résultat diffère, on relit l'étape correspondante du plan. C'est là que se trouve l'erreur.
| Piège | Correction |
|---|---|
return placé dans la boucle | la fonction s'arrête au premier caractère : le return va à la fin |
une chaîne d'elif pour les règles | une seule erreur est signalée : des if indépendants |
comparer sans lower() | « AZERTY » passe le contrôle : comparer en minuscules |
renvoyer seulement True ou False | l'énoncé demande aussi la liste : return valide, errors |
| tout écrire d'un coup puis tester | coder et tester étape par étape |