├── .gitignore ├── setup.cfg ├── tox.ini ├── tests.py ├── setup.py ├── setuptools_git_version.py └── README.rst /.gitignore: -------------------------------------------------------------------------------- 1 | /.cache/ 2 | /.tox/ 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = 3 | --strict 4 | --flakes 5 | --pep8 6 | tests.py 7 | pep8ignore = E501 8 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27, py34 3 | 4 | [testenv] 5 | usedevelop = true 6 | deps = 7 | pytest 8 | pytest-flakes 9 | pytest-pep8 10 | commands = 11 | py.test {posargs} 12 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | from pytest import mark 2 | from setuptools_git_version import format_version 3 | 4 | 5 | @mark.parametrize('git_describe, version', [ 6 | ('v25.6-879-gca0be43', 'v25.6.dev879+ca0be43'), 7 | ('28-0-gca0be43', '28'), 8 | ('28.0-0-gca0be43', '28.0'), 9 | ('28.0-1-gca0be43', '28.0.dev1+ca0be43'), 10 | ]) 11 | def test_git_describe(git_describe, version): 12 | fmt = '{tag}.dev{commitcount}+{gitsha}' 13 | assert format_version(git_describe, fmt) == version 14 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name='setuptools-git-version', 6 | version='1.0.4', 7 | url='https://github.com/pyfidelity/setuptools-git-version', 8 | author='pyfidelity UG', 9 | author_email='mail@pyfidelity.com', 10 | description='Automatically set package version from Git.', 11 | license='http://opensource.org/licenses/MIT', 12 | classifiers=[ 13 | 'Framework :: Setuptools Plugin', 14 | 'Intended Audience :: Developers', 15 | 'License :: OSI Approved :: MIT License', 16 | 'Programming Language :: Python', 17 | ], 18 | py_modules=['setuptools_git_version'], 19 | install_requires=[ 20 | 'setuptools >= 8.0', 21 | ], 22 | entry_points=""" 23 | [distutils.setup_keywords] 24 | version_format = setuptools_git_version:validate_version_format 25 | [console_scripts] 26 | setuptools-git-version = setuptools_git_version:get_git_version 27 | """, 28 | ) 29 | -------------------------------------------------------------------------------- /setuptools_git_version.py: -------------------------------------------------------------------------------- 1 | from pkg_resources import get_distribution 2 | from subprocess import check_output 3 | 4 | 5 | command = 'git describe --tags --long --dirty' 6 | fmt = '{tag}.{commitcount}+{gitsha}' 7 | 8 | 9 | def validate_version_format(dist, attr, value): 10 | try: 11 | version = check_output(command.split()).decode('utf-8').strip() 12 | except: 13 | version = get_distribution(dist.get_name()).version 14 | else: 15 | version = format_version(version=version, fmt=value) 16 | dist.metadata.version = version 17 | 18 | 19 | def format_version(version, fmt=fmt): 20 | parts = version.split('-') 21 | assert len(parts) in (3, 4) 22 | dirty = len(parts) == 4 23 | tag, count, sha = parts[:3] 24 | if count == '0' and not dirty: 25 | return tag 26 | return fmt.format(tag=tag, commitcount=count, gitsha=sha.lstrip('g')) 27 | 28 | 29 | def get_git_version(): 30 | git_version = check_output(command.split()).decode('utf-8').strip() 31 | return format_version(version=git_version) 32 | 33 | 34 | if __name__ == "__main__": 35 | # determine version from git 36 | git_version = get_git_version() 37 | 38 | # monkey-patch `setuptools.setup` to inject the git version 39 | import setuptools 40 | original_setup = setuptools.setup 41 | 42 | def setup(version=None, *args, **kw): 43 | return original_setup(version=git_version, *args, **kw) 44 | 45 | setuptools.setup = setup 46 | 47 | # import the packages's setup module 48 | import setup 49 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | setuptools-git-version 2 | ====================== 3 | 4 | *Automatically set package version from Git.* 5 | 6 | 7 | Introduction 8 | ------------ 9 | 10 | Instead of hardcoding the package version in ``setup.py`` like: 11 | 12 | .. code-block:: python 13 | 14 | setup( 15 | name='foobar', 16 | version='1.0', 17 | ...) 18 | 19 | this package allows to extract it from the underlying Git repository: 20 | 21 | .. code-block:: python 22 | 23 | setup( 24 | name='foobar', 25 | version_format='{tag}.dev{commitcount}+{gitsha}', 26 | setup_requires=['setuptools-git-version'], 27 | ...) 28 | 29 | Please ensure that your git repository has at least one `annotated tag `_, 30 | as ``setuptools-git-version`` will uses tags to determine your current git version. 31 | 32 | Fields 33 | ------ 34 | ``setuptools-git-version`` provides three fields as options for the ``version_format`` string: 35 | 36 | * ``tag``: The latest tag (probably a release version like ``v1.0.3``) in your repository 37 | * ``commitcount``: The number of additional commits on top of this tag (e.g. ``13``) 38 | * ``gitsha``: An abbreviated commit hash of the latest commit in your repository 39 | 40 | Implementation Details 41 | ---------------------- 42 | 43 | ``setuptools-git-version`` uses the following git command to obtain commit information: 44 | 45 | .. code-block:: bash 46 | 47 | git describe --tags --long --dirty 48 | 49 | To ensure that ``setuptools-git-version`` is compatible with your project, please ensure this command runs correctly in 50 | your repository 51 | 52 | 53 | Changes 54 | ------- 55 | 56 | 1.0.4 - 2016-06-22 57 | ++++++++++++++++++ 58 | 59 | - [feature] allow to build a package using a git-based version without modifying it upfront 60 | 61 | 1.0.3 - 2015-04-23 62 | ++++++++++++++++++ 63 | 64 | - [bugfix] rename module to avoid import conflicts 65 | 66 | 67 | 1.0.2 - 2015-04-14 68 | ++++++++++++++++++ 69 | 70 | - [bugfix] make it work with Python 3(.4) 71 | 72 | 73 | 1.0.1 - 2015-04-14 74 | ++++++++++++++++++ 75 | 76 | - brownbag release 77 | 78 | 79 | 1.0 - 2015-04-10 80 | ++++++++++++++++ 81 | 82 | - initial public release 83 | 84 | --------------------------------------------------------------------------------