विषय पर बढ़ें

Mypy

पाइडेंटिक बॉक्स के ठीक बाहर मायपी के साथ अच्छा काम करता है।

हालाँकि, Pydantic एक mypy प्लगइन के साथ भी आता है जो mypy में कई महत्वपूर्ण pydantic-विशिष्ट सुविधाएँ जोड़ता है जो आपके कोड को टाइप-चेक करने की इसकी क्षमता में सुधार करता है।

उदाहरण के लिए, निम्नलिखित स्क्रिप्ट पर विचार करें:

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

किसी विशेष कॉन्फ़िगरेशन के बिना, mypy लापता मॉडल फ़ील्ड एनोटेशन को नहीं पकड़ता है और list_of_ints तर्क के बारे में चेतावनी देता है जिसे Pydantic सही ढंग से पार्स करता है:

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]

लेकिन प्लगइन सक्षम होने पर , यह सही त्रुटि देता है:

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]

पाइडेंटिक मायपी प्लगइन के साथ, आप निडर होकर अपने मॉडलों को रिफैक्टर कर सकते हैं, यह जानते हुए कि यदि आपके फ़ील्ड नाम या प्रकार बदलते हैं तो मायपी कोई गलती पकड़ लेगा।

और भी फायदे हैं! अधिक जानकारी के लिए नीचे देखें।

प्लगइन के बिना mypy का उपयोग करना

आप अपना कोड mypy के माध्यम से चला सकते हैं:

mypy \
  --ignore-missing-imports \
  --follow-imports=skip \
  --strict-optional \
  pydantic_mypy_test.py

सख्त वैकल्पिक

आपके कोड को --strict-optional के साथ पास करने के लिए, आपको डिफ़ॉल्ट के रूप में None वाले सभी फ़ील्ड के लिए Optional[] या Optional[] के उपनाम का उपयोग करने की आवश्यकता है। (यह mypy के साथ मानक है।)

अन्य पाइडेंटिक इंटरफ़ेस

पाइडेंटिक डेटाक्लास और validate_call डेकोरेटर को भी mypy के साथ अच्छा काम करना चाहिए।

Mypy प्लगइन क्षमताएँ

Model.__init__ के लिए एक हस्ताक्षर बनाएं

  • कोई भी आवश्यक फ़ील्ड जिसमें गतिशील रूप से निर्धारित उपनाम नहीं हैं, उन्हें आवश्यक कीवर्ड तर्क के रूप में शामिल किया जाएगा।
  • यदि Config.populate_by_name=True , तो उत्पन्न हस्ताक्षर उपनामों के बजाय फ़ील्ड नामों का उपयोग करेगा।
  • यदि Config.extra='forbid' और आप गतिशील रूप से निर्धारित उपनामों का उपयोग नहीं करते हैं, तो उत्पन्न हस्ताक्षर अप्रत्याशित इनपुट की अनुमति नहीं देगा।
  • वैकल्पिक: यदि init_forbid_extra प्लगइन सेटिंग True पर सेट है, तो __init__ में अनपेक्षित इनपुट त्रुटियां उत्पन्न करेगा, भले ही Config.extra 'forbid' न हो।
  • वैकल्पिक: यदि init_typed प्लगइन सेटिंग True पर सेट है, तो जेनरेट किए गए हस्ताक्षर मॉडल फ़ील्ड के प्रकारों का उपयोग करेंगे (अन्यथा पार्सिंग की अनुमति देने के लिए उन्हें Any के रूप में एनोटेट किया जाएगा)।

Model.model_construct के लिए टाइप किया हुआ हस्ताक्षर बनाएं

  • जब इनपुट डेटा को वैध माना जाता है और उसे पार्स नहीं किया जाना चाहिए तो model_construct विधि __init__ का एक विकल्प है। क्योंकि यह विधि कोई रनटाइम सत्यापन नहीं करती है, त्रुटियों का पता लगाने के लिए स्थैतिक जाँच महत्वपूर्ण है।

Config.frozen सम्मान करें। जमे हुए

  • यदि Config.frozen True है, तो मॉडल फ़ील्ड का मान बदलने का प्रयास करने पर आपको एक mypy त्रुटि प्राप्त होगी; सी एफ नकली अपरिवर्तनीयता .

dataclasses के लिए एक हस्ताक्षर बनाएं

  • कक्षाओं को सजाया गया @pydantic.dataclasses.dataclass मानक पायथन डेटाक्लास के समान ही प्रकार की जाँच की जाती है
  • @pydantic.dataclasses.dataclass डेकोरेटर एक config कीवर्ड तर्क को स्वीकार करता है जिसका अर्थ Config उप-वर्ग के समान है।

Field के default और default_factory के प्रकार का सम्मान करें

  • default और default_factory दोनों वाले फ़ील्ड के परिणामस्वरूप स्थैतिक जाँच के दौरान त्रुटि होगी।
  • default का प्रकार और default_factory मान किसी एक फ़ील्ड के साथ संगत होना चाहिए।

टाइप न किए गए फ़ील्ड के उपयोग के बारे में चेतावनी दें

  • जब भी आप किसी मॉडल पर उसके प्रकार को एनोटेट किए बिना सार्वजनिक विशेषता निर्दिष्ट करेंगे तो आपको एक mypy त्रुटि प्राप्त होगी
  • यदि आपका लक्ष्य क्लासवार सेट करना है, तो आपको टाइपिंग.क्लासवार का उपयोग करके फ़ील्ड को स्पष्ट रूप से एनोटेट करना चाहिए

वैकल्पिक क्षमताएँ:

आवश्यक गतिशील उपनामों के उपयोग को रोकें

  • यदि warn_required_dynamic_aliases प्लगइन सेटिंग True पर सेट है, तो जब भी आप किसी मॉडल पर डायनामिक रूप से निर्धारित उपनाम या उपनाम जनरेटर का उपयोग करते हैं, तो आपको एक mypy त्रुटि प्राप्त होगी Config.populate_by_name=False
  • यह महत्वपूर्ण है क्योंकि यदि ऐसे उपनाम मौजूद हैं, तो mypy __init__ पर चेक कॉल को ठीक से टाइप नहीं कर सकता है। इस मामले में, यह सभी तर्कों को वैकल्पिक मानने में डिफ़ॉल्ट होगा।

प्लगइन सक्षम करना

प्लगइन को सक्षम करने के लिए, बस अपनी mypy कॉन्फ़िगरेशन फ़ाइल में प्लगइन्स की सूची में pydantic.mypy जोड़ें (यह mypy.ini , pyproject.toml , या setup.cfg हो सकता है)।

आरंभ करने के लिए, आपको बस निम्नलिखित सामग्री के साथ एक mypy.ini फ़ाइल बनानी होगी:

[mypy]
plugins = pydantic.mypy

!!! ध्यान दें यदि आप pydantic.v1 मॉडल का उपयोग कर रहे हैं, तो आपको प्लगइन्स की अपनी सूची में pydantic.v1.mypy जोड़ना होगा।

प्लगइन mypy संस्करण >=0.930 के साथ संगत है।

अधिक विवरण के लिए प्लगइन कॉन्फ़िगरेशन दस्तावेज़ देखें।

प्लगइन को कॉन्फ़िगर करना

प्लगइन सेटिंग्स के मूल्यों को बदलने के लिए, अपनी mypy कॉन्फ़िगरेशन फ़ाइल में [pydantic-mypy] नामक एक अनुभाग बनाएं, और उन सेटिंग्स के लिए कोई भी कुंजी-मूल्य जोड़े जोड़ें जिन्हें आप ओवरराइड करना चाहते हैं।

सभी प्लगइन सख्ती झंडे सक्षम (और कुछ अन्य mypy सख्ती झंडे भी) के साथ एक mypy.ini फ़ाइल इस तरह दिख सकती है:

[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

mypy>=0.900 के अनुसार, mypy कॉन्फिग को mypy.ini के बजाय pyproject.toml फ़ाइल में भी शामिल किया जा सकता है। ऊपर जैसा ही कॉन्फ़िगरेशन होगा:

[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

--disallow-any-explicit पर ध्यान दें

यदि आप --disallow-any-explicit mypy कॉन्फिग सेटिंग (या Any पर प्रतिबंध लगाने वाली अन्य सेटिंग्स) का उपयोग कर रहे हैं, तो BaseModel विस्तार करते समय आपको no-any-explicit त्रुटियों का सामना करना पड़ सकता है। ऐसा इसलिए है क्योंकि डिफ़ॉल्ट रूप से, Pydantic का mypy प्लगइन एक हस्ताक्षर के साथ एक __init__ विधि जोड़ता है def __init__(self, field_1: Any, field_2: Any, **kwargs: Any):

!!! नोट "अतिरिक्त हस्ताक्षर क्यों?" Pydantic mypy प्लगइन एक हस्ताक्षर के साथ एक __init__ विधि जोड़ता है def __init__(self, field_1: Any, field_2: Any, **kwargs: Any): फ़ील्ड एनोटेशन से मेल नहीं खाने वाले प्रकारों के साथ मॉडल आरंभ करते समय प्रकार की त्रुटियों से बचने के लिए। उदाहरण के लिए, Model(date='2024-01-01') इस Any हस्ताक्षर के बिना एक प्रकार की त्रुटि उत्पन्न करेगा, लेकिन पाइडेंटिक में स्ट्रिंग '2024-01-01' datetime.date प्रकार में पार्स करने की क्षमता है।

इस समस्या को हल करने के लिए, आपको Pydantic mypy प्लगइन के लिए सख्त मोड सेटिंग्स को सक्षम करना होगा। विशेष रूप से, इन विकल्पों को अपने [pydantic-mypy] अनुभाग में जोड़ें:

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true

init_forbid_extra = True के साथ, **kwargs उत्पन्न __init__ हस्ताक्षर से हटा दिए जाते हैं। init_typed = True के साथ, फ़ील्ड के लिए Any प्रकार को उनके वास्तविक प्रकार के संकेतों से बदल दिया जाता है।

यह कॉन्फ़िगरेशन आपको अपने पाइडेंटिक मॉडल पर त्रुटियां प्राप्त किए बिना --disallow-any-explicit उपयोग करने की अनुमति देता है। हालाँकि, सावधान रहें कि यह सख्त जाँच कुछ वैध पाइडेंटिक उपयोग मामलों (जैसे डेटाटाइम फ़ील्ड के लिए एक स्ट्रिंग पास करना) को प्रकार की त्रुटियों के रूप में चिह्नित कर सकती है।


本文总阅读量