[Distutils] Local version identifiers from PEP 440 in practice
Donald Stufft
donald at stufft.io
Wed Dec 17 02:49:24 CET 2014
> On Dec 16, 2014, at 8:33 PM, Maurits van Rees <m.van.rees at zestsoftware.nl> wrote:
>
> Donald Stufft schreef op 17-12-14 01:54:
>>
>>> On Dec 16, 2014, at 7:46 PM, Maurits van Rees <m.van.rees at zestsoftware.nl> wrote:
>>>
>>> Maurits van Rees schreef op 17-12-14 00:53:
>>>> I have created a very basic python project called 'myproject'. It
>>>> does nothing. I have released a few versions here:
>>>> http://pypi.zestsoftware.nl/public/packagingtest/
>>>
>>> I have now also distributed myproject version 1.1. (This has a
>>> base.jinja2 file and requires Jinja2[i18n], which I need for checking
>>> a corner case; I may report that later).
>>>
>>> Installing 1.1 unexpectedly gives problems, both with pip and
>>> zc.buildout.
>>>
>>> - zc.buildout 2.2.5 and setuptools 7.0: all is well.
>>>
>>> - zc.buildout 2.3.1 and setuptools 8.0.4:
>>>
>>> * When I specify 'myproject = 1.1' in the buildout config, myproject
>>> does not get updated. It sticks at version 1.1+maurits.3.
>>
>> This isn’t a bug, assuming that buildout is translating ``my project = 1.1``
>> to something like ==1.1.
>
> That is indeed what buildout does. Note that buildout config files are basically parsed by ConfigParser, so '==' is not allowed there. That is why buildout uses a different notation here.
>
>> Local versions are used to indicate something that
>> is compatible with 1.1 and they sort as newer than the same version without
>> the local version. The reason they match for a ``==1.1`` is because you want
>> downstream distributors like Debian to be able to set their versions to 1.0+debian.1
>> without breaking things for people who do ``==1.1``.
>
> That is most definitely not what I want. If I tell setuptools or pip or buildout that I want version X, then I don't want roughly version X, but I want exactly version X.
>
> When I request 1.0rc1 and I get 1.0, that is wrong.
> When I request 1.0 and I get 1.0rc1, that is wrong.
>
> To me, the same is true for local version identifiers.
>
> To me, this is the basis for repeatable deployments, knowing that given a buildout file or a pip requirements file you get the same versions and the same code that you got when you tried it a month earlier. It avoids "it works on my machine" when I get an error that a colleague does not get.
>
>
> For clarity, how I use internal releases, so how I would want to use local version identifiers, is:
>
> 1. Use largetrout 1.0 in a project.
>
> 2. Notice a bug.
>
> 3. See that the bug is already fixed in development, but there is no release yet.
>
> 4. Checkout largetrout dev, setup.py version is 1.1.dev0.
>
> 5. Set version to 1.1+internal1 (an internal release of a snapshot of the code that is expected to end up in 1.1).
>
> 6. Make an internal release and use it.
>
> 7. Five more bugs get fixed in largetrout.
>
> 8. largetrout 1.1 is released.
>
> Now when I tell pip or buildout to use largetrout 1.1 I definitely want those five bug fixes from step 7 included.
So the *primary* use case that motivated local versions is things like when Debian patches a copy of a project they can indicate that they’ve done so by changing the version to 1.0+dfsg1 or so instead of 1.0. A related use case is the one you’re talking about. However the primary use case is what influenced the fact that ==1.1 matches ==1.0+foobar.
Important to note, is that ==1.0+foobar will only install that patched version, not any 1.0 version. You can also approximate the kind of pinning you want with the === (which is really the arbitrary equality indicator, which is generally used for people who want to install a version like “dog” which we can’t parse). It’s possible that we could add some sort of a “None” indicator for local versions that says “1.0 and exactly 1.0” though I’m not sure how off the top of my head (Maybe ==1.0+).
Another thing though, what you probably want to do is something like 1.1.dev0+internal1, which will sort as older than 1.1 whenever it is actually released.
>
>>> - pip 1.5.6, setuptools 7.0:
>>>
>>> * pip warns about three different versions:
>>> $ pip install -U -f http://pypi.zestsoftware.nl/public/packagingtest/ myproject==1.1
>>> Downloading/unpacking myproject==1.1
>>> Downloading myproject-1.1+maurits.3.zip
>>> Running setup.py (path:/Users/mauritsvanrees/tmp/venv-older/build/myproject/setup.py) egg_info for package myproject
>>> Requested myproject==1.1, but installing version 1.1-maurits.3
>>> * The warning is correct: not 1.1, but 1.1-maurits.3 is installed.
>>
>> That warning might actually be from a stale build directory laying around and not related to the local version at all.
>
> Let me check. Nope, the same happens with a fresh virtualenv:
>
> mauritsvanrees at procyon:tmp $ virtualenv-2.7 venv-older
> Using real prefix '/Users/mauritsvanrees/buildout/python2.7/parts/opt'
> New python executable in venv-older/bin/python2.7
> Also creating executable in venv-older/bin/python
> Installing setuptools, pip...done.
> mauritsvanrees at procyon:tmp $ cd venv-older
> mauritsvanrees at procyon:venv-older $ . bin/activate
> (venv-older)mauritsvanrees at procyon:venv-older $ pip install -U setuptools==7.0 # this is optional
> Downloading/unpacking setuptools==7.0
> Downloading setuptools-7.0-py2.py3-none-any.whl (534kB): 534kB downloaded
> Installing collected packages: setuptools
> Found existing installation: setuptools 3.6
> Uninstalling setuptools:
> Successfully uninstalled setuptools
> Successfully installed setuptools
> Cleaning up...
> (venv-older)mauritsvanrees at procyon:venv-older $ pip list
> pip (1.5.6)
> setuptools (7.0)
> wsgiref (0.1.2)
> (venv-older)mauritsvanrees at procyon:venv-older $ pip install -U -f http://pypi.zestsoftware.nl/public/packagingtest/ myproject==1.1
> Downloading/unpacking myproject==1.1
> http://pypi.zestsoftware.nl/public/packagingtest/ uses an insecure transport scheme (http). Consider using https if pypi.zestsoftware.nl has it available
> Downloading myproject-1.1+maurits.3.zip
> Running setup.py (path:/Users/mauritsvanrees/tmp/venv-older/build/myproject/setup.py) egg_info for package myproject
>
> warning: no files found matching '*rst'
> warning: no previously-included files matching '*.pyc' found anywhere in distribution
> Requested myproject==1.1, but installing version 1.1-maurits.3
> Installing collected packages: myproject
> Running setup.py install for myproject
>
> warning: no files found matching '*rst'
> warning: no previously-included files matching '*.pyc' found anywhere in distribution
> Successfully installed myproject
> Cleaning up...
> (venv-older)mauritsvanrees at procyon:venv-older $ ls -1 lib/python2.7/site-packages/
> _markerlib
> easy_install.py
> easy_install.pyc
> myproject
> myproject-1.1_maurits.3-py2.7.egg-info
> pip
> pip-1.5.6.dist-info
> pkg_resources.py
> pkg_resources.pyc
> setuptools
> setuptools-7.0.dist-info
>
>
> --
> Maurits van Rees: http://maurits.vanrees.org/
> Zest Software: http://zestsoftware.nl
>
> _______________________________________________
> Distutils-SIG maillist - Distutils-SIG at python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
---
Donald Stufft
PGP: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA
More information about the Distutils-SIG
mailing list