Poetryの操作に慣れていなかったこともあり、セットアップでエラーに遭遇しました。Poetryを触りはじめの頃には恐らくよくあるエラーのはずです。ここでは、発生したエラーとその解決方法について説明します。
発生したエラーについて
Poetryを触りはじめの人なら見覚えがあるかもしれません。
at ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/incompatibility.py:113 in __str__
109│ )
110│
111│ def __str__(self) -> str:
112│ if isinstance(self._cause, DependencyCause):
→ 113│ assert len(self._terms) == 2
114│
115│ depender = self._terms[0]
116│ dependee = self._terms[1]
117│ assert depender.is_positive()
ここだけ見ると分かりづらいので詳細まで広げます。
% poetry add openai -vvv
Creating new session for pypi.org
Source (PyPI): 68 packages found for openai *
Using version ^0.27.8 for openai
Updating dependencies
Resolving dependencies...
1: fact: openai is 0.1.0
1: derived: openai
1: Version solving took 0.001 seconds.
1: Tried 1 solutions.
Stack trace:
16 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:327 in run
325│
326│ try:
→ 327│ exit_code = self._run(io)
328│ except BrokenPipeError:
329│ # If we are piped to another process, it may close early and send a
15 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py:190 in _run
188│ self._load_plugins(io)
189│
→ 190│ exit_code: int = super()._run(io)
191│ return exit_code
192│
14 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:431 in _run
429│ io.input.interactive(interactive)
430│
→ 431│ exit_code = self._run_command(command, io)
432│ self._running_command = None
433│
13 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:473 in _run_command
471│
472│ if error is not None:
→ 473│ raise error
474│
475│ return terminate_event.exit_code
12 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:457 in _run_command
455│
456│ if command_event.command_should_run():
→ 457│ exit_code = command.run(io)
458│ else:
459│ exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED
11 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/base_command.py:119 in run
117│ io.input.validate()
118│
→ 119│ status_code = self.execute(io)
120│
121│ if status_code is None:
10 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/command.py:62 in execute
60│
61│ try:
→ 62│ return self.handle()
63│ except KeyboardInterrupt:
64│ return 1
9 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/add.py:262 in handle
260│ self.installer.whitelist([r["name"] for r in requirements])
261│
→ 262│ status = self.installer.run()
263│
264│ if status == 0 and not self.option("dry-run"):
8 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/installation/installer.py:116 in run
114│ self._execute_operations = False
115│
→ 116│ return self._do_install()
117│
118│ def dry_run(self, dry_run: bool = True) -> Installer:
7 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/installation/installer.py:263 in _do_install
261│ source_root=self._env.path.joinpath("src")
262│ ):
→ 263│ ops = solver.solve(use_latest=self._whitelist).calculate_operations()
264│ else:
265│ self._io.write_line("Installing dependencies from lock file")
6 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/solver.py:74 in solve
72│ with self._progress(), self._provider.use_latest_for(use_latest or []):
73│ start = time.time()
→ 74│ packages, depths = self._solve()
75│ end = time.time()
76│
5 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/solver.py:157 in _solve
155│
156│ try:
→ 157│ result = resolve_version(self._package, self._provider)
158│
159│ packages = result.packages
4 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/__init__.py:18 in resolve_version
16│ solver = VersionSolver(root, provider)
17│
→ 18│ return solver.solve()
19│
3 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:112 in solve
110│ while next is not None:
111│ self._propagate(next)
→ 112│ next = self._choose_package_version()
113│
114│ return self._result()
2 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:432 in _choose_package_version
430│ conflict = False
431│ for incompatibility in self._provider.incompatibilities_for(package):
→ 432│ self._add_incompatibility(incompatibility)
433│
434│ # If an incompatibility is already satisfied, then selecting version
1 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:468 in _add_incompatibility
466│
467│ def _add_incompatibility(self, incompatibility: Incompatibility) -> None:
→ 468│ self._log(f"fact: {incompatibility}")
469│
470│ for term in incompatibility.terms:
後出しになりますが、今回のpyproject.tomlは以下の通り。
[tool.poetry]
name = "openai"
version = "0.1.0"
パッケージ名とインストールするライブラリ名が同一の場合に衝突した故に起こったエラーでした。これはパッケージ開発用として、自身もインストールされる前提での一面も持つPoetryの特性とも言えそうです。
対策としては2通り。
- pyproject.tomlのname指定を被らないようにする
- pipでインストールする(
poetry run pip install openai
)
Poetryの仕様に沿う場合はname指定を被らないようにするほうがベターだと思われます。
あとがき
pipenvでは何も考えずにプロジェクト名を決めていて、インストールするライブラリ名と被ることも多々ありました。同じノリでPoetryを触るとエラーになる状況をみて、特定用途向けなのだなと理解しました。
Poetry自体触った時間がまだまだ少ないので、実装意図等確認しつつ挑戦することにします。