[Distutils] PEP345 - Distutils2 - Cannot pin to exact version

Erik Bray erik.m.bray at gmail.com
Tue Sep 11 21:11:27 CEST 2012


On Tue, Sep 11, 2012 at 2:35 PM, Donald Stufft <donald.stufft at gmail.com> wrote:
> I was digging through PEP386 & PEP345 today, and I noticed something odd
> about the wording of PEP345.
>
> It states:
>
>     When a version is provided, it always includes all versions that starts
> with the same value. For
>     example the "2.5" version of Python will include versions like "2.5.2"
> or "2.5.3". Pre and post
>     releases in that case are excluded. So in our example, versions like
> "2.5a1" are not included
>     when "2.5" is used. If the first version of the range is required, it
> has to be explicitly given. In
>     our example, it will be "2.5.0".
>
> It also states:
>
>     In that case, "2.5.0" will have to be explicitly used to avoid any
> confusion between the "2.5"
>     notation that represents the full range. It is a recommended practice to
> use schemes of the
>     same length for a series to completely avoid this problem.
>
> This effectively translates to an inability to pin to an exact version. Even
> in the case of specifying
> == it checks that the version "starts with" the value you selected. So if
> you pin to "2.5", and the
> author then releases "2.5.1", that will count as ==2.5. If you try to then
> pin to "2.5.0", and the
> author releases "2.5.0.1", then that will count as ==2.5.0.
>
> Essentially this translates to:
>
>     ==2.5       -> >=2.5<2.6
>     ==2.5.0    -> >=2.5.0<2.5.1
>     ==2.5.0.0 -> >=2.5.0.0<2.5.0.1
>
> Which means that version specifiers are _always_ ranges and are never exact
> versions. The PEP
> as written relies on authors to decide beforehand how many digits they are
> going to use in their
> versions, and for them to never increase or decrease that number.
>
> I also checked to see if Distutils2/packaging implemented VersionPredicates
> that way or if they
> allowed specifying an exact version. It turned out that it implements the
> PEP as written:
>
>>>> from distutils2 import version
>>>> predicate = version.VersionPredicate("foo (==2.5)")
>>>> print predicate
> foo (==2.5)
>>>> predicate.match("2.5")
> True
>>>> predicate.match("2.5.0")
> True
>>>> predicate.match("2.5.0.0")
> True
>>>> predicate.mach("2.5.0.5")
> True

That's kind of annoying.  Does anyone know if this is by design?

FWIW there is a workaround. For example if you want to pin to exactly 2.5.1:

>>> predicate = version.VersionPredicate("foo (==2.5.1,<2.5.1.1)")
>>> predicate.match('2.5.1')
True
>>> predicate.match('2.5.2')
False
>>> predicate.match('2.5.1.0')
True
>>> predicate.match('2.5.1.1')


Erik


More information about the Distutils-SIG mailing list