python-poetry / python-poetry/poetry
poetry add does not update existing dependency
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 34.3k
- Forks
- 2.5k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 30
Description
Description
I am trying to update pytest inside my poetry project (2.1.1) to the latest version using the commands. However, poetry does not update my dependency even when I explicitly state the version (latest). This contradicts what is stated here in the docs: https://python-poetry.org/docs/cli/#update.
I quote (emphasis mine):
Note that this will not update versions for dependencies outside their version constraints specified in the pyproject.toml file. In other terms, poetry update foo will be a no-op if the version constraint specified for foo is ~2.3 or 2.3 and 2.4 is available. In order for foo to be updated, you must update the constraint, for example ^2.3. You can do this using the add command.
However, as shown (quoted or not, makes no difference):
$ poetry add "pytest@latest"
Using version ^8.4.1 for pytest
Updating dependencies
Resolving dependencies... (0.0s)
Incompatible constraints in requirements of ... (2.1.1):
pytest (>=8.4.1,<9.0.0)
pytest (>=6.2.5,<=8.2.0)
This is not what happens.
Workarounds
Manually change the pyproject.toml.
Poetry Installation Method
install.python-poetry.org
Operating System
macOS
Poetry Version
2.1.1
Poetry Configuration
$ poetry config --list
cache-dir = "/Users/daniel.soutar/Library/Caches/pypoetry"
data-dir = "/Users/daniel.soutar/Library/Application Support/pypoetry"
installer.max-workers = null
installer.no-binary = null
installer.only-binary = null
installer.parallel = true
installer.re-resolve = true
keyring.enabled = true
python.installation-dir = "{data-dir}/python" # /Users/daniel.soutar/Library/Application Support/pypoetry/python
repositories.google.url = "https://europe-python.pkg.dev/ki-artifact-registries-cf08/ki-pypi"
repositories.test.url = "https://test.pypi.org/simple/"
repositories.testpypi.url = "https://test.pypi.org/legacy/"
requests.max-retries = 0
solver.lazy-wheel = true
system-git-client = false
virtualenvs.create = true
virtualenvs.in-project = true
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/daniel.soutar/Library/Caches/pypoetry/virtualenvs
virtualenvs.prompt = "{project_name}-py{python_version}"
virtualenvs.use-poetry-python = false
Python Sysconfig
sysconfig.log
Paste the output of 'python -m sysconfig', over this line.
Example pyproject.toml
Poetry Runtime Logs
poetry-runtime.log
Loading configuration file /Users/daniel.soutar/Library/Application Support/pypoetry/config.toml
Adding repository google (https://europe-python.pkg.dev/...) and setting it as explicit
Using virtualenv: /Users/daniel.soutar/Documents/path/to/.venv
Checking keyring availability: Checking if keyring is available
[keyring:keyring.backend] Loading KWallet
[keyring:keyring.backend] Loading SecretService
[keyring:keyring.backend] Loading Windows
[keyring:keyring.backend] Loading chainer
[keyring:keyring.backend] Loading libsecret
[keyring:keyring.backend] Loading macOS
Using keyring backend 'macOS Keyring'
Available
Creating new session for pypi.org
[urllib3:urllib3.connectionpool] Starting new HTTPS connection (1): pypi.org:443
[urllib3:urllib3.connectionpool] https://pypi.org:443 "GET /simple/pytest/ HTTP/1.1" 304 0
[filelock:filelock] Attempting to acquire lock 4386110576 on /Users/daniel.soutar/Library/Caches/pypoetry/cache/repositories/PyPI/_http/0/c/2/1/8/0c218d526767991766d9b365a4f3e4449ce3579fd8b0f96a707d5a52.lock
[filelock:filelock] Lock 4386110576 acquired on /Users/daniel.soutar/Library/Caches/pypoetry/cache/repositories/PyPI/_http/0/c/2/1/8/0c218d526767991766d9b365a4f3e4449ce3579fd8b0f96a707d5a52.lock
[filelock:filelock] Attempting to release lock 4386110576 on /Users/daniel.soutar/Library/Caches/pypoetry/cache/repositories/PyPI/_http/0/c/2/1/8/0c218d526767991766d9b365a4f3e4449ce3579fd8b0f96a707d5a52.lock
[filelock:filelock] Lock 4386110576 released on /Users/daniel.soutar/Library/Caches/pypoetry/cache/repositories/PyPI/_http/0/c/2/1/8/0c218d526767991766d9b365a4f3e4449ce3579fd8b0f96a707d5a52.lock
Source (PyPI): 180 packages found for pytest *
Using version ^8.4.1 for pytest
Updating dependencies
Resolving dependencies...
1: fact: ... is 2.1.1
1: derived: ...
0: Duplicate dependencies for pytest
1: Version solving took 0.002 seconds.
1: Tried 1 solutions.
Stack trace:
17 ~/Library/Application Support/pypoetry/venv/lib/python3.9/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
16 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/console/application.py:260 in _run
258│ with directory(self._working_directory):
259│ try:
→ 260│ exit_code = super()._run(io)
261│ except PoetryRuntimeError as e:
262│ io.write_error_line("")
15 ~/Library/Application Support/pypoetry/venv/lib/python3.9/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│
14 ~/Library/Application Support/pypoetry/venv/lib/python3.9/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
13 ~/Library/Application Support/pypoetry/venv/lib/python3.9/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
12 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/cleo/commands/base_command.py:117 in run
115│ io.input.validate()
116│
→ 117│ return self.execute(io) or 0
118│
119│ def merge_application_definition(self, merge_args: bool = True) -> None:
11 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/console/commands/installer_command.py:39 in execute
37│ def execute(self, io: IO) -> int:
38│ PoetryKeyring.preflight_check(io, self.poetry.config)
→ 39│ return super().execute(io)
40│
10 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/cleo/commands/command.py:61 in execute
59│
60│ try:
→ 61│ return self.handle()
62│ except KeyboardInterrupt:
63│ return 1
9 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/console/commands/add.py:376 in handle
374│ self.installer.whitelist([r["name"] for r in requirements])
375│
→ 376│ status = self.installer.run()
377│
378│ if status == 0 and not self.option("dry-run"):
8 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/installation/installer.py:103 in run
101│ self.verbose(True)
102│
→ 103│ return self._do_install()
104│
105│ def dry_run(self, dry_run: bool = True) -> Installer:
7 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/installation/installer.py:241 in _do_install
239│ source_root=self._env.path.joinpath("src")
240│ ):
→ 241│ solved_packages = solver.solve(
242│ use_latest=self._whitelist
243│ ).get_solved_packages()
6 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/puzzle/solver.py:87 in solve
85│ with self._progress(), self._provider.use_latest_for(use_latest or []):
86│ start = time.time()
→ 87│ packages = self._solve()
88│ # simplify markers by removing redundant information
89│ for transitive_info in packages.values():
5 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/puzzle/solver.py:168 in _solve
166│
167│ try:
→ 168│ result = resolve_version(self._package, self._provider)
169│
170│ packages = result.packages
4 ~/Library/Application Support/pypoetry/venv/lib/python3.9/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.9/site-packages/poetry/mixology/version_solver.py:174 in solve
172│ while next is not None:
173│ self._propagate(next)
→ 174│ next = self._choose_package_version()
175│
176│ return self._result()
2 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/mixology/version_solver.py:572 in _choose_package_version
570│ package = locked
571│
→ 572│ package = self._provider.complete_package(package)
573│
574│ conflict = False
1 ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/puzzle/provider.py:620 in complete_package
618│ self._active_root_extras if package.is_root() else dependency.extras
619│ )
→ 620│ deps = self._resolve_overlapping_markers(package, deps, active_extras)
621│ else:
622│ # There are duplicates with different extras.
IncompatibleConstraintsError
Incompatible constraints in requirements of ... (2.1.1):
pytest (>=8.4.1,<9.0.0)
pytest (>=6.2.5,<=8.2.0)
at ~/Library/Application Support/pypoetry/venv/lib/python3.9/site-packages/poetry/puzzle/provider.py:973 in _resolve_overlapping_markers
969│ specific_source_dependency = dep
970│ constraint = constraint.intersect(dep.constraint)
971│ if constraint.is_empty():
972│ # conflict in overlapping area
→ 973│ raise IncompatibleConstraintsError(package, *used_dependencies)
974│
975│ if not any(uses):
976│ # This is an edge case where the dependency is not required
977│ # for the resulting marker. However, we have to consider it anyway
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing poetry add "pytest@latest", then trace the reported entry points in poetry/console/commands/add.py, poetry/installation/installer.py, and poetry/puzzle/provider.py. Compare how the existing pytest dependency and the requested version are combined; done means the command handles the existing dependency without producing incompatible duplicate constraints.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100