検索/大規模なPythonデータ処理システムを、遅延実行を壊さずに直す

大規模なPythonデータ処理システムを、遅延実行を壊さずに直す

並列計算などをする大きなPythonのデータ処理コードをAIに直させる時に使う。変更する層を先に調べ、グラフを組む途中で計算を走らせず、近いテストから順に確かめ、許可なしにリリースやパッケージの公開をしない。

このAIルールを使うには
## 頼まれた動作を、受け持つ層までたどってから直す 大規模なPythonデータ処理または並列計算のコードベースを変更する前に、リポジトリを無差別に読むのではなく、タスク固有の構成図を作る。 関係する層を特定する。 1. 公開コレクションまたは利用者向けインターフェース。 2. 計画と最適化に使うシンボリック式または高水準グラフ。 3. 具体化された低水準タスクと依存関係の辺。 4. スケジューラーまたは実行バックエンド。 5. 設定、ディスパッチ、シリアライズ、ユーティリティの各層。 要求された振る舞いを公開入口から、それを所有する最小の実装層まで追跡する。編集前に隣接するテストと設定を読む。 タスクに応じて移動先を選ぶ。 - スケジューリング動作: 公開計算API、グラフユーティリティ、タスク表現、スケジューラーアダプターの順に確認する。 - グラフ最適化: 高水準グラフのプロトコル、ブロック単位または式の層、具体化処理の順に確認する。 - 配列またはデータフレーム機能: コレクションAPI、演算実装、ディスパッチ、対象を絞ったテストの順に確認する。 - 設定変更: 実行時アクセサー、既定設定、スキーマ、文書を確認する。 - バックエンド対応: バックエンドインターフェース、エントリーポイント登録、ディスパッチ、互換性テストを確認する。 リポジトリの注記にあるモジュール名、行数、依存関係の版は、永続的な事実ではなく移動の手掛かりとして扱う。現在のソースとマニフェストをローカルで確認する。 サブシステムの境界を明確に保つ。公開コレクションの変更では、対応するメタデータ、グラフ、スケジューラー、テスト、文書の更新が必要になる場合があるが、無関係な層は編集しない。 ## リポジトリの環境を使い、一番小さいテスト範囲を選ぶ リポジトリで宣言された環境マネージャーとコマンドを使う。グローバルのPython環境が、対応する依存関係の組み合わせと一致するとは仮定しない。 実装前に次を行う。 1. プロジェクトのマニフェストと利用可能な環境を確認する。 2. 影響を受ける機能を代表する最小の環境を選ぶ。 3. 最も近い既存テスト、フィクスチャ、マーカー、アサーション用ヘルパーを探す。 4. 関係する省略可能な依存関係、機能フラグ、警告ポリシーを記録する。 次の実行には、リポジトリが提供するコマンドラッパーを優先する。 - 失敗する単一テスト。 - 影響を受けるモジュールのテストファイル。 - lintと静的検査。 - 公開例のdoctest。 - 最小依存環境または省略可能機能の環境。 - 変更に必要な場合だけ、より広いCI相当の検査。 警告をエラーとして扱う設定、厳密な想定失敗、タイムアウト、環境固有マーカーなど、厳格なテスト動作を守る。メタデータ、型、パーティション、数値許容差を考慮する遅延コレクション用の共通同等性ヘルパーを使う。 省略可能な依存関係には、場当たり的な条件分岐ではなく、プロジェクト所定のimportヘルパーとスキップ用ヘルパーを使う。新しいAPIを使う時は、対応する最小版と最新版の両方を考慮する。 タスクで許可されていない限り、パッケージのインストール、環境変更、ネットワーク依存テストの有効化を行わない。依存関係がない場合は、実行環境(マシン)を暗黙に変更せず、環境上の制約として報告する。 ## グラフを組む途中で`compute()`を呼ばず、遅延実行を守る 遅延グラフシステムの中心的な不変条件を守る。グラフ構築コードは、計算を実行せずに計算内容を記述しなければならない。 コレクション演算、グラフ層、シンボリック式を定義している最中に、`compute()`や`persist()`のような即時計算メソッドを呼び出してはならない。具体化は、明示的な利用者境界または実行境界で行う。 グラフ構築中は次を行う。 - 可能な限りメタデータから結果を推論する。 - タスクの依存関係を明示的かつ決定的に保つ。 - 安定したキーとトークン化の動作を維持する。 - 隠れた入出力やスケジューラー選択を避ける。 - シンボリック最適化と低水準実行を分離したままにする。 リポジトリの規約に従う。 - 新しいコードには完全な型ヒントを追加する。 - 互換性用importと遅延アノテーションの一貫性を保つ。 - 循環を避けるため、ガード付きの型専用importを使う。 - 標準ライブラリ、第三者、ローカルのimportを予測可能な順序で整理する。 - 公開APIには、文書化されたdocstring形式と実行可能な例を使う。 - 非公開ヘルパー、テスト、ディスパッチ関数には、確立された命名規則を使う。 バックエンド、式、層、設定項目を追加する場合は、必要なすべての登録箇所を更新し、ディスパッチまたは計画処理が新しい実装へ到達することを証明する対象限定テストを追加する。 import時の登録やクエリ計画に影響する機能フラグは、関係するモジュールが初めてimportされる前に設定しなければならない。有効と無効の両方を引き続き対応する場合は、両方の動作をテストする。 対象を絞った不具合を修正する際に、広範なリファクタリングを行わない。無関係な振る舞いを維持し、新しいテスト結果を説明できる最小の変更にする。 ## テストを近い所から広げ、許可なしにリリースしない 段階的に検証範囲を広げる。 1. 対象を絞ったテストで以前の失敗を再現する。 2. 最も近いテストファイルまたはサブシステムのテスト群を実行する。 3. 編集の直接影響を受けるlint、型、doctestの検査を実行する。 4. 関係する省略可能機能、最小依存関係、機能フラグの各構成を実際に実行する。 5. 変更が広いアーキテクチャ境界をまたぐ場合にだけ、全テスト群を使う。 よくある失敗要因を確認する。 - importの循環と登録順序。 - 最初のimport後に変更された機能フラグ。 - 計算結果と一致しないメタデータ。 - 一部のインタープリターで使えない省略可能パッケージ。 - 関連パッケージ間でずれた依存関係の固定版。 - スキーマにない設定の既定値。 - 動作しなくなったdoctestの例。 - 1つのスケジューラーまたはバックエンドでしか通らないテスト。 完了を報告する前に差分をレビューし、実際に実行した確認、合格した確認、未実行の確認を明示する。コードの目視確認だけから成功を推測しない。 リリース作業は別の権限境界である。明示的に許可されない限り、リリース作成、パッケージ公開、タグ送信、成果物のアップロード、外部リリースシステムの変更を決して行わない。 リリース準備が許可された場合は、外部状態を変更する前に、変更履歴の項目、版とパッケージ間の固定版、パッケージ成果物、リポジトリで文書化された手順を確認する。 他者との連絡を求められた場合は、利用者になりすましたり判断を捏造したりせず、証拠と選択肢を示す。