public note

poetry publish コマンドで keyring の ModuleNotFoundError が起きたときの対応メモ

Poetry は依存するパッケージの管理だけでなく、PyPI に公開するのも簡単にできるのでとても便利です。

そんな中、poetry publish コマンドでエラーが発生するようになってしまいました。暫定対応により、現在は publish できています。そのときの対応メモが残っていたので、ブログに転記します。

keyring

github.com

The Python keyring library provides an easy way to access the system keyring service from python. It can be used in any application that needs safe password storage.

エラーメッセージ

poetry publish コマンドを実行したところ、以下のエラーメッセージが表示されました。

Error initializing plugin EntryPoint(name='libsecret', value='keyring.backends.libsecret', group='keyring.backends').
Traceback (most recent call last):
  File "/Users/tosh2230/.poetry/lib/poetry/_vendor/py3.8/keyring/backend.py", line 202, in _load_plugins
    init_func = ep.load()
  File "/Users/tosh2230/.pyenv/versions/3.8.11/lib/python3.8/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/Users/tosh2230/.pyenv/versions/3.8.11/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'keyring.backends.libsecret'

keyring リポジトリでは、keyring/backends/libsecret.py は v23.2.0 から存在しています。

環境

  • macOS Monterey 12.4
  • pyenv: keyring 23.5.0
  • python 3.8.11
  • Poetry version 1.1.13
  • Poetry: keyring 22.3.0

keyring のバージョンが pyenv と Poetry で異なっています...

pyenv: keyring/backends

(記録を残すのを忘れましたが、entry_points.txt から 23.5.0 であることは確認できたので、libsecret.py はあったと思われます)

pyenv: entry_points.txt

$ cat /Users/tosh2230/.pyenv/versions/3.8.11/envs/stairlight/lib/python3.8/site-packages/keyring-23.5.0.dist-info/entry_points.txt
[console_scripts]
keyring = keyring.cli:main

[devpi_client]
keyring = keyring.devpi_client

[keyring.backends]
KWallet = keyring.backends.kwallet
SecretService = keyring.backends.SecretService
Windows = keyring.backends.Windows
chainer = keyring.backends.chainer
libsecret = keyring.backends.libsecret
macOS = keyring.backends.macOS

poetry: keyring/backends

$ ls -l /Users/tosh2230/.poetry/lib/poetry/_vendor/py3.8/keyring/backends
total 104
-rw-r--r--  1 tosh2230  staff   222  2 11 06:31 OS_X.py
-rw-r--r--  1 tosh2230  staff  4739  2 11 06:31 SecretService.py
-rw-r--r--  1 tosh2230  staff  6514  2 11 06:31 Windows.py
-rw-r--r--  1 tosh2230  staff  9556  2 11 06:31 _OS_X_API.py
-rw-r--r--  1 tosh2230  staff     0  2 11 06:31 __init__.py
drwxr-xr-x  9 tosh2230  staff   288  5 27 20:11 __pycache__
-rw-r--r--  1 tosh2230  staff  2198  2 11 06:31 chainer.py
-rw-r--r--  1 tosh2230  staff   836  2 11 06:31 fail.py
-rw-r--r--  1 tosh2230  staff  5852  2 11 06:31 kwallet.py
drwxr-xr-x  5 tosh2230  staff   160  4 23 17:46 macOS
-rw-r--r--  1 tosh2230  staff   360  2 11 06:31 null.py

libsecret.py はないですね

poetry: entry_points.txt

$ cat /Users/tosh2230/.poetry/lib/poetry/_vendor/py3.8/keyring-22.3.0.dist-info/entry_points.txt
[console_scripts]
keyring = keyring.cli:main

[devpi_client]
keyring = keyring.devpi_client

[keyring.backends]
KWallet = keyring.backends.kwallet
SecretService = keyring.backends.SecretService
Windows = keyring.backends.Windows
chainer = keyring.backends.chainer
macOS = keyring.backends.macOS

ここでも libsecret は設定されていないです

keyring での backend 読み込み

backend の読み込みはこのあたりに実装されていますが、環境変数か設定ファイルがない場合は entry_points にしたがって keyring.backends 以下にあるモジュールをインポートする仕様になっていました。

エラーメッセージから libsecret を探しにいっているのがわかりますので、pyenv の entry_points をもとに poetry の keyring/backends を読みにいっているように思えます。

暫定対応

開発環境の状態に左右されないように、設定ファイルを配置しました。こうすれば keyring.backends.OS_X.py だけを読み込みますので、keyring のバージョンが異なることによるインポートエラーを回避できます。

$ cat ~/.config/python_keyring/keyringrc.cfg
[backend]
default-keyring=keyring.backends.OS_X.Keyring

次は、Poetry のソースコードを読んでみようと思います。

参考

github.com

github.com