貢献#
私たちは貢献を心から歓迎し,このガイドがPyVistaコードリポジトリの理解を促進することを願っています.PyVistaソフトウェアパッケージはボランティアベースでメンテナンスされていることに注意してください.したがって,このソフトウェアをすべてのユーザにとって有用なツールにするために,ユーザの質問をサポートし,新しい機能を開発できるコミュニティを育成する必要があります.
このページでは,質問,懸念,機能のリクエスト,または貢献したいことから始めるべき概要を説明します.
尊敬の念を抱くこと#
他の人々,他のソフトウェア,そして(関連性のない)ツールを作るために熱心に働いてきたコミュニティに対して,共感と優しさを示してください.
Pull RequestsやIssuesなどで,他人やその作品を否定するような言い方をしないでください.
ソースリポジトリのクローン作成#
次のコマンドを実行して, pyvista/pyvista からソースリポジトリをクローンし,最新バージョンをインストールできます.
git clone https://github.com/pyvista/pyvista.git
cd pyvista
python -m pip install -e .
注釈
python -m pip install -e . --group dev を使って、開発に必要なパッケージもすべてインストールします。
Codespacesを使ったクイックスタート開発#
開発用コンテナが提供されており,すぐに使い始めることができます。デフォルトのコンテナには,リポジトリコードがお好みのブランチでチェックアウトされ,テスト依存関係を含むすべてのpyvista依存関係がプリインストールされています.さらに, desktop-lite feature を使用してライブインタラクションウィンドウを提供します.ライブインタラクションを使うには Connecting to the desktop の指示に従ってください.
また,OSMesaライブラリと vtk-osmesa を使用したオフスクリーンバージョンも利用できます.
質問#
プロジェクト,そのアプリケーション,またはソフトウェアの使用に関する一般的な質問については,コミュニティが共同であなたの質問に対処できる Discussions リポジトリにdiscussionを作成してください.
Slack に参加することも歓迎しますが,Slack は技術的な議論ではなく,その場限りの会話やコミュニティへの参加に使うべきです.
重要でハイレベルなプロジェクトサポートや関与については, info@pyvista.org まで電子メールをお送りください.
全ての技術的な会話については, issues ページ で議論を作成していただければ,すぐに対処いたします.ディスカッションのページに投稿することで,必要な専門知識を持つコミュニティメンバーが問題に対処でき,得られた情報は他のユーザーが見つけるのに引き続き利用できます.
バグの報告#
ここで配布されているコードの使用中にバグ,クラッシュ,または奇妙な点に遭遇した場合は,すぐに対処できるよう適切なラベルを付けて issues ページ に報告してください.問題を報告する際は,再現できるように,過度に記述してください.可能な限り,トレースバック,スクリーンショット,およびサンプルファイルを提供してください.
機能の要望#
PyVistaのコードベースを改善するためのアイデアを投稿することを推奨します. issuesページ に Feature Request ラベルをつけて改善を提案してください.説明的なタイトルを使用し,コミュニティがその機能を実装するのに役立つ十分な背景情報を提供してください.たとえば,特定のファイル形式のリーダーが必要な場合は,そのファイル形式のドキュメントへのリンクを提供し,操作するスクリーンショットを含むサンプルファイルを提供してください.問題のスレッドをディスカッションの場として使用し,フィードバックを提供します.
新しいコードの提供#
PyVistaを改善する方法についてアイデアがある場合は,まず機能リクエストとして問題を作成してください.これは,コントリビューションの実装方法を検討するためのスレッドとして使用できます.
PyVista用のコーディングと開発を始める準備ができたら,詳細については Development Practices セクションを参照してください.
ライセンス#
コントリビュートされたコードはすべて,リポジトリーにあるMITライセンスの下でライセンスされます.自分でコードを作成しなかった場合は,既存のライセンスに互換性があり,コントリビュートされたファイルに含まれていることを確認するか,元の作成者からコードを再ライセンスする許可を得る必要があります.
開発手法#
この節では,PyVistaリポジトリで開発を行う方法について説明します.このリポジトリに直接コントリビュートする場合は,ここで説明するプラクティスに従ってください.
ガイドライン#
配列への直接アクセスと直感的なPythonプロパティを介したVisualization Toolkit (VTK) への直接アクセスにより,VTKライブラリ全体をあらゆる分野の研究者が容易にアクセスできるようにしたいと考えています.PyVistaをVTKの価値あるPythonインターフェースにするためには,さらに改善するために皆さんの助けが必要です.
1つか2つの興味深い解析アルゴリズムをフィルタとして追加したい場合,新しいプロットルーチンを実装したい場合,あるいは1-2のタイプミスを修正したい場合,あなたの努力は大歓迎です.
私たちが信じている3つの一般的なコーディングパラダイムがあります.
直感的な操作. PyVistaの目標は,直感的で使いやすいインターフェースをVTKライブラリーに戻すことです.すべての新機能には,初心者ユーザがライブラリの大部分にアクセスできるように,直感的な命名規則と明示的なキーワード引数が必要です.
すべてをドキュメント化します .少なくとも,追加されたメソッドまたはクラスのdocstringを含めます.何をしているのかを説明するのではなく,なぜそうしているのかを説明し,新しい機能の簡単な例を示します.
テストを続ける. 高いテストカバレッジを目指します.詳細については, テストを参照してください.
著作権に関する2つの重要なガイドラインがあります.
ライセンスが利用できない,または商用使用が禁止されているデータセットは含めないでください.それらはすべてのプロジェクトのライセンスを損なう可能性があります.
ライセンスが利用できないコードスニペット(Stack Overflowなど )や商用使用が禁止されているコードスニペットは使用しないでください.それらはすべてのプロジェクトのライセンスを損なう可能性があります.
私達の Code of Conduct もご覧ください.
GitHub経由でPyVistaにコントリビュートする#
新しいコードをpyvistaに送信するには,まず pyvista GitHub リポジトリ をフォークし,フォークしたリポジトリをあなたのコンピュータにクローンします.次に,ローカルリポジトリの Branch Naming Conventions Section に基づいて新しいブランチを作成します.
次に,新しい機能を追加し,ローカルでコミットします.特に変更が複雑な場合は,過去のコミットに戻すことが役立つことが多いので,頻繁にコミットするようにしてください.また,頻繁に検査をしてください.テストの自動化については,以下の テストのセクション を参照してください.
コードをサブミットする準備ができたら, Creating a New Pull Request section の手順に従ってプルリクエストを作成します.
コーディングスタイル#
行幅が79文字を超えて99文字コードまで許されることを除き,可能な限り PEP 8 に準拠します.これは標準ではなく,むしろ例外となる傾向があるはずです.スタイルの不一致によるエネルギーの浪費を防ぐために, ruff format によって統一されたコードスタイルが強制されます.
一般に、関数のシグネチャでは、位置指定キーワードよりもキーワードのみの引数の方が好まれます ( PEP 3102 参照)。また、位置指定引数は、可能な限り1つか2つに制限すべきです。 ブール型引数は常にキーワードのみであるべきです。 これも ruff によって強制されます。
docstringに関しては,PyVistaは numpydoc スタイルに従っています. Docstrings を参照してください.
PEP 8以外でコーディングする場合は, PEP 20 - The Zen of Python を考慮してください.
import this
PyVistaは pre-commit を使用して,PEP8やその他のスタイルを自動的に強制します.詳しくは スタイルチェックのセクション を参照してください.
ドキュメンテーションスタイル#
PyVistaは,以下の例外を除き, Google Developer Documentation Style に従っています.
一人称の代名詞を許可します.これらの代名詞(例えば "We")は "PyVista Developers" を指し,PyVistaに貢献するすべての人を指すことができます.
未来形も可.
これらのルールはすべてのテキストファイル(例えば *.md, *.rst )に適用され,Pythonのソースファイルには部分的に適用されます.
これらのルールは,GitHub Actionsを介して Vale を使用することで強制され,Valeをローカルで実行することができます.
pip install vale
vale --config doc/.vale.ini doc pyvista examples ./*.rst --glob='!*{_build,AUTHORS.rst}*'
LinuxやmacOSであれば,実行可能です:
make docstyle
Docstrings#
PyVistaでは,Python docstringsを使用して,Python APIのリファレンスドキュメントを作成しています.Docstringsは,開発者や対話型のPythonユーザー,そしてオンラインドキュメントの読者に読まれます.このセクションでは,PyVista用のdocstringの書き方について説明します.
PyVistaはdocstringのスタイルとして numpydoc に従っています.以下を除き,すべて numpydoc Style Guide に従ってください.
すべてのパブリックメソッドの
ParametersとReturnsを必ず記述してください.Exampleのセクションを追加することを強くお勧めします.PyVistaは,ビジュアルなライブラリなので,プロットを示す例を追加することは,ユーザーが個々のメソッドが何を行うかを理解するのにとても役立ちます.
オプションのパラメータで,
Noneの代わりにデフォルト値がある場合は,optionalの代わりにdefault: <value>を使用します.
サンプル docstring は以下の通りです:
def slice_x(self, x=None, generate_triangles=False):
"""Create an orthogonal slice through the dataset in the X direction.
Parameters
----------
x : float, optional
The X location of the YZ slice. By default this will be the X center
of the dataset.
generate_triangles : bool, default: False
If this is enabled, the output will be all triangles. Otherwise the
output will consist of the intersection polygons.
Returns
-------
pyvista.PolyData
Sliced dataset.
Examples
--------
Slice the random hills dataset with one orthogonal plane.
>>> from pyvista import examples
>>> hills = examples.load_random_hills()
>>> slices = hills.slice_x(5, generate_triangles=False)
>>> slices.plot(line_width=5)
See :ref:`slice_example` for more examples using this filter.
"""
pass # implementation goes here
以下のことに注意してください:
generate_trianglesのパラメータ定義では,default: Falseを使用し, docstring の "description" セクションにデフォルトを含めません.各パラメータの間には改行が入ります.これは
numpydocのドキュメントで,パラメータの docstring の間に空白行がないのとは異なります.この docstring には,リターンセクションとサンプルセクションも含まれています.
関数の戻り値が1つの場合,リターンセクションにはパラメータ名を含めません.複数の戻り値(図示せず)には,入力パラメータと同じ形式で,各戻り値に対して説明的なパラメータ名を付ける必要があります.
サンプルセクションは,ギャラリーの "完全なサンプル" が存在する場合,それを参照します.
さらに、ランダムに生成されたデータを使用するdocstringの例は、再現可能でなければなりません。 詳しくは ランダムデータの生成 を参照のこと。
これらの標準は numpydoc-validate を使って pre-commit で実施され,エラーは次のように報告されます:
+-----------------+--------------------------+---------+-------------------------------------------------+
| file | item | check | description |
+=================+==========================+=========+=================================================+
| cells.py:85 | cells.create_mixed_cells | RT05 | Return value description should finish with "." |
+-----------------+--------------------------+---------+-------------------------------------------------+
| cells.py:85 | cells.create_mixed_cells | RT05 | Return value description should finish with "." |
+-----------------+--------------------------+---------+-------------------------------------------------+
| features.py:250 | features.merge | PR09 | Parameter "datasets" description should finish |
| | | | with "." |
+-----------------+--------------------------+---------+-------------------------------------------------+
もし,何らかの理由で関数のルールに例外を設ける必要がある場合は, pyproject.toml の [tool.numpydoc_validation] セクションに例外を追加するか,インラインコメントを追加して特定のチェックを除外してください.例えば、docstringから Return セクションを省略したり, __init__ のようなマジックメソッドのRT01チェックをスキップすることができます.
def __init__(self, foo): # numpydoc ignore=RT01
"""Initialize A Class."""
super().__init__()
self.foo = foo
numpydoc Validation で利用可能なバリデーションチェックを参照してください.
非推奨の機能またはその他の後方互換性のない変更#
PyVistaで後方互換性のない変更を実装するときは,ユーザーに新しい変更に適応する機会を与えるよう注意する必要があります.後方互換性のない変更は,次の手順で進める必要があります.
古い動作を保持し,使用すべき新しいインターフェイスを示す
PyVistaDeprecationWarningを発行します.古い動作を保持しますが,使用しなければならない新しいインターフェイスを示す
pyvista.core.errors.DeprecationErrorを発行します.古い動作を削除します.
可能な限り,PyVistaの開発者は,ユーザーがソフトウェアやスクリプトを更新できるように,少なくとも3つのマイナーバージョンの後方互換性を確保するように努めるべきです.
これはある関数のソフト非推奨の例です. PyVistaDeprecationWarning の警告と .. deprecated のSphinxディレクティブの両方を使用していることに注意してください.
import warnings
from pyvista.core.errors import PyVistaDeprecationWarning
def addition(a, b):
"""Add two numbers.
.. deprecated:: 0.37.0
Since PyVista 0.37.0, you can use :func:`pyvista.add` instead.
Parameters
----------
a : float
First term to add.
b : float
Second term to add.
Returns
-------
float
Sum of the two inputs.
"""
# deprecated 0.37.0, convert to error in 0.40.0, remove 0.41.0
warnings.warn(
'`addition` has been deprecated. Use pyvista.add instead',
PyVistaDeprecationWarning,
)
add(a, b)
def add(a, b):
"""Add two numbers."""
pass # implementation goes here
上記のコード例では,3つのマイナーリリースでエラーに変換し,次のマイナーリリースで完全に削除するためにコメントが作られていることに注目してください.重要な変更の場合はこれを長くし,些細な変更の場合は短くすることができます.
以下は,非推奨の警告メッセージを出すエラーテストコードを追加する例です.
with pytest.warns(PyVistaDeprecationWarning):
addition(a, b)
if pv._version.version_info[:2] > (0, 40):
raise RuntimeError("Convert error this function")
if pv._version.version_info[:2] > (0, 41):
raise RuntimeError("Remove this function")
上記のコード例では,古いテストコードはv0.40とv0.41でエラーを発生させます.これによって,バージョンアップ時に非推奨を削除し忘れることを防ぐことができます.
注釈
新しいバージョンをリリースする際には、バージョン番号を次の開発バージョンに更新する必要があります。 例えば、バージョン0.37.0をリリースする場合、次の開発バージョンは0.37.0より大きい0.38.0.dev0でなければなりません。 このため、テストコードではバージョンが0.40.0や0.41.0より大きいかどうかをチェックする必要があります。
既存のメソッドや関数に追加のパラメータを追加する場合には, .. versionadded というsphinxディレクティブを使用することが推奨されます.例えば:
def Cube(clean=True):
"""Create a cube.
Parameters
----------
clean : bool, default: True
Whether to clean the raw points of the mesh.
.. versionadded:: 0.33.0
"""
ブランチの命名規則#
開発を効率化するために,ブランチの命名には次の要件があります.これらの要件は,コア開発者がコードを調べる前に,あるブランチがどのような種類の変更を導入しているかを知るのに役立ちます.
fix/,patch/,bug/: マイナーなバグ修正,パッチ,または実験的な変更feat/: 新しい特徴または重要な追加を導入する変更junk/: 古くなったら削除できる実験的な変更についてmaint/とci/: リポジトリまたはCIルーチンの一般的な保守用doc/: 文書のみに関連する変更の場合no-ci/: CIルーチンをトリガーしてはならない影響の少ないアクティビティの場合testing/: テストの改善または変更release/: リリース(下記参照)breaking-change/: 後方互換性を破壊する変更
テスト#
変更を行った後,プルリクエストを作成する前にローカルで変更をテストしてください.コミットまたはプルリクエストの後に次のテストが実行されます.変更から新しい問題を追跡するには,ローカルで次の手順を実行してください.
PyVistaの包括的なユニットテスト群を実行するには、PyVistaをすべてのテスト依存パッケージとともにインストールします:
pip install -e . --group test
すべてをインストールしたら,さまざまなテストスイートを実行できます.
ユニットテスト#
プライマリテストスイートを実行し,カバレッジレポートを生成します.
python -m pytest -v --cov pyvista
ユニットテストには時間がかかることがあります.高速化したい場合は, n フラグでプロセッサの数を設定してください.これは pytest-xdist を使用して,複数のプロセスを利用するものです.使用例です.
python -m pytest -n <NUMCORE> --cov pyvista
PRを投稿する際には、すべての修正を徹底的にテストすることを強く推奨します。 これは、 codecov GitHub action が 90% という目標を設定することで、CI でさらに徹底されます。つまり、PR で修正されたコードの 90% がテストされるようになります。 ブランチカバレッジは CI 上で測定され、フルカバレッジを保証するためには if 節の両方の値をテストしなければならないことを意味します。 ブランチカバレッジの詳細については、 coverage documentation を参照してください。
必要であれば、 # pragma: no cover または # pragma: no branch のコメントを追加することで、特定の行のコードカバレッジを無効にすることができます。詳しくは excluding code を参照してください。しかし、コードカバレッジの除外はめったに使うべきでなく、簡単な代替案が見つからない場合は、PRスレッドで注意深く正当化しなければなりません。
CIは、vtkとの十分な互換性を確保するために、複数のvtkバージョンをテストするように構成されています。必要であれば、特定のテストが必要とする vtk の最小および/または最大のバージョンをカスタム pytest marker needs_vtk_version で制御することができます (包括的および排他的符号に注意):
@pytest.mark.needs_vtk_version(9, 1)
def test():
"""Test is skipped if pv.vtk_version_info < (9,1)"""
@pytest.mark.needs_vtk_version((9, 1))
def test():
"""Test is skipped if pv.vtk_version_info < (9,1)"""
@pytest.mark.needs_vtk_version(less_than=(9, 1))
def test():
"""Test is skipped if pv.vtk_version_info >= (9,1)"""
@pytest.mark.needs_vtk_version(at_least=(8, 2), less_than=(9, 1))
def test():
"""Test is skipped if pv.vtk_version_info >= (9,1) or pv.vtk_version_info < (8,2,0)"""
@pytest.mark.needs_vtk_version(less_than=(9, 1))
@pytest.mark.needs_vtk_version(8, 2)
def test():
"""Test is skipped if pv.vtk_version_info >= (9,1) or pv.vtk_version_info < (8,2,0)"""
@pytest.mark.needs_vtk_version(9, 1, reason='custom reason')
def test():
"""Test is skipped with a custom message"""
VTK Dev Wheelのテスト#
ほとんどのユニットテストは、安定したVTKリリースで実行されます。 しかし、最新のVTK開発用ホイールでテストを実行することは、時として有益です。 これらをローカルにインストールするには
pip install vtk --upgrade --pre --extra-index-url https://wheels.vtk.org
GitHub 上の CI では、vtk-dev-testing ラベルを使用することで、VTK dev wheel によるユニットテストを有効にすることができます。テストはラベルが貼られているときにのみ実行されます。
注釈
PRは、 main からブランチを更新するなどの新しいコミットが必要か、ラベルを適用してCIを再実行するためにクローズ/再オープンする必要があります。
Docstringテスト#
docstring内のすべてのコード例を実行します.
python -m pytest -v --doctest-modules pyvista
注釈
また、docstringによって生成された画像に対しても追加のテストが行われる。 詳しくは ドキュメント画像の回帰テスト を参照のこと。
スタイルチェック#
PyVistaは, コーディングスタイルのセクション で説明されているようにPEP8標準に従っており, pre-commit を使ってスタイルチェックを実装しています.
コードが最小限のコードスタイリング基準に適合していることを確認するために,以下を実行してください.
pip install pre-commit
pre-commit run --all-files
もし pre-commit をインストールする際に setuptools に関連する問題が発生した場合は, pre-commit Issue #2178 comment で解決できる可能性がありますので参照してください.
また,pre-commit hookとして次のように実行することでインストールすることもできます.
pre-commit install
こうすれば,スタイルチェックに失敗したコードをプッシュすることは不可能になります.例えば,各コミットでスタイル要件を満たしているかどうかが自動的にチェックされます:
$ pre-commit install
$ git commit -m "added my cool feature"
codespell................................................................Passed
ruff.....................................................................Passed
実際の環境のインストールは, pre-commit install に続く最初のコミットの前に行われます.これは少し時間がかかりますが,それ以降のコミットでは実際のスタイルチェックが行われるだけです.
上記の作業を実施していない,または実施できる状況であっても,プルリクエストに pre-commit.ci autofix とコメントすることで,手動で自動修正をトリガーすることができます.
イメージ回帰テストに関する注意事項#
PyVista は基本的に描画モジュールなので,何らかの回帰テストで生成した画像を実際にチェックする必要があります.実際には,これはかなりの作業になります.
OpenGLソフトウェアとハードウェアレンダリングでは,レンダリングされるイメージがわずかに異なります.
CI (仮想フレームバッファを使用します)をデスクトップイメージ(ハードウェアアクセラレーションを使用します)と一致させたいと考えています.
OSによってレンダリングされるイメージは異なります.
各プラットフォームと環境では,Linuxと比較してわずかに異なるイメージをレンダリングするため(これらの画像は),すべてのOSでこれらのテストを実行するのは最適ではありません.プロットを実際に見ることなく,プロットによって何か根本的な変化があったかどうかを知る必要があります(dev.pyvista.comのドキュメントのように).
これらの点に基づいて,イメージ回帰テストはLinux CIでのみ行われ,マルチサンプリングは,ソフトウェアベースのレンダリングとハードウェアベースのレンダリングの最大の違いの1つと思われるため,無効になっています.
画像キャッシュは ./tests/plotting/image_cache としてここに保存されます.
大きな画像でgitを汚したくないので,画像解像度は400x400で低く保たれます.バージョンや環境によって多少の違いがあることが予想されるため, error < IMAGE_REGRESSION_ERROR は許容されます(警告としてログに記録されます.)が,この値を超えるとエラーが発生します.
pytest には,画像リグレッションテストを制御する2つのメカニズム, --reset_image_cache と --ignore_image_cache があります.
pytest tests/plotting --reset_image_cache
--reset_image_cache を実行すると, tests/plotting/test_plotting.py の各テストに対して新しいイメージが作成されます.テストや,メジャーまたはマイナーリリースの可能性がある場合を除き,推奨されません.Linux上で実行していて,リグレッションテストを一時的に無視したい場合は, --ignore_image_cache を使用することができます.CIテストでは,回帰テストが引き続き行われることを理解してください.
現在のところ,画像は tests/plotting/test_plotting.py にあるテストからのみキャッシュされます. デフォルトでは, Plotter.show を使用するテストは,自動的に画像をキャッシュします. 画像のキャッシュをスキップするには, verify_image_cache フィクスチャを使用します.
def test_add_background_image_not_global(verify_image_cache):
verify_image_cache.skip = True # Turn off caching
plotter = pyvista.Plotter()
plotter.add_mesh(sphere)
plotter.show()
# Turn on caching for further plotting
verify_image_cache.skip = False
...
これにより,プロッタを閉じる直前に,現在のレンダリングウィンドウがCI内のイメージに対して検証されます.イメージが存在しない場合は,必ず次を使用して結果のイメージを追加してください.
git add tests/plotting/image_cache/*
ユニットテスト中に,画像のリグレッションに失敗して,ローカルに生成された画像をリグレッションテストスイートと比較したい場合, pytest-pyvista が --generated_image_dir フラグを使って新しい生成画像をすべてローカルディレクトリに書き込めるようにします.
例えば,以下は tests/plotting にある,関数名に volume が含まれるテストについて, pytest が生成したすべての画像を debug_images/ に書き込むものです.
pytest tests/plotting/ -k volume --generated_image_dir debug_images
詳しくは pytest-pyvista を参照してください.
注釈
追加の回帰テストもドキュメント画像に対して行われます。 詳しくは ドキュメント画像回帰テスト を参照してください。
入力検証テストに関する注意事項#
pyvista.core.validation パッケージには2つの異なるテストスイートがあり、 pytest で実行されます:
通常のユニットテストは
tests/core/test_validation.pyで行う。tests/core/typingのユニットテストをカスタマイズして、タイプヒントをテストできるようにしました。
カスタムユニットテストは、検証パッケージのタイプヒントが静的にも動的にも正しいことをチェックします。 これは主に validate_array や関連する関数の型ヒントのような、複雑でオーバーロードされた関数のシグネチャをチェックするために使用されます。
個々のテストケースは、1行のPythonコードとして記述されます:
reveal_type(arg) # EXPECTED_TYPE: "<T>"
ここで arg は mypy に解析させたい引数で、"<T>" は Mypy が返すと予想される型です。
例えば、 validate_array 関数は、デフォルトでは、入力に浮動小数点数のリストが与えられると、浮動小数点数のリストを返します。型ヒントはこれを反映する必要がある。 これをテストするために、 validate_array([1.0]) という関数呼び出しのテストケースを次のように書くことができます:
reveal_type(validate_array([1.0])) # EXPECTED_TYPE: "list[float]"
このテストで Mypy が返す実際の型は、以下のコマンドで生成できます。 grep は入力文字列からの出力のみを返す必要があることに注意してください。そうでない場合は、 pyvista パッケージのすべての Mypy エラーが報告されます。
mypy -c "from pyvista.core._validation import validate_array; reveal_type(validate_array([1.0]))" | grep \<string\>
このテストケースでは、 Mypy によって明らかにされた型は次のとおりです:
"builtins.list[builtins.float]"
明らかにされた型は完全修飾されています、つまり builtins を含んでいることに注意してください。 簡潔にするために、カスタムテストスイートではこれを省略し、 list だけが期待される型に含まれることを要求しています。 したがって、このテストケースでは EXPECTED_TYPE 型は "list[float]" であり、 "builtins.list[builtins.float]" ではありません。 (同様に、 numpy.ndarray が期待されるテストでは、パッケージ名 numpy も省略する必要があります。)
任意の数の関連するテストケース(1行に1つのテストケース)を記述し、1つの .py ファイルに含めることができます。 テストケースは全て tests/core/typing/validation_cases に格納されます。
テストは次のようにして実行することができます:
pytest tests/core/typing
実行されると Mypy のインスタンスが全てのテストケースを静的に解析します。 実際に Mypy によって明らかにされた型は、各テストケースで定義された EXPECTED_TYPE と比較されます。
さらに、 pyanalyze パッケージは、実行時に実際に返される型が静的に公開された型と一致するかどうかをテストします。 これには pyanalyze.runtime.get_compatibility_error メソッドが使用されます。 新しい検証関数のために新しいタイピングテストケースが追加された場合、新しい関数は tests/core/typing/test_validation_typing.py のインポートリストに追加されなければなりません。
ドキュメントの作成#
ドキュメントの依存関係をインストールします:
python -m pip install -e . --group docs
LinuxまたはMac OSでドキュメントをビルドします.
make -C doc html
Windows でドキュメントをビルドします.
cd doc
python -msphinx -M html source _build
python -msphinx -M html . _build
生成されたドキュメントは doc/_build/html ディレクトリにあります.
最初にローカルでドキュメントをビルドするときは,すべてのサンプルをビルドする必要があるため,しばらく時間がかかるでしょう.最初のビルドの後は,ドキュメントの作成にかかる時間はほんのわずかなものになるはずです.
これをローカルでテストするには、httpサーバーをのhtmlディレクトリで実行する必要があります:
make serve-html
ローカルビルドのクリア#
ローカルにビルドしたドキュメントをクリアする必要がある場合は,実行してください.
make -C doc clean
これは,ギャラリーの例を含むすべてをクリアします.もしギャラリーのサンプル以外をクリアしたいだけなら,実行します.
make -C doc clean-except-examples
これにより,すべてのサンプルを強制的に再構築することなく,キャッシュをクリアすることができます.
ドキュメントの並列ビルド#
以下でLinuxやMac OSでのドキュメントのビルド時間を改善することができます.
make -C doc phtml
これは効果的に SPHINXOPTS=-j を呼び出し,特にマルチコアコンピュータで有用です.
ドキュメント画像回帰テスト#
画像のリグレッションテストは、公開されているすべてのドキュメント画像に対して実施されます。文書が作成されると、生成された画像はすべて自動的に以下に保存されます
ビルド画像ディレクトリ:
./doc/_build/html/_images
回帰テストでは、生成された画像と以下に保存されている画像を比較します
ドキュメント画像キャッシュ:
./tests/doc/doc_image_cache
すべての画像をテストするには、pytest を実行します:
pytest tests/doc/tst_doc_build.py::test_static_images
テストはこのコマンドで明示的に実行する必要があります。 テストファイル名の先頭に tst をつけるのは、特に pytest によって自動的に実行されないようにするためです (pytest はデフォルトで test を先頭に持つすべてのテストを収集します)。これはテストがドキュメントのビルドを必要とし、テストの主要な形式ではないからです。
実行されると、テストはまずビルド画像を前処理します。 その画像は:
Build Image Directoryから収集されます。最大400x400ピクセルにリサイズ。
./_doc_debug_imagesにJPEG画像としてフラットディレクトリに保存されます。
次に、 ./_doc_debug_images にある前処理済みの画像と Doc Image Cache にあるキャッシュ画像を pyvista.compare_images() を使って比較します。
テストは3つの方法で失敗する可能性があります。失敗したテストの画像を簡単に見直せるように、画像のコピーは以下のように作成されます;
2つの画像の比較に失敗した場合:
キャッシュ画像は
./_doc_debug_images_failed/errors/from_cacheにコピーされます。ビルド画像は
./_doc_debug_images_failed/errors/from_buildにコピーされます。
画像がキャッシュにあるが、ビルドにない場合:
キャッシュ画像は
./_doc_debug_images_failed/errors/from_cacheにコピーされます。
画像はビルド内にあるが、キャッシュにない場合:
ビルド画像は
./_doc_debug_images_failed/errors/from_buildにコピーされます。
エラーの代わりに警告が発生した場合、画像は errors の代わりに warnings サブディレクトリに保存されます。
失敗したテストを解決するために、from_build または from_cache にある画像を Doc Image Cache にコピーしたり、Doc Image Cache から削除したりすることができます。 例えば、新しいdocstringの例やプロットを追加する場合、最初はテストが失敗し、 from_build にある画像が Doc Image Cache に追加されます。 同様に、例題を削除する場合、 from_cache の画像は Doc Image Cache から削除されます。
テストが不安定な場合、例えばビルドが同じプロットに対して異なるイメージを生成することがある場合、複数のバージョンのイメージは flaky test ディレクトリ ./tests/doc/flaky_tests に保存することができます。 テストイメージと同じ名前のフォルダを作成し、すべてのバージョンのイメージをこのディレクトリに保存する必要があります。 このテストでは、まずビルドイメージを通常通り Doc Image Cache にあるキャッシュイメージと比較します。 この比較が失敗した場合、ビルド画像は flaky test ディレクトリのすべての画像と比較されます。 いずれかの比較が成功すればテストは成功です、しかしサブディレクトリに保存されます。 flaky テストによって警告が発せられた場合、画像は warnings の代わりに flaky サブディレクトリに保存されます。
注釈
docイメージキャッシュに追加したり更新したりするために、ドキュメントイメージをローカルでビルドする必要はありません。 ドキュメントは CI テストの一環として自動的にビルドされ、(1) 前処理済みのビルドイメージと (2) 失敗したテストケースに対して成果物が生成されます。 これらの成果物は、GitHubからダウンロードして確認することができる。
アーティファクトと一緒に保存されたデバッグ画像は、ドキュメン画像をローカルでビルドする "simulate" にも使用できます。 画像をローカルの Build Image Directory にコピーすれば、あたかもドキュメントがすでにビルドされているかのように、ローカルでテストを実行してデバッグすることができます。
注釈
これらのテストは pyvista が生成するプロットが正しいことを保証するための 追加的な テストカバレッジを提供することを意図しており、テストの主要なソースとして使用すべきではありません。 最初に考慮すべきテスト方法については、 Docstring Testing と Notes Regarding Image Regression Testing を参照してください。
インタラクティブプロットテスト#
PyVista のドキュメントでは、カスタムディレクティブ pyvista-plot を使って、静的な画像と対話的なプロットファイルを生成しています。 インタラクティブなファイルは .vtksz という拡張子を持ち、高解像度のデータセットをプロットすると比較的大きくなります。
インタラクティブなプロットが不必要にドキュメントビルドのサイズを大きくしないように、 .vtksz ファイルのサイズに制限が設けられています。 インタラクティブなプロットがこの制限を超えないことをテストするには、以下を実行してください:
pytest tests/doc/tst_doc_build.py::test_interactive_plot_file_size
これらの(複数の)テストのいずれかが失敗した場合、プロットを生成したサンプルを修正する必要があります、例えば:
使用する(複数の)データセットを単純化します。例えば、クロップ、クリップ、ダウンサンプル、デシメートなど、プロットの複雑さを軽減します。
プロットを強制的に静的なものにします。 docstrings では、plot ディレクティブに
force_staticオプションを指定します、例えば:.. pyvista-plot:: :force_static: >>> import pyvista as pv >>> # Your example code here >>> # ... >>> mesh = pv.sphere() >>> mesh.plot()
sphinx galleryの使用例:
# sphinx_gallery_start_ignore PYVISTA_GALLERY_FORCE_STATIC_IN_DOCUMENT = True # sphinx_gallery_end_ignore
または
plot()やshow()を呼び出す前にPYVISTA_GALLERY_FORCE_STATICを使用すると、1つのプロットに対して静的描画を強制することができます。 詳細は 新しいギャラリーを追加する例 を参照してください。
注釈
プロットの複雑さを減らすことは、処理時間の短縮にもつながるので好ましいです。
参考
plot指示文によって生成された静的画像に対して行われたテストについては、 Documentation Image Regression Testing を参照してください。
CIドキュメントのビルドでキャッシュを制御する#
PRのドキュメントのビルド時間を短縮するために、GitHub上のCIではキャッシュされたsphinxギャラリー、サンプルデータ、sphinxビルドディレクトリが使用されています。 場合によっては、キャッシュが特定の PR に対して問題を引き起こすことがあります。 特定のPRのキャッシュを無効にするには、以下のラベルのいずれかをPRに適用します。
no-example-data-cacheno-gallery-cacheno-sphinx-build-cache
PRは、 main からブランチを更新するなどの新しいコミットが必要か、ラベルを適用してCIを再実行するためにクローズ/再オープンする必要があります。
ドキュメンテーションへの貢献#
PyVistaのドキュメントは,3つのソースから作成されています:
pyvistaのクラス,関数,モジュールから, sphinx.ext.autodoc を使用して,Docstringを取得します.doc/からテストを再構築examples/からのギャラリー例
一般的な使い方やAPIの説明は doc/api と docstrings に記述してください. 完全なギャラリーのサンプルは examples に置いてください.
ランダムデータの生成#
すべての文書は再現可能でなければなりません。特に、ランダムデータを使用する文書や例は、毎回同じランダムデータが生成されるように適切にシードされるべきです。これにより、ユーザーはドキュメントのコードをコピーして、同じ結果とプロットをローカルに生成することができます。
NumPyの乱数生成器(RNG)を使用する場合は、スクリプトの最初にRNGを作成し、スクリプトの残りの部分でこのRNGを使用する必要があります。必ずシード値を含めてください。例えば、こうです:
import numpy as np
rng = np.random.default_rng(seed=0)
rng.random() # generate a floating point number between 0 and 1
詳細はScientific Pythonの NumPyの乱数生成器を使用するためのベストプラクティス を参照してください。
新しい例の追加#
PyVistaのサンプルには2つの形式があります.個々のメソッドの機能を示す基本的なコードスニペットと,1つまたは複数のコンセプトを表示する完全なギャラリーの例です. 小さなコードサンプルやスニペットは doc/api ディレクトリやドキュメント文字列に含まれています.一方,完全なギャラリーサンプルは,ダウンロード可能なスクリプトとして実行するために,このリポジトリのルートにある examples ディレクトリに含まれています.
本格的なスタンドアロンサンプルを追加するには,PyVista Repository のルートディレクトリにある examples ディレクトリに,該当するサブディレクトリのいずれかにあなたのサンプルを追加してください. もし,既存のディレクトリがあなたのサンプルのカテゴリと一致しない場合は,新しいディレクトリを作成し,新しいカテゴリを記述した README.txt を記述してください. さらに,これらのサンプルはsphinx gallery 拡張を使って作成されていますので, Sphinx-Gallery が定めるコーディングガイドラインに従ってください.
詳しくは 新しいギャラリーを追加する例 を参照してください.
新しいデータセットの追加#
もし取り上げたいデータセットがあったり,ギャラリーのサンプルの一部に含めたいデータセットがある場合は,それを pyvista/vtk-data に追加し,そこにある指示に従ってください.それから, pyvista/examples/downloads.py にデータセットをダウンロードするための新しい関数を追加する必要があります.これは以下のように簡単です.
def download_my_new_mesh(load=True):
"""Download my new mesh."""
return _download_dataset(_dataset_my_new_mesh, load=load)
_dataset_my_new_mesh = _SingleFileDownloadableDatasetLoader(
'mydata/my_new_mesh.vtk'
)
データセットのロードに使用するオブジェクト _dataset_my_new_mesh を(モジュールスコープ付き)関数の外側で定義し、新しい download_my_new_mesh 関数はこのオブジェクトを使用してデータセットのダウンロードとロードを行う必要があります。データセットローダー変数は _dataset_ で始まる必要がある。
これにより以下が有効になります:
>>> from pyvista import examples
>>> dataset = examples.download_my_new_mesh()
複数のファイルを持つ複雑なデータセットをロードする場合や、特別な処理を必要とする場合は、適切なデータセットローダーを作成するための詳細については、プライベートな pyvista/examples/_dataset_loader.py モジュールを参照してください。
このようにデータセットローダーを使うことで、新しいデータセットのメタデータを収集することができます。 My New Mesh Dataset というタイトルの新しいデータセットカードが自動的に生成され、 データセットギャラリー に含まれます。
新しい download_my_new_mesh 関数の docstring には、次のように記述してください。
examplesセクションにあるデータセットのプロット例
See alsoセクションにあるデータセットの新しい(自動生成された)ギャラリーカードへの参照リンク
例えば:
def download_my_new_mesh(load=True):
"""Download my new mesh.
Examples
--------
>>> from pyvista import examples
>>> dataset = examples.download_my_new_mesh()
>>> dataset.plot()
.. seealso::
:ref:`My New Mesh Dataset <my_new_mesh_dataset>`
See this dataset in the Dataset Gallery for more info.
"""
注釈
numpydoc が明示的な参照を解析する方法に制限があるため、 See Also の代わりに seealso ディレクティブを使用する必要があります。
データセットギャラリーを拡張する#
関連するデータセットが複数ある場合や、似たようなプロパティを持つ既存のデータセットをグループ化したい場合は、 データセットギャラリー を拡張することで、これらのデータセットを新しい card carousel に表示することができます。
例えば、 カテゴリ別にデータセットをブラウズする に新しい Instrument データセットカテゴリを追加して、楽器のデータセットを2つ並べるには、次のようにします。
以下のステップを完了します:
doc/source/make_tables.pyで新しいカルーセルを定義します、例えば:class InstrumentCarousel(DatasetGalleryCarousel): """Class to generate a carousel of instrument dataset cards.""" name = 'instrument_carousel' doc = 'Instrument datasets.' badge = CategoryBadge('Instrument', ref='instrument_gallery') @classmethod def fetch_dataset_names(cls): return sorted( ( 'guitar', 'trumpet', ) )
ここで
nameはカルーセル用に生成される.rstファイルの名前を定義するために内部的に使用される。docはカルーセルの上のヘッダーにあるドキュメントに表示されるカルーセルの短い説明です。badgeはカルーセル内の全てのデータセットに参照タグを付与します。バッジの引数refには新しい参照先を指定する必要があります(詳細は後述します) 。fetch_dataset_namesは、カルーセルに含めるデータセット名のリストを返す。データセット名にはload_、download_、dataset_の接頭辞をつけてはならない。
新しいカルーセルクラスを
doc/source/make_tables.pyで定義したCAROUSEL_LIST変数に追加します。これにより、カルーセルの rst が自動生成されるようになります。doc/source/api/examples/dataset_gallery.rstファイルを更新して、新しく生成された<name>_carousel.rstファイルを含めます。例えば、カルーセルを新しいドロップダウン項目として追加するには、以下を追加します:... dropdown:: Instrument Datasets :name: instrument_gallery .. include:: /api/examples/dataset-gallery/instrument_carousel.rst
ここで:
ドロップダウン名
:name: <reference>は、先ほど定義したバッジのref変数でなければなりません。これにより、新しいバッジをクリックすると、新しいドロップダウンメニューにリンクするようになります。インクルードされた
.rstファイルの名前は、新しいCarouselクラスで定義されたname変数と一致する必要があります。
ドキュメントをビルドしたら、カルーセルがギャラリーの一部になるはずです。
新規Pull Requestの作成#
ブランチをローカルでテストしたら,mainにマージする際に pyvista GitHub でpull requestを作成します.これにより,継続的インテグレーション (CI) テストが自動的に実行され,変更が複数のプラットフォームで機能することが検証されます.
他のユーザーがコードをレビューできるようにするには,pyvistaコントリビュータグループの他の少なくとも1人のメンバーが,コードがコミュニティの標準を満たしているかどうかをレビューして検証する必要があります.承認後,書き込み権限があればブランチをマージすることができます.書き込みパーミッションがない場合,レビュー担当者または書き込みパーミッションを持つ別のユーザーがブランチをマージし,PRブランチを削除します.
ブランチをカレントリリースブランチ(下記参照)とマージする必要があるかもしれませんので, fix/ ブランチであれば削除しないでください.
ドキュメントをプレビューする#
pyvistaのメインリポジトリからのブランチのPRの場合、ドキュメントは自動的に Netifly GitHub actions を使ってデプロイされます。 しかし、フォークからPRを提出する新しい貢献者は、ドキュメントのビルドの非対話的なサブセットを含む軽量のドキュメントCI成果物をダウンロードすることができます。 これは通常500Mbの重さで、Build Documentation CIジョブの Upload non-interactive HTML documentation ステップから利用できます。
ブランチモデル#
このプロジェクトは,安定性を犠牲にすることなく機能の迅速な開発を可能にする分岐モデルを持っており, Trunk Based Development アプローチに厳密に従います.
ブランチモデルの主な特徴は次のとおりです.
mainブランチは主要な開発ブランチです.すべてのフィーチャー,パッチ,およびその他のブランチをここにマージする必要があります.すべてのPRは適用可能なCIチェックをすべてパスする必要がありますが,変更によって予期しない副作用や単体テストで検出されなかったバグが発生する可能性があるため,このブランチは機能的に不安定になる可能性があります.マイナーリリース(例えば
release/0.24)をベースにしたrelease/ブランチがいくつかあり,そこには PyPI/ にも反映される安定版のコードベースが含まれています.fix/ブランチの修正パッチは,mainブランチとこれらのブランチの両方にマージする必要があります.新しいパッチリリースを作成する必要がある場合,これらのリリースブランチのpyvista/_version.pyが更新され,セマンティックバージョン(例えばv0.24.1)がタグ付けされます.これによりCIはPyPIにプッシュし,テストされていない機能を気にすることなく,過去のバージョンのpyvistaのホットフィックスを迅速にプッシュすることができます.マイナーリリース候補が準備できたら,
mainから新しいreleaseブランチが作成され,次のマイナーバージョン(例えばrelease/0.25)がインクリメントされ,徹底的にテストされます.安定していると判断された場合,リリースブランチにはバージョン(この場合のv0.25.0)のタグが付けられ,必要に応じて変更が加えられた場合にはmainとマージされます.mainで機能開発が継続され,ホットフィックスはこのリリースに統合されます.必要に応じてパッチを適用できるように,古いリリースブランチは削除しないでください.
マイナーリリース手順#
マイナーリリースは, pyvista の機能と安定性を改善する機能およびバグリリースです.マイナーリリースが作成される前に,次のことが発生します.
mainブランチからrelease/MAJOR.MINORという名前の新しいブランチを作成します(例:release/0.25).pyvista/_version.pyの開発バージョン番号を更新し,コミットします(例:0, 26, 'dev0').ブランチをGitHubにプッシュし,mainにマージする今回のリリースの新しいPRを作成します.リリースに注力している間は,mainへの開発はこの時点では制限されるべきです.テストのセクション で概説されているように,すべてのテストをローカルで実行し,すべてが合格していることを確認します.
リンクが古くなっていないことを確認するために,リンクチェックを行いながらドキュメントをローカルにテストしてビルドします.また,
make cleanを実行して,結果がキャッシュされていないことを確認してください.cd doc make clean # deletes the sphinx-gallery cache make doctest-modules make html -b linkcheck
ドキュメントをビルドしたら,ローカル・ビルドを開き,サンプル・ギャラリーで明らかな問題がないか調べてください.
新しいリリースを機能的にテストするのは
pyvistaコミュニティの責任です.このブランチをローカルにインストールして運用環境で使用することをお勧めします.検出されたバグについては,ホットフィックスをこのリリースブランチにプッシュする必要があります.このブランチが安定版として一般公開されると,PR は main にマージされます.
release/MAJOR.MINORブランチのバージョン番号を更新した後,release/MAJOR.MINORブランチはvMAJOR.MINOR.0リリースというタグが付けられます.リリースブランチは削除されません.次のようにリリースにタグを付けます:git tag v$(python -c "import pyvista as pv; print(pv.__version__)")
タグが正しく作成されたことを再度確認し,ブランチとタグをプッシュしてください.
git push origin HEAD git push origin v$(python -c "import pyvista as pv; print(pv.__version__)")
リリースのすべての変更のリストを作成します. GitHub's compare feature を活用して,最後のタグや
mainブランチとの違いを確認することは,しばしば役に立ちます.特定の貢献者が新機能に感謝したい場合は,GitHubのユーザー名と適切な場所の記載で,新しい貢献者を必ず確認してください.前の手順のリリースノートを GitHubの新リリース の説明に入れてください.
ビール,コーヒー,水を飲みに行って, @regro-cf-autotick-bot がconda-forge PyVista feedstock のプルリクエストを開くのを待って,そのプルリクエストをマージします.
Discussions ページで新リリースを発表し,お祝いしましょう.
パッチリリース手順#
パッチリリースは重要なバグフィックスのためのもので,マイナーリリースまで待つことはできないものです.パッチリリースの手順は
必要な(複数の)バグフィックスを該当するリリースブランチにプッシュします.これは通常,最新のリリースブランチ(例
release/0.25)です.次のパッチ増分で
pyvista/_version.pyを更新し(例:v0.25.1),コミットし,リリースブランチとマージするPRをオープンします.これにより,pyvistaコミュニティはバグ修正リリースを検証し,承認する機会を得ます.追加のホットフィックスは,このPRの範囲外でなければなりません.承認されたら,リリースブランチとマージしますが,
mainブランチのバージョンを増やす理由がないため,mainとはマージしません.次に,リリースブランチから適切なバージョン番号(正しい手順については上記を参照してください.)のタグを作成します.必要に応じて,リリースノートページを作成します.また,condaからPRを開き,マイナーリリースセクションの手順10の指示に従います.
依存バージョンポリシー#
PythonとVTKの依存関係#
私たちは、サポートされているすべての Python バージョン と、それらの Python バージョンをサポートしている VTK バージョン をサポートしています。私たちは SPEC 0 に従いたいのですが、VTKのインターフェイスライブラリとして、VTKのバージョンに従います。