自作Pythonライブラリで、GitHub Actionsなどでのmypyでの型チェックは入れているのですが、追加でPyrightでのチェックも入れたいと思い検証してみたのでその備忘録です。
※普段はCI的に組み込んだりはしていないもののVS Code上でのPylance(内部でPyrightが使われています)での型チェックは使っていました。
※PyrightやPylanceとはなんぞや・・・という方はちょっと古いですが以前記事を書いているのでそれらをご確認ください。
そもそも何故今までmypyのようにCIに組み込んでいなかったのか
mypyはpipでさくっと入れることができます。一方でPyrightはPythonで書かれているわけではなくpipだけでさくっとインストールが効きませんでした(node.jsなど依存関係で色々考えたりが必要になったり等)。PythonライブラリのプロジェクトだったのでPyrightだけのために例外的にその辺りで必要なことが増えるのは微妙だな・・・と思い、今まではさくっと使えるmypyのみをCIに組み込んでPyrightはVS Code上でPylance経由でのみ使っていました。
しかしながら少し前に(マイクロソフト公式のものではありませんが)その辺りをpipのみで扱えるように楽にしてくれたライブラリが公開されていることを知りました。
該当のライブラリのページでも以下のように「その辺のインストール面倒だからpipだけで楽にしたかったんだ」的なことが書かれています。
Pyright is written in TypeScript and requires node to be installed and is normally installed with npm, this could be a barrier for entry for some python developers as they may not have node or npm, installed on their machine, I wanted to make pyright as easy to install as any normal python package.
ということでこちらを使って試していきます。
使う環境
自作のPythonライブラリでは最低サポートバージョンのPython3.6に合わせてローカルではpython:3.6.12-buster
をベースとしたイメージを使っていました(デプロイ時のチェックではGitHub Actions上でPython3.6~3.10まで一通りテストなどを通しています)。
自作ライブラリ:
以下のようなOSになっています(GitHub Actions上ではUbuntuで通っているのでUbuntuでもきっと問題無い・・・と思われます)。
$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
Pyrightをpipでインストールしてみる
pipだけでいけるようなので実際にpipで試してみます。
$ pip install pyright
...
Successfully installed nodeenv-1.6.0 pyright-0.0.13
特に何か引っかかることもなく、且つインストールもさくっと終わりました。依存関係としてnode関係のものも降ってきていることが分かります。
ヘルプの表示をしてみます。
$ pyright --help
* Install prebuilt node (17.3.0) ..... done.
Usage: pyright [options] files...
Options:
--createstub <IMPORT> Create type stub file(s) for import
--dependencies Emit import dependency information
-h,--help Show this help message
--ignoreexternal Ignore external imports for --verifytypes
--lib Use library code to infer types when stubs are missing
...
最初にInstall prebuilt node (17.3.0) ..... done.
といったような表示がされており、このインストールではぼちぼち時間がかかりました。どうやら初回のコマンド実行時に追加のインストールが動くようです。2回目以降はこの処理はスキップされています。
実際に動かしてみる
コマンドの詳細は以下のドキュメントに記載されています。
細かい点を調べたりは後で必要に応じてやるとして、ひとまずはオプション設定無しで実行してみます。
$ pyright
No configuration file found.
No pyproject.toml file found.
stubPath /mnt/apysc/typings is not a valid directory.
Assuming Python platform Linux
Searching for source files
Enumeration of workspace source files is taking longer than 10 seconds.
...
Found 786 source files
...
apysc/tests/_type/test_dictionary.py:180:17 - error: Argument of type "Literal['c']" cannot be assigned to parameter "key" of type "_K@Dictionary | ExpressionString" in function "__getitem__"
Type "Literal['c']" cannot be assigned to type "_K@Dictionary | ExpressionString"
Type "Literal['c']" cannot be assigned to type "_K@Dictionary"
"Literal['c']" is incompatible with "ExpressionString" (reportGeneralTypeIssues)
14 errors, 0 warnings, 0 infos
Completed in 41.781sec
ちゃんとチェックが通ってエラーなどが表示されました・・・!どうやら現在786モジュール存在して、且つPyrightで14件エラーで引っかかっているようです。普段からVS Code上でPylanceでチェックしていたおかげかモジュール数の割には新しいLintで引っかかる件数は比較的少な目なようです。また、処理時間もこのモジュール数にしては組み込んでも問題無さそうに思えます(GitHub AcitonsではLintやテストなどは並列実行しますし)。
後は発生しているエラーを直してGitHub Actionsにもチェックを組み込めば完了です!
mypyで引っかかるところがPylanceで引っかからなかったり、逆にmypy側で引っかからなかったり・・・といったことは微妙にあるのでこれで両方でチェックされるようになりよりデプロイされるコードで堅牢感が増してくれそうに思います。