Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-release version of a package not found even with --allow-prereleases #3538

Closed
3 tasks done
kubami opened this issue Jan 4, 2021 · 25 comments
Closed
3 tasks done
Labels
area/solver Related to the dependency resolver kind/bug Something isn't working as expected

Comments

@kubami
Copy link

kubami commented Jan 4, 2021

  • 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).
  • OS version and name: archlinux
  • Poetry version: 1.1.4
  • Python version: 3.7.7

Issue

I am trying to install a pre-release verion of https://github.com/elastic/enterprise-search-python

Their recommended installation method is

python -m pip install --pre elastic-enterprise-search
which works fine.

When trying to install it with poetry using

poetry add --allow-prereleases elastic-enterprise-search
I am getting an old version: 0.2.1 (the same as the one without the --allow-prereleases switch.

Am I doing something wrong? Or is it that this package is configured incorrectly?

@kubami kubami added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Jan 4, 2021
@kubami
Copy link
Author

kubami commented Feb 10, 2021

when trying to install as above it doesn't work.
however when I specify the version explicitly the page installs correctly

# pyproject.toml
[tool.poetry.dependencies]
elastic-enterprise-search = {version = "7.10.0b1", allow-prereleases = true}

@markf94
Copy link

markf94 commented Mar 31, 2021

I second this! I'm unable to install pre-release versions with the --allow-prerelease flag using either Poetry 1.1.4 or 1.1.5. Even did a fresh reinstall of poetry on my system and still have the same problem. However, it does work for my colleagues with the same/similar setup.

Also verified that I can install the pre-release version when explicitly defining its version in pyproject.toml and it works in that case. However, I would like it to always pick the latest pre-release...

@ClementWalter
Copy link

I have the same problem with poetry 1.1.5. All private repos so I can't point out to the given packages, but essentially:

mypackage = { version = "^3.0.0", allow-prereleases = true}

does not resolve to using the 3.0.0.dev0 version, while if I write directly:

mypackage = { version = "^3.0.0.dev0", allow-prereleases = true}

poetry works fine.

But maybe there is a standard way of defining prerelease versions I am missing?

@alexporter8013
Copy link

looks like doing:

mypackage = { version = "^3.0.0*", allow-prereleases = true}

works fine for poetry 1.1.5 works just fine for me. If allowing pre-releases just adding a wildcard * is probably the best bet to get the latest pre-release.

@bushshrub
Copy link

I know this is an old issue but this still seems to be a problem.

@abn
Copy link
Member

abn commented May 19, 2022

@xiurobert did you try the version on master? This might have been fixed by #5500.

@dimbleby
Copy link
Contributor

dimbleby commented May 19, 2022

I think that poetry takes the view that

  • ^3.0.0 is asking for something >= 3.0.0
  • 3.0.0b1 is strictly before 3.0.0

in which case I wouldn't expect #5500 to make a difference. But also it's not clear to me that this is wrong!

For instance today (poetry 1.2.0b1 exists but 1.2.0 does not):

  • poetry = { version = "^1.0.0", allow-prereleases = true} does allow version 1.2.0b1 to be installed
  • but poetry = { version = "^1.2.0", allow-prereleases = true} fails, finding no matching versions

which is probably correct, there is no available version that is >= 1.2.0.

Possibly this should be documented or documented better, I haven't checked what the docs do say but clearly this is confusing to lots of people.

@abn
Copy link
Member

abn commented May 19, 2022

^3.0.0b1 == { version = "^3.0.0", allow-prereleases = true } -> this includes all pre-releases in the lowerbound. Unless the upperbound is <= pre-releases there are not included (iirc).

@dimbleby
Copy link
Contributor

@abn I'm struggling to parse that! Really not sure what you mean?

@abn
Copy link
Member

abn commented May 19, 2022

Should have explained it clearer. Effectively when searching for a compatible version ^3.0.0 with allow-prereleases = true behaves the same as ^3.0.0b1. The behaviour being, 3.0.0a1 or earlier is disallowed, 3.0.0b1 | 3.0.0b2 | 3.0.0rc1 | 3.0.0 etc. are allowed.

@dimbleby
Copy link
Contributor

dimbleby commented May 19, 2022

You mean: that's what you think the behaviour should be? Per my example - and indeed this issue - that's not what the behaviour is.

(Isn't 3.0.0a1 just as good a pre-release version as 3.0.0b1 - why should one but not the other be disallowed?)

@abn
Copy link
Member

abn commented May 19, 2022

When selecting packaegs if dependency allows for prereleases, they are selected else discarded.

if constraint.allows(package.version) or (
package.is_prerelease()
and constraint.allows(package.version.next_patch())
):
packages.append(package)

When finding the best candidate, we select the prerelease if there are only prereleases available and/or preleases are explicitly allowed.

if (
candidate.is_prerelease()
and not dependency.allows_prereleases()
and not only_prereleases
):

(Isn't 3.0.0a1 just as good a pre-release version as 3.0.0b1 - why should one but not the other be disallowed?)

All pre-releases are not made equal. This is more about PEP 440 that poetry.

Pre-releases for a given release are ordered first by phase (alpha, beta, release candidate) and then by the numerical component within that phase.

Ref: https://peps.python.org/pep-0440/#pre-releases

@dimbleby
Copy link
Contributor

Yes, I found the same code - but I don't find any code in the solver that would pay attention to allow_prereleases. ie my interpretation is that poetry today does allow pre-releases to be found in repositories, but the flag does not make any difference to how it interprets constraints.

This is consistent with the observed behaviour - it'll use poetry 1.2.0b1 if the constraint is ^1.0.0, but not if the constraint is ^1.2.0.

My assertion is that this is reasonable, if confusing, it sounds as though you are more willing to call this a bug.

(The a1 vs b1 thing is a bit of a side-issue, perhaps I should drop it. But the flag is called allow-prereleases, not allow-prereleases-except-not-alpha-prereleases!)

@abn
Copy link
Member

abn commented May 19, 2022

(The a1 vs b1 thing is a bit of a side-issue, perhaps I should drop it. But the flag is called allow-prereleases, not allow-prereleases-except-not-alpha-prereleases!)

Oh what i meant was if you said ^3.0.0b1 this will exclude since b1 is the lower bound and it implicitly allows pre-releases. Think that was miscommunicated.

the flag does not make any difference to how it interprets constraints.

This is correct. The solver works only on the pre-selected candidates iirc. And since the allow-prereleases flag is a Poetry feature, it is not propagated to the candidate dependencies.

My assertion is that this is reasonable, if confusing, it sounds as though you are more willing to call this a bug.

I not saying you are wrong here. I am indicating that the there is a bug in the candidate selection not the solver - ie. we were not selecting pre-releases when searching for package candidates.

@bushshrub
Copy link

bushshrub commented May 25, 2022

@xiurobert did you try the version on master? This might have been fixed by #5500.

Sorry, didn't get the chance to test it. I ended up returning back to virtualenvs. Will give it a shot again when I work on my personal projects.

@dbrennand
Copy link

dbrennand commented Jun 1, 2022

I'm having some trouble installing python-telegram-bot pre-release version 20.0a0:

Poetry version 1.1.13
# pyproject.toml
[tool.poetry.dependencies]
python = "^3.10"
# 1 - Installs version 13.12
# python-telegram-bot = {version = "^13.12", allow-prereleases = true}
# 2 - SolverProblemError
# python-telegram-bot = {version = "20.0a0", allow-prereleases = true}
# 3 - SolverProblemError
# python-telegram-bot = {version = "^20.0a0", allow-prereleases = true}

I'm quite confused and not sure how I can install the pre-release 😞

@dimbleby
Copy link
Contributor

dimbleby commented Jun 1, 2022

2 installs python-telegram-bot 20.a0 just fine for me at both 1.1.13 and master.

@dbrennand
Copy link

2 installs python-telegram-bot 20.a0 just fine for me at both 1.1.13 and master.

Huh, you're right. Not sure what I was doing wrong earlier 😅 😆 Thanks 👍🏻

user@computer:~/RSS_Feederbot$ poetry --version
Poetry version 1.1.13
user@computer:~/RSS_Feederbot$ cat pyproject.toml
[tool.poetry]
name = "rss_feederbot"
version = "1.0.0"
description = "An RSS feed reading Telegram bot"
license = "MIT"

[tool.poetry.dependencies]
python = "^3.10"
reader = "^2.12"
loguru = "^0.6.0"
python-telegram-bot = {version = "20.0a0", allow-prereleases = true}
emoji = "^1.7.0"

[tool.poetry.dev-dependencies]
black = "^22.3.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
user@computer:~/RSS_Feederbot$ poetry install

@TBBle
Copy link
Contributor

TBBle commented Jun 7, 2022

This looks like the original request is working now.

Testing on Poetry (version 1.2.0b2) (which includes #5500), in a trivial project using poetry-1.2 init -n and then poetry-1.2 lock. (poetry-1.2 is because I'm using pipx, and I already have Poetry 1.1.13 as poetry)

poetry-1.2 add --lock --allow-prereleases "elastic-enterprise-search<8.2.0"

chose 8.1.0a1, which is the latest pre-release before 8.2.0. Without --allow-preleases, it chooses 7.17.0.

poetry-1.2 add --lock --allow-prereleases "opentelemetry-api"

chose 1.12.0rc1 (it guessed ^1.12.0rc1 for the version match), which is a newer pre-release than the latest release. Without --allow-prereleases it chooses 1.11.1, with guessed version match ^1.11.1.

poetry-1.2 add --lock "opentelemetry-semantic-conventions" --allow-prereleases

chose 0.31b0 (it guessed ^0.31b0) as this is the latest pre-release, and there has never been a non-pre-release. It does the same thing without --allow-prereleases. I note that the pyproject.toml doesn't record the allow-prereleases flag in this case, because it wasn't provided, but a pre-release version was selected. I'm not sure if there's any scope for this to be an issue though, since once we have the guessed version match, that will accept pre-releases anyway, irrespective of the flag.

i.e.

poetry-1.2 add --lock "opentelemetry-api=^1.12.0rc0"

happily selected 1.12.0rc1.

So perhaps --allow-prereleases could be slightly-better documented that it only applies when guessing a constraint for names provided without constraints (which is probably the common use-case).

Although if that's true, I'm not sure why it's recorded in pyproject.toml, since that last command, with or without --allow-prereleases has only the following, non-meaningful differences:

diff --git a/poetry.lock b/poetry.lock
index 400fdf9..07b5111 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -48,7 +48,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.10"
-content-hash = "1ede8f5bb37ee43871f3bfbaee39e1abd027d0443aa65b5d7319abb2c0aac657"
+content-hash = "eb1e42b0bf10677fc70e389d22034d17f0c2ecfa35f508d8f6f3997a03a7777a"

 [metadata.files]
 deprecated = [
diff --git a/pyproject.toml b/pyproject.toml
index 16d3cef..609e097 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ readme = "README.md"

 [tool.poetry.dependencies]
 python = "^3.10"
-opentelemetry-api = "^1.12.0rc0"
+opentelemetry-api = {version = "^1.12.0rc0", allow-prereleases = true}


 [build-system]

i.e. in both cases it guessed the same constraint, locked the same packages, etc.

@wolph
Copy link

wolph commented Oct 6, 2022

Previously I was able to use ^3.0.* to select the latest pre-release, but it seems that's broken now. Is there a new syntax that works for the latest pre-release?

What doesn't work:

aiogram = { version = "^3.0.*", allow-prereleases = true}
aiogram = { version = "3.0.*", allow-prereleases = true}
aiogram = { version = "3.*", allow-prereleases = true}
aiogram = { version = "^3.0.0", allow-prereleases = true}
aiogram = { version = "^3.0", allow-prereleases = true}
aiogram = { version = "^3", allow-prereleases = true}

@dimbleby
Copy link
Contributor

dimbleby commented Oct 6, 2022

all of the above are asking for a version that is equal to or later than 3.0.0. A pre-release is before 3.0.0.

Provide a version bound that does not rule out the pre-release you want eg <4

@neersighted
Copy link
Member

This issue is a bit of a jumble -- as far as I can tell however, things are currently as they should be. That is to say, --allow-prereleases works as expected during poetry add, and interacts properly now with version constraints.

If you want to use ^ with a beta release, you need to realize the part that comes after ^ sets the lower bound. So ^3.0.0a1, with allow-prereleases = true will take the latest prerelease greater to alpha 1 or later. ^3 with allow-prereleases = true will work for 3.0.1a1, but that is because it comes after the lower bound of 3.0.0.

I'm closing this for now -- if you have a request/idea for docs improvement, please open a docs issue. If you think you are having trouble with allow-prereleases itself (as opposed to figuring out the correct version specifier for your use case), please feel free to chime in here -- but I would make sure your usage of the version specifier is correct first.

@neersighted neersighted removed the status/triage This issue needs to be triaged label Oct 6, 2022
@neersighted neersighted added the area/solver Related to the dependency resolver label Oct 6, 2022
@wolph
Copy link

wolph commented Oct 6, 2022

all of the above are asking for a version that is equal to or later than 3.0.0. A pre-release is before 3.0.0.

Provide a version bound that does not rule out the pre-release you want eg <4

That makes sense... silly of me. I just find it odd that ^3.0.* worked earlier and stopped working now

sjdemartini added a commit to sjdemartini/graphene-django-permissions that referenced this issue Oct 19, 2022
Only encountered this in CI, where poetry 1.2 started getting installed
(https://github.com/sjdemartini/graphene-django-permissions/actions/runs/3284716438/jobs/5411001549),
since originally I was using Poetry 1.1 locally:

```
poetry.core.constraints.version.exceptions.ParseConstraintError: Could not parse version constraint: ^3.0.0*
```

Poetry 1.2 (released August 2022) contained a backwards incompatible
change for `allow-preleases` logic, which led to this breakage (and
difference from 1.1). See
python-poetry/poetry#3538 (comment)
for the new preferred approach.
@ozancaglayan
Copy link

Hello,

Is this supposed to work if we keep the version the same (e.g. rc1) but force re-releases into a development PyPI? This changes the buildID of the underlying package but I can't make poetry to fetch the new one unless I append the buildID to the dependency in pyproject.toml

Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area/solver Related to the dependency resolver kind/bug Something isn't working as expected
Projects
None yet
Development

No branches or pull requests