Differences between revisions 1 and 17 (spanning 16 versions)
Revision 1 as of 2009-03-28 01:00:28
Size: 38
Editor: 67
Comment:
Revision 17 as of 2009-03-28 18:59:18
Size: 8773
Editor: 67
Comment:
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

=== Larry Hastings ===
Sorry for the crazy moon proposal here, but I have example code that I think even works. (Though I'm not operating on enough sleep, so sorry 'cause I already know the code is crappy.)
[[attachment:lch.version.py]]

The basic idea:
 * A version string should be transformable into a version tuple.
 * Version tuples are tuples of arbitrary length containing only integers.
 * A version tuple conceptually ends with an infinite number of 0 fields; (1,3) == (1, 3, 0, 0, 0)
 * While you see integers, accumulate them, and when it's done int().
 * While you see alphanumerics, accumulate them, and when it's done map it if it's a known string ("alpha", "beta") otherwise break up the characters into individual numbers.
 * Pre-releases (alpha, beta) are represented by having a negative number in the version tuple.
 * When you compare version tuples, if there are any negative fields, split there and compare the non-negative parts first.

I doubt y'all will go for this. But I thought you should at least consider supporting a more flexible format. People like to express their version numbers a wide variety of ways, and most folks could find a way to map their personal weird approach to something this approach would make consistent.

=== Erik LaBianca ===

Just throwing this out there since it's a little different from what was discussed earlier, but I think has some merit:

* Versions are a series of integers. Ie 0.0.1, 1.0.0, or 12.5.7.9. Versions define the "intended API level" of the software in question.

Pre-release versions are denoted by a version, followed by a string (I suggest "pre" but it doesn't really matter), followed by a series of integers, seperated by periods if needed. Pre-releases are important because while they may be an implementation of a future API version, they are likely to be buggy or incomplete.

* For instance 1.0.0pre2.1 > 1.0.0pre2 > 1.0.0pre1 < 1.0.0.

* Or for the case of daily builds, 1.0.0pre1 > 1.0.0pre0.20090327 < 1.0.0

This obviously trades away the flexibility of roll-your-own naming entirely, but makes up for it by defining a standard that leaves enough flexibility to represent most cases easily. It is easy to parse and explain, extensible, and able to cover most use cases aside from that of "backported bug fixes". I believe that eliminating words will be a net positive because it eliminates any complaints along the lines of "you included alpha, beta, and rc but where's pre-release or testing?!".

=== Trent Mick ===

The proposal that I believe we tentatively were agreeing on towards the end of last night's Open Space
is basically distutil's `StrictVersion` plus the allowance of 'c' for "release candidates".

{{{
    Good:
        1.2 # equivalent to "1.2.0"
        1.2.0
        1.2a1
        1.2.3a2
        1.2.3b1
        1.2.3c1
    Bad:
        1 # mininum two numbers
        1.2.3.4 # max 3 numbers
        1.2a # release level must have a release serial
        1.2.3b
}}}

Code for this: [[attachment:verlib.py]]

Two stabs and what we discussed. We should pick *one* of these (or, of course, one of the
other proposals here):

* `RationalVersion1`
  Close to distutils' `StrictVersion` in that it only allows between 2 and 3
  `<num>.` sections. I.e. "1.2.3", but not "1.2.3.4".

* `RationalVersion2`
  Allows any number of `<num>.` sections (still must be at least 2 of them).


{{{
>>> from verlib import *
>>> V = RationalVersion1

>>> V('1.2.3')
1.2.3
>>> V('1.2.3').info
(1, 2, 3, None, 0)

>>> V('1.2.3a4')
'1.2.3a4'
>>> V('1.2.3a4').info
(1, 2, 3, 'a', 4)

>>> (V('1.0.0') > V('1.0.0c2') > V('1.0.0c1') > V('1.0.0b2') > V('1.0.0b1')
... > V('1.0.0a2') > V('1.0.0a1'))
True
}}}

Some stats against the list of current `PyPI` versions that MvL provided:

{{{
-- matches againsts current PyPI versions
count: 4975
RationalVersion1 matches: 1986 (39.92%)
RationalVersion2 matches: 2386 (47.96%)
-- with some naive cleaning up of PyPI versions (e.g. '1.0-alpha1' -> '1.0a1')
cleaned RationalVersion1 matches: 2499 (50.23%)
cleaned RationalVersion2 matches: 3003 (60.36%)
}}}


A link from RubyGems that might be interesting:

* Version Policy: http://rubygems.org/read/chapter/7

    Because RubyGems provides support for version comparisons, we want to pick a policy that works well with the RubyGems comparisons and gives the end user what they expect. We call such a policy “rational”. Also, if we call non-working policies “irrational”, then we apply a little bit of social engineering to gently prod offenders to conform.



=== Georg Brandl ===

Simple modification of Larry's proposal: split the tuple at the "tag" (defined by an alpha part in the version number), and allow only one tag. Map alpha, beta and rc to known negative values, and every other tag to a value lower than all of these (so that setuptools' .dev-r102 would still work correctly).

Sample implementations at [[attachment:gb.version.py]].


=== Tom Crawley ===

The setuptools versioning scheme is described [[http://peak.telecommunity.com/DevCenter/setuptools#specifying-your-project-s-version|here]]. It is pretty similiar to the schemes which have been proposed so far. The setuptools versioning scheme should meet most of our needs and has found wide acceptance in the community. Neither of the two current distuils versioning schemes are widely used. The setuptools versioning scheme is geared to the needs of developers who are the primary audience of distuils and provides a useful scheme for controlling software releases.

Third party packagers each have their own version schemes with their own features and idiosyncracies . We cannot accomodate every third party packager within the Python versioning scheme. We should focus primarily on the needs of developers as without developer buyin the scheme will not be adopted. We can accomodate third parties by allowing inclusion of packager specific version numbers with the metadata that is distributed with the Python application distribution. This would look something like:
{{{
version = 1.0.pre1

[rpm]
version = 1.0

}}}

This would enable a version numbering scheme per packaging scheme and would also allow for extensibility as new packaging schemes are developed. The information in
the tags can be processed downstream by packaging organisations.

The idea put forward by Larry Hastings is an excellent method for converting pre-release and post release tags to a numeric based schema. It could be included as an example of tag scheme conversion from the setuptools versioning scheme to a completely numeric packaging scheme.

=== Dan Callahan ===

Rough sketch of an idea:

A version is a series of "."-separated numeric fields. The introduction of a
non-numeric character anywhere in the version string marks the version as a
pre-release.

For sorting: Compare numeric fields as tuples of integers. For equivalent
numeric versions, prefer ones that do not have any trailing non-numeric fields.

In essence: '3.1' == '3.1.0' > '3.1.rc' > '3.1.0.funtime32'

This simply and flexibly handles pre-release versioning. Post-releases are
handled by incrementing the least significant numeric field.

This is, in essence, the inverse of Loose Version in distutils -- it handles
pre-releases instead of post-releases, but still has room for "non-standard"
annotations.

=== Matthias Klose ===

Pointing to the [[http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version|version numbering scheme used by Debian]], which is in production use for many years. Pointing out some points:

 * It is a strict system, not relying on heuristics and any special meanings of strings like alpha, beta, rc, pre.


 * It allows correction of a bad version number by allowing prefixing the version by an epoch (: character).

 * It allows to write a version number very close to the upstream version, handling parts of the version number which should be considered less than another version (using the tilde character), e.g. 1.0~alpha1 < 1.0.

 * The paragraph about the "debian_revision" mentioned in the referenced URL is not appropriate for a python version. It would be nice if the version system could handle this revisions usually by packages for distributions of operating systems.

 * Characters which cannot directly be encoded on the filesystem can be encoded using %<hexvalue> and be used when the version number needs to be encoded in a file name.

Examples:
{{{
  1.0 < 1.0.0 < 1.0.1 < 1.1 < 1.10

  2.1 < 1:1.0

  3.1~~svn20090328 < 3.1~alpha1 < 3.1
}}}

Describe DistutilsVersionFight here.

Larry Hastings

Sorry for the crazy moon proposal here, but I have example code that I think even works. (Though I'm not operating on enough sleep, so sorry 'cause I already know the code is crappy.) lch.version.py

The basic idea:

  • A version string should be transformable into a version tuple.
  • Version tuples are tuples of arbitrary length containing only integers.
  • A version tuple conceptually ends with an infinite number of 0 fields; (1,3) == (1, 3, 0, 0, 0)
  • While you see integers, accumulate them, and when it's done int().
  • While you see alphanumerics, accumulate them, and when it's done map it if it's a known string ("alpha", "beta") otherwise break up the characters into individual numbers.
  • Pre-releases (alpha, beta) are represented by having a negative number in the version tuple.
  • When you compare version tuples, if there are any negative fields, split there and compare the non-negative parts first.

I doubt y'all will go for this. But I thought you should at least consider supporting a more flexible format. People like to express their version numbers a wide variety of ways, and most folks could find a way to map their personal weird approach to something this approach would make consistent.

Erik LaBianca

Just throwing this out there since it's a little different from what was discussed earlier, but I think has some merit:

* Versions are a series of integers. Ie 0.0.1, 1.0.0, or 12.5.7.9. Versions define the "intended API level" of the software in question.

Pre-release versions are denoted by a version, followed by a string (I suggest "pre" but it doesn't really matter), followed by a series of integers, seperated by periods if needed. Pre-releases are important because while they may be an implementation of a future API version, they are likely to be buggy or incomplete.

* For instance 1.0.0pre2.1 > 1.0.0pre2 > 1.0.0pre1 < 1.0.0.

* Or for the case of daily builds, 1.0.0pre1 > 1.0.0pre0.20090327 < 1.0.0

This obviously trades away the flexibility of roll-your-own naming entirely, but makes up for it by defining a standard that leaves enough flexibility to represent most cases easily. It is easy to parse and explain, extensible, and able to cover most use cases aside from that of "backported bug fixes". I believe that eliminating words will be a net positive because it eliminates any complaints along the lines of "you included alpha, beta, and rc but where's pre-release or testing?!".

Trent Mick

The proposal that I believe we tentatively were agreeing on towards the end of last night's Open Space is basically distutil's StrictVersion plus the allowance of 'c' for "release candidates".

    Good:
        1.2         # equivalent to "1.2.0"
        1.2.0
        1.2a1
        1.2.3a2
        1.2.3b1
        1.2.3c1
    Bad:
        1           # mininum two numbers
        1.2.3.4     # max 3 numbers
        1.2a        # release level must have a release serial
        1.2.3b

Code for this: verlib.py

Two stabs and what we discussed. We should pick *one* of these (or, of course, one of the other proposals here):

* RationalVersion1

  • Close to distutils' StrictVersion in that it only allows between 2 and 3 <num>. sections. I.e. "1.2.3", but not "1.2.3.4".

* RationalVersion2

  • Allows any number of <num>. sections (still must be at least 2 of them).

>>> from verlib import *
>>> V = RationalVersion1

>>> V('1.2.3')
1.2.3
>>> V('1.2.3').info
(1, 2, 3, None, 0)

>>> V('1.2.3a4')
'1.2.3a4'
>>> V('1.2.3a4').info
(1, 2, 3, 'a', 4)

>>> (V('1.0.0') > V('1.0.0c2') > V('1.0.0c1') > V('1.0.0b2') > V('1.0.0b1') 
...  > V('1.0.0a2') > V('1.0.0a1'))
True

Some stats against the list of current PyPI versions that MvL provided:

-- matches againsts current PyPI versions
count: 4975
RationalVersion1 matches: 1986 (39.92%)
RationalVersion2 matches: 2386 (47.96%)
-- with some naive cleaning up of PyPI versions (e.g. '1.0-alpha1' -> '1.0a1')
cleaned RationalVersion1 matches: 2499 (50.23%)
cleaned RationalVersion2 matches: 3003 (60.36%)

A link from RubyGems that might be interesting:

* Version Policy: http://rubygems.org/read/chapter/7

  • Because RubyGems provides support for version comparisons, we want to pick a policy that works well with the RubyGems comparisons and gives the end user what they expect. We call such a policy “rational”. Also, if we call non-working policies “irrational”, then we apply a little bit of social engineering to gently prod offenders to conform.

Georg Brandl

Simple modification of Larry's proposal: split the tuple at the "tag" (defined by an alpha part in the version number), and allow only one tag. Map alpha, beta and rc to known negative values, and every other tag to a value lower than all of these (so that setuptools' .dev-r102 would still work correctly).

Sample implementations at gb.version.py.

Tom Crawley

The setuptools versioning scheme is described here. It is pretty similiar to the schemes which have been proposed so far. The setuptools versioning scheme should meet most of our needs and has found wide acceptance in the community. Neither of the two current distuils versioning schemes are widely used. The setuptools versioning scheme is geared to the needs of developers who are the primary audience of distuils and provides a useful scheme for controlling software releases.

Third party packagers each have their own version schemes with their own features and idiosyncracies . We cannot accomodate every third party packager within the Python versioning scheme. We should focus primarily on the needs of developers as without developer buyin the scheme will not be adopted. We can accomodate third parties by allowing inclusion of packager specific version numbers with the metadata that is distributed with the Python application distribution. This would look something like:

version = 1.0.pre1

[rpm]
version = 1.0

This would enable a version numbering scheme per packaging scheme and would also allow for extensibility as new packaging schemes are developed. The information in the tags can be processed downstream by packaging organisations.

The idea put forward by Larry Hastings is an excellent method for converting pre-release and post release tags to a numeric based schema. It could be included as an example of tag scheme conversion from the setuptools versioning scheme to a completely numeric packaging scheme.

Dan Callahan

Rough sketch of an idea:

A version is a series of "."-separated numeric fields. The introduction of a non-numeric character anywhere in the version string marks the version as a pre-release.

For sorting: Compare numeric fields as tuples of integers. For equivalent numeric versions, prefer ones that do not have any trailing non-numeric fields.

In essence: '3.1' == '3.1.0' > '3.1.rc' > '3.1.0.funtime32'

This simply and flexibly handles pre-release versioning. Post-releases are handled by incrementing the least significant numeric field.

This is, in essence, the inverse of Loose Version in distutils -- it handles pre-releases instead of post-releases, but still has room for "non-standard" annotations.

Matthias Klose

Pointing to the version numbering scheme used by Debian, which is in production use for many years. Pointing out some points:

  • It is a strict system, not relying on heuristics and any special meanings of strings like alpha, beta, rc, pre.
  • It allows correction of a bad version number by allowing prefixing the version by an epoch (: character).
  • It allows to write a version number very close to the upstream version, handling parts of the version number which should be considered less than another version (using the tilde character), e.g. 1.0~alpha1 < 1.0.

  • The paragraph about the "debian_revision" mentioned in the referenced URL is not appropriate for a python version. It would be nice if the version system could handle this revisions usually by packages for distributions of operating systems.
  • Characters which cannot directly be encoded on the filesystem can be encoded using %<hexvalue> and be used when the version number needs to be encoded in a file name.

Examples:

  1.0 < 1.0.0 < 1.0.1 < 1.1 < 1.10

  2.1 < 1:1.0

  3.1~~svn20090328 < 3.1~alpha1 < 3.1

Distutils/VersionComparison (last edited 2009-05-11 08:52:26 by dslb-088-064-058-218)

Unable to edit the page? See the FrontPage for instructions.