Sie arbeiten seit einer ganzen Weile für eine Sicherheitsfirma an einer Codebase, für Python-code haben Sie nie Typehints verwendet. Eines Tages stirbt ihr lockerer Chef bei einem Unterwasserabenteuer. Und ausgerechnet Cyber-Chris nimmt seinen Platz ein! Ihnen ist sofort bewusst: Bearbeiten Sie Ihren Python-code nicht sofort, werden sie gefeuert!
Nun geht es ans eingemachte! Ein Fehler könnten Ihnen ihren Job kosten!
Bearbeiten Sie den Code so, dass via Typehinting jeder Variablen- und Rückgabetyp sofort ersichtlich wird!
# Fehlermeldungen für den Nutzer
message_1 = "Das Passwort ist zu kurz!"
message_2 = "Das Passwort muss min. 3 Buchstaben enthalten!"
message_3 = "Das Passwort muss min. 2 Zahlen enthalten!"
message_4 = "Das Passwort benötigt min. 1 Sonderzeichen!"
# Alle Zahlen, Buchstaben und Sonderzeichen auf der Welt hust hust
numbers = (3, 9, 4, 2)
characters = {"letters": ('W', 'h', 'e', 'a', 't', 'l', 'e', 'y'), "special": ('!', '?', '-', '@')}
# Diese Funktion nimmt ein Passwort, bestehend aus einem String und prüft, ob dieses Passwort sicher ist.
def naive_password_check(password):
password_length = len(password)
if(password_length < 8):
print(message_1)
return False
if(character_counter(password, characters["letters"]) < 3):
print(message_2)
return False
if(number_counter(password) < 2):
print(message_3)
return False
if(character_counter(password, characters["special"]) < 1):
print(message_4)
return False
return True
# Helferfunktionen
def character_counter(password, characters):
i = 0
for char in password:
if char in characters:
i = i + 1
return i
def number_counter(password):
i = 0
for char in password:
try:
if int(char) in numbers:
i = i + 1
except:
continue
return i
def main():
if(naive_password_check("Wheatley!42")):
print("Stein starkes Passwort!")
return 0
if __name__ == "__main__":
main()
Dem Python Interpreter sind typehints völlig Schnuppe. Der Interpreter hätte Sie z.B. in Aufgabe 2 nicht davon abgehalten, naive_password_check(123)
auszuführen, obwohl 123 ein Integer und kein String ist. Der Python Interpreter hätte auch nicht gemeckert, wenn naive_password_check
was anderes als ein Boolean zurückgegeben hätte. Natürlich stößt der Interpreter beim interpretieren dann ggf. trotzdem auf Probleme, da die Typen nicht kompatibel sind. Probieren Sie es gerne selbst aus!
Abhilfe schafft hier das Programm mypy
. mypy ist ein sogennanter Typechecker. Typechecker überprüfen, ob man richtig mit Variablen und Funktionen beüzglich den Typen umgeht. Ein typecheck mit mypy bezüglich diesem Python-code würde z.B. diesen Fehler aufrufen:
def stringify(num: int) -> str:
return num
#test2.py:2: error: Incompatible return value type (got "int", expected "str") [return-value]
Es ist hier wichtig anzumerken, dass mypy Variablen und Funktionen logischerweise nur dann typechecken kann, wenn man ihre jeweiligen Typen getypehinted hat. mypy wird Variablen und Funktionen ohne type-hint sogar überspringen!
Hier wird mypy z.B. nicht meckern, da es main überspringt:
def main():
naive_password_check(9000)
return 0
So würde es aber klappen:
def main()->int:
naive_password_check(9999)
return 0
# test.py:59: error: Argument 1 to "naive_password_check" has incompatible type "int"; expected "str" [arg-type]
Möchte man, dass mypy alles trotzdem checkt, so kann man die Option --strict
hinzügen, dass heißt man tippt dann mypy FILE --strict
in die Konsole ein (siehe Installation unten). mypy wird dann meckern, wenn man vergessen hat etwas zu typehinten.
Überprüfen Sie mit dem Programm mypy
selbstständig, ob Ihre Typehints sinnvoll sind.
Auf der VM bzw. auf den meisten Linux distros geht es ganz einfach:
sudo apt install mypy
in die Konsole eingeben und Passwort eingeben. Falls nicht auf der VM und apt nicht Packetmanager der jeweiligen Distro, einfach pip oder ggf. anderen Packetmanger nutzen. Auf Debian/Ubuntu/Mint müsst es klappen.mypy FILE [OPTIONEN]
kann man im Terminal sein Code checken. Eine Datei test.py
welche sich auf dem Desktop befindet, würde man z.B. mit mypy ~/Desktop/test.py
checken (~
ist ein Alias für den Pfad zum home-directory, tippen Sie echo ~
in die Konsole ein um zu sehen wie der Pfad ausgeschrieben aussehen würde).Sonst:
pip install mypy
eingeben in Terminal/CMD. Dazu muss pip auf ihrem Rechner installiert sein.# So geben Sie den Type einer Variable an
var_1: int = 1
var_2: float = 1.0
var_4: bool = True
var_5: str = "test"
# Für Listen und Dictionaries macht man das so
var_6: list[int] = [1]
var_7: dict[str, float] = {"field": 2.0}
# Die Parametertypen und Rückgabetyp einer Funktion gibt man so an
def stringify(num: int) -> str:
return str(num)
Weitere Informationen unter https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html