Last active
July 13, 2019 03:13
-
-
Save gregschmit/2d508019423c655837e569be7a3f9f72 to your computer and use it in GitHub Desktop.
A `version.py` to include in Django apps that provides an interface for git versioning. In `setup.py` (in the parent directory) you can `from purge import version` and then use `version.get_version()` to get the version programmatically.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This module provides versioning hooks for a Python package in a Git repository. | |
Verbiage: MAJOR.MINOR.PATCH | |
To start versioning at 0.1.x, just do ``git tag -a v0.1 -m 'version 0.1'``. Each | |
commit will increment the PATCH level by 1 according to this module's | |
``get_version()``. When you want to increment the MINOR, just do ``git tag -a | |
v0.2 -m 'version 0.2'``. | |
In your ``setup.py`` you should stamp the directory so when you generate your | |
package sdist/bdist, the ``VERSION_STAMP`` exists (since your sdist/bdist won't | |
have the ``.git`` directory telling the user which version they have): | |
from my_module_name import version | |
version.stamp_directory('./my_module_name') | |
You should also get the version from ``get_version`` and ensure your | |
``VERSION_STAMP`` gets included in your sdists/bdists, like: | |
... | |
setup( | |
name='my-module-name', | |
version=version.get_version(), | |
packages=find_packages(), | |
include_package_data=True, | |
package_data={'my_module_name': ['VERSION_STAMP']}, | |
... | |
At the end of your ``setup.py`` you should un-stamp the directory: | |
... | |
version.unstamp_directory('./my_module_name') | |
Finally, source distributions don't listen to ``package_data`` instructions, so | |
you need to include the following in a ``MANIFEST.in`` file in the same | |
directory as ``setup.py``: | |
include */VERSION_STAMP | |
""" | |
import os | |
from subprocess import Popen, PIPE, STDOUT | |
def cmd_out(cmd): | |
""" | |
Helper for running shell commands. | |
""" | |
wd = os.path.dirname(os.path.realpath(__file__)) | |
p = Popen(cmd, shell=True, cwd=wd, stdout=PIPE, stderr=STDOUT) | |
r, _ = p.communicate() | |
res = r.strip().decode() | |
return res, p.returncode | |
def get_version(): | |
""" | |
Get the version, first by trying to read the ``VERSION_STAMP``, and if that | |
fails, by attempting to use ``git`` annotated tags. | |
""" | |
git_options = ['git', '/usr/local/bin/git', '/usr/bin/git'] | |
d = os.path.dirname(os.path.realpath(__file__)) | |
try: | |
x = open(os.path.join(d, 'VERSION_STAMP'), 'rb').read().strip().decode() | |
if x: return x | |
except OSError: | |
pass | |
for g in git_options: | |
gitver, _ = cmd_out('{0} describe --tags --always'.format(g)) | |
gitchanged, _ = cmd_out('{0} diff-index HEAD --'.format(g)) | |
gitver = gitver.replace('v', '').split('-g')[0].replace('-', '.') | |
if ' ' in gitver: gitver = '0' | |
else: break | |
if not gitver or 'fatal' in gitver or '\n' in gitver: | |
return '0' | |
if gitchanged.strip(): | |
gitver += '+changed' | |
return gitver | |
def stamp_directory(d): | |
""" | |
Write the ``VERSION_STAMP`` file. | |
""" | |
v = get_version() | |
with open(os.path.join(d, 'VERSION_STAMP'), 'wb') as f: | |
f.write(v.encode() + b'\n') | |
def unstamp_directory(d): | |
""" | |
Remove the ``VERSION_STAMP`` file. | |
""" | |
os.remove(os.path.join(d, 'VERSION_STAMP')) | |
if __name__ == '__main__': | |
print(get_version()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment