研究開発部 Architectグループ ML PlatformチームのKAZYこと新井です。ちなみに名古屋にある中部支店に所属です。
今回はPoetryでプライベートパッケージ(ライブラリ)を扱うテーマの第2弾です。
はじめに
2022/08/31に1.2.0がリリースされました。*1
Release 1.2.0 · python-poetry/poetry · GitHub
その中からプライベートパッケージに関係ありそうなところをピックアップして紹介します。*2
以前書いたGitHub/AWS CodeArtifact/GCP Artifact RegistoryでのPoetryを用いたプライベートパッケージ作成方法の記事を前提としていますので必要に応じてお読みいただければと思います。 buildersbox.corp-sansan.com
パッケージのソースをコマンドで追加/削除/参照ができるようになりました
デフォルトのインストールソース*3以外からのパッケージインストールするための設定をこれまではpyproject.tomlに手書きしなければなりませんでしたが、コマンドで追加や削除ができるようになりました。 AWS CodeArtifactやGCP Artifact Registryでプライベートリポジトリを使う場合は必要な操作なので覚えておくと良さそうです。
https://python-poetry.org/blog/announcing-poetry-1.2.0/#source-add
例えばURLがhttps://example.com/simple
のリポジトリをsample-repoという名前で登録する場合は以下コマンドで出来ます。 --secondary
*4や--default
*5といったオプションも用意されているので必要に応じて使い分けましょう。
$ poetry source add sample-repo https://example.com/simple/ Adding source with name sample-repo.
pyproject.tomlを見ると書き込まれています。
$ cat pyproject.toml ︙略 [[tool.poetry.source]] name = "sample-repo" url = "https://example.com/simple/" default = false secondary = false ︙略
コマンドで内容の確認や削除も出来ます。
# 書き込んだ内容の確認 $ poetry source show name : sample-repo url : https://example.com/simple/ default : no secondary : no # 削除 $ poetry source remove sample-repo Removing source with name sample-repo # 削除できたか確認 $ poetry source show No sources configured for this project.
GCP Artifact Registryのパッケージ作成が簡単にできるようになりました。
以前書いた記事でGCP Artifact Registryでの利用方法を当時正式にリリースされていなかったバージョン1.2で紹介していたのですが正式にリリースされました! *6
1リポジトリで複数のパッケージをGitHubで管理ができるようになりました。
以前は一つのリポジトリに複数パッケージを置いて管理することがうまくできませんでしたが、1.2からは追加する際のURLの末尾に#subdirectory
とパッケージへのパスを書くことでリポジトリのルートディレクトリ以外に存在するパッケージをインストールできるようになりました。
https://python-poetry.org/blog/announcing-poetry-1.2.0/#subdirectory-support-for-git-dependencies
具体例で示します。 例えば以下のようなpackage_a, package_bという2つのパッケージを含むリポジトリがあるとします。
$ mkdir my_github_repo $ poetry new my_github_repo/package_a $ poetry new my_github_repo/package_b $ tree my_github_repo my_github_repo/ ├── package_a │ ├── README.md │ ├── package_a │ │ └── __init__.py │ ├── pyproject.toml │ └── tests │ └── __init__.py └── package_b ├── README.md ├── package_b │ └── __init__.py ├── pyproject.toml └── tests └── __init__.py
このリポジトリからpackage_a, package_bそれぞれを以下のコマンドでインストールできるようになりました。 ブランチやタグも同時に指定できます。
# package_aをvX.X.Xのタグでインストール $ poetry add git+https://github.com/myorg/my_github_repo@vX.X.X#subdirectory=package_a # package_bデフォルトのブランチの最新でインストール $ poetry add git+https://github.com/myorg/my_github_repo#subdirectory=package_b
pyproject.tomlの中を見ればサブディレクトリ単位で管理ができているかが確認できます。
$ cat pyproject.toml ︙略 [tool.poetry.dependencies] package-a = {git = "https://github.com/myorg/my_github_repo", rev = "vX.X.X", subdirectory = "package_a"} package-b = {git = "https://github.com/myorg/my_github_repo", subdirectory = "package_b"} ︙
パブリッシュ時のコンフリクトエラーがスキップできるようになりました。
poetry publishに--skip-existing
というオプションが追加されました。
$ poetry publish --skip-existing
これまでは同じパッケージ名のパッケージ*7をパブリッシュすると以下のようなエラーを吐いて異常終了のステータスになっていました。
HTTP Error 409: Conflict | b"Asset 'package_a-0.4.0-py3-none-any.whl' already exists."
--skip-existing
オプションを利用すれば同じパッケージがコンフリクトしてもスキップして終了ステータスがエラーになりません。
Publishing package_a (v0.4.0) to private-repository - Uploading package_a-0.4.0-py3-none-any.whl 0% - Uploading package_a-0.4.0-py3-none-any.whl 100% - Uploading package_a-0.4.0-py3-none-any.whl File exists. Skipping - Uploading package_a-0.4.0.tar.gz 0% - Uploading package_a-0.4.0.tar.gz 100% - Uploading package_a-0.4.0.tar.gz File exists. Skipping # スキップしている
CI/CD周りの設定で自動でパブリッシュするようなフローを組んでいると、パッケージ本体のバージョンを変えないような更新を行った際に自動でCDが走って失敗してしまう事が起きていましたがこちらのオプションで気軽に避けることができますね。
パッケージのバージョンの更新忘れ等でコンフリクトが起きていてもCDが成功してしまい気が付かないといったことも起きてくると思うので、こちらのオプションを使うかは慎重になったほうが良さそうだと思いました。
おわりに
私の中ではGCPでもいい感じにPoetryでプライベートパッケージ管理ができるようになったことが嬉しいです。
アナウンス
求人
私の所属するML Platformチームを含む、研究開発部Architectグループでは一緒に働く仲間を募集しています。よろしくお願いします。
R&D MLOps/DevOpsエンジニア / Sansan株式会社
*1:2022/10現在の最新は1.2.1ですね。
*2:もっと見たい場合はこちらを御覧ください。https://python-poetry.org/blog/announcing-poetry-1.2.0/
*3:デフォルトはhttps://pypi.org/です。
*4:PyPIを優先させたい時に使います。
*5:プライベートレポジトリからのみパッケージを探したい時に使います。
*6:1.1系ではどうやって使えば良いのか正直よくわかりませんでした。
*7:内容が異なるかどうかは問題ではなくあくまでファイル名です