Mypy
Pydantic funktioniert sofort gut mit mypy .
Pydantic wird jedoch auch mit einem Mypy-Plugin ausgeliefert, das mypy eine Reihe wichtiger pydantic-spezifischer Funktionen hinzufügt, die die Fähigkeit zur Typprüfung Ihres Codes verbessern.
Betrachten Sie beispielsweise das folgende Skript:
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
class Model(BaseModel):
age: int
first_name = 'John'
last_name: Optional[str] = None
signup_ts: Optional[datetime] = None
list_of_ints: List[int]
m = Model(age=42, list_of_ints=[1, '2', b'3'])
print(m.middle_name) # not a model field!
Model() # will raise a validation error for age and list_of_ints
Ohne spezielle Konfiguration erkennt mypy die fehlende Modellfeldanmerkung nicht und warnt vor dem Argument list_of_ints
, das Pydantic korrekt analysiert:
test.py:15: error: List item 1 has incompatible type "str"; expected "int" [list-item]
test.py:15: error: List item 2 has incompatible type "bytes"; expected "int" [list-item]
test.py:16: error: "Model" has no attribute "middle_name" [attr-defined]
test.py:17: error: Missing named argument "age" for "Model" [call-arg]
test.py:17: error: Missing named argument "list_of_ints" for "Model" [call-arg]
Aber wenn das Plugin aktiviert ist , wird der richtige Fehler angezeigt:
9: error: Untyped fields disallowed [pydantic-field]
16: error: "Model" has no attribute "middle_name" [attr-defined]
17: error: Missing named argument "age" for "Model" [call-arg]
17: error: Missing named argument "list_of_ints" for "Model" [call-arg]
Mit dem pydantic mypy-Plugin können Sie Ihre Modelle furchtlos umgestalten, da Sie wissen, dass mypy alle Fehler erkennt, wenn sich Ihre Feldnamen oder -typen ändern.
Es gibt noch weitere Vorteile! Weitere Einzelheiten finden Sie weiter unten.
Verwendung von mypy ohne das Plugin¶
Sie können Ihren Code über mypy ausführen mit:
mypy \
--ignore-missing-imports \
--follow-imports=skip \
--strict-optional \
pydantic_mypy_test.py
Streng optional¶
Damit Ihr Code mit --strict-optional
übergeben werden kann, müssen Sie Optional[]
oder einen Alias von Optional[]
für alle Felder mit None
als Standard verwenden. (Dies ist Standard bei mypy.)
Andere Pydantic-Schnittstellen¶
Pydantic- Datenklassen und der validate_call
-Dekorator sollten auch gut mit mypy funktionieren.
Funktionen des Mypy-Plugins¶
Generieren Sie eine Signatur für Model.__init__
¶
- Alle erforderlichen Felder, die keine dynamisch ermittelten Aliase haben, werden als erforderliche Schlüsselwortargumente einbezogen.
- Wenn
Config.populate_by_name=True
, verwendet die generierte Signatur die Feldnamen anstelle von Aliasnamen. - Wenn
Config.extra='forbid'
und Sie keine dynamisch ermittelten Aliase verwenden, lässt die generierte Signatur keine unerwarteten Eingaben zu. - Optional: Wenn die Plugin-Einstellung
init_forbid_extra
aufTrue
gesetzt ist, lösen unerwartete Eingaben in__init__
Fehler aus, auch wennConfig.extra
nicht'forbid'
ist. - Optional: Wenn die Plugin-Einstellung
init_typed
aufTrue
gesetzt ist, verwendet die generierte Signatur die Typen der Modellfelder (andernfalls werden sie alsAny
annotiert, um das Parsen zu ermöglichen).
Generieren Sie eine typisierte Signatur für Model.model_construct
¶
- Die
model_construct
-Methode ist eine Alternative zu__init__
wenn bekannt ist, dass Eingabedaten gültig sind und nicht analysiert werden sollten. Da diese Methode keine Laufzeitvalidierung durchführt, ist eine statische Überprüfung wichtig, um Fehler zu erkennen.
Respektieren Sie Config.frozen
¶
- Wenn
Config.frozen
True
ist, erhalten Sie einen Mypy-Fehler, wenn Sie versuchen, den Wert eines Modellfelds zu ändern. vgl. falsche Unveränderlichkeit .
Generieren Sie eine Signatur für dataclasses
¶
- Klassen dekoriert mit
@pydantic.dataclasses.dataclass
werden genauso typgeprüft wie Standard-Python-Datenklassen - Der
@pydantic.dataclasses.dataclass
Der Dekorator akzeptiert einconfig
Schlüsselwortargument, das dieselbe Bedeutung wie dieConfig
-Unterklasse hat.
Beachten Sie den Typ des Field
default
und default_factory
¶
- Ein Feld mit sowohl einem
default
als auch einemdefault_factory
führt bei der statischen Prüfung zu einem Fehler. - Der Typ des
default
unddefault_factory
-Werts muss mit dem des Felds kompatibel sein.
Warnen Sie vor der Verwendung untypisierter Felder¶
- Sie erhalten jedes Mal einen Mypy-Fehler, wenn Sie einem Modell ein öffentliches Attribut zuweisen, ohne seinen Typ zu kommentieren
- Wenn Sie eine ClassVar festlegen möchten, sollten Sie das Feld mithilfe von typing.ClassVar explizit mit Anmerkungen versehen
Optionale Funktionen:¶
Verhindern Sie die Verwendung erforderlicher dynamischer Aliase¶
- Wenn die Plugin-Einstellung
warn_required_dynamic_aliases
aufTrue
gesetzt ist, erhalten Sie jedes Mal einen Mypy-Fehler, wenn Sie einen dynamisch ermittelten Alias oder Aliasgenerator für ein Modell mitConfig.populate_by_name=False
verwenden. - Dies ist wichtig, denn wenn solche Aliase vorhanden sind, kann mypy Prüfaufrufe an
__init__
nicht richtig eingeben. In diesem Fall werden alle Argumente standardmäßig als optional behandelt.
Aktivieren des Plugins¶
Um das Plugin zu aktivieren, fügen Sie einfach pydantic.mypy
zur Liste der Plugins in Ihrer mypy-Konfigurationsdatei hinzu (dies könnte mypy.ini
, pyproject.toml
oder setup.cfg
sein).
Um zu beginnen, müssen Sie lediglich eine mypy.ini
-Datei mit folgendem Inhalt erstellen:
[mypy]
plugins = pydantic.mypy
!!! Hinweis Wenn Sie pydantic.v1
-Modelle verwenden, müssen Sie pydantic.v1.mypy
zu Ihrer Plugin-Liste hinzufügen.
Das Plugin ist mit den Mypy-Versionen >=0.930
kompatibel.
Weitere Informationen finden Sie in den Plugin- Konfigurationsdokumenten.
Konfigurieren des Plugins¶
Um die Werte der Plugin-Einstellungen zu ändern, erstellen Sie in Ihrer Mypy-Konfigurationsdatei einen Abschnitt mit dem Namen [pydantic-mypy]
und fügen Sie alle Schlüssel-Wert-Paare für Einstellungen hinzu, die Sie überschreiben möchten.
Eine mypy.ini
Datei mit allen aktivierten Plugin-Striktheitsflags (und auch einigen anderen Mypy-Striktheitsflags) könnte wie folgt aussehen:
[mypy]
plugins = pydantic.mypy
follow_imports = silent
warn_redundant_casts = True
warn_unused_ignores = True
disallow_any_generics = True
check_untyped_defs = True
no_implicit_reexport = True
# for strict mypy: (this is the tricky one :-))
disallow_untyped_defs = True
[pydantic-mypy]
init_forbid_extra = True
init_typed = True
warn_required_dynamic_aliases = True
Ab mypy>=0.900
kann die mypy-Konfiguration auch in der Datei pyproject.toml
statt in mypy.ini
enthalten sein. Die gleiche Konfiguration wie oben wäre:
[tool.mypy]
plugins = [
"pydantic.mypy"
]
follow_imports = "silent"
warn_redundant_casts = true
warn_unused_ignores = true
disallow_any_generics = true
check_untyped_defs = true
no_implicit_reexport = true
# for strict mypy: (this is the tricky one :-))
disallow_untyped_defs = true
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
warn_required_dynamic_aliases = true
Hinweis zu --disallow-any-explicit
¶
Wenn Sie die Mypy-Konfigurationseinstellung --disallow-any-explicit
(oder andere Einstellungen, die Any
verbieten) verwenden, können beim Erweitern von BaseModel
no-any-explicit
Fehler auftreten. Dies liegt daran, dass mypy
-Plugin von Pydantic standardmäßig eine __init__
Methode mit einer Signatur wie „ hinzufügt def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):
!!! Hinweis „Warum die zusätzliche Signatur?“ Das Pydantic- mypy
-Plugin fügt eine __init__
Methode mit einer Signatur wie hinzu def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):
um Typfehler zu vermeiden, wenn Modelle mit Typen initialisiert werden, die nicht mit den Feldanmerkungen übereinstimmen. Beispielsweise würde Model(date='2024-01-01')
ohne diese Any
Signatur einen Typfehler auslösen, aber Pydantic hat die Möglichkeit, die Zeichenfolge '2024-01-01'
in einen datetime.date
-Typ zu analysieren.
Um dieses Problem zu beheben, müssen Sie die Einstellungen für den strengen Modus für das Pydantic-Mypy-Plugin aktivieren. Fügen Sie insbesondere diese Optionen zu Ihrem Abschnitt [pydantic-mypy]
hinzu:
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
Mit init_forbid_extra = True
werden die **kwargs
aus der generierten __init__
Signatur entfernt. Mit init_typed = True
werden die Any
Typen für Felder durch ihre tatsächlichen Typhinweise ersetzt.
Mit dieser Konfiguration können Sie --disallow-any-explicit
verwenden, ohne dass bei Ihren Pydantic-Modellen Fehler auftreten. Beachten Sie jedoch, dass diese strengere Prüfung einige gültige Pydantic-Anwendungsfälle (z. B. die Übergabe einer Zeichenfolge für ein Datum/Uhrzeit-Feld) als Typfehler markieren kann.
本文总阅读量次