pandas のメンテナンス#

このガイドは pandas のメンテナー向けです。pandas の開発プロセスやメンテナーになるために必要な手順を理解したいコントリビューターにとっても興味深い内容かもしれません。

主なコントリビューションガイドはpandas へのコントリビューションで確認できます。

役割#

pandas は **トリアージ** と **コア** チームメンバーの2つの権限レベルを使用します。

トリアージメンバーは、イシューとプルリクエストにラベルを付けたり、閉じたりできます。

コアチームメンバーは、イシューとプルリクエストにラベルを付けたり、閉じたり、プルリクエストをマージしたりできます。

GitHub は権限の全リストを公開しています。

タスク#

pandas は主にボランティアプロジェクトであるため、これらのタスクはトリアージやメンテナーの「期待」として読むべきではありません。むしろ、メンテナーであることの一般的な説明です。

  • 新規に提出されたイシューのトリアージ(イシューのトリアージを参照)

  • 新規にオープンされたプルリクエストのレビュー

  • 既存のイシューとプルリクエストの更新に対応

  • 停滞しているイシューとプルリクエストの議論と決定を推進

  • API 設計の質問に対して、一貫性と保守性を確保するための経験/知恵を提供

  • プロジェクト組織(開発者会議の開催/参加、pandas の代表)

https://matthewrocklin.com/blog/2019/05/18/maintainer は興味深い背景情報となるでしょう。

イシューのトリアージ#

トリアージは、コミュニティから報告されたイシューに対処するための重要な第一歩であり、部分的な貢献であっても pandas のメンテナンスに大いに役立ちます。以下のすべての手順が完了するまで、「Needs Triage」タグは削除しないでください。

ここでは、新規にオープンされたイシューをトリアージする典型的なワークフローを紹介します。

  1. イシューをオープンしてくれた報告者に感謝する

    イシュー・トラッカーは、多くの人にとって、ライブラリを使用するだけでなく、pandas プロジェクト自体との最初のやり取りとなります。そのため、私たちはそれが歓迎され、快適な体験であることを望んでいます。

  2. 必要な情報は提供されていますか?

    理想的には、報告者はイシューテンプレートに記入しますが、多くの人はそうしません。重要な情報(使用している pandas のバージョンなど)が欠落している場合は、遠慮なくそれを尋ね、「Needs info」ラベルをイシューに付けてください。報告はバグ報告と機能強化リクエストのガイドラインに従う必要があります。テンプレートに従っていない場合は、そのリンクを貼りたいと思うかもしれません。

    タイトルがイシューを正確に反映していることを確認してください。不明確な場合は、自分で編集してください。

  3. これは重複したイシューですか?

    私たちは多くのオープンイシューを抱えています。新しいイシューが明らかに重複している場合、新しいイシューに「Duplicate」とラベルを付け、元のイシューへのリンクを付けてイシューを閉じます。報告者には引き続き感謝し、元のイシューにコメントを寄せるよう促し、可能であれば修正を試みるよう勧めましょう。

    新しいイシューが、より良い、またはわずかに異なる例などの関連情報を提供している場合は、元のイシューにコメントとして、または元の投稿の編集として追加してください。

  4. イシューは最小限で再現可能ですか??

    バグ報告の場合、報告者には最小限の再現可能な例を提供してもらうようお願いしています。https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports には良い説明があります。例が再現不可能であるか、あるいは_明らかに_最小限ではない場合は、報告者に例を提供してもらうか、提供されたものを簡略化できるかどうか尋ねてください。最小限の再現可能な例を作成するのは大変な作業であることを認識してください。報告者が苦労している場合は、自分で作成して元の投稿に含めるように編集することができます。

    再現可能な例が提供できない場合は、「Needs info」ラベルを追加します。

    再現可能な例が提供されているが、簡略化できる点がある場合は、より簡潔な再現可能な例で元の投稿を編集します。

    イシューがメインブランチに存在し、すべての手順が完了するまで「Needs Triage」タグが付いていることを確認してください。メインブランチに存在することを確認したら、イシューにコメントを追加して、他の人が確認済みであることを知るようにしてください。

  5. これは明確に定義された機能リクエストですか?

    一般的に、pandas は、プルリクエストが作成される前に、イシューで新しい機能について議論し、設計することを好みます。提出者には、新しい機能の提案された API を含めるように促してください。完全な docstring を書かせることは、詳細を特定する良い方法です。

    新しい機能リクエストには「Needs Discussion」のタグを付けてください。提案が pandas の範囲内であるかどうかを決定する前に、複数の pandas メンテナーによる議論が必要になるためです。

  6. これは使い方に関する質問ですか?

    使い方に関する質問は、pandas タグを付けて StackOverflow で質問されることを推奨します。https://stackoverflow.com/questions/tagged/pandas

    簡単に答えられる場合は、関連するドキュメントセクションにリンクを貼り、今後この種の質問は StackOverflow で行うべきであることを伝え、イシューを閉じても構いません。

  7. どのようなラベルとマイルストーンを追加すべきですか?

    関連するラベルを適用します。これはある種の芸術であり、経験とともに身につくものです。同様のイシューを見て、どのようにラベルが付けられているかを感じ取ってください。

    イシューが明確に定義されており、修正が比較的単純であると思われる場合は、イシューに「Good first issue」のラベルを付けます。

    上記が完了したら、「needs triage」ラベルを忘れずに削除してください。

リグレッションの調査#

リグレッションとは、以前は動作していたコードを意図せずに壊してしまうバグのことです。リグレッションを調査する一般的な方法は、バグを導入した最初のコミットを見つけるgit bisectを使用することです。

例えば、ユーザーが pandas バージョン 1.5.0 では pd.Series([1, 1]).sum()3 を返し、バージョン 1.4.0 では 2 を返していたと報告したとします。まず、pandas ディレクトリ内に t.py というファイルを作成し、次の内容を記述します。

import pandas as pd
assert pd.Series([1, 1]).sum() == 2

そして、以下を実行します。

git bisect start
git bisect good v1.4.0
git bisect bad v1.5.0
git bisect run bash -c "python setup.py build_ext -j 4; python t.py"

これにより、動作を変更した最初のコミットが見つかります。C 拡張機能は各ステップで再構築する必要があるため、検索には時間がかかる場合があります。

bisect を終了し、現在のバージョンを再構築します。

git bisect reset
python setup.py build_ext -j 4

対応するイシューの下に調査結果を報告し、コミット作成者にメンションして意見を求めます。

上記の bisect run コマンドでは、t.py0 で終了した場合にコミットは良好とみなされ、それ以外の場合は不良とみなされます。例外を発生させることが目的の動作である場合は、適切な try/except ステートメントでコードを囲みます。GH 35685 にその他の例があります。

イシューのクローズ#

ここは慎重に:多くの人は、イシューをクローズすることを、会話が終了したと解釈します。動作がバグではないと判断された場合、または機能が範囲外であると判断された場合は、報告者に返信するか、自分でイシューをクローズする時間を与えるのが通常最善です。ただし、報告者が連絡を絶ってしまうこともあり、その場合は会話が途絶えた後にイシューをクローズします。イシューをクローズすべきだと考えられるが、完全に確信がない場合は、「closing candidate」ラベルを適用し、他のメンテナーが見てくれるのを待ちましょう。

プルリクエストのレビュー#

誰でもプルリクエストをレビューできます。通常のコントリビューター、トリアージ担当者、またはコアチームメンバーです。しかし、プルリクエストが準備が整ったときにマージできるのはコアチームメンバーだけです。

プルリクエストをレビューする際に確認すべき事項をいくつか示します。

  • テストは適切な場所にあるべきです: 密接に関連するテストと同じファイル内。

  • 新しい公開 API は doc/source/reference/ 内のどこかに含まれている必要があります。

  • 新規/変更された API は、docstring で versionadded または versionchanged ディレクティブを使用する必要があります。

  • ユーザー向け変更は、適切なファイルに whatsnew を含める必要があります。

  • 回帰テストは、# GH-1234 のように元の GitHub イシュー番号を参照する必要があります。

  • プルリクエストにはラベルが付けられ、適切なマイルストーンが割り当てられている必要があります(リグレッション修正と小さなバグ修正の場合は次のパッチリリース、それ以外の場合は次のマイナーマイルストーン)。

  • 変更は、当社のバージョンポリシーに準拠している必要があります。

バックポート#

pandas はポイントリリース (例: 1.4.3) をサポートしており、その目的は以下の通りです。

  1. 最初のマイナーバージョンリリースで導入された新機能のバグを修正します。

  • 例: 1.4 で新しい機能が追加され、バグが含まれていた場合、1.4.3 で修正を適用できます。

  1. 以前のいくつかのマイナーリリースで動作していたバグを修正します。バックポートが適切であるというコアチームメンバー間の合意があるべきです。

  • 例: 1.2 で動作していた機能が 1.3 以降動作しなくなった場合、1.4.3 で修正を適用できます。

pandas のマイナーリリースは GitHub ブランチに基づいているため(例: 1.4 のポイントリリースは 1.4.x ブランチに基づいています)、"バックポート" とは、プルリクエストの修正を main ブランチと次のポイントリリースに関連付けられた正しいマイナーブランチにマージすることを意味します。

デフォルトでは、プルリクエストが GitHub インターフェース内で次のポイントリリース・マイルストーンに割り当てられている場合、プルリクエストがマージされると @meeseeksdev ボットによってバックポート処理が自動的に行われるはずです。プルリクエストを正しいバージョンブランチにバックポートする新しいプルリクエストが作成されます。マージの競合により、手動でコードの競合に対処するプルリクエストを作成する必要がある場合もあります。

ボットが自動的にバックポートプロセスを開始しない場合は、マージされたプルリクエストに GitHub コメントを書き込んでバックポートをトリガーすることもできます。

@meeseeksdev backport version-branch

これにより、特定の変更をブランチにバックポートするワークフローがトリガーされます(例: @meeseeksdev backport 1.4.x)。

古いイシューの整理#

pandas のすべてのオープンイシューにはコストがかかります。オープンイシューは、重複を見つけるのを困難にし、pandas で何をする必要があるのかを知るのを難しくする可能性があります。とはいえ、イシューをクローズすること自体が目標ではありません。私たちの目標は、pandas を可能な限り最高の状態にすることであり、それはオープンイシューの品質を高く保つことで最もよく達成されます。

まれに、バグが修正されてもプルリクエストにイシューがリンクされていないことがあります。このような場合、「これは修正されましたが、テストが必要です」とコメントし、イシューに「Good First Issue」と「Needs Test」のラベルを付けます。

古いイシューがイシューテンプレートに従っていない場合は、元の投稿を編集して、最小限の例、実際の出力、および期待される出力を含めます。イシュー報告の統一性は重要です。

古いイシューに再現可能な例がない場合は、「Needs Info」というラベルを付け、提供するように依頼するか(可能であれば自分で作成するか)、合理的にすぐに提供されない場合は、イシューのクローズのポリシーに従ってクローズします。

古いプルリクエストの整理#

時折、コントリビューターがプルリクエストを完了できないことがあります。変更を要求する最後のレビューからしばらく(例えば2週間)経っている場合、まだ作業に興味があるかどうか優しく尋ねてください。さらに2週間ほど返信がない場合は、彼らの作業に感謝し、以下のいずれかの対応をしてください。

  • プルリクエストをクローズする。

  • コントリビューターのブランチにプッシュして、彼らの作業を完成させる(pandas-core の一員である場合)。これは、重要な PR を完成させたり、小さなマージの競合を修正したりするのに役立つ場合があります。

プルリクエストをクローズする場合は、元のイシューに「#1234 で停滞しているPRがあり、役に立つかもしれません。」とコメントし、PRが比較的承認に近かった場合は、イシューに「Good first issue」のラベルを付けることを検討してください。

pandas メンテナーになる#

完全なプロセスは、当社のガバナンス文書に記載されています。要約すると、イシュートラッカーで役立つことで関心を示した人には、喜んでトリアージ権限を付与します。

メンテナーを追加するための必須手順は以下の通りです。

  1. コントリビューターに連絡し、参加の意向を尋ねます。

  2. 招待を受け入れた場合、コントリビューターを適切なGitHub チームに追加します。

  • pandas-core はコアチームメンバー向けです。

  • pandas-triage は pandas トリアージメンバー向けです。

pandas-core に追加する場合、さらに2つの手順があります。

  1. コントリビューターを pandas Google グループに追加します。

  2. コントリビューターの GitHub ハンドルを pandas-dev/pandas/web/pandas/config.yml に追加するためのプルリクエストを作成します。

現在のコアチームメンバーのリストはpandas-dev/pandasにあります。

プルリクエストのマージ#

プルリクエストをマージできるのはコアチームメンバーのみです。いくつかのガイドラインがあります。

  1. 通常、承認なしに自分のプルリクエストを自分でマージすべきではありません。CIを修正するための小さな変更(例:パッケージのバージョンを固定するなど)は例外です。変更に非常に自信がある場合、他のコアチームメンバーの承認があれば自分でマージしても問題ありません。

  2. 活発な議論があるプルリクエストや、コアメンテナーから -1 の票があるプルリクエストはマージすべきではありません。pandas は合意に基づいて運営されています。

  3. 大きな変更については、少なくとも2人のコアチームメンバーから +1 を得るのが良いでしょう。

イシューのクローズに記載されている項目に加えて、プルリクエストに正しいマイルストーンが割り当てられていることを確認する必要があります。

パッチリリース・マイルストーンでマージされたプルリクエストは、通常、ボットによってバックポートされます。ボットがマージに気づいたことを確認してください(通常、1分以内にコメントを残します)。手動でのバックポートが必要な場合は実行し、手動で実行したら「Needs backport」ラベルを削除してください。タグ付けする前にマイルストーンの割り当てを忘れた場合は、ボットに以下のコマンドでバックポートを要求できます。

@Meeseeksdev backport <branch>

ベンチマークマシン#

現在、チームは pandas の ASV パフォーマンスベンチマーク用のウェブサイトをホストするための専用ハードウェアを所有しています。結果はhttps://asv-runner.github.io/asv-collection/pandas/に公開されています。

構成#

マシンはtomaugspurger/asv-runnerにあるAnsibleプレイブックで設定できます。

公開#

結果は別の GitHub リポジトリ tomaugspurger/asv-collection に公開されます。最後に、ドキュメントサーバーに cron ジョブがあり、tomaugspurger/asv-collection からプルし、/speed から提供しています。ウェブサーバーへのアクセスについては Tom または Joris に問い合わせてください。

デバッグ#

ベンチマークは Airflow によってスケジュールされます。結果を表示およびデバッグするためのダッシュボードがあります。表示するには SSH トンネルを設定する必要があります。

ssh -L 8080:localhost:8080 pandas@panda.likescandy.com

リリースプロセス#

リリースプロセスでは、pandas のスナップショット(Git コミット)が特定のバージョン番号でユーザーに提供されます。リリース後、新しい pandas バージョンは以下の場所で利用可能になります。

pandas の新しいバージョンをリリースするプロセスは、次のセクションで詳しく説明します。

手順には <version> が含まれており、リリースするバージョン(例: 1.5.2)に置き換える必要があります。また、リリースするブランチ <branch> は、リリースするバージョンが新しいバージョンのリリース候補であるか、それ以外のバージョンであるかによって異なります。リリース候補は main からリリースされ、その他のバージョンはそれぞれのブランチ(例: 1.5.x)からリリースされます。

前提条件#

新しい pandas バージョンをリリースするためには、次の権限が必要です。

  • pandas および pandas-feedstock リポジトリへのマージ権限。後者については、GitHub ユーザー名を conda-forge レシピに追加する PR を開いてください。

  • 新しいタグをプッシュするための、pandas リポジトリの main へのプッシュ権限。

  • PyPI への書き込み権限.

  • 当社のウェブサイト / ドキュメンテーションサーバーへのアクセス。公開鍵をインフラ委員会と共有し、メインサーバーユーザーの authorized_keys ファイルに追加してもらってください。

  • アナウンスを公開するためのソーシャルメディアアカウントへのアクセス。

プレリリース#

  1. コアチームと次のトピックについて合意します。

    • リリース日(メジャー/マイナーリリースは通常6ヶ月ごと、パッチリリースはx.x.5まで毎月行われ、その直後に次のメジャー/マイナーリリースが行われます)

    • ブロッカー(リリースに含めるべきイシューとPR)

    • リリースするバージョンの次のバージョン

  2. リリースするバージョンのリリースノートを更新・整理します。これには以下が含まれます。

    • リリースの最終日を設定する

    • 使用されていない箇条書きを削除する

    • 書式設定の問題、誤字脱字などがないことを確認する。

  3. リリースするブランチの最後のコミットで CI がグリーンであることを確認します。

  4. リリース候補でない場合は、リリースするブランチへのすべてのバックポートプルリクエストがマージされていることを確認します。

  5. リリースするバージョンの次のバージョン用に、新しいイシューとマイルストーンを作成します。リリースがリリース候補だった場合、通常は次のメジャー/マイナーリリースと次のパッチリリースの両方について、イシューとマイルストーンを作成したいと考えます。パッチリリースのマイルストーンには、on-merge: backport to <branch> という説明を追加し、タグ付けされたPRがボットによってリリースブランチに自動的にバックポートされるようにします。

  6. リリースするマイルストーン内のすべてのイシューとPRのマイルストーンを次のマイルストーンに変更します。

リリース#

  1. リリースするブランチの最後のコミットで、空のコミットとタグを作成します。

    git checkout <branch>
    git pull --ff-only upstream <branch>
    git clean -xdf
    git commit --allow-empty --author="Pandas Development Team <[email protected]>" -m "RLS: <version>"
    git tag -a v<version> -m "Version <version>"  # NOTE that the tag is v1.5.2 with "v" not 1.5.2
    git push upstream <branch> --follow-tags
    

新しいバージョンのドキュメントは、タグがプッシュされるとトリガーされるCIのドキュメントジョブによって、自動的にビルドおよび公開されます。

  1. リリースがリリース候補の場合のみ、タグ作成直後に新しいブランチを作成します。例えば、pandas 1.4.0rc0 をリリースする場合、1.4 系へのコミットをバックポートするために 1.4.x ブランチを作成し、1.5.0 の開発開始を示すタグも作成します(次のバージョンであると仮定して)。

    git checkout -b 1.4.x
    git push upstream 1.4.x
    git checkout main
    git commit --allow-empty -m "Start 1.5.0"
    git tag -a v1.5.0.dev0 -m "DEV: Start 1.5.0"
    git push upstream main --follow-tags
    
  2. ホイールステージングエリアからソースディストリビューションとホイールをダウンロードします。ホイールが欠落していないか(例えば、ビルド失敗のためなど)注意して確認してください。

    scripts/download_wheels.sh を、ホイール/sdist をダウンロードしたいバージョンで実行すれば、うまくいきます。このスクリプトは、pandas のクローン内に dist フォルダを作成し、ダウンロードされたホイールと sdist をそこに配置します。

    scripts/download_wheels.sh <VERSION>
    
  3. 新しい GitHub リリースを作成します。

    • タグ: <version>

    • タイトル: Pandas <version>

    • 説明: 同じ種類(リリース候補、メジャー/マイナーまたはパッチリリース)の最後のリリースから説明をコピーします。

    • ファイル: 生成されたばかりの pandas-<version>.tar.gz ソースディストリビューション

    • プレリリースとして設定: リリース候補の場合のみチェック

    • 最新リリースとして設定: チェックを外さない限りチェックされたまま(古いバージョンのパッチリリースをリリースする場合を除く。例: 1.5 がリリースされた後に 1.4.5 をリリースする場合)

  4. PyPI にホイールをアップロード

    twine upload pandas/dist/pandas-<version>*.{whl,tar.gz} --skip-existing
    
  5. GitHub リリースは数時間後に自動化された conda-forge PR をトリガーします。(待ちたくない場合は、@conda-forge-admin, please update version というタイトルのイシューを開いてボットをトリガーできます。)CI がグリーンになったらマージし、conda-forge パッケージが生成されます。

    手動でPRを行う必要がある場合、通常、バージョン、sha256、およびビルドフィールドを変更する必要があります。最後のリリース以降、レシピの他の部分が変更されている場合は、それらの変更は ci/meta.yaml で利用できるはずです。

リリース後#

  1. 安定版ドキュメントへのシンボリックリンクを更新します。当社のウェブサーバーにログインし、メジャーおよびマイナーリリースの場合は /var/www/html/pandas-docs/stableversion/<latest-version> に、パッチリリースの場合は version/<minor>version/<patch> に変更します。具体的な手順は以下の通りです(例のバージョン番号をリリースするバージョンに適切なものに置き換えてください)。

    • サーバーにログインし、正しいユーザーを使用します。

    • cd /var/www/html/pandas-docs/

    • ln -sfn version/2.1 stable (メジャーまたはマイナーリリースの場合)

    • ln -sfn version/2.0.3 version/2.0 (パッチリリースの場合)

  2. メジャーまたはマイナーリリースをリリースする場合は、ソースコードに PR を開いて web/pandas/versions.json を更新し、ドキュメントのドロップダウンメニューに目的のバージョンを表示させます。

  3. リリースされたバージョンのマイルストーンとイシューをクローズします。

  4. 次のリリースのための新しいイシューを、推定リリース日とともに作成します。

  5. 次のバージョンのリリースノートのプレースホルダーを含む PR を開きます。例えば、1.5.3 の PR を参照してください。使用するテンプレートは、メジャー、マイナー、またはパッチリリースであるかによって異なることに注意してください。

  6. 公式チャネルで新しいリリースを発表します(以前のアナウンスを参照として使用してください)。

    • pandas-dev および pydata メーリングリスト

    • Twitter、Mastodon、Telegram、LinkedIn

  7. このリリース手順を更新し、誤りを修正し、前回のリリース以降の変更について更新します。