-
-
Notifications
You must be signed in to change notification settings - Fork 47.8k
-
https://docs.python.org/3/library/exceptions.html#exception-groups (New in Python 3.11)
ExceptionGroups
are useful for validating data and telling the user of multiple failures.
For example, if we are examining a string to see if it qualifies as a strong password (#10885) we want to see if it
- is long enough
- not too long
- has lowercase characters
- has uppercase characters
- has acceptable special characters
- does not have unacceptable special characters
- does not have too much repetition
If each of these raised a separate exception then we could use an ExceptionGroup
to tell the user all of the problems at once. We could tell them that the proposed password is too short and has no uppercase characters and has a ~
which is an unacceptable special character.
The contribution should solve a normal algorithm problem but should an ExceptionGroup
to provide detailed feedback.
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment
-
Hi @cclauss,
is this something what you are looking for?
from typing import List, Tuple, Callable from collections import Counter class PasswordTooShort(Exception): pass class PasswordTooLong(Exception): pass class NoLowercaseCharacter(Exception): pass class NoUppercaseCharacter(Exception): pass class NoSpecialCharacter(Exception): pass class UnacceptableSpecialCharacter(Exception): pass class TooMuchRepetition(Exception): pass def _check_repetition(password: str, max_repetition: int) -> bool: count = Counter(password) return any(_ > max_repetition for _ in count.values()) def validate_password(password: str) -> None: checks: List[Tuple[Callable[[str], bool], Exception]] = [ (lambda pwd: len(pwd) < 8, PasswordTooShort("Password is too short.")), (lambda pwd: len(pwd) > 20, PasswordTooLong("Password is too long.")), ( lambda pwd: not any(c.islower() for c in pwd), NoLowercaseCharacter("Password has no lowercase characters."), ), ( lambda pwd: not any(c.isupper() for c in pwd), NoUppercaseCharacter("Password has no uppercase characters."), ), ( lambda pwd: not any(c in "1234567890" for c in pwd), NoSpecialCharacter("Password has no acceptable special characters."), ), ( lambda pwd: any(c in ",~@" for c in pwd), UnacceptableSpecialCharacter( "Password has unacceptable special characters." ), ), ( lambda pwd: _check_repetition(pwd, 2), TooMuchRepetition("Password has too much repetition."), ), ] errors = [error for predicate, error in checks if predicate(password)] if errors: raise ExceptionGroup("Password Validation Errors", errors) if __name__ == "__main__": try: validate_password("passssw~rd1") except ExceptionGroup as e: for exception in e.exceptions: print(exception)
Beta Was this translation helpful? Give feedback.