massive editing to extend the rational - thanks Pachi
This commit is contained in:
parent
1356583428
commit
8436e4f7bb
128
pep-0386.txt
128
pep-0386.txt
|
@ -12,20 +12,25 @@ Created: 4-June-2009
|
|||
Abstract
|
||||
========
|
||||
|
||||
This PEP proposes the inclusion of a new version comparison system in
|
||||
Distutils.
|
||||
This PEP proposes a new version comparison schema system in Distutils.
|
||||
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
Distutils will soon extend the metadata standard, by including an
|
||||
``install_requires``-like field from Setuptools [#requires]_ among
|
||||
other changes. This field will be called ``Requires-Dist``.
|
||||
In Python there are no real restriction yet on how a project should manage its
|
||||
versions, and how they should be incremented.
|
||||
|
||||
These changes are located in PEP 345 [#pep345]_.
|
||||
Distutile provides a `version` distribution meta-data field but it is freeform and
|
||||
current users, such as PyPI usually consider the latest version pushed as the
|
||||
`latest` one, regardless of the expected semantics.
|
||||
|
||||
The ``Requires-Dist`` field will allow a package to define a dependency on
|
||||
Distutils will soon extend its capabilities to allow distributions to express a
|
||||
dependency on other distributions through the `Requires-Dist` metadata field
|
||||
(see PEP 345 [#pep345]_) and it will optionally allow to use that field to
|
||||
restrict the dependency to a set of compatible versions.
|
||||
|
||||
The ``Requires-Dist`` field will allow a distribution to define a dependency on
|
||||
another package and optionally restrict this dependency to a set of
|
||||
compatible versions, so one may write::
|
||||
|
||||
|
@ -38,33 +43,45 @@ This also means that Python projects will need to follow the same convention
|
|||
than the tool that will be used to install them, so they are able to compare
|
||||
versions.
|
||||
|
||||
That's why Distutils needs to provide a robust standard and reference
|
||||
version scheme, and an API to provide version comparisons.
|
||||
That is why this PEP proposes, for the sake of interoperability, a standard
|
||||
schema to express version information and its comparison semantics.
|
||||
|
||||
This PEP describes a new version scheme that will be added in Distutils.
|
||||
Furthermore, this will make OS packagers work easier when repackaging standards
|
||||
compliant distributions, as of now it can be difficult to decide how two
|
||||
distribution versions compare.
|
||||
|
||||
Of course developers are **not** required to conform to this scheme, but
|
||||
it is suggested to use it as a standard for interoperability between the
|
||||
existing Python distributions installers.
|
||||
|
||||
Current status
|
||||
==============
|
||||
Requisites and current status
|
||||
=============================
|
||||
|
||||
In Python there are no real restriction yet on how a project should manage
|
||||
its versions, and how they should be incremented. They are no standard
|
||||
either, even if they are a few conventions widely used, like having a major
|
||||
and a minor revision (1.1, 1.2, etc.).
|
||||
It is not in the scope of this PEP to come with an universal versioning schema,
|
||||
intented to support many or all existing versioning schemas. There will always
|
||||
be competing grammars, either mandated by distro or project policies or by
|
||||
historical reasons and we cannot expect that to change.
|
||||
|
||||
Developers are free to put in the `version` meta-data of their package any
|
||||
string they want, and push a new release at PyPI. This version will appear
|
||||
as the `latest` for end users.
|
||||
The proposed schema should be able to express the usual versioning semantics,
|
||||
so it's possible to parse any alternative versioning schema and transform it
|
||||
into a compliant one. This is how OS packagers usually deal with the existing
|
||||
version schemas and is a preferable alternative than supporting an arbitrary
|
||||
set of versioning schemas.
|
||||
|
||||
Some project are also using dates as their major version numbers, or a custom
|
||||
versioning standard that is sometimes quite exotic.
|
||||
Conformance to usual practice and conventions, as well as a simplicity are a
|
||||
plus, to ease frictionless adoption and painless transition. Practicality beats
|
||||
purity, sometimes.
|
||||
|
||||
The problem with this freedom is that the package will be harder to re-package
|
||||
for OS packagers, that need to have stricter conventions. The worst case is
|
||||
when a packager is unable to easily compare the versions he needs to package.
|
||||
Projects have very different versioning needs, but the following are widely
|
||||
considered important semantics:
|
||||
|
||||
1. there should be possible to express more than one versioning level
|
||||
(usually this is expressed as major and minor revision and, sometimes,
|
||||
also a micro revision).
|
||||
2. most projects need special meaning versions for "pre-releases" (such as
|
||||
"alpha", "beta", "rc"), and these have widely used aliases ("a" stands
|
||||
for "alpha", "b" for "beta" and "c" for "rc").
|
||||
3. some projects also need "post-releases" of regular versions,
|
||||
mainly for installer work which can't be clearly expressed otherwise.
|
||||
4. development versions allow packagers of unreleased work to avoid version
|
||||
clash with later regular releases.
|
||||
|
||||
For people that want to go further and use a tool to manage their version
|
||||
numbers, the two major ones are:
|
||||
|
@ -120,6 +137,11 @@ your project::
|
|||
>>> v1 > v2
|
||||
False
|
||||
|
||||
The problem with this is that while it allows expressing requisite any
|
||||
nesting level it doesn't allow to express special meaning versions
|
||||
(pre and post-releases as well as development versions), as expressed in
|
||||
requisites 2, 3 and 4.
|
||||
|
||||
The `StrictVersion` class is more strict. From the doc::
|
||||
|
||||
Version numbering for meticulous retentive and software idealists.
|
||||
|
@ -166,13 +188,12 @@ numbers::
|
|||
>>> v2 < v3
|
||||
True
|
||||
|
||||
Although, it lacks a few elements to make it usable:
|
||||
It adds pre-release versions, and some structure, but lacks a few semantic
|
||||
elements to make it usable, such as development releases or post-release tags,
|
||||
as expressed in requisites 3 and 4.
|
||||
|
||||
- development releases
|
||||
- post-release tags
|
||||
- development releases of post-release tags.
|
||||
Also, notice that Distutils version classes are not really used in the community.
|
||||
|
||||
Notice that Distutils version classes are not really used in the community.
|
||||
|
||||
Setuptools
|
||||
----------
|
||||
|
@ -226,13 +247,18 @@ deal with them so they can be compared::
|
|||
>>> V('FunkyVersion')
|
||||
('*funkyversion', '*final')
|
||||
|
||||
In this schema practicality takes priority over purity, but as a result it
|
||||
doesn't enforce any policy and leads to very complex semantics due to the lack
|
||||
of a clear standard. It just tries to adapt to widely used conventions.
|
||||
|
||||
Caveats of existing systems
|
||||
---------------------------
|
||||
|
||||
The major problem with the described version comparison tools is that they are
|
||||
too permissive. Many of the versions on PyPI [#pypi]_ are obviously not useful
|
||||
versions, which makes it difficult for users to grok the versioning that a
|
||||
particular package was using and to provide tools on top of PyPI.
|
||||
too permissive and, at the same time, aren't capable of expressing some of the
|
||||
required semantics. Many of the versions on PyPI [#pypi]_ are obviously not
|
||||
useful versions, which makes it difficult for users to grok the versioning that
|
||||
a particular package was using and to provide tools on top of PyPI.
|
||||
|
||||
Distutils classes are not really used in Python projects, but the
|
||||
Setuptools function is quite spread because it's used by tools like
|
||||
|
@ -273,6 +299,7 @@ Some examples probably make it clearer::
|
|||
... < V('1.0a2.1')
|
||||
... < V('1.0b1.dev456')
|
||||
... < V('1.0b2')
|
||||
... < V('1.0b2.post345')
|
||||
... < V('1.0c1.dev456')
|
||||
... < V('1.0c1')
|
||||
... < V('1.0.dev456')
|
||||
|
@ -355,38 +382,41 @@ version during PyCon 2009, 4287 of them:
|
|||
suggestion
|
||||
- 3474 (81.04%) match when using this suggestion method
|
||||
|
||||
When a tool needs to work with versions, the best strategy is to use
|
||||
When a tool needs to work with versions, a strategy is to use
|
||||
``suggest_rational_version`` on the versions string. If this function returns
|
||||
``None``, it means that the provided version is not close enough to the
|
||||
standard scheme::
|
||||
standard scheme. If it returns a version that slighlty differs from
|
||||
the original version, it's a suggested rational version. Last, if it
|
||||
returns the same string, it means that the version matches the scheme.
|
||||
|
||||
Here's an example of usage ::
|
||||
|
||||
>>> from verlib import suggest_rational_version, RationalVersion
|
||||
>>> import warnings
|
||||
>>> def validate_version(version):
|
||||
... rversion = suggest_rational_version(version)
|
||||
... if rversion is None:
|
||||
... raise ValueError('Cannot work with "%s"' % version)
|
||||
... if rversion != version:
|
||||
... warnings.warn('"%s" is not a rational version, '
|
||||
... 'it has been transformed into "%s" '
|
||||
... 'for interoperability.' % (version, rversion))
|
||||
... return RationalVersion(rversion)
|
||||
...
|
||||
|
||||
>>> validate_version('2.4rc1')
|
||||
__main__:8: UserWarning: "2.4rc1" is not a rational version, it has been transformed into "2.4c1" for interoperability.
|
||||
RationalVersion('2.4c1')
|
||||
|
||||
>>> validate_version('2.4c1')
|
||||
RationalVersion('2.4c1')
|
||||
|
||||
>>> validate_version('foo')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
File "<stdin>", line 1, in <module>
|
||||
File "<stdin>", line 4, in validate_version
|
||||
ValueError: Cannot work with "foo"
|
||||
|
||||
>>> validate_version('1.24.33')
|
||||
RationalVersion('1.24.33')
|
||||
|
||||
>>> validate_version('1.24.330pre1')
|
||||
RationalVersion('1.24.330c1')
|
||||
|
||||
>>> validate_version('2008.12.11')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Cannot work with "2008.12.11"
|
||||
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
|
|
Loading…
Reference in New Issue