Source code for versiontag
import os
import subprocess
import re
import logging
__default_version__ = 'r0.0.0'
logger = logging.getLogger(__name__)
[docs]def __get_git_tag():
"""
Read the Git project version by running ``git describe --tags`` in the current-working-directory.
:return: Project version string
"""
with open(os.devnull, 'wb') as devnull:
version = subprocess.check_output(['git', 'describe', '--tags'], stderr=devnull)
version = version.rstrip()
if hasattr(version, 'decode'):
version = version.decode('utf-8')
return version
[docs]def __get_cache_file():
"""
Get the path to the version cache file.
:return: File path string
"""
return os.path.join(os.getcwd(), 'version.txt')
[docs]def __open_cache_file(mode):
"""
Open the version cache file in the given mode and return the file object.
:param mode: Mode to open file. See `Python file modes <https://docs.python.org/3/library/functions.html#open>`_.
:return: File object
"""
return open(__get_cache_file(), mode)
[docs]def cache_git_tag():
"""
Try to read the current version from git and, if read successfully, cache it into the version cache file. If
the git folder doesn't exist or if git isn't installed, this is a no-op. I.E. it won't blank out a
pre-existing version cache file upon failure.
:return: Project version string
"""
try:
version = __get_git_tag()
with __open_cache_file('w') as vf:
vf.write(version)
except Exception:
version = __default_version__
return version
[docs]def convert_to_pypi_version(version):
"""
Convert a git tag version string into something compatible with `PEP-440 <https://www.python.org/dev/peps/pep-0440/>`_.
:param version: The input version string, normally directly out of git describe.
:return: PEP-440 version string
Usage::
>>> convert_to_pypi_version('r1.0.1') # Normal Releases
1.0.1
>>> convert_to_pypi_version('r1.0.1-dev1') # Dev Releases
1.0.1.dev1
>>> convert_to_pypi_version('r1.0.1-a1') # Alpha Releases
1.0.1a1
>>> convert_to_pypi_version('r1.0.1-b4') # Beta Releases
1.0.1b4
>>> convert_to_pypi_version('r1.0.1-rc2') # RC Releases
1.0.1rc2
>>> convert_to_pypi_version('r1.0.1-12-geaea7b6') # Post Releases
1.0.1.post12
"""
v = re.search('^[r,v]{0,1}(?P<final>[0-9\.]+)(\-(?P<pre>(a|b|rc)[0-9]+))?(\-(?P<dev>dev[0-9]+))?(\-(?P<post>[0-9]+))?(\-.+)?$', version)
if not v:
return __default_version__
# https://www.python.org/dev/peps/pep-0440/#final-releases
version = v.group('final')
# https://www.python.org/dev/peps/pep-0440/#pre-releases
if v.group('pre'):
version += v.group('pre')
# https://www.python.org/dev/peps/pep-0440/#developmental-releases
if v.group('dev'):
version += '.%s' % v.group('dev')
# https://www.python.org/dev/peps/pep-0440/#post-releases
if v.group('post'):
version += '.post%s' % v.group('post')
return version
[docs]def get_version(pypi=False):
"""
Get the project version string.
Returns the most-accurate-possible version string for the current project.
This order of preference this is:
1. The actual output of ``git describe --tags``
2. The contents of the version cache file
3. The default version, ``r0.0.0``
:param pypi: Default False. When True, returns a PEP-440 compatible version string.
:return: Project version string
"""
version = __default_version__
try:
with __open_cache_file('r') as vf:
version = vf.read().strip()
except Exception:
pass
try:
version = __get_git_tag()
except Exception:
pass
if pypi:
version = convert_to_pypi_version(version)
if version == __default_version__:
logger.warning("versiontag could not determine package version using cwd %s. Returning default: %s" % (os.getcwd(), __default_version__))
return version