python について
コーディングエージェント向けの Python コーディング規約監査スキルです。ruff による検査と、境界、型、信頼性、運用、並行処理、テストの判断を組み合わせます。
主な機能
- 01ruff の lint・フォーマット検査
- 02境界とデータフローのレビュー
- 03公開契約と型の確認
- 04信頼性と運用の監査
- 05並行処理とテストの確認
活用シーン
- 01コミット前の Python 変更監査
- 02規約に沿ったコードレビュー
- 03lint の基本設定の導入
- 04検証や信頼性の方針選定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ahgraber/ skills --skill pythonインストール後、Claude Code で/pythonを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/design-boundaries.mdmulti-python-testing.mdpython-testing.mdscripts/test_pypi_security_audit.pytest_uv_security_audit.py詳細
Python ハウススタイル監査
概要
Python のハウススタイルを監査として捉えます。コードを書く際にルールブックを参照し続けるのではなく、対象(差分、ファイル、パッケージ、リポジトリ)を調べて違反を報告します。 監査は 2 つの層に分かれます。機械的なチェックは ruff に任せ、リンターでは表現できない判断が必要なチェックも行います。 最先端のコーディングエージェントはすでに適切な Python を書くため、以下のチェックは、確認する価値のある残りのハウススタイル上の好みに限定しています。
以下に示すデフォルトは、すべて望ましい出発点です。 デフォルトがプロジェクトの制約と相反する場合や、結果を悪化させる場合は、プロジェクトの方針に従い、トレードオフとそれを補う対策(テスト、可観測性、移行、ロールバック)を明記してください。
使用する場面
- Python の変更が完了し、コミットまたはリリースを控えている場合:仕上げの一環として差分を監査します。
- Python コードのレビュー、監査、健全性チェック、クリーンアップを依頼された場合、または標準に準拠しているか尋ねられた場合。
- 信頼性、構成、型付け/検証、境界、並行処理の方法を選ぶ場合:該当する tier 2 のセクションがハウスデフォルトです。
- Python の変更に必要な検証チェックを決める場合。
- プロジェクトに lint ポリシーがなく、新たに導入する必要がある場合(tier 1 がベースラインです)。
使用しない場面
- テストを書く場合 —
writing-testsを使用してください。Python 固有の内容は、そのreferences/python-testing.mdに記載されています。 - ノートブックのイベントループの仕組みを扱う場合 —
python-notebooks-asyncを使用してください。 - デモまたはチュートリアル用のノートブックを作成する場合 —
interactive-notebook-demoを使用してください。 - 差分のマージ可否を判定する場合 —
code-reviewを使用してください。このスキルでは、Python 固有の観点を提供します。
呼び出し時の通知
- このスキルの実行時は、ユーザーに
pythonと伝えてください。 ユーザーがスキル名またはスラッシュコマンドを指定した場合は、通知を省略します。表記やスペースは一致していなくてもかまいません。 このスキル独自のトリガー一覧にあるフレーズはスキル名ではありません。作業内容を名指ししても、スキル名を指定したことにはなりません。
共通のデフォルト
- プロジェクトで定義された Python バージョンを使用します。
- 環境と依存関係には
uvを使用し、チェックはuv run ...で実行します。 .ipynbが明示的に必要な場合を除き、.ipynbより#%%形式の.pyノートブックを優先します。- ローカルのポリシーを優先します。リポジトリの構成、リンターのルール、プロジェクトの慣習は、以下のすべてに優先します。
Tier 1 — 機械的な監査(ruff)
最終確認日:2026-08-18 — デフォルトルールの対象範囲とバージョンに関する注記を、https://docs.astral.sh/ruff/default-rules/ と ruff の変更履歴で再確認してください。
まず、プロジェクト独自の構成で実行します。
uv run ruff check .
uv run ruff format --check .
- ruff >= 0.16 では、幅広いデフォルトルールセット(413 ルール)が有効になります。bugbear、blind except、
try/except/pass、タイムゾーン情報のない datetime、非同期コードでのブロッキング呼び出しとタイムアウトの欠如、参照が残らないasyncio.create_task、未使用の async、ログ呼び出しの誤用が、すべて初期状態で機械的にチェックされます。 ruff がチェックする内容を手作業で監査しないでください。ruff を実行し、検出結果をルール ID とともに引用してください。 - プロジェクトで古い ruff のバージョンが固定されている場合、または
selectが制限されている場合は、ローカルのポリシーに従ってください。レビュー対象の変更に実質的な影響がある場合に限り、ハウスベースラインとの差を記載します。 - プロジェクトに lint ポリシーがない場合は、押し付けるのではなく、次の設定を出発点として提案してください。
[tool.ruff.lint]
extend-select = [
"ANN2", # missing return types on public functions
"ASYNC", # async hygiene beyond the default subset
"DTZ", # full naive-datetime coverage
"S113", # requests calls without timeout
"T20", # stray print in library/service code
"TRY", # exception design (raise/except hygiene)
]
ignore = ["TRY003"] # long messages in raise — noisy in practice
- ruff >= 0.16 は Markdown 内の Python コードブロックもフォーマットし、
ruff: ignore[rule-name]抑制コメントをサポートします。新たに抑制を追加する場合は、単独のnoqaコードよりもこちらを優先してください。 - 依存関係またはロックファイルを変更する場合は、対象プロジェクトのルートから、監査スクリプトをこのスキルの
scripts/内にあるフルパスで指定して実行してください:uv run pytest <path-to-this-skill>/scripts/test_uv_security_audit.py <path-to-this-skill>/scripts/test_pypi_security_audit.py -v。 どちらのスクリプトも検出事項を警告しますが、失敗にはしません。警告内容を確認してください。
Tier 2 — 判断を伴う監査
以下の各検出項目について、対象を調べてください。 これらは機械的にチェックできません。各検出事項について、ファイル名と行番号を示し、具体的な修正案を提示してください。 各項目では、確認する内容、問題となる理由、および解決に用いるハウスデフォルトを示します。
境界とデータフロー
このクラスの指摘に対する修正を提案する前に、これらのデフォルト設定の根拠と修正に関する詳しいガイダンスについて、references/design-boundaries.md を読んでください。
- コアのビジネスロジック内で、ファイルの入出力、環境変数の読み取り、時刻や乱数の取得が行われていないか確認します。 コアに埋め込まれた副作用があると、モックなしではロジックをテストできず、判断がインフラに依存します。 デフォルトでは、Functional Core / Imperative Shell を採用します。コアは入力に基づいて判断を計算し、シェルが副作用を実行します。
- 外部入力が検証される前にドメインロジックへ渡されていないか確認します。 コールスタックの深い位置でチェックを行うと、不正なデータがすでに広がった後になってしまいます。 境界で入力を検証・正規化すれば、その先では入力を信頼できます。
- ORM モデル、プロバイダー SDK の型、永続化スキーマがモジュール境界を越えていないか確認します。 境界を越えるものはすべて契約となり、内部型を渡すとスキーマ全体も引きずられます。 代わりに、必要最小限の DTO または値オブジェクトを共有します。
- モジュール境界をまたぐトランザクションがないか確認します。 共有トランザクションは各モジュールの障害モードを結び付け、誰も管理しないロールバックの複雑さを生みます。 モジュール間の処理はイベントやジョブを通じて調整し、デフォルトでは結果整合性を採用します。
- 先走った抽象化、深い継承、
utils/commonの何でも入れる場所がないか確認します。 2つ目の具体的な用途が現れる前に作られた抽象化は、たいてい適切ではありません。また、utils モジュールは誰も所有しないコードの置き場になります。 最小限のゴールデンパスを作り、コンポジションを優先します。
契約と型付け
このクラスの指摘に対する修正を提案する前に、これらのデフォルト設定の根拠と修正に関する詳しいガイダンスについて、references/design-boundaries.md を読んでください。
- 型指定がない、または
Anyと型付けされた公開関数がないか確認します。 公開シグネチャは契約です。型がなければ呼び出し側は推測することになり、リファクタリング時の安全策も失われます。 内部ヘルパーには、同じ厳密さは必要ありません。 - 関数が必要とするより具体的すぎる型の引数や、関数が実際に返す値より曖昧すぎる型の戻り値がないか確認します。
抽象インターフェース(
Mapping、Sequence、Protocolなど)を受け入れれば、呼び出し側が特定のコンテナー型を使わずに済みます。戻り値には具体的な型を指定し、呼び出し側が受け取る値を把握できるようにします。 - 内部のデータフローに pydantic モデルが組み込まれていないか確認します。
検証は境界で行うものです。あらゆる場所でモデルを使うとオーバーヘッドが増え、内部実装がスキーマ層に結び付きます。
pydantic は信頼境界、つまり API の入力、設定、外部データに限定し、新しいコードでは v2 API(
model_validate、model_dump)を使用します。 - 非推奨化、バージョン管理、移行に関する説明なしに公開契約を変更していないか確認します。 下流の利用者が気付かないまま壊れる可能性があります。 追加的な変更を優先します。意図的に互換性を破る場合は、移行計画も用意します。
信頼性ポリシー
- 明示的なタイムアウトが設定されていない外部 I/O と、期限が設定されていない長時間実行処理を探します。
ライブラリのデフォルト値は無制限、または任意であるため、障害発生時のレイテンシーが予測不能になります。
すべての外部 I/O に明示的なタイムアウトを設定し、レイヤーごとに相対タイムアウトを再計算するのではなく、絶対期限(
time.monotonic() + budget)をネストされた呼び出しに渡します。 - 無制限の再試行、複数レイヤーで重ねて行われる再試行、または恒久的な障害に対する再試行を探します。
無制限の再試行は単一の障害を再試行の嵐に変え、複数レイヤーでの再試行は試行回数を増幅し、検証エラーへの再試行は本当の修正を遅らせるだけです。
試行回数と全体の期限で再試行を制限し、ジッターを加えた指数バックオフを行い、
Retry-Afterを尊重し、再試行ロジックは厳密に 1 つのレイヤーに置きます。 - 冪等性が保証されていない、再試行される書き込みを探します。 曖昧な障害の後に再試行すると、書き込みが二重に適用される可能性があります。 冪等性キーまたは重複排除トークンを使うか、その操作の自動再試行を無効にします。
- 例外メッセージ文字列との照合で再試行可能かどうかを判定している箇所を探します。
メッセージのテキストは契約ではなく、予告なく変更されます。
エラー種別と
retryableフラグを使ったポリシーデータとして再試行可能性を表し、再試行可能な結果と恒久的な結果にはそれぞれ異なる終端状態を設けます。 - 不透明な成否だけを報告するバッチ操作を探します。 呼び出し元はどの項目が成功したか判断できないため、安全な復旧方法はすべての項目の再実行だけになります。 全件成功か全件失敗かが実際の契約でない限り、項目ごとの結果を返します。
ランタイムと運用
- 使用時点で遅延して設定を読み込む箇所を探します。
設定値の欠落や形式不正があると、起動時ではなく実行開始から数分、あるいは数時間後に発覚します。
型付き設定(例:
pydantic-settings)を読み込み、起動時に検証し、インポート時に設定関連の副作用が発生しないようにします。 - シグナル処理、上限時間のあるドレイン、または
try/finallyによるクリーンアップを備えていないシャットダウン経路を探します。 SIGTERM が処理されないとサブプロセスが孤立し、状態が不完全に書き込まれます。ドレインに上限時間がないと、再起動時にプロセスがハングします。 終了シグナルを処理し、新しい処理の受け付けを停止し、期限内に処理中の作業をドレインし、try/finallyでサブプロセス、一時ファイル、ハンドルをクリーンアップします。 - 終端状態が暗黙的になっているジョブを探します。 再試行回数を使い切った状態が保留中の作業として扱われると、失敗が見えなくなり、キューに未処理の項目がたまります。 再試行可能な結果と恒久的な結果を異なる状態として記録し、デッドレターに関するポリシーを明示します。
- 構造化されていない、または失敗ごとに複数回出力される失敗ログを探します。 重複する自由形式のログは、集計、フィルタリング、相関付けができません。 エントリーポイントで一度だけロギングを設定し、モジュールロガーを使い、操作 ID、フェーズ、試行回数を含めて意味のある境界で各失敗を一度だけ記録し、シークレットを含めないようにします。
- 依存関係を確認せずに OK を返すヘルスチェックまたはレディネスプローブを探します。 実態と異なるプローブは、それに依存するオーケストレーターから連鎖障害を隠してしまいます。
並行処理
- ワークロードに合っていない並行処理モデルを探します。
I/O の並列処理にスレッドを使うと、
asyncioなら避けられる同期処理のバグが増えます。一方、CPU バウンドの処理ではasyncioは役に立たず、プロセスが必要です。 ワークロードに応じてモデルを選び、明確な理由がある場合に限ってスレッドを使います。 - 無制限の並列処理、つまり制限のないコレクションに対する
gatherまたはsubmitを探します。 数千もの並行タスクは、イベントループを圧迫したり、メモリやファイルハンドルを使い果たしたりします。 セマフォまたはキューで並行処理数を制限します。 - 親を停止しても子が停止しない、またはクリーンアップを省略するキャンセル処理を探します。 孤立したタスクは接続を開いたままにし、プロセスが終了するまでリソースをリークさせます。 キャンセルを子タスクに伝播し、例外を再送出する前に子タスクのクリーンアップを待ちます。
- 実施前後の測定を行わないパフォーマンス改善を探します。 プロファイリングなしの最適化は間違った問題を解決し、その複雑さだけが残ります。 まず測定し、改善効果を確認するためにもう一度測定します。
テスト
Python 固有のテスト方法については、references/python-testing.md を参照してください。
- 契約で保証される値に複数の書き込み経路があるのに、正規の経路しかテストされていない箇所を探します。 重複排除のショートカットやキャッシュの高速経路によって、契約で求められる値が気付かないうちに欠落することがあります。 書き込み箇所ごとに独自のテストが必要です。また、派生フィールドの不変条件は、合成後の出力に対するテストが必要です。
- モックの呼び出し回数のアサーションが動作のアサーションの代わりになっている箇所、定義元ではなくインポート先に適用すべきパッチ、シグネチャの不整合を検出できる autospec ではなく単独の
Mock()が使われている箇所を探します。 これらはいずれも、動作が誤っているのにテストが通る原因になります。 - 回帰テストが先に失敗することを確認せずに実装されたバグ修正を探します。 一度も失敗しなかったテストでは、バグが解消されたことを証明できません。
報告
- ティア 1 はコマンドを実行して出力を引用し、ティア 2 の指摘はファイルと行番号、違反しているデフォルト、修正案を添えて報告します。
- 「チームのデフォルトに違反」と「このプロジェクト独自の規約に違反」を区別します。後者の優先度が高くなります。
- 依頼された場合、またはタスク自体がクリーンアップである場合にのみ、指摘箇所を修正します。それ以外の場合は報告します。
参考資料
references/design-boundaries.md— Functional Core / Imperative Shell、モジュールの所有権、境界の契約、pydantic の配置、契約の進化references/python-testing.md— Python 固有のテスト方法(writing-testsにも共有されています)references/multi-python-testing.md— nox + uv によるバージョンマトリックステスト