PEP 426: Propose Ruby's "pessimistic version constraints"
- makes the default handling of version specifiers match Ruby's ~> operator - explicitly base == and != on string prefix matching - cleaned up various examples related to the version specifiers - give the version specifiers section more structure
This commit is contained in:
parent
6f23bce51b
commit
92f4a2321d
183
pep-0426.txt
183
pep-0426.txt
|
@ -861,7 +861,7 @@ ordered as shown::
|
|||
Within a post-release (``1.0.post1``), the following suffixes are permitted
|
||||
and are ordered as shown::
|
||||
|
||||
devN, <no suffix>
|
||||
.devN, <no suffix>
|
||||
|
||||
Note that ``devN`` and ``postN`` must always be preceded by a dot, even
|
||||
when used immediately following a numeric version (e.g. ``1.0.dev456``,
|
||||
|
@ -976,8 +976,9 @@ Date based versions
|
|||
|
||||
As with other incompatible version schemes, date based versions can be
|
||||
stored in the ``Private-Version`` field. Translating them to a compliant
|
||||
version is straightforward: the simplest approach is to subtract the year
|
||||
of the first release from the major component in the release number.
|
||||
public version is straightforward: the simplest approach is to subtract
|
||||
the year before the first release from the major component in the release
|
||||
number.
|
||||
|
||||
|
||||
Version specifiers
|
||||
|
@ -987,61 +988,106 @@ A version specifier consists of a series of version clauses, separated by
|
|||
commas. Each version clause consists of an optional comparison operator
|
||||
followed by a version identifier. For example::
|
||||
|
||||
0.9, >= 1.0, != 1.3.4, < 2.0, ~= 2.0
|
||||
0.9, >= 1.0, != 1.3.4, < 2.0
|
||||
|
||||
Each version identifier must be in the standard format described in
|
||||
`Version scheme`_.
|
||||
|
||||
The comma (",") is equivalent to a logical **and** operator.
|
||||
|
||||
Comparison operators must be one of ``<``, ``>``, ``<=``, ``>=``, ``==``,
|
||||
``!=`` or ``~=``.
|
||||
|
||||
The ``==`` and ``!=`` operators are strict - in order to match, the
|
||||
version supplied must exactly match the specified version, with no
|
||||
additional trailing suffix. When no comparison operator is provided,
|
||||
it is equivalent to ``==``.
|
||||
|
||||
The special ``~=`` operator is equivalent to using the following pair
|
||||
of version clauses::
|
||||
|
||||
>= V, < V+1
|
||||
|
||||
where ``V+1`` is the next version after ``V``, as determined by
|
||||
incrementing the last numeric component in ``V`` (for example, if ``V ==
|
||||
1.0a3``, then ``V+1 == 1.0a4``, while if ``V == 1.0``, then ``V+1 ==
|
||||
1.1``). In other words, this operator matches any release that starts
|
||||
with the mentioned components.
|
||||
|
||||
This approach makes it easy to depend on a particular release series
|
||||
simply by naming it in a version specifier, without requiring any
|
||||
additional annotation. For example, the following pairs of version
|
||||
specifiers are equivalent::
|
||||
|
||||
~= 2
|
||||
>= 2, < 3
|
||||
|
||||
~= 3.3
|
||||
>= 3.3, < 3.4
|
||||
|
||||
Whitespace between a conditional operator and the following version
|
||||
identifier is optional, as is the whitespace around the commas.
|
||||
|
||||
|
||||
Compatible release
|
||||
------------------
|
||||
|
||||
A compatible release clause omits the comparison operator and matches any
|
||||
version that is expected to be compatible with the specified version.
|
||||
|
||||
For a given release identifier ``V.N``, the compatible release clause is
|
||||
equivalent to the pair of comparison clauses::
|
||||
|
||||
>= V.N, < V+1
|
||||
|
||||
where ``V+1`` is the next version after ``V``, as determined by
|
||||
incrementing the last numeric component in ``V``. For example,
|
||||
the following version clauses are approximately equivalent::
|
||||
|
||||
2.2
|
||||
>= 2.2, < 3.dev0
|
||||
|
||||
1.4.5
|
||||
>= 1.4.5, < 1.5.dev0
|
||||
|
||||
The difference between the two is that using a compatible release clause
|
||||
does *not* count as `explicitly mentioning a pre-release`__.
|
||||
|
||||
__ `Handling of pre-releases`_
|
||||
|
||||
If a pre-release, post-release or developmental release is named in a
|
||||
compatible release clause as ``V.N.suffix``, then the suffix is ignored
|
||||
when determining the upper limit of compatibility::
|
||||
|
||||
2.2.post3
|
||||
>= 2.2.post3, < 3.dev0
|
||||
|
||||
1.4.5a4
|
||||
>= 1.4.5a4, < 1.5.dev0
|
||||
|
||||
|
||||
Version comparisons
|
||||
-------------------
|
||||
|
||||
A version comparison clause includes a comparison operator and a version
|
||||
identifier, and will match any version where the comparison is true.
|
||||
|
||||
Comparison clauses are only needed to cover cases which cannot be handled
|
||||
with an appropriate compatible release clause, including coping with
|
||||
dependencies which do not have a robust backwards compatibility policy
|
||||
and thus break the assumptions of a compatible release clause.
|
||||
|
||||
The defined comparison operators are ``<``, ``>``, ``<=``, ``>=``, ``==``,
|
||||
and ``!=``.
|
||||
|
||||
The ordered comparison operators ``<``, ``>``, ``<=``, ``>=`` are based
|
||||
on the consistent ordering defined by the standard `Version scheme`_.
|
||||
|
||||
The ``==`` and ``!=`` operators are based on string comparisons - in order
|
||||
to match, the version being checker must start with exactly that sequence of
|
||||
characters.
|
||||
|
||||
.. note::
|
||||
|
||||
The use of ``==`` when defining dependencies for published distributions
|
||||
is strongly discouraged, as it greatly complicates the deployment of
|
||||
security fixes (the strict version comparison operator is intended
|
||||
primarily for use when defining dependencies for particular
|
||||
applications while using a shared distribution index).
|
||||
|
||||
|
||||
Handling of pre-releases
|
||||
------------------------
|
||||
|
||||
Pre-releases of any kind, including developmental releases, are implicitly
|
||||
excluded from all version specifiers, *unless* a pre-release or developmental
|
||||
developmental release is explicitly mentioned in one of the clauses. For
|
||||
example, this specifier implicitly excludes all pre-releases and development
|
||||
release is explicitly mentioned in one of the clauses. For example, these
|
||||
specifiers implicitly exclude all pre-releases and development
|
||||
releases of later versions::
|
||||
|
||||
2.2
|
||||
>= 1.0
|
||||
|
||||
While these specifiers would include them::
|
||||
While these specifiers would include at least some of them::
|
||||
|
||||
2.2.dev0
|
||||
2.2, != 2.3b2
|
||||
>= 1.0a1
|
||||
>= 1.0c1
|
||||
>= 1.0, != 1.0b2
|
||||
>= 1.0, < 2.0.dev123
|
||||
|
||||
|
||||
Dependency resolution tools should use the above rules by default, but
|
||||
should also allow users to request the following alternative behaviours:
|
||||
|
||||
|
@ -1054,34 +1100,26 @@ controlled on a per-distribution basis.
|
|||
Post-releases and purely numeric releases receive no special treatment -
|
||||
they are always included unless explicitly excluded.
|
||||
|
||||
Given the above rules, projects which include the ``.0`` suffix for
|
||||
the first release in a series, such as ``2.5.0``, can easily refer
|
||||
specifically to that version with the clause ``==2.5.0``, while the clause
|
||||
``~=2.5`` refers to that entire series.
|
||||
|
||||
Some examples:
|
||||
Examples
|
||||
--------
|
||||
|
||||
* ``Requires-Dist: zope.interface (~=3.1)``: any version that starts with 3.1,
|
||||
* ``Requires-Dist: zope.interface (3.1)``: version 3.1 or later, but not
|
||||
version 4.0 or later. Excludes pre-releases and developmental releases.
|
||||
* ``Requires-Dist: zope.interface (3.1.0)``: version 3.1.0 or later, but not
|
||||
version 3.2.0 or later. Excludes pre-releases and developmental releases.
|
||||
* ``Requires-Dist: zope.interface (==3.1)``: any version that starts
|
||||
with 3.1, excluding pre-releases and developmental releases.
|
||||
* ``Requires-Dist: zope.interface (3.1.0,!=3.1.3)``: version 3.1.0 or later,
|
||||
but not version 3.1.3 and not version 3.2.0 or later. Excludes pre-releases
|
||||
and developmental releases. For this particular project, this means: "any
|
||||
version of the 3.1 series but not 3.1.3". This is equivalent to:
|
||||
``>=3.1, !=3.1.3, <3.2``.
|
||||
* ``Requires-Python: 2.6``: Any version of Python 2.6 or 2.7. It
|
||||
automatically excludes Python 3 or later.
|
||||
* ``Requires-Python: 3.2, < 3.3``: Specifically requires Python 3.2,
|
||||
excluding pre-releases.
|
||||
* ``Requires-Dist: zope.interface (==3.1)``: equivalent to ``Requires-Dist:
|
||||
zope.interface (3.1)``.
|
||||
* ``Requires-Dist: zope.interface (~=3.1.0)``: any version that starts with
|
||||
3.1.0, excluding pre-releases. Since that particular project doesn't
|
||||
use more than 3 digits, it also means "only the 3.1.0 release".
|
||||
* ``Requires-Python: 3``: Any Python 3 version, excluding pre-releases.
|
||||
* ``Requires-Python: >=2.6,<3``: Any version of Python 2.6 or 2.7, including
|
||||
post-releases (if they were used for Python). It excludes pre releases of
|
||||
Python 3.
|
||||
* ``Requires-Python: ~=2.6.2``: Equivalent to ">=2.6.2,<2.6.3". So this includes
|
||||
only Python 2.6.2. Of course, if Python was numbered with 4 digits, it would
|
||||
include all versions of the 2.6.2 series, excluding pre-releases.
|
||||
* ``Requires-Python: ~=2.5``: Equivalent to ">=2.5,<2.6".
|
||||
* ``Requires-Dist: zope.interface (~=3.1,!=3.1.3)``: any version that starts
|
||||
with 3.1, excluding pre-releases of 3.1 *and* excluding any version that
|
||||
starts with "3.1.3". For this particular project, this means: "any version
|
||||
of the 3.1 series but not 3.1.3". This is equivalent to:
|
||||
">=3.1,!=3.1.3,<3.2".
|
||||
* ``Requires-Python: >=3.3a1``: Any version of Python 3.3+, including
|
||||
* ``Requires-Python: 3.3a1``: Any version of Python 3.3+, including
|
||||
pre-releases like 3.4a1.
|
||||
|
||||
|
||||
|
@ -1437,10 +1475,10 @@ Changing the interpretation of version specifiers
|
|||
The previous interpretation of version specifiers made it very easy to
|
||||
accidentally download a pre-release version of a dependency. This in
|
||||
turn made it difficult for developers to publish pre-release versions
|
||||
of software to the Python Package Index, as leaving the package set as
|
||||
public would lead to users inadvertently downloading pre-release software,
|
||||
while hiding it would defeat the purpose of publishing it for user
|
||||
testing.
|
||||
of software to the Python Package Index, as even marking the package as
|
||||
hidden wasn't enough to keep automated tools from downloading it, and also
|
||||
made it harder for users to obtain the test release manually through the
|
||||
main PyPI web interface.
|
||||
|
||||
The previous interpretation also excluded post-releases from some version
|
||||
specifiers for no adequately justified reason.
|
||||
|
@ -1449,6 +1487,16 @@ The updated interpretation is intended to make it difficult to accidentally
|
|||
accept a pre-release version as satisfying a dependency, while allowing
|
||||
pre-release versions to be explicitly requested when needed.
|
||||
|
||||
The "some forward compatibility assumed" default version constraint is
|
||||
taken directly from the Ruby community's "pessimistic version constraint"
|
||||
operator [4]_ to allow projects to take a cautious approach to forward
|
||||
compatibility promises, while still easily setting a minimum required
|
||||
version for their dependencies. It is made the default behaviour rather
|
||||
than needing a separate operator in order to explicitly discourage
|
||||
overspecification of dependencies by library developers. The explicit
|
||||
comparison operators remain available to cope with dependencies with
|
||||
unreliable or non-existent backwards compatibility policies.
|
||||
|
||||
|
||||
Packaging, build and installation dependencies
|
||||
----------------------------------------------
|
||||
|
@ -1546,6 +1594,9 @@ justifications for needing such a standard can be found in PEP 386.
|
|||
.. [3] Version compatibility analysis script:
|
||||
http://hg.python.org/peps/file/default/pep-0426/pepsort.py
|
||||
|
||||
.. [4] Pessimistic version constraint
|
||||
http://docs.rubygems.org/read/chapter/16
|
||||
|
||||
Appendix A
|
||||
==========
|
||||
|
||||
|
|
Loading…
Reference in New Issue