{ "info": { "author": "Tyler Crumpton", "author_email": "tyler.crumpton@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: ISC License (ISCL)", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Software Development :: Version Control" ], "description": ".. image:: https://travis-ci.org/habnabit/vcversioner.png\n\n===========\nvcversioner\n===========\n\n`Elevator pitch`_: you can write a ``setup.py`` with no version information\nspecified, and vcversioner will find a recent, properly-formatted VCS tag and\nextract a version from it.\n\nIt's much more convenient to be able to use your version control system's\ntagging mechanism to derive a version number than to have to duplicate that\ninformation all over the place. I eventually ended up copy-pasting the same\ncode into a couple different ``setup.py`` files just to avoid duplicating\nversion information. But, copy-pasting is dumb and unit testing ``setup.py``\nfiles is hard. This code got factored out into vcversioner.\n\n\nBasic usage\n-----------\n\nvcversioner installs itself as a setuptools hook, which makes its use\nexceedingly simple::\n\n from setuptools import setup\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={},\n )\n\nThe presence of a ``vcversioner`` argument automagically activates vcversioner\nand updates the project's version. The parameter to the ``vcversioner``\nargument can also be a dict of keyword arguments which |find_version|\nwill be called with.\n\nTo allow tarballs to be distributed without requiring a ``.git`` (or ``.hg``,\netc.) directory, vcversioner will also write out a file named (by default)\n``version.txt``. Then, if there is no VCS program or the program is unable to\nfind any version information, vcversioner will read version information from\nthe ``version.txt`` file. However, this file needs to be included in a\ndistributed tarball, so the following line should be added to ``MANIFEST.in``::\n\n include version.txt\n\nThis isn't necessary if ``setup.py`` will always be run from a checkout, but\notherwise is essential for vcversioner to know what version to use.\n\nThe name ``version.txt`` also can be changed by specifying the ``version_file``\nparameter. For example::\n\n from setuptools import setup\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={\n 'version_file': 'custom_version.txt',\n },\n )\n\nFor compatibility with `semantic versioning`_, ``vcversioner`` will strip\nleading ``'v'``\\ s from version tags. That is, the tag ``v1.0`` will be\ntreated as if it was ``1.0``.\n\nOther prefixes can be specified to be stripped by using the ``strip_prefix``\nargument to vcversioner. For compatibility with ``git-dch``, one could specify\nthe ``strip_prefix`` as ``'debian/'``.\n\n\nNon-hook usage\n--------------\n\nIt's not necessary to depend on vcversioner; while `pip`_ will take care of\ndependencies automatically, sometimes having a self-contained project is\nsimpler. vcversioner is a single file which is easy to add to a project. Simply\ncopy the entire ``vcversioner.py`` file adjacent to the existing ``setup.py``\nfile and update the usage slightly::\n\n from setuptools import setup\n import vcversioner\n\n setup(\n # [...]\n version=vcversioner.find_version().version,\n )\n\nThis is necessary because the ``vcversioner`` distutils hook won't be\navailable.\n\n\nVersion modules\n---------------\n\n``setup.py`` isn't the only place that version information gets duplicated. By\ngenerating a version module, the ``__init__.py`` file of a package can import\nversion information. For example, with a package named ``spam``::\n\n from setuptools import setup\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={\n 'version_module_paths': ['spam/_version.py'],\n },\n )\n\nThis will generate a ``spam/_version.py`` file that defines ``__version__`` and\n``__revision__``. Then, in ``spam/__init__.py``::\n\n from spam._version import __version__, __revision__\n\nSince this acts like (and *is*) a regular python module, changing\n``MANIFEST.in`` is not required.\n\n\nCustomizing VCS commands\n------------------------\n\nvcversioner by default tries to detect which VCS is being used and picks a\ncommand to run based on that. For git, that is ``git --git-dir %(root)s/.git\ndescribe --tags --long``. For hg, that is ``hg log -R %(root)s -r . --template\n'{latesttag}-{latesttagdistance}-hg{node|short}'``.\n\nAny command should output a string that describes the current commit in the\nformat ``1.0-0-gdeadbeef``. Specifically, that is ``--``.\nThe revision should have a VCS-specific prefix, e.g. ``g`` for git and ``hg``\nfor hg.\n\nHowever, sometimes this isn't sufficient. If someone wanted to only use\nannotated tags, the git command could be amended like so::\n\n from setuptools import setup\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={\n 'vcs_args': ['git', 'describe', '--long'],\n },\n )\n\nThe ``vcs_args`` parameter must always be a list of strings, which will not be\ninterpreted by the shell. This is the same as what ``subprocess.Popen``\nexpects.\n\nThis argument used to be spelled ``git_args`` until support for multiple VCS\nsystems was added.\n\n\nDevelopment versions\n--------------------\n\nvcversioner can also automatically make a version that corresponds to a commit\nthat isn't itself tagged. Following `PEP 386`_, this is done by adding a\n``.post`` suffix to the version specified by a tag on an earlier commit. For\nexample, if the current commit is three revisions past the ``1.0`` tag, the\ncomputed version will be ``1.0.post3``.\n\nThis behavior can be disabled by setting the ``include_dev_version`` parameter\nto ``False``. In that case, the aforementioned untagged commit's version would\nbe just ``1.0``.\n\n`PEP 440`_ states that versions created during development cycles should use\nthe ``.dev`` suffix instead of ``.post``. This suffix can be used by setting \nthe ``use_dev_not_post`` parameter to ``True``. This suffix references a \ncorresponding future release, so vcversioner will assume that the future\nrelease is a single version higher than the current commit. For example, if the \ncurrent commit is one revision past the ``2.0.1`` tag, the computed version\nwill be ``2.0.2dev1``.\n\nSince hg requires a commit to make a tag, there's a parameter\n``decrement_dev_version`` to subtract one from the number of commits after the\nmost recent tag. If the VCS used is detected to be hg (i.e. the revision starts\nwith ``'hg'``) and ``decrement_dev_version`` is not specified as ``False``,\n``decrement_dev_version`` will be automatically set to ``True``.\n\n\nProject roots\n-------------\n\nIn order to prevent contamination from other source repositories, vcversioner\nin the 1.x version series will only look in the project root directory for\nrepositories. The project root defaults to the current working directory, which\nis often the case when running setup.py. This can be changed by specifying the\n``root`` parameter. Someone concerned with being able to run setup.py from\ndirectories other than the directory containing setup.py should determine the\nproject root from ``__file__`` in setup.py::\n\n from setuptools import setup\n import os\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={\n 'root': os.path.dirname(os.path.abspath(__file__)),\n },\n )\n\nTo get the same behavior in the 0.x version series, ``vcs_args`` can be set to\ninclude the ``--git-dir`` flag::\n\n from setuptools import setup\n\n setup(\n # [...]\n setup_requires=['vcversioner'],\n vcversioner={\n vcs_args=['git', '--git-dir', '%(root)s/.git', 'describe',\n '--tags', '--long'],\n },\n )\n\nBy default, ``version.txt`` is also read from the project root.\n\n\nSubstitutions\n~~~~~~~~~~~~~\n\nAs seen above, *root*, *version_file*, and *vcs_args* each support some\nsubstitutions:\n\n``%(root)s``\n The value provided for *root*. This is not available for the *root*\n parameter itself.\n\n``%(pwd)s``\n The current working directory.\n\n``/`` will automatically be translated into the correct path separator for the\ncurrent platform, such as ``:`` or ``\\``.\n\n\nSphinx documentation\n--------------------\n\n`Sphinx`_ documentation is yet another place where version numbers get\nduplicated. Fortunately, since sphinx configuration is python code, vcversioner\ncan be used there too. Assuming vcversioner is installed system-wide, this is\nquite easy. Since Sphinx is typically run with the current working directory as\n``/docs``, it's necessary to tell vcversioner where the\nproject root is. Simply change your ``conf.py`` to include::\n\n import vcversioner\n version = release = vcversioner.find_version(root='..').version\n\nThis assumes that your project root is the parent directory of the current\nworking directory. A slightly longer version which is a little more robust\nwould be::\n\n import vcversioner, os\n version = release = vcversioner.find_version(\n root=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))).version\n\nThis version is more robust because it finds the project root not relative to\nthe current working directory but instead relative to the ``conf.py`` file.\n\nIf vcversioner is bundled with your project instead of relying on it being\ninstalled, you might have to add the following to your ``conf.py`` before\n``import vcversioner``::\n\n import sys, os\n sys.path.insert(0, os.path.abspath('..'))\n\nThis line, or something with the same effect, is sometimes already present when\nusing the sphinx ``autodoc`` extension.\n\n\nRead the Docs\n~~~~~~~~~~~~~\n\nUsing vcversioner is even possible when building documentation on `Read the\nDocs`_. If vcversioner is bundled with your project, nothing further needs to\nbe done. Otherwise, you need to tell Read the Docs to install vcversioner\nbefore it builds the documentation. This means using a ``requirements.txt``\nfile.\n\nIf your project is already set up to install dependencies with a\n``requirements.txt`` file, add ``vcversioner`` to it. Otherwise, create a\n``requirements.txt`` file. Assuming your documentation is in a ``docs``\nsubdirectory of the main project directory, create ``docs/requirements.txt``\ncontaining a ``vcversioner`` line.\n\nThen, make the following changes to your project's configuration: (Project\nconfiguration is edited at e.g.\nhttps://readthedocs.org/dashboard/vcversioner/edit/)\n\n- Check the checkbox under **Use virtualenv**.\n- If there was no ``requirements.txt`` previously, set the **Requirements\n file** to the newly-created one, e.g. ``docs/requirements.txt``.\n\n\n.. _Elevator pitch: http://en.wikipedia.org/wiki/Elevator_pitch\n.. _pip: https://pypi.python.org/pypi/pip\n.. _PEP 386: http://www.python.org/dev/peps/pep-0386/\n.. _PEP 440: http://www.python.org/dev/peps/pep-0440/#developmental-releases\n.. _Sphinx: http://sphinx-doc.org\n.. _Read the Docs: https://readthedocs.org/\n.. _semantic versioning: http://semver.org/\n\n.. |find_version| replace:: ``find_version``\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/tylercrumpton/vcversioner", "keywords": "", "license": "ISC", "maintainer": "", "maintainer_email": "", "name": "tcversioner", "package_url": "https://pypi.org/project/tcversioner/", "platform": "", "project_url": "https://pypi.org/project/tcversioner/", "project_urls": { "Homepage": "https://github.com/tylercrumpton/vcversioner" }, "release_url": "https://pypi.org/project/tcversioner/2.16.0.0.post6/", "requires_dist": null, "requires_python": "", "summary": "Use version control tags to discover version numbers", "version": "2.16.0.0.post6" }, "last_serial": 3411535, "releases": { "2.16.0.0.post4": [ { "comment_text": "", "digests": { "md5": "fb1a386cba8d47d049024d4af098340d", "sha256": "be332d7a05f45142c013d087b58c451acd83a03560d1be50d06a55eaf9e30ef2" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post4-py2-none-any.whl", "has_sig": false, "md5_digest": "fb1a386cba8d47d049024d4af098340d", "packagetype": "bdist_wheel", "python_version": "any", "requires_python": null, "size": 14820, "upload_time": "2016-09-16T20:25:22", "url": "https://files.pythonhosted.org/packages/13/e3/ad9fd21318e9816b0897318530c98ec93956311fec4aa0afc877525d174e/tcversioner-2.16.0.0.post4-py2-none-any.whl" } ], "2.16.0.0.post5": [ { "comment_text": "", "digests": { "md5": "fef1f25af91d0ed2c94c48a49e8c5987", "sha256": "2774d42bd83464f5e62538ceb0c57740b18c819707bf2657b5184d581fd99a3d" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post5-py2-none-any.whl", "has_sig": false, "md5_digest": "fef1f25af91d0ed2c94c48a49e8c5987", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 14820, "upload_time": "2016-09-16T20:31:03", "url": "https://files.pythonhosted.org/packages/3b/d0/4eadc0dca45dd34528d62bfc26004af927b184df222d3bebb0cdc9fc19a8/tcversioner-2.16.0.0.post5-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8d6b69a432e303f0b532e8f114afd485", "sha256": "d7087680346dca702f37c0096474b2f308cfdc98b42e2e119c84daaef0207bf5" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post5.zip", "has_sig": false, "md5_digest": "8d6b69a432e303f0b532e8f114afd485", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20042, "upload_time": "2016-09-16T20:31:06", "url": "https://files.pythonhosted.org/packages/68/3b/42b0423bc1c454cfa76a778016309d3ea66e86e86f911789c0d8284b857f/tcversioner-2.16.0.0.post5.zip" } ], "2.16.0.0.post6": [ { "comment_text": "", "digests": { "md5": "42ecfccfb6da159473be54be58fb31f1", "sha256": "2b65d4c4e74515795dbb8b492cf542c2afb25759f600abd3b2d5f6a604c95f57" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post6-py2-none-any.whl", "has_sig": false, "md5_digest": "42ecfccfb6da159473be54be58fb31f1", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19109, "upload_time": "2017-12-12T23:06:23", "url": "https://files.pythonhosted.org/packages/df/f8/0814dde88456c58d8da5943fc2951a1440c6778e2c5595e9cbc4b1a6e763/tcversioner-2.16.0.0.post6-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "646fe00190b13635b1fcd43acb855abb", "sha256": "f2cc63566bb5185a3780d5863b7609cdafc37fc669251694d482981b7fa0b8cb" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post6.tar.gz", "has_sig": false, "md5_digest": "646fe00190b13635b1fcd43acb855abb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9570, "upload_time": "2017-12-12T23:06:25", "url": "https://files.pythonhosted.org/packages/3a/0d/050d99552bd77abc344541e74427ad1c12bce9ffc9210785876e56d11500/tcversioner-2.16.0.0.post6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "42ecfccfb6da159473be54be58fb31f1", "sha256": "2b65d4c4e74515795dbb8b492cf542c2afb25759f600abd3b2d5f6a604c95f57" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post6-py2-none-any.whl", "has_sig": false, "md5_digest": "42ecfccfb6da159473be54be58fb31f1", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19109, "upload_time": "2017-12-12T23:06:23", "url": "https://files.pythonhosted.org/packages/df/f8/0814dde88456c58d8da5943fc2951a1440c6778e2c5595e9cbc4b1a6e763/tcversioner-2.16.0.0.post6-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "646fe00190b13635b1fcd43acb855abb", "sha256": "f2cc63566bb5185a3780d5863b7609cdafc37fc669251694d482981b7fa0b8cb" }, "downloads": -1, "filename": "tcversioner-2.16.0.0.post6.tar.gz", "has_sig": false, "md5_digest": "646fe00190b13635b1fcd43acb855abb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9570, "upload_time": "2017-12-12T23:06:25", "url": "https://files.pythonhosted.org/packages/3a/0d/050d99552bd77abc344541e74427ad1c12bce9ffc9210785876e56d11500/tcversioner-2.16.0.0.post6.tar.gz" } ] }