プラグインを使用したMypy拡張機能

こんにちは、友達。 そして、私たちは新しいコースを立ち上げることの強度を高め続けており、4月の終わりに「Web-developer in Python」コースが開始されることをすでに喜んで発表しています。 この点で、私たちは伝統的に有用な資料の翻訳を共有しています。 始めましょう。



Pythonは動的型付け言語であることが知られています。 静的型チェックツールでは解析が困難なDSLのようなフレームワークを書くのは非常に簡単です。 それにもかかわらず、 プロトコルリテラルタイプなどのmypyの最新の機能革新、メタクラスの基本的なサポート、記述子のサポートにより、多くの場合正確なタイプを取得できますが、誤検知やその他のマイナス要因を回避することは依然として困難です。 この問題を解決し、フレームワークごとに型システムをカスタマイズする必要を回避するために、 mypyプラグインシステムをサポートしています 。 プラグインはPythonのモジュールであり、ライブラリまたはフレームワークと対話するクラスと関数のタイプをチェックするときにmypyが呼び出すプラグインフックを提供します。 したがって、返された関数のタイプをより正確に区別することができます。これは、表現が非常に困難であるか、デコレーターの効果を反映するクラスのメソッドを自動的に生成します。 プラグインシステムのアーキテクチャの詳細と機能の完全なリストを参照するには、 ドキュメントをご覧ください。







標準ライブラリの関連プラグイン



Mypyには、基本的な関数とクラス、およびctypes



contextlib



およびdataclasses



を実装するためのデフォルトのプラグインが付属していdataclasses



。 また、 attrs



プラグインも含まれています(歴史的にmypy用に書かれた最初のサードパーティプラグインです)。 これらのプラグインにより、 mypyはこれらのライブラリ関数を使用して、タイプをより正確に判別し、タイプのコードを正しくチェックできます。 これを例で示すには、コードスニペットを見てください。



 from dataclasses import dataclass from typing import Generic, TypeVar @dataclass class TaggedVector(Generic[T]): data: List[T] tag: str position = TaggedVector([0, 0, 0], 'origin')
      
      





上記では、クラスが定義されるときにget_class_decorator_hook()



が呼び出されます。 これにより、 __init__()



を含む自動生成されたメソッドが関数本体に追加されます。 Mypyは、このようなコンストラクターを使用して、 TaggedVector[int]



position



の型として正しく計算します。 例からわかるように、プラグインはジェネリッククラスでも機能します。



もう1つのコードを次に示します。



 from contextlib import contextmanager @contextmanager def timer(title: str) -> Iterator[float]: ... with timer(9000) as tm: ...
      
      





ここで、 get_function_hook()



contextmanager



デコレータの正確な戻り値の型を提供するため、装飾された関数の呼び出しは特定の型に準拠しているかどうかを確認できます。 mypyはエラーを認識できるようになりました。timer timer()



引数は文字列でなければなりません。



プラグインとスタブの組み合わせ



動的なPython関数を使用することに加えて、フレームワークはしばしば大きなAPIを持つという問題に直面します。 Mypyは、これらのライブラリを使用するコードをチェックするためにライブラリのスタブファイルを必要とします(ライブラリにビルトインアノテーションが含まれていない場合のみ)。これはあまり一般的ではありません。 typehedを使用した大規模なフレームワークのスタブを配布することは一般的ではありません。





PEP 561で導入されたスタブパッケージは次のことを行います。





さらに、 pip



使用すると、ライブラリのさまざまなスタブと対応するmypyプラグインを1つのディストリビューションに結合できます。 フレームワークまたは対応するmypyプラグインのスタブは簡単に開発して1つのディストリビューションにまとめることができます。プラグインはスタブの欠落または不正確な定義を埋めるため、非常に便利です。



このようなパッケージの最新の例はSQLAlchemyスタブとプラグインで 、バージョン0.1の最初のパブリックリリースがあり、これは少し前にPyPIで公開されました。 このプロジェクトは初期のAlphaバージョンであるという事実にもかかわらず、DropBoxで安全に使用して型チェックを改善できます。 プラグインは、基本的なORM宣言を理解します。



 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String)
      
      





上記のコードスニペットでは、プラグインはget_dynamic_class_hook()



を使用して、 mypyにBaseが有効な基本クラスであることを伝えます。 次に、 get_base_class_hook()



が呼び出されてユーザーを定義し、自動生成された属性を追加します。 次に、モデルのインスタンスを作成します。



user = User(id=42, name=42)







get_function_hook()



呼び出されるため、 mypyはエラーを示す可能性があります。ユーザー名の代わりにinteger



値が受信されます。



スタブはColumn



汎用記述子として定義するため、モデル属性は正しい型を取得します。



 id_col = User.id # Inferred type is "Column[int]" name = user.name # Inferred type is "Optional[str]"
      
      





より正確な型をスタブに追加するPRを歓迎します(コアモジュールの進捗状況はここで追跡します )。



スタブの作業中に発見したいくつかの落とし穴を以下に示します。





最近リリースされたmypyプラグイン



すでに人気のあるPythonフレームワーク用のプラグインがいくつかあります。 上記のSQLAlchemyプラグインとは別に、スタブと組み込みmypyプラグインを含むその他の注目すべきサンプルパッケージには、 DjangoおよびZopeインターフェース用のスタブが含まれています。 これらのプロジェクトで積極的な作業が進行中です。



スタブパッケージとプラグインパッケージのインストールと接続



pipを使用して、 mypyおよび/またはスタブのプラグインパッケージをmypyが既にインストールされている仮想環境にインストールします。



  $ pip install sqlalchemy-stubs
      
      





Mypyはインストールされたスタブを自動的に検出します。 インストールしたプラグインを接続するには、mypy.ini(またはユーザー設定ファイル)に直接それらを含めます:



 [mypy] plugins = sqlmypy, mypy_django_plugin.main
      
      





mypyプラグインの開発とスタブの作成



使用するフレームワーク用のスタブとプラグインのパッケージを開発する場合、sqlalchemy-stubsリポジトリをテンプレートとして使用できます。 setup.py



、データ駆動型テストを使用したテストインフラストラクチャ、およびプラグイン用のフックセット(プラグインフック)を含むプラグインクラスの例が含まれていsetup.py



stubgenを使用して、 mypyに付属するスタブを自動的に生成し、使用を開始することをお勧めします。 Stubgen



mypy 0.670



改善されました。



mypyプラグインシステムの詳細については、 ドキュメントをご覧ください 。 また、記事で説明したプラグインのソースコードをインターネットで検索することもできます。 質問がある場合は、 ここで質問できます



4月15日は、モスクワPythonコミュニティの主催者の1人であるVladimir Filonovが開催するコースの無料のオープンウェビナーになります。 そして今、翻訳された資料に対するあなたのコメントを待っています。



All Articles