Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .bzrignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
build
dist
*.egg-info
.tox
__pycache__
.tox
build
dist
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.egg-info
*.pyc
.tox
__pycache__
build
dist
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
language: python
install:
sudo apt-get install git bzr
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
- "3.4"
script: python setup.py test
31 changes: 31 additions & 0 deletions doc/changes.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
Release history
***************

.. _version_1_10:

Version 1.10
============

* Add support for python3.2, python3.3 and python3.4. This represents the
current Ubuntu LTS release (12.04), current Debian testing release and
upcoming Ubuntu LTS release (14.04). This is where the development happens now
so support for 3.x is now first-class and should be promptly fixed, if any
bugs are discovered.
* Drop support for python2.4, python2.5, python3.0 and python3.1. Those
versions are either very old and not actively used anymore, except for legacy
systems or represent the early, virtually unused python3 versions. Support
for python2.7 will be retained indefinitely. The status of 2.6 is uncertain
as it's not used by any systems I'm interested in anymore and I cannot test
it easily.
* Split off :class:`versiontools.VersionBase` from
:class:`versiontools.Version` so that it can be used outside of the VCS
context. This allows for derivative versions classes to easily reuse the
common parts. The normal Version class is now just focused on discovering
version control system.
* Add :class:`versiontools.git_support.GitShellIntegration` that does not
depend on python git classes and instead parses git output. It is therefore
more likely to just work out of the box on otherwise empty virtualenv. It
also provides good support for python3.x without being bound to python-git.
* Add :class:`versiontools.bzr_support.BzrShellIntegration` that does not
depend on python2.x bzr classes and instead parses bzr output. It is
therefore more likely to just work out of the box on otherwise empty
virtualenv. It also provides good support for python3.x without being bound
to bzrlib that is likely going to stay on python2.7 forever.

.. _version_1_9_1:

Version 1.9.1
Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Version Tools Documentation
===========================

.. seealso:: To get started quickly see :ref:`usage`
.. seealso:: See what's new in :ref:`version_1_9_1`
.. seealso:: See what's new in :ref:`version_1_10`

.. note::
This document may be out of date, the bleeding edge version is always
Expand Down
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
entry_points="""
[versiontools.vcs_integration]
bzr=versiontools.bzr_support:BzrIntegration
bzr_sh=versiontools.bzr_support:BzrShellIntegration
git=versiontools.git_support:GitIntegration
git_sh=versiontools.git_support:GitShellIntegration
hg=versiontools.hg_support:HgIntegration
[distutils.setup_keywords]
version=versiontools.setuptools_hooks:version
Expand All @@ -47,13 +49,11 @@
("License :: OSI Approved :: GNU Library or Lesser General Public"
" License (LGPL)"),
"Operating System :: OS Independent",
"Programming Language :: Python :: 2.4",
"Programming Language :: Python :: 2.5",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.0",
"Programming Language :: Python :: 3.1",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Topic :: Software Development :: Version Control",
],
zip_safe=True)
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py24, py25, py26, py27, py31, py32
envlist = py26, py27, py32, py33, py34

[testenv]
commands = {envpython} setup.py test
155 changes: 128 additions & 27 deletions versiontools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
.. note: Since version 1.1 we should conform to PEP 386
"""

__version__ = (1, 9, 1, "final", 0)
__version__ = (1, 10, 0, "dev", 0)
__all__ = ["VersionBase", "Version", "format_version", "handle_version"]


import inspect
Expand All @@ -34,15 +35,15 @@
import sys


class Version(tuple):
class VersionBase(tuple):
"""
Smart version class.

Version class is a tuple of five elements and has the same logical
components as :data:`sys.version_info`.
Base class for Version class.

In addition to the tuple elements there is a special :attr:`vcs` attribute
that has all of the data exported by the version control system.
Keep the core logic without any VCS awareness or support. The VersionBase
class is a tuple of five elements and has the same logical components as
:data:`sys.version_info`.

.. versionadded:: 1.10
"""

_RELEASELEVEL_TO_TOKEN = {
Expand All @@ -59,7 +60,7 @@ def __new__(cls, major, minor, micro=0, releaselevel="final", serial=0):
variables except for releaselevel are silently converted to integers
That is::

>>> Version("1.2.3.dev".split("."))
>>> VersionBase("1.2.3.dev".split("."))
(1, 2, 3, "dev", 0)

:param major:
Expand Down Expand Up @@ -124,8 +125,6 @@ def to_int(v):
("serial must be greater than zero for"
" %s releases") % releaselevel)
obj = tuple.__new__(cls, (major, minor, micro, releaselevel, serial))
object.__setattr__(obj, '_source_tree', cls._find_source_tree())
object.__setattr__(obj, '_vcs', None)
return obj

major = property(
Expand All @@ -148,6 +147,116 @@ def to_int(v):
operator.itemgetter(4),
doc="Serial number")

def __str__(self):
"""
Return a string representation of the version tuple.

The string is not a direct concatenation of all version components.
Instead it's a more natural 'human friendly' version where components
with certain values are left out.

The following table shows how a version tuple gets converted to a
version string.

+-------------------------------+-------------------+
| __version__ | Formatter version |
+===============================+===================+
| ``(1, 2, 0, "final", 0)`` | ``"1.2"`` |
+-------------------------------+-------------------+
| ``(1, 2, 3, "final", 0)`` | ``"1.2.3"`` |
+-------------------------------+-------------------+
| ``(1, 3, 0, "alpha", 1)`` | ``"1.3a1"`` |
+-------------------------------+-------------------+
| ``(1, 3, 0, "beta", 1)`` | ``"1.3b1"`` |
+-------------------------------+-------------------+
| ``(1, 3, 0, "candidate", 1)`` | ``"1.3c1"`` |
+-------------------------------+-------------------+
| ``(1, 3, 0, "dev", 0)`` | ``"1.3.dev"`` |
+-------------------------------+-------------------+
"""
version = "%s.%s" % (self.major, self.minor)
if self.micro != 0:
version += ".%s" % self.micro
token = self._RELEASELEVEL_TO_TOKEN.get(self.releaselevel)
if token:
version += "%s%d" % (token, self.serial)
if self.releaselevel == "dev":
version += ".dev"
return version


class Version(VersionBase):
"""
Smart version class.

Version class is a tuple of five elements and has the same logical
components as :data:`sys.version_info`.

In addition to the tuple elements there is a special :attr:`vcs` attribute
that has all of the data exported by the version control system.
"""

def __new__(cls, major, minor, micro=0, releaselevel="final", serial=0):
"""
Construct a new version tuple.

There is some extra logic when initializing tuple elements. All
variables except for releaselevel are silently converted to integers
That is::

>>> Version("1.2.3.dev".split("."))
(1, 2, 3, "dev", 0)

:param major:
Major version number

:type major:
:class:`int` or :class:`str`

:param minor:
Minor version number

:type minor:
:class:`int` or :class:`str`

:param micro:
Micro version number, defaults to ``0``.

:type micro:
:class:`int` or :class:`str`

:param releaselevel:
Release level name.

There is a constraint on allowed values of releaselevel. Only the
following values are permitted:

* 'dev'
* 'alpha'
* 'beta'
* 'candidate'
* 'final'

:type releaselevel:
:class:`str`

:param serial:
Serial number, usually zero, only used for alpha, beta and
candidate versions where it must be greater than zero.

:type micro:
:class:`int` or :class:`str`

:raises ValueError:
If releaselevel is incorrect, a version component is negative or
serial is 0 and releaselevel is alpha, beta or candidate.
"""
obj = super(Version, cls).__new__(
cls, major, minor, micro, releaselevel, serial)
object.__setattr__(obj, '_source_tree', cls._find_source_tree())
object.__setattr__(obj, '_vcs', None)
return obj

@property
def vcs(self):
"""
Expand Down Expand Up @@ -211,7 +320,7 @@ def from_expression(cls, pkg_expression):
a variable that holds the actual version. The version cannot be a plain
string and instead must be a tuple of five elements as described by the
:class:`~versiontools.Version` class.

The variable that holds the version should be called ``__version__``.
If it is called something else the actual name has to be specified
explicitly in ``pkg_expression`` by appending a colon (``:``) and the
Expand All @@ -225,7 +334,7 @@ def from_expression(cls, pkg_expression):
else:
# Allow people not to include the identifier separator
module_or_package = pkg_expression
identifier = ""
identifier = ""
# Use __version__ unless specified otherwise
if identifier == "":
identifier = "__version__"
Expand Down Expand Up @@ -295,17 +404,9 @@ def __str__(self):
| Mercurial | Tip revision number, e.g. ``54`` |
+-----------+------------------------------------------------+
"""
version = "%s.%s" % (self.major, self.minor)
if self.micro != 0:
version += ".%s" % self.micro
token = self._RELEASELEVEL_TO_TOKEN.get(self.releaselevel)
if token:
version += "%s%d" % (token, self.serial)
if self.releaselevel == "dev":
if self.vcs is not None:
version += ".dev%s" % self.vcs.revno
else:
version += ".dev"
version = super(Version, self).__str__()
if self.releaselevel == "dev" and self.vcs is not None:
version += str(self.vcs.revno)
return version

@classmethod
Expand All @@ -320,8 +421,8 @@ def _find_source_tree(cls):
frame, filename, lineno, func_name, context, context_index = record
if context is None or context_index >= len(context):
continue
if (func_name == "<module>" and "__version__" in
context[context_index]):
if (func_name == "<module>"
and "__version__" in context[context_index]):
caller = frame
break
else:
Expand All @@ -347,7 +448,7 @@ def _query_vcs(self):
if self._source_tree is None:
return
for entrypoint in pkg_resources.iter_entry_points(
"versiontools.vcs_integration"):
"versiontools.vcs_integration"):
try:
integration_cls = entrypoint.load()
integration = integration_cls.from_source_tree(
Expand Down
Loading