Mypy
Pydantic bekerja dengan baik dengan mypy langsung dari kotaknya.
Namun, Pydantic juga dilengkapi dengan plugin mypy yang menambahkan sejumlah fitur penting khusus pydantic ke mypy yang meningkatkan kemampuannya untuk memeriksa tipe kode Anda.
Misalnya, perhatikan skrip berikut:
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
Tanpa konfigurasi khusus apa pun, mypy tidak menangkap anotasi bidang model yang hilang dan memperingatkan tentang argumen list_of_ints
yang diurai oleh Pydantic dengan benar:
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]
Tetapi dengan plugin yang diaktifkan , ini memberikan kesalahan yang benar:
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]
Dengan plugin pydantic mypy, Anda tanpa rasa takut dapat memfaktorkan ulang model Anda karena mengetahui mypy akan menangkap kesalahan apa pun jika nama atau jenis bidang Anda berubah.
Ada manfaat lainnya juga! Lihat di bawah untuk lebih jelasnya.
Menggunakan mypy tanpa plugin¶
Anda dapat menjalankan kode Anda melalui mypy dengan:
mypy \
--ignore-missing-imports \
--follow-imports=skip \
--strict-optional \
pydantic_mypy_test.py
Opsional Ketat¶
Agar kode Anda dapat lolos dengan --strict-optional
, Anda perlu menggunakan Optional[]
atau alias Optional[]
untuk semua bidang dengan None
sebagai default. (Ini standar dengan mypy.)
Antarmuka Pydantic lainnya¶
Kelas data Pydantic dan dekorator validate_call
juga harus bekerja dengan baik dengan mypy.
Kemampuan Plugin Mypy¶
Hasilkan tanda tangan untuk Model.__init__
¶
- Bidang wajib apa pun yang tidak memiliki alias yang ditentukan secara dinamis akan disertakan sebagai argumen kata kunci wajib.
- Jika
Config.populate_by_name=True
, tanda tangan yang dihasilkan akan menggunakan nama bidang, bukan alias. - Jika
Config.extra='forbid'
dan Anda tidak menggunakan alias yang ditentukan secara dinamis, tanda tangan yang dihasilkan tidak akan mengizinkan masukan yang tidak diharapkan. - Opsional: Jika pengaturan plugin
init_forbid_extra
diatur keTrue
, masukan tak terduga ke__init__
akan menimbulkan kesalahan meskipunConfig.extra
bukan'forbid'
. - Opsional: Jika pengaturan plugin
init_typed
diatur keTrue
, tanda tangan yang dihasilkan akan menggunakan jenis bidang model (jika tidak, maka tanda tangan tersebut akan diberi anotasiAny
untuk memungkinkan penguraian).
Hasilkan tanda tangan yang diketik untuk Model.model_construct
¶
- Metode
model_construct
merupakan alternatif dari__init__
ketika data masukan diketahui valid dan tidak boleh diurai. Karena metode ini tidak melakukan validasi runtime, pemeriksaan statis penting untuk mendeteksi kesalahan.
Hormati Config.frozen
¶
- Jika
Config.frozen
adalahTrue
, Anda akan mendapatkan kesalahan mypy jika mencoba mengubah nilai bidang model; lih. kekekalan palsu .
Hasilkan tanda tangan untuk dataclasses
¶
- kelas dihiasi dengan
@pydantic.dataclasses.dataclass
tipenya diperiksa sama dengan kelas data Python standar - Itu
@pydantic.dataclasses.dataclass
dekorator menerima argumen kata kunciconfig
yang memiliki arti yang sama dengan subkelasConfig
.
Hormati jenis Field
default
dan default_factory
¶
- Bidang dengan
default
dandefault_factory
akan menghasilkan kesalahan selama pemeriksaan statis. - Jenis nilai
default
dandefault_factory
harus kompatibel dengan salah satu bidang.
Peringatkan tentang penggunaan bidang yang tidak diketik¶
- Anda akan mendapatkan kesalahan mypy setiap kali Anda menetapkan atribut publik pada model tanpa memberi anotasi pada tipenya
- Jika tujuan Anda adalah menetapkan ClassVar, Anda harus secara eksplisit memberi anotasi pada bidang tersebut menggunakan mengetik.ClassVar
Kemampuan Opsional:¶
Cegah penggunaan alias dinamis yang diperlukan¶
- Jika pengaturan plugin
warn_required_dynamic_aliases
diatur keTrue
, Anda akan mendapatkan kesalahan mypy setiap kali Anda menggunakan alias atau generator alias yang ditentukan secara dinamis pada model denganConfig.populate_by_name=False
. - Hal ini penting karena jika alias tersebut ada, mypy tidak dapat mengetikkan panggilan cek ke
__init__
dengan benar. Dalam hal ini, secara default akan memperlakukan semua argumen sebagai opsional.
Mengaktifkan Plugin¶
Untuk mengaktifkan plugin, cukup tambahkan pydantic.mypy
ke daftar plugin di file konfigurasi mypy Anda (bisa berupa mypy.ini
, pyproject.toml
, atau setup.cfg
).
Untuk memulai, yang perlu Anda lakukan hanyalah membuat file mypy.ini
dengan konten berikut:
[mypy]
plugins = pydantic.mypy
!!! catatan Jika Anda menggunakan model pydantic.v1
, Anda harus menambahkan pydantic.v1.mypy
ke daftar plugin Anda.
Plugin ini kompatibel dengan versi mypy >=0.930
.
Lihat dokumen konfigurasi plugin untuk lebih jelasnya.
Mengonfigurasi Plugin¶
Untuk mengubah nilai pengaturan plugin, buat bagian di file konfigurasi mypy Anda yang disebut [pydantic-mypy]
, dan tambahkan pasangan nilai kunci apa pun untuk pengaturan yang ingin Anda ganti.
File mypy.ini
dengan semua tanda keketatan plugin diaktifkan (dan beberapa tanda keketatan mypy lainnya juga) mungkin terlihat seperti:
[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
Mulai mypy>=0.900
, konfigurasi mypy juga dapat disertakan dalam file pyproject.toml
daripada mypy.ini
. Konfigurasi yang sama seperti di atas adalah:
[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
Catatan tentang --disallow-any-explicit
¶
Jika Anda menggunakan pengaturan konfigurasi mypy --disallow-any-explicit
(atau pengaturan lain yang melarang Any
), Anda mungkin mengalami kesalahan no-any-explicit
saat memperluas BaseModel
. Ini karena secara default, plugin mypy
Pydantic menambahkan metode __init__
dengan tanda tangan seperti def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):
!!! catatan "Mengapa tanda tangan tambahan?" Plugin Pydantic mypy
menambahkan metode __init__
dengan tanda tangan seperti def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):
untuk menghindari kesalahan ketik saat menginisialisasi model dengan tipe yang tidak cocok dengan anotasi bidang. Misalnya Model(date='2024-01-01')
akan memunculkan kesalahan tipe tanpa tanda tangan Any
ini, tetapi Pydantic memiliki kemampuan untuk mengurai string '2024-01-01'
menjadi tipe datetime.date
.
Untuk mengatasi masalah ini, Anda perlu mengaktifkan pengaturan mode ketat untuk plugin Pydantic mypy. Secara khusus, tambahkan opsi ini ke bagian [pydantic-mypy]
Anda:
[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
Dengan init_forbid_extra = True
, **kwargs
dihapus dari tanda tangan __init__
yang dihasilkan. Dengan init_typed = True
, bidang Tipe Any
diganti dengan petunjuk tipe sebenarnya.
Konfigurasi ini memungkinkan Anda menggunakan --disallow-any-explicit
tanpa mendapatkan kesalahan pada model Pydantic Anda. Namun, perlu diketahui bahwa pemeriksaan yang lebih ketat ini mungkin menandai beberapa kasus penggunaan Pydantic yang valid (seperti meneruskan string untuk bidang datetime) sebagai kesalahan tipe.
本文总阅读量次