poetry: Failed to install packages that target a range of python versions if local python version is not fixed
- I am on the latest Poetry version.
- I have searched the issues of this repo and believe that this is not a duplicate.
- If an exception occurs when executing a command, I executed it again in debug mode (
-vvv
option).
▶ poetry debug:info
Poetry
======
* Version: 0.12.17
* Python: 3.7.0
Virtualenv
==========
* Python: 3.7.0
* Implementation: CPython
* Path: /Users/user/projectX/.venv
* Valid: True
System
======
* Platform: darwin
* OS: posix
* Python: /Users/user/.pyenv/versions/3.7.0
pyproject.toml
[tool.poetry]
name = "projectX"
version = "0.1.0"
description = ""
authors = ["user <user@cie.com>"]
[tool.poetry.dependencies]
python = "^3.7"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
Issue
When I try to install a dependency that target a range of python versions, that seems to contains the python version I target in my pyproject.toml
it fails with the following error.
▶ poetry add kedro -vvv
Using virtualenv: /Users/user/projectX/.venv
PyPI: 7 packages found for kedro *
Using version ^0.15.1 for kedro
Updating dependencies
Resolving dependencies...
1: fact: projectX is 0.1.0
1: derived: projectX
1: fact: projectX depends on kedro (^0.15.1)
1: selecting projectX (0.1.0)
1: derived: kedro (^0.15.1)
PyPI: 1 packages found for kedro >=0.15.1,<0.16.0
1: fact: kedro (0.15.1) requires Python >=3.5, <3.8
1: derived: not kedro (0.15.1)
1: fact: no versions of kedro match >0.15.1,<0.16.0
1: conflict: no versions of kedro match >0.15.1,<0.16.0
1: ! kedro (>0.15.1,<0.16.0) is partially satisfied by not kedro (0.15.1)
1: ! which is caused by "kedro (0.15.1) requires Python >=3.5, <3.8"
1: ! thus: kedro is forbidden
1: ! kedro (>=0.15.1,<0.16.0) is satisfied by kedro (^0.15.1)
1: ! which is caused by "projectX depends on kedro (^0.15.1)"
1: ! thus: version solving failed
1: Version solving took 0.037 seconds.
1: Tried 1 solutions.
[SolverProblemError]
The current project must support the following Python versions: ^3.7
Because no versions of kedro match >0.15.1,<0.16.0
and kedro (0.15.1) requires Python >=3.5, <3.8, kedro is forbidden.
So, because projectX depends on kedro (^0.15.1), version solving failed.
Exception trace:
/Users/user/.poetry/lib/poetry/_vendor/py3.7/cleo/application.py in run() at line 94
status_code = self.do_run(input_, output_)
/Users/user/.poetry/lib/poetry/console/application.py in do_run() at line 88
return super(Application, self).do_run(i, o)
/Users/user/.poetry/lib/poetry/_vendor/py3.7/cleo/application.py in do_run() at line 197
status_code = command.run(input_, output_)
/Users/user/.poetry/lib/poetry/console/commands/command.py in run() at line 77
return super(BaseCommand, self).run(i, o)
/Users/user/.poetry/lib/poetry/_vendor/py3.7/cleo/commands/base_command.py in run() at line 146
status_code = self.execute(input_, output_)
/Users/user/.poetry/lib/poetry/_vendor/py3.7/cleo/commands/command.py in execute() at line 107
return self.handle()
/Users/user/.poetry/lib/poetry/console/commands/add.py in handle() at line 139
status = installer.run()
/Users/user/.poetry/lib/poetry/installation/installer.py in run() at line 73
self._do_install(local_repo)
/Users/user/.poetry/lib/poetry/installation/installer.py in _do_install() at line 165
ops = solver.solve(use_latest=self._whitelist)
/Users/user/.poetry/lib/poetry/puzzle/solver.py in solve() at line 38
packages, depths = self._solve(use_latest=use_latest)
/Users/user/.poetry/lib/poetry/puzzle/solver.py in _solve() at line 180
raise SolverProblemError(e)
add [-D|--dev] [--git GIT] [--path PATH] [-E|--extras EXTRAS] [--optional] [--python PYTHON] [--platform PLATFORM] [--allow-prereleases] [--dry-run] [--] <name> (<name>)...
As you can see from the error and from the kedro pypi release page, the target python version is Python >=3.5, <3.8
.
I specify python ^3.7
in my pyprojet.toml
and as you can see when I run poetry debug:info
my python version is * Python: 3.7.0
.
Other info, if I change the pyproject.toml
:
[tool.poetry.dependencies]
python = "^3.7"
To:
[tool.poetry.dependencies]
python = "3.7"
It’s working
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 49
- Comments: 46 (9 by maintainers)
Commits related to this issue
- Trying to overcome Poetry's bug Apparently, Poetry 1.0 does not handle dependencies on specific versions of Python correctly: https://github.com/python-poetry/poetry/issues/1413 While waiting for P... — committed to litebird/litebird_sim by ziotom78 4 years ago
- Use "dataclasses" (#60) * Add dependency on dataclasses for py36 * Rename Detector->DetectorInfo and make it a dataclass Using `@dataclass` vastly simplifies the implementation of `Detector`, ... — committed to litebird/litebird_sim by ziotom78 4 years ago
- switch from ^ to ~ for python version range https://github.com/python-poetry/poetry/issues/1413#issuecomment-607776371 — committed to ConorSheehan1/shot by ConorSheehan1 3 years ago
- Poetry build failures (#19) * switch from ^ to ~ for python version range https://github.com/python-poetry/poetry/issues/1413#issuecomment-607776371 * revert back to ^, same as rich source, add... — committed to ConorSheehan1/shot by ConorSheehan1 3 years ago
- hacky solution to https://github.com/python-poetry/poetry/issues/1413 — committed to nznobody/example-python by nznobody 3 years ago
- poetry: Set version with tilde ~ instead of carrot ^ See also: https://github.com/python-poetry/poetry/issues/1413#issuecomment-607776371 — committed to tmux-python/libtmux by tony 3 years ago
- ci: Use python 3.9 to avoid 3.10 poetry + dataclasses issue See also: https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/libtmux by tony 3 years ago
- ci: Use python 3.9 to avoid 3.10 poetry + dataclasses issue See also: https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/libtmux by tony 3 years ago
- ci: Use python 3.9 to avoid 3.10 poetry + dataclasses issue See also: https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/libtmux by tony 3 years ago
- ci: Lock python at 3.9 (lower than 3.10) to avoid poetry / dataclasses bug See also: - https://github.com/tmux-python/libtmux/pull/339 - https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/tmuxp by tony 3 years ago
- ci: Lock python at 3.9 (lower than 3.10) to avoid poetry / dataclasses bug See also: - https://github.com/tmux-python/libtmux/pull/339 - https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/tmuxp by tony 3 years ago
- ci: Lock python at 3.9 (lower than 3.10) to avoid poetry / dataclasses bug See also: - https://github.com/tmux-python/libtmux/pull/339 - https://github.com/python-poetry/poetry/issues/1413 — committed to tmux-python/tmuxp by tony 3 years ago
- ci: Lock python at 3.9 to avoid poetry bug See also: https://github.com/python-poetry/poetry/issues/1413 — committed to tony/django-slugify-processor by tony 3 years ago
- ci: Lock python at 3.9 to avoid poetry bug See also: https://github.com/python-poetry/poetry/issues/1413 — committed to tony/django-slugify-processor by tony 3 years ago
- ci: Pin python at 3.9 to avoid poetry bug with black See also: https://github.com/python-poetry/poetry/issues/1413 — committed to git-pull/website by tony 3 years ago
- Use setuptools for ouster-sensor-tools package (MR !1652) Since external teams are using the checker tool in this package, it makes sense to use the most "standard" packaging tools and not require th... — committed to ouster-lidar/ouster_example by deleted user 4 years ago
Hello,
the “issue” here is one of the most misunderstood of poetry’s version resolving.
poetry
checks if the versions that are given in thepyproject.toml
are always valid and not just with the currently used python version.So, if one define that the project is compatible with python
^3.6
this means it’s compatible with all python versions >=3.6 but <4.0.Let’s have a look at one of the examples above:
dataclass
is not available for python >3.7 here.Or this one:
The python requirement for the project has no upper boundary but
taskipy
has.A further requirement is, that there is one major version of a package that is compatible with all python version. If this is not the case, the cli is not able to resolve this and we have to help by defining the version in the
pyproject.toml
. See here how this looks like.fin swimmer
Why does Poetry not try to find the latest release of a package that DOES fulfill the constraints?
This is so frustrating. I have a brand new project that I have defined as such:
Super basic. Nothing special. Created it with init, setup the env with
poetry env use c:\python37\python.exe
and no problem thus far.Then I run this:
At what point did I say that newproject depends on pyproj? I am adding it right now. It chose that version, and then complains that the version isn’t compatible. If we look at the pypi for pyproj, it’s clear to see that while 3.3.0 is Python 3.8 or above, 3.2.1 works with Python 3.7. So why won’t poetry use it instead when I have not asked for a specific version of it? If the argument is that Poetry is not a package installer but a dependency manager, it should absolutely be able to find the correct dependency given the constraints.
@nils-werner I know it might be confusing but there is actually a good and logical reason behind the way Poetry behaves in those cases.
As an example, I will take the
taskipy
example mentioned by @matthijskooijman:>=3.7
taskipy
which declares being compatible only with Python>=3.6,<4.0
.taskipy
would not be satisfied for Python>=4.0
(the difference between>=3.7
and>=3.6,<4.0
)At this point, you have two choices, either change the
python
requirement of your project to>=3.7,<4.0
(however, note that this is not what I would personally recommend because it would mean changing the declared compatible Python versions to accommodate the dependencies) or specify that thetaskipy
dependency should only be installed for Python>=3.7,<4.0
by using thepython
property or themarkers
property:It will now work properly.
This will be better explained when the
1.1
version of Poetry is released:On another note
No, the lock file is system and Python version agnostic.
I also ran into this problem just now. I hear that this is intentional, but I’m not sure why.
I think this is the essence. Why do all python versions given in the
pyproject.toml
need to valid with all dependencies?Or, to make it more specific, look at this example:
I can see that installing taskipy would limit the python versions that the project works with to < 4.0. And apparently the solution here, would be to modify the project’s python requirement to be >=3.7,<4.0, making it a subset of the taskipy allowed python versions (did I get that right?).
But why does one need to do this manually? Isn’t this something that poetry could sort out? If every library, and the project, declares what Python versions it works with, then poetry can figure out what the resulting supported Python range is? If this results in an empty set of Python versions, that’s of course problematic, but that does not seem to be the case at hand.
I can see that there is some documentation value in a project’s
pyproject.toml
listing the effective usable Python versions for the project, but there is also value in documenting the python requirement of the project itself, without any dependency-imposed requirements. Especially since the latter can easily change when updating dependencies, that means that you would end up artificially limiting the python versions for the project, and then having to reconsider (manually check) whether the requirements can be relaxed again whenever dependencies are updated.If this is is indeed the rationale for this requirement, I guess that the proper solution could be to have two python version requirements for the project: One that shows the requirements of the project itself, and one that shows the requirements of the project and all its requirements combined (where the former is manually configured and the latter is automatically determined by poetry whenever the lock file changes).
Another thing I wondered: Is this same policy applied to normal dependencies, or just to the python version? In other words, if a project depends on package
A ^1.0
and also on a packageB
that depends onA >= 1.0
, will this also produce the same error (I suspect not, since then the micromanagement of dependency versions might have been way too complicated). I guess the documentation value of listing the effectively viable versions of a package might be lower than for the python version, so if there is indeed an inconsistency here, that could explain this.Just experienced the same strange behavior.
Seems like when you use tilde requirement for Python:
~3.7
this will work as expected.IMO, the caret requirements
^4.2
is very hard to understand and use properly. I propose to discard them at all.changing ‘python = “^3.8”’ to ‘python = “~3.8”’ allowed to get around the erroneous dependency constraint resulting in an error (as per above)
I @finswimmer, thanks for the explanation.
You have given a few examples for why we should decide/pin the Python version first, and then install dependencies. However, can’t you just use these as arguments against version deciding/pinning, too?
That’s exactly my thought when starting out: What versions do I/does this library support? Most likely it is
python>=3.6
. Why do I have to go look at each individual dependency and adjust my Python version accordingly?Syntax features are available in a wide range of Python versions. If a user wants to use a specific syntax, say
f
-strings. That doesn’t mean they have to pickpython==3.6
, but insteadpython>=3.6
. If now a dependency comes along and requirespython>=3.7
, that’s fine,f
-strings are still there.I am not saying I should not care, but why exactly do I have to know this? Say in a scenario where I want to use Django 3, shouldn’t Poetry figure out that
django>=3.0
in fact needspython>=3.6
?(Sidenote: the fact that poetry wants me to switch Python versions using
poetry env use
, but is nevertheless still able to create the correct environment, does not make sense to me, either.)I absolutely get that the Python version should be pinned during deployment, but that’s what
poetry.lock
does/should do, no?The mental model I have: Python is just another dependency, just like any package from PyPI. In my mental model I should not have to treat it specially. If I and all my dependencies define their compatible version range (and I don’t have a conflict somewhere), Poetry should be able to find a valid Python version that suits all. It should be flexible in
pyproject.toml
and pinned inpoetry.lock
. And I shouldn’t have to pick a Python version prior to runningpoetry install
. But that’s just my mental model, maybe I am wrong somewhere and am just failing to see it. 😃I have the same when I want to add PySide2.
When I use the ‘fix’ from @MarcBoissonneault (changing to
python = "3.7"
) it works.I just stumbled upon this myself when using a dependency that depends on the backport of
dataclasses
.Installing version
0.6
of dataclasses works fine, but0.7
haspython_requires=">=3.6, <3.7"
insetup.py
and that seems to trip uppoetry
’s resolver.After having been stuck in this rabbit hole for several hours, I would like to add my thoughts to this very old thread. I think the rationale behind the current behaviour is very inconsistent.
Basically, poetry is first lying on our behalf, and a few moments later, it is calling us out on that lie.
What is the lie?
When we write
python = "^3.11"
in the .toml file, we are lying. We are boldly and confidently declaring that our package will be compatible with any future version of Python 3.But we can’t know that for certain. Future minor versions of Python 3 may break our own code. Or the packages we depend on may not be upgraded to support those Python versions.
Is the lie acceptable?
Well, if you want to be very hardcore about compatibility, the lie is not acceptable. You should only state compatibility with currently known minor versions, after testing those versions.
However, for many of us, the lie is fully acceptable. We understand that the creator of an imaginary and now abandoned my_hello_world package can’t know with 100% certainty if Python 3.47 is going to deprecate the
print
statement, so his code stops working. So he is gambling when he writes ^3.11. But if that means that we can also use his package in year 2039 without being forced into using python 3.11, this gamble is acceptable. After all, we had 16 years to find a replacement for his package after he stopped maintaining it.We also understand that other packages, which our package depends on, are not yet released for Python minor versions, which do not exist yet. There is no pandas package for Python 3.13, because Python 3.13 has not yet been released. But if we include pandas as a dependency in our project, we can be quite confident that there will be a pandas package for Python 3.13 if someone downloads our package to his python 3.13 environment a few years from now. And if there isn’t a pandas package, his package manager should tell him to downgrade his python version anyway.
Does poetry think that the lie is acceptable? Poetry seems to think that the lie is not acceptable. And based on the comments from finswimmer in this thread, this is intentional.
Consequently, when I try to include pandas as a dependency in my package, my screen will be filled with red text stating:
“Hey! What are you doing? You have said that your package is compatible with all future minor versions of Python 3, and now you try to install pandas, which have no packages for Python 3.13.”
Well, duh! Python 3.13 isn’t released yet (as least not in a stable version), so of course there is no pandas package for Python 3.13.
Who made the lie?
This is the funny thing. Poetry did!
When I use poetry for creating a new environment with the command
poetry new --src <packagename>
, poetry will create a pyproject.toml file containing this:That is not really consistent with poetry’s hardcore approach to dependencies, is it?
Why not let the default entry in pyproject.toml be this:
That would be in line with poetry’s hardcore approach to dependency solving, and then it would be up to the developer to slacken the dependencies if he has reason for doing that.
TL;DR In my opinion, the poetry developers need to make a choice and stick consistently to it:
With the current behaviour, I first have to create the environment with poetry, then manually edit the pyproject.toml file to make the change from ^3.11 to ~3.11, and then I can start adding packages.
@finswimmer I will argue that, since this many people got confused, this is actually a bug that needs to be resolved somehow. We’d at least appreciate the proper way to do this, as currently no solution is posted. Maybe a solution could be included in the docs?
Same problem when trying to add the
dataclasses
backport package for Python 3.6:Poetry version: 1.0.3
I have the same with
pandas = "^0.25.1"
andpython = ">=3.5, <3.8"
Hello @matthijskooijman,
at first place
poetry
is a tool for development. When you start with a new python project, the first question you have to answer is: What python versions will I support. The reasons for the answer can be different: You need to use a special syntax that is only available in on version, you know your target platform, you already know that you will need a specific package that is only available for python x.y, …Once you’ve answer this question and write it down to your
pyproject.toml
poetry will make sure that with the dependencies you try to add, this goal can be reached.Might be possible, but that’s not how should manage your python project. As I said, you first have to decide what python versions you want to support, because this is essential for the python syntax you will use. Having valid dependencies is only the second step. Not the other way round.
No, this will not produce an error. Because the version constraints for the package tell poetry from which versions it can choose. Which one it will choose depends on the other packages in the project and there dependencies.
fin swimmer
But we do bend our vision, because we specify that
taskipy
is not needed forpython >= 4.0
, even when that is not true.I would greatly prefer to just state the dependencies as they are in reality, so
poetry
can correctly deduce that my package is not installable forpython >= 4.0
and can provide feedback to users that do want to install my package with python 4.0.It might still be useful if this information is also shared with the current package maintainer, but I do not think it should prevent adding the dependencie. i.e. I can imagine that running
poetry add
will say "Adding packagetaskipy
limits the effective supported python versions (declared>= 3.7
, effective>= 3.7 <= 4.0
) and then continue adding it. Maybe this information could be displayed on request as well, or maybe stored in an automatically updated field in pyproject.toml or poetry.lock?Exactly.
That does not really seem right either: Aren’t you now specifying that for Python >= 4.0,
taskipy
is not needed? If you would be using Python 4.0, poetry would happily install withouttaskipy
, thinking it has produced a working set of dependencies, while in reality your application will break due to a missing dependency?Hey @hnykda,
sorry if this was not clear enough. So here is another try 😃
The important thing I wanted to point out here, was “like pip”.
pip
’s purpose is to install a package into an environment. Of course Poetry need to do this as well. But this is not the main purpose of Poetry, it’s just a thing that have to be done. From the docs, the goal of Poetry is:To reach this goal, Poetry needs to make sure that your project definition is valid. And that’s the main task. Poetry thinks in “projects” and not in “current environment”. And this is why it complains, if the current environments fits to the needs of a dependency, but the project definitions doesn’t fit.
Is it somehow clearer now?
fin swimmer
This is also my question, which is how I ended up here…
python=~3.8
, which I understand to mean>=3.8, ≤3.9
.flake8
, it tells meflake8
version6.1.0
is not compatible with3.8.1
, so it doesn’t satisfy the range. Makes sense…5.0.4
, which is compatible with>=3.6
?This is really counter-intuitive, a bad API design example tbh
@skorokithakis This won’t be treated as a bug since it’s not one but the intended behavior.
That being said I agree that, since it’s confusing for some people, we should give guidance to resolve the issue. That’s something that is in progress and will be available in the next feature release (
1.1
). Here is what it will look like:I had the same problem trying to install
coverage
4.5.4 withpython = ">=3.7"
. Changing it to"^3.7"
resolved.