mcpField
P
python-typing

python-typing

github.com/paldom開発253 回インストール7 週間前に更新
リポジトリ

python-typing について

Python パッケージに静的型チェックを導入するスキルです。新規プロジェクトやレガシーコードを扱うチーム向けに、チェッカーの選定、固定バージョンでの設定、段階的な厳格化、エラー対応、配布物内の型情報マーカーの検証を案内します。

主な機能

  1. 01主要な型チェッカーを一つ選定
  2. 02チェッカーを固定し pyproject.toml を設定
  3. 03例外を管理しながら段階的に厳格化
  4. 04型エラーと抑制コメントの対応
  5. 05ビルド成果物内の py.typed を検証

活用シーン

  1. 01新しい Python パッケージに型チェックを導入
  2. 02レガシーコードへ段階的にチェックを追加
  3. 03下流利用者向けにライブラリの型注釈を配布

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/paldom/python-skills --skill python-typing

インストール後、Claude Code で/python-typingを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
checker-selection.md
py-typed-distribution.md
strictness-ratchet.md
scripts/
check_py_typed.py

詳細

Python の型付け

チームが根拠を示せる厳格さの方針で、ユーザーの Python パッケージに静的型チェックを導入します。チェッカーは1つに絞ってバージョンを固定し、pyproject.toml で設定し、モジュールごとの例外設定は負債として追跡し、段階的に厳格化します。また、ライブラリの場合は、ビルドした wheel に py.typed マーカーが確実に含まれることを検証します。さらに、チェッカーが報告するエラーの修正方法も扱います。

使用しない場合

  • Ruff の lint または format の失敗。型注釈スタイルに関する ANN ルールも含みます。これらは型チェックではなく lint です(インストールされている場合は python-lint スキルを使用してください)。
  • テストスイートまたは pytest のセットアップの失敗(python-testing)。
  • 実行時の例外。実行時に発生した TypeError は、チェッカーの設定作業ではなく、バグとして直接デバッグしてください。
  • チェッカーを実行する CI ワークフローの YAML(python-ci)、または pre-commit の設定(python-precommit)。このスキルで動作するコマンドを、それらに引き継ぎます。
  • py.typed マーカーそのものを除く、パッケージのメタデータ、ビルドバックエンド、wheel のビルド(python-packaging)。

ワークフロー

1. 選択する前に調査する
  • レイアウト:src/ かフラットか、インポートするパッケージ名、ライブラリ(公開済みで利用者がいる)かアプリケーションか。
  • requires-python で指定された最低サポート Python バージョン。チェッカーは、実行中のインタープリターではなく、このバージョンを対象にする必要があります。
  • チェッカーの プラグイン が必要なフレームワーク依存関係:grep -E "django|sqlalchemy|pydantic" pyproject.toml。プラグインがあるのは mypy のみです。これにより、チェッカーの選択が決まることがあります。
  • 既存の設定([tool.mypy]、[tool.pyright]、mypy.ini、pyrightconfig.json)。黙って置き換えず、既存の設定を拡張してください。
  • 新規プロジェクトかレガシーコードベースか(おおよその型注釈の網羅率)。これにより、ステップ4で最初から厳格にするか、段階的に厳格化するかが決まります。
2. チェッカーを1つ選ぶ — 競争の行方はまだ決まっていません

型チェッカーの分野では、現在も競争が続いており、決着していません(mypy、pyright/basedpyright、ty、Pyrefly、zuban)。どれかを明らかな勝者として紹介せず、速度倍率や適合率も引用しないでください。出回っている数値は単一の情報源に基づき、一部は反証されています。妥当な選択基準は次のとおりです。

状況選択
Django(django-stubs)または Pydantic プラグインに依存するスタックmypy + フレームワークのプラグイン(SQLAlchemy 2.x はネイティブで型付けされています。mypy プラグインは非推奨で、mypy 1.10 で更新が停止しました)
プラグインが不要な新規プロジェクトで、チームが VS Code を使用pyright(standard、次に strict)
VS Code 以外のエディター(Neovim、Helix、Cursor)を使用する場合、またはより厳しいデフォルト設定が必要な場合basedpyright
uv/Ruff を使い、ベータ版の頻繁な変更を許容できる場合ty をローカルで試験導入し、CI ゲートには mypy または pyright を維持
数百万行規模のモノレポPyrefly を評価

CI ゲートとして使うプライマリチェッカーは1つに決めてください。 エディターで pyright(Pylance)を使い、CI では別のチェッカーを使うのは一般的です。一方、2つのチェッカーを ゲートとして 実行すると、抑制コメントを並行して管理する必要があります(注意点5)。詳細とトレードオフについては、references/checker-selection.md を参照してください。

3. バージョンを固定してインストールし、uv で実行する

バージョンを正確に固定してください。チェッカーのリリースでは新しい診断が定期的に追加されるため、バージョンを固定しないと、無関係な PR によって CI が失敗します。以下の固定バージョンは、PyPI にある最新リリースに置き換えてください。

uv add --dev "mypy==2.3.1"         # or: "pyright==1.1.413" (PyPI wrapper, bundles node)
uv run mypy src tests               # or: uv run pyright

uv を使わない場合(参考用、1回限り):python -m pip install "mypy==2.3.1" を実行してから、python -m mypy src tests を実行します。依存関係に手を加えずに ty を試験導入する場合は、uvx --from "ty==0.0.80" ty check src を実行してください(こちらも最新の固定バージョンに置き換えてください。ty はまだ 1.0 より前のバージョンです)。

4. pyproject.toml で設定する

mypy と pyright は異なるテーブルを参照するため、移行中に両方を共存させられます。mypy の場合、strict = true によって、型注釈のないコードも mypy のチェック対象になります(注意点1)。

[tool.mypy]
python_version = "3.10"          # lowest supported, from requires-python
strict = true
warn_unused_ignores = true
# plugins = ["pydantic.mypy"]    # only if pydantic is a dependency

[[tool.mypy.overrides]]
module = ["some_untyped_lib.*"]  # third-party deps that ship no types
ignore_missing_imports = true

pyright / basedpyright の場合(フォークでは [tool.basedpyright] を使用してください):

[tool.pyright]
include = ["src", "tests"]
exclude = ["**/legacy"]                # added on top of pyright's defaults (node_modules, __pycache__, .*)
typeCheckingMode = "standard"          # "strict" for new projects
pythonVersion = "3.10"

ty は pyproject.toml の [tool.ty](または ty.toml)を読み込みます。設定項目は少なく、ベータ版で変更される可能性があるため、古い例をそのまま信頼せず、uv run ty --help を確認してください。

5. 厳格さの設定 — 初日から厳格にするか、段階的に引き上げます。後から一斉に適用してはいけません
  • 新規プロジェクト:最初のコミットから strict = true / typeCheckingMode = "strict" にします。厳格さを後から適用すると、コントリビューターに負担がかかり、エラーが大量に発生します。
  • レガシーコードベース:段階的に引き上げます。グローバルでは厳格にしつつ、モジュールごとの例外を設け、例外は減らす一方にします。
[tool.mypy]
strict = true

[[tool.mypy.overrides]]
module = ["myapp.legacy.*"]      # exempt, migrate module-by-module
ignore_errors = true

pyright では、同等の設定として standard をベースに、厳格にチェックする範囲を指定する strict = ["src/myapp/core"] 配列を使います。両方のチェッカーにおける段階的な完全適用については、references/strictness-ratchet.md を参照してください。

  • チームが確認できる場所(CONTRIBUTING または README)に方針を記録します。選択したチェッカー、実行コマンド、例外は減らす一方にするというルールを記載してください。
6. py.typed を同梱し、wheel を検証します(ライブラリ)

py.typed マーカーがない場合、PEP 561 により、チェッカーはライブラリからのすべてのインポートを Any として扱います。ソースには型注釈があっても、利用者にはひそかに見えない状態になります。

touch src/<pkg>/py.typed

ビルドバックエンドによって、.py 以外のファイルをパッケージに含めるかどうかは異なります(setuptools では [tool.setuptools.package-data] が必要ですが、hatchling では通常含まれます)。そのため、ソースツリーを信用せず、アーティファクトを検証してください。

uv build
python3 "${CLAUDE_SKILL_DIR}/scripts/check_py_typed.py" --package <pkg>

このスクリプトは、ソースパッケージ、最新の wheel、または最新の sdist のいずれかに py.typed が含まれていない場合、ゼロ以外の値で終了します。バックエンドごとの設定とスタブ配布の選択肢については、references/py-typed-distribution.md を参照してください。

7. 報告されたエラーを修正します

次の順にトリアージします。

  1. まず実際のバグを修正します — Optional の誤用、戻り値の型の誤り、到達不能な分岐などです。これらこそ型チェックの成果なので、抑制しないでください。
  2. 型付けされていないサードパーティーのインポート — types-* のスタブパッケージが存在する場合はインストールし、バージョンを固定します(スタブのバージョンはライブラリとは別に管理します)。それでもだめな場合に限り、モジュール単位の ignore_missing_imports オーバーライドを使います。グローバルフラグは使わないでください。
  3. 実際に誤検出されたエラー — エラーコードを指定したコメントで抑制します。mypy では # type: ignore[arg-type]、pyright では # pyright: ignore[reportArgumentType] を使い、古くなった抑制コメントでビルドが失敗するように、warn_unused_ignores(mypy)/reportUnnecessaryTypeIgnoreComment(pyright)を有効にしておきます。
  4. グローバル設定を緩めてエラーを解決してはいけません。
8. 引き継ぎます

型チェックコマンドが契約となります。python-ci スキル(インストール済みの場合)がこれを CI ジョブにし、python-precommit がフックに組み込みます。これはこのスキルの役割ではありません。ローカルでコマンドが通るところまでで終了してください。

出力仕様

以下をすべて満たせば完了です。

  • プライマリチェッカーがちょうど 1 つで、開発依存関係にバージョンを固定して追加され、pyproject.toml で設定されている。
  • uv run <checker> ... が src(および、理由を明記して意図的に除外していない限り tests)に対して終了コード 0 で終了する。
  • 厳格さに関する方針が記録されている。厳格にするか、現在の段階と負債として追跡する例外リストを記録する。
  • ライブラリの場合:py.typed がパッケージに含まれ、さらに新しくビルドした wheel に対して scripts/check_py_typed.py が成功する。
  • すべての抑制コメントでエラーコードが指定されており、未使用の抑制の検出が有効になっている。
  • チームが確認できる場所に実行コマンドが記載されている。

失敗しやすい点と注意事項

  1. mypy がエラーなしでも、チェック済みとは限りません。 デフォルトでは mypy は型注釈のない関数本体をスキップするため、「エラーなし」の実行でも、コードベースの大半が無視されている可能性があります。エラーなしの実行結果を信頼する前に、check_untyped_defs = true(または strict)を設定してください。
  2. 全体への strict 設定とモジュールごとの緩和は両立しません。 どちらのツールにも長年の問題(mypy #11401、pyright #601)があり、モジュールごとに strict ルールをきれいに緩和することはできません。うまくいく方法は、全体に strict を設定してモジュールごとに ignore_errors(mypy)を使うか、standard をベースに、strict にするディレクトリを配列で指定する方法(pyright)です。
  3. pyright は mypy よりレガシーコードで多くのエラーを出します。 もともと型注釈のないコードもチェックしているため、いきなり strict にすると一度に大量のエラーが見つかります。既存のコードベースでは、まず standard から始めてください。
  4. ホイールに py.typed が含まれていないのは、典型的な見えにくい失敗です。マーカーファイルが git にはあるのに、バックエンドが成果物から除外してしまい、下流のユーザーには気付かれないまま Any が渡されます。ソースツリーではなく、ビルドしたホイールを必ず確認してください(手順 6)。
  5. チェッカーが 2 つあると、抑制も 2 種類必要です。 チェッカーの判定は一致しないため(kwargs の型付け、__new__ の型推論、ユニオン型の拡張など)、同じ行で # type: ignore[...] と # pyright: ignore[...] の両方が必要になることがあります。このコストを承知のうえで受け入れるか、ゲートを 1 つにしてください。
  6. strict の設定は互換性がありません。 mypy の strict、pyright の strict、basedpyright の「recommended」プリセット、ty/Pyrefly のルールは、それぞれ異なる契約です。あるチェッカーでエラーがゼロでも、ほかのチェッカーについては何も保証されません。
  7. Pydantic との摩擦。 チェッカーは before/wrap バリデーターの内部を確認できないため、検証前の入力型を使ってコンストラクターを呼び出すと、誤検知が発生します。トレードオフのある選択肢として、mypy と pydantic.mypy プラグインの併用、モデルモジュールに限定したルールの抑制、または(最先端の選択肢として)Pyrefly の実験的な Pydantic 統合があります。別の注意点として、静的解析で問題のないモデルでも、実行時の安全性が保証されるわけではありません。Pydantic は独自の strict モードを有効にしない限り、デフォルトで値を強制変換します("30" は 30 になります)。
  8. ty/Pyrefly の成熟度。 プラグインシステムがないため(Django/SQLAlchemy/Pydantic のプラグインスタックは移行できません)、ベータ版相当の仕様変更が頻繁にあり、pyright から移行すると、以前は検出できていた診断を見逃す可能性があります。ty の「段階的保証」(注釈の削除や緩和によって新たなエラーが発生することはなく、精度を上げると実際の問題が見つかる場合がある)により、段階的な試験導入には適しています。ただし、エディターやローカルで使うツールとしては適していますが、OSS パッケージの CI ゲートとして使うには時期尚早です。
  9. pyright の exclude は追加指定です。 カスタム項目はデフォルト(**/node_modules、**/__pycache__、**/.*)に追加され、デフォルトが優先されます。そのため、include に指定してもドットディレクトリを除外対象から外せません。代わりにコードを移動してください。
  10. Ruff は型チェッカーではありません。 Ruff の ANN ルールは型注釈のスタイルをチェックするもので、型エラーは一切検出しません。lint が通っても、型については何もわかりません。
  11. チェッカーのアップグレードでデフォルト設定が変わります。 mypy 2.0(2026-05)では、--local-partial-types と --strict-bytes がデフォルトで有効になり、--allow-redefinition のセマンティクスが変更され、--python-version 3.9 が削除され、実験的な並列チェック(--num-workers N)が追加されました。通常のバージョンアップでも CI が新たに失敗する可能性があります。そのため、手順 3 ではバージョンを正確に固定し、計画的にアップグレードします。

同梱リソース

  • references/checker-selection.md — 有力候補の概要、比較表、選定ガイド、エディターと CI を組み合わせるパターン。
  • references/strictness-ratchet.md — mypy と pyright の完全な設定例を含む、段階的な strict モードの導入。
  • references/py-typed-distribution.md — PEP 561 の配布方法、バックエンドごとのパッケージ設定、検証方法。
  • scripts/check_py_typed.py — ソースパッケージとビルド済みの wheel/sdist 成果物内に py.typed があることを確認します。読み取り専用で、失敗時はゼロ以外の終了コードを返します。

コメント