[Distutils] Local version identifiers from PEP 440 in practice

Donald Stufft donald at stufft.io
Wed Dec 17 03:48:18 CET 2014

> On Dec 16, 2014, at 9:10 PM, Ethan Furman <ethan at stoneleaf.us> wrote:
> On 12/16/2014 05:49 PM, Donald Stufft wrote:
>> 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+).
> Let me see if I understand correctly:
> I release my dbf package as 1.3.
> Somebody at Debian fixes a bug, and rather than wait for me to release the next version just slap a local tag on it --
> so now there is:
>  - 1.3  (mine)
>  - 1.3+debian1
> At this point, a non-debian user asking for 1.3 will get mine, whereas a debian user would get the 1.3+debian1 version.
> Correct?  Plus, a debian user asking for 1.4 would also get 1.3+debian1?
> Now, I fix that bug plus a few more, and make a 1.4 release.  A non-debian user would get my 1.4 release.  Which version
> will a debian user get?
>  - 1.3+debian1 ?
>  - 1.4 ?
> If my 1.4 does not sort higher than a 1.3+blahblah anything, that's not good.

The versions given here would sort like this (oldest to newest): 1.3, 1.3+debian1, 1.4.

Debian users would not get 1.3+debian1 via ``pip install yourthing``, or buildout, or easy_install.

Debian users would (in this hypothetical situation) install ``apt-get python-yourthing`` and get a copy of the library which is your 1.3 with some debian patches applies to it with the version 1.3+debian1.

So you’d only ever get a hypothetical +debian1 from apt-get (although in other situations it may come from pip, but it won’t be on PyPI).

Now if you have 1.3+debian1 installed via apt-get (or any means really), and you’ll get the following behaviors (show with pip):

- pip install yourthing -> 1.3+debian1 satisfies the constraint of anything, so it stays installed.
- pip install yourthing==1.3 -> 1.3+debian1 satisfies the constraint of ==1.3, so it stays installed.
- pip install yourthing>=1.3 -> 1.3+debian1 satisfies the constraint of >= 1.3, so it stays installed.
- pip install yourthing>=1.4 -> 1.3+debian1 does not satisfy the constraint of >=1.4, so pip will upgrade it to 1.4.
- pip install —upgrade youthing -> You’ve requested an upgrade, so pip will see 1.4 exists and will install it.
- pip install —upgrade yourthing==1.3 -> You’ve requested an upgrade, but there’s nothing newer than 1.3+debian1 that matches the constraint so it stays installed
- pip install -upgrade youthing>=1.3 -> You’ve requested an upgrade, pip will see 1.4 exists and satisfies the constraint and will install it.
- pip install —upgrade yourthing>1.4 -> you’ve requested an upgrade and 1.3+debian1 is not >= 1.4, so pip will see 1.4 exists and install it.

Does that make sense? Essentially a +whatever is the _weakest_ version indicator, and 1.3+debian1 can be thought of semantically as “version 1.3 plus some patches indicates by debian1”. Since there are patches on top of version 1.3, it considers 1.3+debian1 as newer than 1.3, but since 1.4 is newer than 1.3 it considers 1.4 as newer than 1.3+debian1 regardless of the patches.

Donald Stufft
PGP: 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA

More information about the Distutils-SIG mailing list