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=True
zal 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_extra
plugin-instelling is ingesteld opTrue
, zullen onverwachte invoer naar__init__
fouten veroorzaken, zelfs alsConfig.extra
niet'forbid'
is. - Optioneel: Als de plug-ininstelling
init_typed
is ingesteld opTrue
, gebruikt de gegenereerde handtekening de typen modelvelden (anders worden ze geannoteerd alsAny
om parseren mogelijk te maken).
Genereer een getypte handtekening voor Model.model_construct
¶
- De
model_construct
methode 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.frozen
True
is, 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.dataclass
worden op dezelfde manier gecontroleerd als standaard Python-dataklassen - De
@pydantic.dataclasses.dataclass
decorateur accepteert eenconfig
trefwoordargument dat dezelfde betekenis heeft als deConfig
-subklasse .
Respecteer het type default
en default_factory
van het Field
¶
- Velden met zowel een
default
als eendefault_factory
resulteren in een fout tijdens de statische controle. - Het type van de waarde
default
endefault_factory
moet 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_aliases
is ingesteld opTrue
, krijgt u elke keer dat u een dynamisch bepaalde alias of aliasgenerator gebruikt op een model metConfig.populate_by_name=False
een 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.
本文总阅读量次