[PYTHON] Extrahieren Sie mypy-Fehler, die Sie in Verbindung mit git behoben haben

19 neue Absolventen. Seit diesem Jahr habe ich die Serverseite berührt und verschiedene Dinge getan.

Dieses Mal werde ich darüber sprechen, wie die Zunahme / Abnahme der mypy-Fehlerausgabe in Verbindung mit git auf leicht verständliche Weise angezeigt werden kann.

Vorwort: Was ist Mypy?

Es ist ein Tool, das statische Analysen für Typanmerkungen in Python durchführt. Ich empfehle Ihnen, den Artikel des Vorfahren zu lesen. mypy wird es tun Ich habe mypy gemacht

Einführung

Am Anfang stand, dass die Version von mypy in meinem Fall schon lange nicht mehr aktualisiert wurde (0,540). Wenn Sie sich den Release Note ansehen, heißt es Freitag, 20. Oktober 2017 usw.

Als ich versuchte, die neueste Version lokal mit einem leichten Gefühl zu installieren, gab es viele Fehler im Zusammenhang mit den im Update hinzugefügten Kontrollpunkten. Wenn Sie die Option hinzufügen, sie vorerst zu unterdrücken, wird sie vergehen, aber ... das ist ...

Lassen Sie uns beheben

Und ich habe versucht, den Fehler zu beheben, aber es wurde normal schmerzhaft. Da die Fehler ungleichmäßig im Projektcode verteilt sind, der ziemlich groß ist, ist es psychisch schmerzhaft, dass keine Verbesserung sichtbar wird, wenn man ihn nur ein wenig behebt ...

Es ist unmöglich. Lassen Sie uns visualisieren ...

Hat gemacht

Visualisierung ist eine Übertreibung (weil es sich um Informationen handelt, die von Anfang an sichtbar sind). Wäre es nicht schön, wenn die Liste der von mir zerstörten Fehler leicht verständlich angezeigt würde? Ich dachte. Die Richtlinie ist einfach: Führen Sie mypy vor und nach der Änderung zweimal aus, um einen Unterschied zu erhalten. Es gibt eine Richtlinie, nach der es möglich sein sollte, etwas zu tun, indem der Unterschied zwischen dem Arbeitsbaum und HEAD in Verbindung mit git aufgerufen wird. Die Ausführungszeit wird verdoppelt, aber andererseits kann mypy nur auf die Differenzdatei ausgerichtet werden, so dass ich mit der hoffnungsvollen Beobachtung fortfahren werde, dass es in Ordnung ist.

Deshalb habe ich es geschafft. https://github.com/fujita-ma/mymypy

Es gibt keinen ernsthaften Grund, in Rost zu schreiben. Da es viel zeilenweise Textverarbeitung gab, war es meiner Meinung nach einfach, die Iteratorverarbeitung ohne Stress zu schreiben. Es ist in Ordnung, Python zu verwenden, aber um ehrlich zu sein, wollte ich es in einer Sprache tun, die ich bei der Arbeit nicht verwendet habe.

Versuchen Sie es mit

Versuchen Sie es mit dem Code im mypy-Beispiel. http://www.mypy-lang.org/examples.html

main.py


class BankAccount:
    def __init__(self, initial_balance=0):
        self.balance = initial_balance
    def deposit(self, amount):
        self.balance += amount
    def withdraw(self, amount):
        self.balance -= amount
    def overdrawn(self):
        return self.balance < 0

my_account = BankAccount(15)
my_account.withdraw(5)
print(my_account.balance)

Lass uns mypy laufen lassen.

❯ mypy --strict ./
main.py:2: error: Function is missing a type annotation
main.py:4: error: Function is missing a type annotation
main.py:6: error: Function is missing a type annotation
main.py:8: error: Function is missing a return type annotation
main.py:11: error: Call to untyped function "BankAccount" in typed context

Ich erhalte eine Fehlermeldung. Nachdem Sie dies einmal festgeschrieben haben, ändern Sie einige Anmerkungen und versuchen Sie, mypy bzw. mymypy auszuführen.

main.py


class BankAccount:
    def __init__(self, initial_balance: int = 0) -> None:  # Annotated
        self.balance = initial_balance
    def deposit(self, amount):
        self.balance += amount
    def withdraw(self, amount):
        self.balance -= amount
    def overdrawn(self):
        return self.balance < 0

my_account = BankAccount(15)
my_account.withdraw(5)
print(my_account.balance)
❯ mypy --strict ./
main.py:4: error: Function is missing a type annotation
main.py:6: error: Function is missing a type annotation
main.py:8: error: Function is missing a return type annotation
main.py:12: error: Call to untyped function "withdraw" in typed context
❯ mymypy
main.py
-main.py:2:_: error: Function is missing a type annotation
main.py:4:4: error: Function is missing a type annotation
main.py:6:6: error: Function is missing a type annotation
main.py:8:8: error: Function is missing a return type annotation
-main.py:11:11: error: Call to untyped function "BankAccount" in typed context
+main.py:12:12: error: Call to untyped function "withdraw" in typed context

Der Fehler wird rot hervorgehoben! Als Nebenprodukt wird der hinzugefügte Fehler grün hervorgehoben. Es ist üblich, dass Sie einen Fehler beheben und einen weiteren versteckten Fehler erhalten. Ich werde alles richtig zerquetschen.

Wenn Sie alle Anmerkungen richtig hinzufügen, sieht es wie ↓ aus.

main.py


class BankAccount:
    def __init__(self, initial_balance: int = 0) -> None:
        self.balance = initial_balance
    def deposit(self, amount: int) -> None:
        self.balance += amount
    def withdraw(self, amount: int) -> None:
        self.balance -= amount
    def overdrawn(self) -> bool:
        return self.balance < 0

my_account = BankAccount(15)
my_account.withdraw(5)
print(my_account.balance)
❯ mypy --strict ./

❯ mymypy
main.py
-main.py:2:_: error: Function is missing a type annotation
-main.py:4:_: error: Function is missing a type annotation
-main.py:6:_: error: Function is missing a type annotation
-main.py:8:_: error: Function is missing a return type annotation
-main.py:11:11: error: Call to untyped function "BankAccount" in typed context

Ich konnte 5 Fehler durch meine eigene Arbeit zerstören. Ich bin glücklich.

Versuchen Sie es in einem geeigneten Repository

Lass uns ein bisschen spielen. Revisionen werden gemäß "git diff" behandelt. Wenn Sie also ein geeignetes Commit angeben, können Sie den Unterschied zwischen ihnen ermitteln. Werfen Sie einen Blick in das Repository von mypy, um Commits zu erhalten.

a5005f4aa977e4911bce5c828fd707ca8680d592 The `inner_types` attribute seems to have no effect. Ich habe ein Commit gefunden, das offenbar überarbeitet wurde.

Lassen Sie es uns klonen und auf mymypy ausführen.

❯ mymypy a5005f4~ a5005f4
mypy/checker.py
mypy/checker.py:64:64: error: Module 'mypy.semanal' has no attribute 'set_callable_name'
-mypy/checker.py:2813:_: error: Too many arguments for "PartialType"
-mypy/checker.py:2823:_: error: Too many arguments for "PartialType"
mypy/checker.py:2959:2959: error: unused 'type: ignore' comment
-mypy/checker.py:3022:_: error: "PartialType" has no attribute "inner_types"
-mypy/checker.py:3024:_: error: "PartialType" has no attribute "inner_types"
mypy/checker.py:4137:4133: error: unused 'type: ignore' comment
-mypy/checker.py:4311:_: error: "PartialType" has no attribute "inner_types"
mypy/checkexpr.py
mypy/checkexpr.py:203:203: error: unused 'type: ignore' comment
-mypy/checkexpr.py:592:_: error: "PartialType" has no attribute "inner_types"
-mypy/checkexpr.py:606:_: error: "PartialType" has no attribute "inner_types"
mypy/checkexpr.py:2368:2361: error: Returning Any from function declared to return "Optional[str]"
mypy/checkexpr.py:3003:2996: error: unused 'type: ignore' comment
mypy/type_visitor.py
mypy/type_visitor.py:167:167: error: unused 'type: ignore' comment
mypy/type_visitor.py:207:207: error: unused 'type: ignore' comment
mypy/type_visitor.py:229:229: error: unused 'type: ignore' comment
-mypy/type_visitor.py:293:_: error: "PartialType" has no attribute "inner_types"
mypy/types.py
mypy/types.py:190:190: error: unused 'type: ignore' comment
mypy/types.py:497:497: error: Returning Any from function declared to return "T"
mypy/types.py:520:520: error: Returning Any from function declared to return "T"
mypy/types.py:808:808: error: Returning Any from function declared to return "Union[Dict[str, Any], str]"
mypy/types.py:1557:1557: error: Returning Any from function declared to return "T"
mypy/types.py:1669:1669: error: Returning Any from function declared to return "T"
mypy/types.py:1789:1786: error: Returning Any from function declared to return "T"
mypy/types.py:1844:1841: error: unused 'type: ignore' comment
mypy/types.py:1889:1886: error: Returning Any from function declared to return "T"

Sie können den Effekt des Refactorings sehen. Spaß ✌ ('ω' ✌) Drei ✌ ('ω') ✌ Drei (✌'ω ') ✌ (totes Wort)

abschließend

Ich habe es nach einem Stimmungswechsel mit einer angemessenen Richtlinie geschafft, bin aber zufrieden, weil es mit einem guten Gefühl angezeigt werden konnte. Ich werde es für mein Geschäft verwenden, weil es sehr viel ist. ~~ Wenn Sie es tatsächlich verwenden, werden Sie viele Fehler finden ~~

Recommended Posts

Extrahieren Sie mypy-Fehler, die Sie in Verbindung mit git behoben haben
Beachten Sie, dass ich mich mit HTML in Beautiful Soup befasst habe
Arbeitsnotiz, die ich i18n mit Flask App ausprobiert habe
Ich habe PyQCheck, eine Bibliothek, die QuickCheck mit Python ausführen kann, in PyPI registriert.
Ich habe versucht, die Pferde vorherzusagen, die mit LightGBM unter den Top 3 sein werden