pipenv icon indicating copy to clipboard operation
pipenv copied to clipboard

new 'pre' syntax in Pipfile

Open gsemet opened this issue 6 years ago • 45 comments

Placeholder ticket for the proposition we talk with Kenneth.

Add the following syntax in the Pipfile:

...
mypkg = { version = "*", pre="true"}
...

This would allow to allow prerelease resolution for one package only.

Change the pipenv install mypkg --pre behavior. It will set the setting described above only for this very package. Today it turns on a general 'pre' setting for the whole Pipfile, leading other packages to also resolve to prerelease.

Change the pipenv update and pipenv lock behavior. They should take into account the presence of the pre=true setting for some package.

Here are some impact I think might happen

  • if a version of package is describe at >=1.0 in one dependency, and another package define the pre=true while a new version 2.0.0.b1 is available on pypi, pipenv install should take it
  • I don't see any syntax to turn the general pre setting in the Pipfile. Maybe we can document users need to do a pipenv update --pre or pipenv lock --pre to turn the general 'pre' settings on.

gsemet avatar Mar 16 '18 09:03 gsemet

I am assigning myself to this task, but I might take some time to enter into the code

gsemet avatar Mar 16 '18 09:03 gsemet

@frostming how does this proposal interact with the changes you made here recently?

techalchemy avatar Apr 10 '18 23:04 techalchemy

The change in my PR is: when installing wildcard versions from CLI, Pipfile won't be modified.

With the proposal here, when we do pipenv install mypkg --pre, we are willing to replace the entry, right? The simpliest way is to add an extra arg pre to add_package_to_pipfile.

I am glad to help when it comes true.

frostming avatar Apr 11 '18 00:04 frostming

Hello! Any updates or estimates on this?

Gr1N avatar Jul 09 '18 18:07 Gr1N

If there's no progress on this I'd like to make it happen, otherwise I will revert to virtualenv/pip.

@frostming With your proposal, how would that end up looking in the Pipfile? I'm not familiar with how requirements are really parsed, briefly browsed some code. Completely ballparking, please correct me. Would it have to follow syntax akin to: EDIT: Per initial issue comment:

...
mypkg = { version = "*", pre="true"}
...

remingtonc avatar Jul 09 '18 23:07 remingtonc

I was on it, but there have been some change in the resolver I need to redo it completly. I would be glad to get some help on it

gsemet avatar Jul 10 '18 06:07 gsemet

I found that pin to specific prerelease version works for even allow_prereleases or --pre is provided

jxltom avatar Sep 22 '18 14:09 jxltom

@gsemet where are you with making this a reality? Would be happy to help push this along

ive solved it in a weird way, definitely should make it available like @gsemet has suggested. However, you can fix a single package as a prerelease without wrecking the rest of the pipfile by going the editable route and directly specifying the release tag rather than the package in pypa i.e.

marshmallow = {editable = true,ref = "3.0.0rc4",git = "https://github.com/marshmallow-code/marshmallow.git"}

ekhaydarov avatar Feb 09 '19 18:02 ekhaydarov

@gsemet where are you with making this a reality? Would be happy to help push this along

ive solved it in a weird way, definitely should make it available like @gsemet has suggested. However, you can fix a single package as a prerelease without wrecking the rest of the pipfile by going the editable route and directly specifying the release tag rather than the package in pypa i.e.

marshmallow = {editable = true,ref = "3.0.0rc4",git = "https://github.com/marshmallow-code/marshmallow.git"}

Thanks for the workaround. I will note that this also works without editable = true, as in:

marshmallow = {ref = "3.0.0rc4",git = "https://github.com/marshmallow-code/marshmallow.git"}

ajenkins-cargometrics avatar Feb 28 '19 13:02 ajenkins-cargometrics

@ekhaydarov Did nothing really, sorry :( had a baby, and has been lost in the resolver once :( not have many will to dig into it for this damned resolver for the moment :'(

gsemet avatar Feb 28 '19 13:02 gsemet

Okay so what I'm about to outline might either be a bug or a stronger incentive for this feature request...

Assume we have this Pipfile:

[dev-packages]
my_package = { path = ".", editable=true }

And the package in . builds a pre-release version, then the whole affair ends in:

[pipenv.exceptions.ResolutionFailure]:       ResolutionFailure: ERROR: ERROR: Could not find a version that matches my_package 

Which is either a bug, because if people specify path="." , they expect that whatever is in . gets installed regardless of its pre-release/alpha/beta status (especially if it's in the [dev-packages] section) or it is a strong incentive to resolve this issue, because if not resolved, there is no other way to develop your alpha/beta/pre-release version with pipenv. One could even argue that if a package is in the [dev-packages] section, users would expect that alpha, beta and pre-release versions get installed even without explicitly allowing pre-releases versions for those.

You tell me if, I should rather open another issue to have pre-releases be considered if path= is specified in a dependency and then another for them to be considered for all packages under [dev-packages].

con-f-use avatar Mar 27 '19 15:03 con-f-use

Hi. I do not have any issue using pipenv install -e . or -e deps/mysubmodule, even with preversion. Don't know if it comes from the -e.

But I actually stopped using this feature for current module, too complex to maintain. Just have Pipfile[.lock] declare your dependencies, and have a Makefile with a target doing:

install-dev:
    pipenv install --dev --ignore-pipfile --deploy
    pipenv run pip install -e .

Bonus:

update:
    pipenv update --clear

Full cookiecutter provided here.

gsemet avatar Mar 27 '19 17:03 gsemet

Ha! Thanks, you helped me realize that my problem is something slightly different.

Locking failes because the project in path='./' itself has a requirement that's only satisfyable by dev versions. So it's one level below.

con-f-use avatar Mar 27 '19 18:03 con-f-use

If I take the road of specifying versions explicitly, is there a way to specify versions loosely without allowing pre-releases when allow_prereleases = true?

DrPyser avatar Apr 05 '19 19:04 DrPyser

By "loosely" I mean something like ==x.* or >=x.y, i.e. a partially fixed version.

DrPyser avatar Apr 05 '19 20:04 DrPyser

yes only for non-prerelease:

pipenv install 'mydeps>=1.2,<1.3'

I agree that ==1.2 should means every bugfix version (1.2.1, 1.2.2, 1.2.3,...), but we don't want to have all the mess npm have with this.

gsemet avatar Apr 05 '19 20:04 gsemet

I could reformulate: is there a way to turn the problem around and use allow_prereleases = true(because I need prerelease versions of some packages) but explicitly disallow prerelease versions for other packages while still using loose(partially pinned/bounded) version specifications?

But then I'm realizing that this wouldn't solve the problem for subdependencies.

Seems to me this issue is pretty critical. It doesn't actually make sense to allow prerelease versions for all your dependencies, since the usability of prerelease versions depends on each project. Some projects have very stable prereleases while others don't, and using their prerelease versions will break your app.

Isn't there a workable fix which could at least allow a pinned version to be a prerelease, without requiring the global allow_prerelease = true?

DrPyser avatar Apr 05 '19 20:04 DrPyser

@gsemet So ==1.2.* would include prereleases, but >=1.2,<1.3 would not?

DrPyser avatar Apr 05 '19 20:04 DrPyser

if you use --pre >=1.2,<1.3 will find preversion. Most of the time you do not want to take prerelease, and if really, you need to freeze the version to use. --pre is global, meaning it will find prerelease for every dependencies. The pre syntax in pipfile would allow to set one or two deps to find prerelease, and only them. But we do have it.

gsemet avatar Apr 05 '19 21:04 gsemet

Just wanted to mention #3651 here, because I proposed a per-package level option of either requires=[...] or pip_options=[...] to solve that issue, just like pre discussed here. At some point the maintainers could think about making a bunch of other Pipenv and pip options available per-package.

con-f-use avatar Apr 05 '19 21:04 con-f-use

Sorry, I thought you couldn't pin prerelease versions without using allow_prereleases = true. The problem is less critical than I thought, then.

DrPyser avatar Apr 05 '19 22:04 DrPyser

It is really painful we can't do this for dev packages.

j-walker23 avatar Aug 23 '19 23:08 j-walker23

Just noting that pipenv isn't currently abiding by one of the usability recommendations that was included in the PEP 440 specification. Specifically: "By default, dependency resolutions tools SHOULD ... accept remotely available pre-releases for version specifiers where there is no final or post release that satisfies the version specifier"

ncoghlan avatar Sep 03 '19 08:09 ncoghlan

This bit me recently when trying to use Pipenv to set up and manage some load tests using locustio. It requires a newer version of gevent and wouldn't successfully let me pipenv install locustio until I added the --pre argument.

dragon788 avatar Dec 21 '19 15:12 dragon788

It constantly bits me, because black doesn't have stable releases yet.

pipenv + black = 💥

andrey-semakin avatar Jan 08 '20 10:01 andrey-semakin

@andrey-semakin FYI, black = "==19.10b0" works. Not ideal of course, but pipenv will install it without issue.

dms-cat avatar Jan 13 '20 22:01 dms-cat

FYI, black = "==19.10b0" works. Not ideal of course, but pipenv will install it without issue.

Just thought I'd note here that this won't work if you have a different dependency which requires black, but doesn't pin it to a specific version, e.g. pytest-black or flake8-black. More in-depth description of that problem over at #3928 and peterjc/flake8-black#18.

So for this Pipfile, there is no workaround which doesn't involve globally enabling prereleases, which is a big no-no for many users.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[packages]

[dev-packages]
black = "==19.10b0"
pytest-black = "==0.3.8"

tharradine avatar May 28 '20 01:05 tharradine

@tharradine ha! I wasted so, so, so, so many hours on this exact scenario bc of the successful workarounds mentioned. I finally gave up, and force all my devs to manually pip install the black stuff, or their forced commit hooks will never work : ).

And I always get complaints when their env is updated and now missing this manual pip dependency. It's freaking never ending.

I just sucked it up bc I knew I'd never get any help here because of the package lol. It's https://github.com/pausan/cblack.

Black for 2 indent python!! haha, not going to be any love there.

Glad you posted some legit third party packages!

j-walker23 avatar Jun 04 '20 03:06 j-walker23

Is there really no effective workaround or progress on this? I'd like to be able to use pre-releases for internally-generated artifacts during development, but still depend on release versions of public libraries. I'm not sure pipenv is suited for this (trivial and common) workflow while this issue persists.

wlievens avatar Jul 17 '20 14:07 wlievens

Just switch to some other tool like poetry, there is little hope this will get solved soon given the history.

Diaoul avatar Jul 17 '20 15:07 Diaoul