On Sat, Jun 10, 2017 at 6:59 AM, Guenter Milde via Docutils-develop
Post by Guenter Milde`sys.version_info` shows that it is fairly easy to design a
`version_info` tuple that sorts versions chronologically.
...
Post by Guenter Mildea) Name the releaselevels so that alphabetical sorting matches release
chronology.
b) Invert the meaning of the boolean value in the last item because in
Python False < True and we need "repository" < "release"
...
Post by Guenter MildeWith this scheme, `docutils.__version_info__` will sort in chronological
order. A client requiring a feature introduced in 0.14.rc2 can check in a
if __version_info__ > (0, 14, 'candidate', 2, True)
It's easy, it's done. See patch below.
@David: OK to commit?
Not yet. Lots of issues, below.
Why has docutils `__version_info__` but sys `version_info`?
Because we have docutils.__version__ and docutils.__version_details__.
So docutils.__version_info__ matches that pattern.
Python has a multitude of modules and packages, so the version info
can go in a specific module. If we want to do the same thing, it would
be something like docutils.utils.version_info or
docutils.utils.version.info. I'd rather leave it as
docutils.__version_info__.
Index: test/test__init__.py
===================================================================
--- test/test__init__.py (Revision 8102)
+++ test/test__init__.py (Arbeitskopie)
@@ -23,6 +23,45 @@
err = docutils.ApplicationError(u'\u0169')
self.assertEqual(unicode(err), u'\u0169')
+ self.assertEqual(len(docutils.__version_info__), 6)
+ self.assertEqual(type(docutils.__version_info__.major), int)
+ self.assertEqual(type(docutils.__version_info__.minor), int)
+ self.assertEqual(type(docutils.__version_info__.micro), int)
+ self.assertEqual(type(docutils.__version_info__.releaselevel), str)
+ self.assertEqual(type(docutils.__version_info__.serial), int)
Missing a test for .release::
+ self.assertEqual(type(docutils.__version_info__.release), bool)
+
+ """Return version identifier matching `version_info`."""
+ identifier = '%s.%s%s' % (version_info.major, version_info.minor,
+ '.%s' % version_info.micro if version_info.micro else '')
+ identifier += 'rc' + str(version_info.serial)
That's too simple. It should check the releaselevel string, and use a
lookup table.
Replace "released" with "release" globally.
+ identifier += '.dev'
+ return identifier
+
+ self.assertEqual(docutils.__version__, self.version_info2identifier(
+ docutils.__version_info__))
+
+ identifiers = ['0.13.1',
+ '0.14.dev',
+ '0.14rc1',
+ '0.14rc2.dev',
+ '0.14rc2',
+ '0.14',
+ '0.14.1.dev',
+ '0.14.1rc1.dev',
+ '0.14.1rc1',
+ '0.14.1']
+ version_infos = [docutils.identifier2version_info(identifier)
+ for identifier in identifiers]
+ self.assertEqual(version_infos, sorted(version_infos))
+
+
unittest.main()
Index: docutils/__init__.py
===================================================================
--- docutils/__init__.py (Revision 8102)
+++ docutils/__init__.py (Arbeitskopie)
@@ -50,35 +50,35 @@
- writers: Format-specific output translators.
"""
-import sys
+import re, sys
-1 on parsing the version string into __version_info__. So we don't
need to import re.
As I wrote in a docstring in docutils.__init__: "Rather than parsing
the `__version__` text, use `__version_info__`." It would be
incredibly hypocritical for us to say this then go ahead and do it
ourselves.
from collections import namedtuple
+ VersionInfo = namedtuple('version_info',
+ 'major minor micro releaselevel serial released')
If we do this, the names should match::
version_info = namedtuple('version_info', ...)
Replace "released" with "release" globally.
- namedtuple = None
+ self.keys = tuple('major minor micro releaselevel serial released'.split())
+ setattr(self, key, arg)
+ return 'version_info(' + ', '.join(
+ ['%s=%r' % (key, getattr(self, key))
+ for key in self.keys]) + ')'
+ return cmp(tuple(getattr(self, key) for key in self.keys), other)
+
+
This seems far too clever to me. And why add code that we're just
going to strip away soon? Let's just stick to a simple static tuple.
__docformat__ = 'reStructuredText'
-__version_info__ = (0, 14, 0, 'rc', 2, True)
- __version_info__ = (
- namedtuple(
- 'version_info',
- ['major', 'minor', 'micro', 'releaselevel', 'serial', 'development'])
- (*__version_info__))
+__version__ = '0.14rc2.dev'
-__version__ = '%s.%s%s%s%s%s' % (
- __version_info__[0], # major
- __version_info__[1], # minor
- ('.%s' % __version_info__[2]) if __version_info__[2] else '', # micro
- __version_info__[3], # releaselevel
- __version_info__[4] if __version_info__[4] else '', # serial
- '.dev' if __version_info__[5] else '') # development
-
major.minor[.micro][{releaselevel}serial][.dev]
* The major number will be bumped when the project is feature-complete, and
@@ -85,20 +85,58 @@
later if there is a major change in the design or API.
* The minor number is bumped whenever there are new features.
* The micro number is bumped for bug-fix releases. Omitted for micro=0.
-* The releaselevel string is used for pre-releases, one of 'a' (alpha),
- 'b' (beta), or 'rc' (release candidate). Omitted for final releases.
-* The serial number is used when
-* The '.dev' suffix indicates active development, unreleased, before the
- version indicated.
+* Pre-releases are marked by appended 'rc' + serial number.
+* The '.dev' suffix indicates snapshots and installs from the repository.
Rather than parsing the `__version__` text, use `__version_info__`.
"""
-__version_details__ = 'repository'
+_version_regexp = re.compile(r"""
+ (?P<release>
+ (?P<major>[0-9]+)
+ \.(?P<minor>[0-9]+)
+ (\.(?P<micro>[0-9]+))?
+ )
+ (?P<pre> # pre-release segment
+ (?P<pre_l>(a|b|rc))
+ (?P<pre_n>[0-9]+)?
+ )?
+ (\.(?P<dev>dev))? # dev segment
+ """, re.VERBOSE)
+
+ """Convert Docutils version identifier to a `version_info` namedtuple"""
+ segments = _version_regexp.match(identifier).groupdict()
+ releaselevel = 'candidate'
+ releaselevel = ''
+ releaselevel = 'final'
+ return VersionInfo(
+ major=int(segments['major']),
+ minor=int(segments['minor']),
+ micro=segments['micro'] and int(segments['micro']) or 0,
+ releaselevel=releaselevel,
+ serial=segments['pre_n'] and int(segments['pre_n']) or 0,
+ released=not segments['dev'])
+
+__version_info__ = identifier2version_info(__version__)
+
-1. Way too complicated, without a need or benefit. The correct
process is to build the identifier string from the static components,
rather than parsing the string into the components.
-1, too clever, not needed. In addition to checking
docutils.__version_details__, we want to be able to just look at the
docutils/__init__.py source and see the same thing. It should be a
simple static string.
+__version_details__ = ''
"""Extra version details (e.g. 'snapshot 2005-05-29, r3410', 'repository',
'prerelease', 'release'), modified automatically & manually."""
+ __version_details__ = 'repository'
+ __version_details__ = 'prerelease'
+ __version_details__ = 'release'
Way too complicated. I can't even tell if this is correct. The code
can be in development state (i.e., 'repository') while it's in the
releaselevel='candidate' state.
Release level ( __version_info__.releaselevel) and
__version_info__.release are orthogonal. __version_details__ is
related to both.
And this is way too much code to add to docutils/__init__.py. Removing
the unnecessary cleverness should drop the line count. But if a
significant amount of these additions survive review (e.g.
identifier2version_info), it should go in docutils/utils/ instead (in
__init__.py or a new module).
Let's spell out the sequence of versions, past, present, & future, as
if we had been using the __version_info__ structure we're discussing.
Note, this is what we *should have been doing*. What we actually did
is mentioned in comments. Can we agree on this sequence?
1. Docutils 0.12 was released on 2014-07-06:
version=0.12.0 # short for major=0, minor=12, micro=0
releaselevel='final'
serial=0
release=True
__version__='0.12'
__version_details__='release'
2. Development of Docutils 0.13 commenced immediately afterwards:
version=0.13.0
releaselevel='alpha'
serial=0
release=False
__version__='0.13a0.dev' # was actually '0.13'
__version_details__='repository'
3. Docutils 0.13 was announced on 2016-12-05 (no alpha or release
candidate), but there was no release:
version=0.13.0
releaselevel='final'
serial=0
release=True
__version__='0.13'
__version_details__='release'
4. An issue with the Docutils versioning scheme was noted
(https://sourceforge.net/p/docutils/feature-requests/50/) and
Docutils 0.13.1 was released on 2016-12-09:
version=0.13.1
releaselevel='final'
serial=0
release=True
__version__='0.13.1'
__version_details__='release'
5. Development of Docutils 0.13.2 commenced immediately afterwards:
version=0.13.2
releaselevel='alpha'
serial=0
release=False
__version__='0.13.2a0.dev' # was actually '0.13.2a'
__version_details__='repository'
6. Docutils 0.14rc1 was released on 2017-05-27. First there was a
'prerelease' in r8076:
version=0.14.0
releaselevel='alpha'
serial=0
release=False
__version__='0.14a0.dev' # was actually '0.14.0a' in r8076,
# changed to '0.14a0' in r8081
__version_details__='prerelease'
Then the actual release was cut in r8087:
version=0.14.0
releaselevel='candidate'
serial=1
release=True
__version__='0.14rc1'
__version_details__='prerelease'
7. Immediately afterward, in r8089:
version=0.14.0
releaselevel='candidate'
serial=2
release=False
__version__='0.14rc2.dev' # was actually '0.14rc2' in r8089,
# changed to '0.14rc2.dev' in r8091
__version_details__='repository'
8. Upcoming release of Docutils 0.14rc2:
version=0.14.0
releaselevel='candidate'
serial=2
release=True
__version__='0.14rc2'
__version_details__='prerelease'
9. Immediately afterward, in preparation for the final release:
version=0.14.0
releaselevel='final'
serial=0
release=False
__version__='0.14.dev'
__version_details__='repository'
10. The final release of Docutils 0.14:
version=0.14.0
releaselevel='final'
serial=0
release=True
__version__='0.14'
__version_details__='release'
11. Immediately afterward, the trunk becomes:
version=0.15.0
releaselevel='alpha'
serial=0
release=False
__version__='0.15a0.dev'
__version_details__='repository'
12. If we need to cut a bugfix release of 0.14, we'll create a branch
off step 10 and set:
version=0.14.1
releaselevel='alpha'
serial=0
release=False
__version__='0.14.1a0.dev'
__version_details__='repository'
David Goodger
<http://python.net/~goodger>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Docutils-develop mailing list
Docutils-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/docutils-develop
Please use "Reply All" to reply to the list.