Mypy
Pydantic werkt direct uit de doos goed met mypy .
Pydantic wordt echter ook geleverd met een mypy-plug-in die een aantal belangrijke pydantic-specifieke functies aan mypy toevoegt die de mogelijkheid om uw code te controleren verbeteren.
Neem bijvoorbeeld het volgende script:
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
Zonder enige speciale configuratie vangt mypy de ontbrekende modelveldannotatie niet op en waarschuwt voor het list_of_ints argument dat Pydantic correct parseert:
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]
Maar als de plug-in is ingeschakeld , geeft deze de juiste foutmelding:
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]
Met de pydantic mypy-plug-in kunt u uw modellen onbevreesd herstructureren, wetende dat mypy fouten zal ontdekken als uw veldnamen of typen veranderen.
Er zijn ook andere voordelen! Zie hieronder voor meer details.
Mypy gebruiken zonder de plug-in¶
U kunt uw code via mypy uitvoeren met:
mypy \
--ignore-missing-imports \
--follow-imports=skip \
--strict-optional \
pydantic_mypy_test.py
Strikt optioneel¶
Om ervoor te zorgen dat uw code wordt doorgegeven met --strict-optional , moet u Optional[] of een alias Optional[] gebruiken voor alle velden met None als standaard. (Dit is standaard bij mypy.)
Andere Pydantic-interfaces¶
Pydantic dataclasses en de validate_call decorateur zouden ook goed moeten werken met mypy.
Mogelijkheden voor Mypy-plug-ins¶
Genereer een handtekening voor Model.__init__¶
- Alle verplichte velden die geen dynamisch bepaalde aliassen hebben, worden opgenomen als vereiste trefwoordargumenten.
- Als
Config.populate_by_name=Truezal de gegenereerde handtekening de veldnamen gebruiken in plaats van aliassen. - Als
Config.extra='forbid'en u geen gebruik maakt van dynamisch bepaalde aliassen, zal de gegenereerde handtekening geen onverwachte invoer toestaan. - Optioneel: Als de
init_forbid_extraplugin-instelling is ingesteld opTrue, zullen onverwachte invoer naar__init__fouten veroorzaken, zelfs alsConfig.extraniet'forbid'is. - Optioneel: Als de plug-ininstelling
init_typedis ingesteld opTrue, gebruikt de gegenereerde handtekening de typen modelvelden (anders worden ze geannoteerd alsAnyom parseren mogelijk te maken).
Genereer een getypte handtekening voor Model.model_construct¶
- De
model_constructmethode is een alternatief voor__init__wanneer bekend is dat invoergegevens geldig zijn en niet mogen worden geparseerd. Omdat deze methode geen runtime-validatie uitvoert, is statische controle belangrijk om fouten op te sporen.
Respecteer Config.frozen¶
- Als
Config.frozenTrueis, krijgt u een mypy-fout als u de waarde van een modelveld probeert te wijzigen; vgl. valse onveranderlijkheid .
Genereer een handtekening voor dataclasses¶
- klassen versierd met
@pydantic.dataclasses.dataclassworden op dezelfde manier gecontroleerd als standaard Python-dataklassen - De
@pydantic.dataclasses.dataclassdecorateur accepteert eenconfigtrefwoordargument dat dezelfde betekenis heeft als deConfig-subklasse .
Respecteer het type default en default_factory van het Field¶
- Velden met zowel een
defaultals eendefault_factoryresulteren in een fout tijdens de statische controle. - Het type van de waarde
defaultendefault_factorymoet compatibel zijn met die van het veld.
Waarschuw voor het gebruik van niet-getypeerde velden¶
- Elke keer dat u een openbaar kenmerk aan een model toewijst zonder het type ervan te annoteren, krijgt u een mypy-fout
- Als het uw doel is om een ClassVar in te stellen, moet u het veld expliciet annoteren met behulp van typing.ClassVar
Optionele mogelijkheden:¶
Voorkom het gebruik van vereiste dynamische aliassen¶
- Als de plugin-instelling
warn_required_dynamic_aliasesis ingesteld opTrue, krijgt u elke keer dat u een dynamisch bepaalde alias of aliasgenerator gebruikt op een model metConfig.populate_by_name=Falseeen mypy-fout. - Dit is belangrijk omdat als dergelijke aliassen aanwezig zijn, mypy geen check-aanroepen naar
__init__kan typen. In dit geval worden alle argumenten standaard als optioneel behandeld.
De plug-in inschakelen¶
Om de plug-in in te schakelen, voegt u gewoon pydantic.mypy toe aan de lijst met plug-ins in uw mypy-configuratiebestand (dit kan mypy.ini , pyproject.toml of setup.cfg zijn).
Om aan de slag te gaan, hoeft u alleen maar een mypy.ini bestand te maken met de volgende inhoud:
[mypy]
plugins = pydantic.mypy
!!! opmerking Als u pydantic.v1 -modellen gebruikt, moet u pydantic.v1.mypy toevoegen aan uw lijst met plug-ins.
De plug-in is compatibel met mypy-versies >=0.930 .
Zie de plug-inconfiguratiedocumentatie voor meer details.
De plug-in configureren¶
Om de waarden van de plug-in-instellingen te wijzigen, maakt u een sectie in uw mypy-configuratiebestand met de naam [pydantic-mypy] en voegt u eventuele sleutel-waardeparen toe voor de instellingen die u wilt overschrijven.
Een mypy.ini bestand waarin alle striktheidsvlaggen van de plug-in zijn ingeschakeld (en ook enkele andere striktheidsvlaggen van mypy) kan er als volgt uitzien:
[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
Vanaf mypy>=0.900 kan mypy config ook worden opgenomen in het bestand pyproject.toml in plaats van mypy.ini . Dezelfde configuratie als hierboven zou zijn:
[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
Opmerking over --disallow-any-explicit¶
Als u de --disallow-any-explicit mypy config-instelling gebruikt (of andere instellingen die Any verbieden), kunt u no-any-explicit fouten tegenkomen bij het uitbreiden BaseModel . Dit komt omdat mypy -plug-in van Pydantic standaard een __init__ methode toevoegt met een handtekening zoals def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):
!!! note "Waarom de extra handtekening?" De Pydantic mypy -plug-in voegt een __init__ methode toe met een handtekening zoals def __init__(self, field_1: Any, field_2: Any, **kwargs: Any): om typefouten te voorkomen bij het initialiseren van modellen met typen die niet overeenkomen met de veldannotaties. Model(date='2024-01-01') zou bijvoorbeeld een typefout opleveren zonder deze Any -handtekening, maar Pydantic heeft de mogelijkheid om de string '2024-01-01' te ontleden in een datetime.date type.
Om dit probleem op te lossen, moet u strikte modusinstellingen inschakelen voor de Pydantic mypy-plug-in. Voeg specifiek deze opties toe aan uw [pydantic-mypy] sectie:
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
Met init_forbid_extra = True worden de **kwargs verwijderd uit de gegenereerde __init__ handtekening. Met init_typed = True worden de velden Any types vervangen door hun daadwerkelijke typehints.
Met deze configuratie kunt u --disallow-any-explicit gebruiken zonder fouten te krijgen op uw Pydantic-modellen. Houd er echter rekening mee dat deze strengere controle sommige geldige Pydantic-gebruiksscenario's (zoals het doorgeven van een string voor een datetime-veld) als typefouten kan markeren.
本文总阅读量次