pax_global_header00006660000000000000000000000064130322473100014505gustar00rootroot0000000000000052 comment=f5f9bc2fb5f55b1f394ef97dd492db410e4c03c2 python-versioneer-0.18/000077500000000000000000000000001303224731000151355ustar00rootroot00000000000000python-versioneer-0.18/.gitignore000066400000000000000000000001521303224731000171230ustar00rootroot00000000000000*.pyc /_test/ /build/ /versioneer.py /git_version.py /MANIFEST /dist/ /versioneer.egg-info/ /.idea /.tox/ python-versioneer-0.18/.travis.yml000066400000000000000000000011371303224731000172500ustar00rootroot00000000000000sudo: false language: python cache: pip before_cache: - rm -f $HOME/.cache/pip/log/debug.log branches: except: - /^WIP-.*$/ python: - "2.6" - "2.7" - "3.2" - "3.3" - "3.4" - "3.5" - "3.6-dev" - "pypy" - "pypy3" install: # virtualenv>=14.0.0 is incompatible with python 3.2 - if [[ $TRAVIS_PYTHON_VERSION != '3.2' ]]; then pip install -U tox virtualenv; else travis_retry pip install tox "virtualenv<14.0.0"; fi script: - if [[ $TRAVIS_PYTHON_VERSION == '3.6-dev' ]]; then tox -e py3.6; else tox -e py${TRAVIS_PYTHON_VERSION}; fi matrix: allow_failures: - python: "pypy3" python-versioneer-0.18/INSTALL.md000066400000000000000000000122211303224731000165630ustar00rootroot00000000000000# Installation First, decide on values for the following configuration variables: * `VCS`: the version control system you use. Currently accepts "git". * `style`: the style of version string to be produced. See "Styles" below for details. Defaults to "pep440", which looks like `TAG[+DISTANCE.gSHORTHASH[.dirty]]`. * `versionfile_source`: A project-relative pathname into which the generated version strings should be written. This is usually a `_version.py` next to your project's main `__init__.py` file, so it can be imported at runtime. If your project uses `src/myproject/__init__.py`, this should be `src/myproject/_version.py`. This file should be checked in to your VCS as usual: the copy created below by `setup.py setup_versioneer` will include code that parses expanded VCS keywords in generated tarballs. The 'build' and 'sdist' commands will replace it with a copy that has just the calculated version string. This must be set even if your project does not have any modules (and will therefore never import `_version.py`), since "setup.py sdist" -based trees still need somewhere to record the pre-calculated version strings. Anywhere in the source tree should do. If there is a `__init__.py` next to your `_version.py`, the `setup.py setup_versioneer` command (described below) will append some `__version__`-setting assignments, if they aren't already present. * `versionfile_build`: Like `versionfile_source`, but relative to the build directory instead of the source directory. These will differ when your setup.py uses 'package_dir='. If you have `package_dir={'myproject': 'src/myproject'}`, then you will probably have `versionfile_build='myproject/_version.py'` and `versionfile_source='src/myproject/_version.py'`. If this is set to None, then `setup.py build` will not attempt to rewrite any `_version.py` in the built tree. If your project does not have any libraries (e.g. if it only builds a script), then you should use `versionfile_build = None`. To actually use the computed version string, your `setup.py` will need to override `distutils.command.build_scripts` with a subclass that explicitly inserts a copy of `versioneer.get_version()` into your script file. See `test/demoapp-script-only/setup.py` for an example. * `tag_prefix`: a string, like 'PROJECTNAME-', which appears at the start of all VCS tags. If your tags look like 'myproject-1.2.0', then you should use tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this should be an empty string, using either `tag_prefix=` or `tag_prefix=''`. * `parentdir_prefix`: a optional string, frequently the same as tag_prefix, which appears at the start of all unpacked tarball filenames. If your tarball unpacks into 'myproject-1.2.0', this should be 'myproject-'. To disable this feature, just omit the field from your `setup.cfg`. This tool provides one script, named `versioneer`. That script has one mode, "install", which writes a copy of `versioneer.py` into the current directory and runs `versioneer.py setup` to finish the installation. To versioneer-enable your project: * 1: Modify your `setup.cfg`, adding a section named `[versioneer]` and populating it with the configuration values you decided earlier (note that the option names are not case-sensitive): ```` [versioneer] VCS = git style = pep440 versionfile_source = src/myproject/_version.py versionfile_build = myproject/_version.py tag_prefix = parentdir_prefix = myproject- ```` * 2: Run `versioneer install`. This will do the following: * copy `versioneer.py` into the top of your source tree * create `_version.py` in the right place (`versionfile_source`) * modify your `__init__.py` (if one exists next to `_version.py`) to define `__version__` (by calling a function from `_version.py`) * modify your `MANIFEST.in` to include both `versioneer.py` and the generated `_version.py` in sdist tarballs `versioneer install` will complain about any problems it finds with your `setup.py` or `setup.cfg`. Run it multiple times until you have fixed all the problems. * 3: add a `import versioneer` to your setup.py, and add the following arguments to the setup() call: version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), * 4: commit these changes to your VCS. To make sure you won't forget, `versioneer install` will mark everything it touched for addition using `git add`. Don't forget to add `setup.py` and `setup.cfg` too. ## Post-Installation Usage Once established, all uses of your tree from a VCS checkout should get the current version string. All generated tarballs should include an embedded version string (so users who unpack them will not need a VCS tool installed). If you distribute your project through PyPI, then the release process should boil down to two steps: * 1: git tag 1.0 * 2: python setup.py register sdist upload If you distribute it through github (i.e. users use github to generate tarballs with `git archive`), the process is: * 1: git tag 1.0 * 2: git push; git push --tags Versioneer will report "0+untagged.NUMCOMMITS.gHASH" until your tree has at least one tag in its history. python-versioneer-0.18/MANIFEST.in000066400000000000000000000012541303224731000166750ustar00rootroot00000000000000# we need to include a lot, because this package isn't really made up of # packages include MANIFEST.in README.md .travis.yml NOTES developers.md details.md recursive-include src *.py recursive-include test *.py *.cfg README MANIFEST.in include test/demoapp/bin/rundemo include test/demoapp/MANIFEST.in include test/demoapp/README include test/demoapp/setup.py include test/demoapp/src/demo/__init__.py include test/demoapp-script-only/MANIFEST.in include test/demoapp-script-only/README include test/demoapp-script-only/src/demo/placeholder include test/demoapp-script-only/src/dummy include test/demoapp-script-only/src/rundemo-template include test/demoapp2-distutils/bin/rundemo python-versioneer-0.18/NEWS.md000066400000000000000000000003021303224731000162260ustar00rootroot00000000000000## Release 0.18 (01-Jan-2017) * switch to entrypoints to get the right executable suffix on windows (#131) * update whitespace to appease latest flake8 Thanks to xoviat for the windows patch. python-versioneer-0.18/NOTES000066400000000000000000000072501303224731000157540ustar00rootroot00000000000000# -*- org -*- * github tarballs ** when downloaded from the "tags" page, look like: warner-python-ed25519-0.4-0-gdeb78a0.tar.gz ** and unpack into: warner-python-ed25519-deb78a0/ ** That's a bummer, I was hoping they'd be like "python-ed25519-0.4.tar.gz" and unpack into python-ed25519-0.4/ . * git attributes --help: add .gitattributes, with "_version.py export-subst" then put $Format:XXX$ in the file, with XXX from git-log's --pretty=format: $Format:%H$ -> commit hash %h -> abbreviated commit hash %d -> ref names, like git log --decorate also "filename export-ignore": won't be added to an archive might be possible to get github's 'git archive' to put the tag name into a _version.py file * first attempt at a plan: ** in the source tree - commit a _version.py with a s="$Format:%d$" and some massaging code - need to parse, strip boring refs, return highest non-boring one ** when using archive from github - __init__.py pulls massaged string from _version.py ** when building from checkout for testing - 'setup.py build' does git-describe and replaces _version.py with a one-line variable set - trouble: modifying a committed file, VCS will complain - avoid by subclassing 'build', only modify build/lib../../_version.py ** when building sdist from checkout - 'setup.py sdist' does git-describe and replaces _version.py - less trouble with modifying a committed file, if we always do sdist from a clean checkout (which is probably a good idea anyways) ** when running from source from checkout - ?? need to do git-describe from _version.py, eww ** problems: *** modifying _version.py during 'setup.py build' (for testing), leaves tree in modified state, and you don't want to accidentally replace that _version.py *** really we want to modify a file in build/, not in the source tree - might be possible for 'setup.py build', since we can get control after the superclass method has run - 'setup.py build' uses distutils.command.build_py build_py.build_module to copy things into the build directory, can use to figure out the _version.py to modify. Check for hardlinks. Hm, looks like build doesn't use hardlinks, although sdist does. - probably not so possible for 'setup.py sdist'. But maybe that's ok. - actually, cmd.sub_commands=[] is a list of (name,runp) that are invoked after self.filelist is created (but not populated), could be used to invoke extra commands - self.make_release_tree() is what creates the tree that will be archived.. could override that, modify _version.py on the way out - good to know: make_release_tree() creates hardlinks if possible. If 'setup.py build' does this too, that would explain why it's not always necessary to rebuild when source files are changed. - need to delink _version.py before changing it - make_release_tree(base_dir, files) creates os.path.join(base_dir,f) for f in files **** let's investigate this: - 'setup.py build' runs superclass, looks for .git, if present: - use git-describe - locate build/STUFF/../_version.py - replace it with one-line string variable set - if no .git, assume the version number is already good, leave it alone - 'setup.py sdist' looks for .git first, modifies _version.py in source tree, then runs superclass *** could modify a different file, one which is in .gitignore - _version.py will need to import that *** setup.py build * current problems ** DONE running 'setup.py build' from a git-archive tree - need version_from_expanded_variable() in versioneer.py too, not just _version.py python-versioneer-0.18/README.md000066400000000000000000000301261303224731000164160ustar00rootroot00000000000000The Versioneer ============== * like a rocketeer, but for versions! * https://github.com/warner/python-versioneer * Brian Warner * License: Public Domain * Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy * [![Latest Version] (https://pypip.in/version/versioneer/badge.svg?style=flat) ](https://pypi.python.org/pypi/versioneer/) * [![Build Status] (https://travis-ci.org/warner/python-versioneer.png?branch=master) ](https://travis-ci.org/warner/python-versioneer) This is a tool for managing a recorded version number in distutils-based python projects. The goal is to remove the tedious and error-prone "update the embedded version string" step from your release process. Making a new release should be as easy as recording a new tag in your version-control system, and maybe making new tarballs. ## Quick Install * `pip install versioneer` to somewhere to your $PATH * add a `[versioneer]` section to your setup.cfg (see below) * run `versioneer install` in your source tree, commit the results ## Version Identifiers Source trees come from a variety of places: * a version-control system checkout (mostly used by developers) * a nightly tarball, produced by build automation * a snapshot tarball, produced by a web-based VCS browser, like github's "tarball from tag" feature * a release tarball, produced by "setup.py sdist", distributed through PyPI Within each source tree, the version identifier (either a string or a number, this tool is format-agnostic) can come from a variety of places: * ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows about recent "tags" and an absolute revision-id * the name of the directory into which the tarball was unpacked * an expanded VCS keyword ($Id$, etc) * a `_version.py` created by some earlier build step For released software, the version identifier is closely related to a VCS tag. Some projects use tag names that include more than just the version string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool needs to strip the tag prefix to extract the version identifier. For unreleased software (between tags), the version identifier should provide enough information to help developers recreate the same tree, while also giving them an idea of roughly how old the tree is (after version 1.2, before version 1.3). Many VCS systems can report a description that captures this, for example `git describe --tags --dirty --always` reports things like "0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the 0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has uncommitted changes. The version identifier is used for multiple purposes: * to allow the module to self-identify its version: `myproject.__version__` * to choose a name and prefix for a 'setup.py sdist' tarball ## Theory of Operation Versioneer works by adding a special `_version.py` file into your source tree, where your `__init__.py` can import it. This `_version.py` knows how to dynamically ask the VCS tool for version information at import time. `_version.py` also contains `$Revision$` markers, and the installation process marks `_version.py` to have this marker rewritten with a tag name during the `git archive` command. As a result, generated tarballs will contain enough information to get the proper version. To allow `setup.py` to compute a version too, a `versioneer.py` is added to the top level of your source tree, next to `setup.py` and the `setup.cfg` that configures it. This overrides several distutils/setuptools commands to compute the version when invoked, and changes `setup.py build` and `setup.py sdist` to replace `_version.py` with a small static file that contains just the generated version data. ## Installation See [INSTALL.md](./INSTALL.md) for detailed installation instructions. ## Version-String Flavors Code which uses Versioneer can learn about its version string at runtime by importing `_version` from your main `__init__.py` file and running the `get_versions()` function. From the "outside" (e.g. in `setup.py`), you can import the top-level `versioneer.py` and run `get_versions()`. Both functions return a dictionary with different flavors of version information: * `['version']`: A condensed version string, rendered using the selected style. This is the most commonly used value for the project's version string. The default "pep440" style yields strings like `0.11`, `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section below for alternative styles. * `['full-revisionid']`: detailed revision identifier. For Git, this is the full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". * `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the commit date in ISO 8601 format. This will be None if the date is not available. * `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that this is only accurate if run in a VCS checkout, otherwise it is likely to be False or None * `['error']`: if the version string could not be computed, this will be set to a string describing the problem, otherwise it will be None. It may be useful to throw an exception in setup.py if this is set, to avoid e.g. creating tarballs with a version string of "unknown". Some variants are more useful than others. Including `full-revisionid` in a bug report should allow developers to reconstruct the exact code being tested (or indicate the presence of local changes that should be shared with the developers). `version` is suitable for display in an "about" box or a CLI `--version` output: it can be easily compared against release notes and lists of bugs fixed in various releases. The installer adds the following text to your `__init__.py` to place a basic version in `YOURPROJECT.__version__`: from ._version import get_versions __version__ = get_versions()['version'] del get_versions ## Styles The setup.cfg `style=` configuration controls how the VCS information is rendered into a version string. The default style, "pep440", produces a PEP440-compliant string, equal to the un-prefixed tag name for actual releases, and containing an additional "local version" section with more detail for in-between builds. For Git, this is TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags --dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and that this commit is two revisions ("+2") beyond the "0.11" tag. For released software (exactly equal to a known tag), the identifier will only contain the stripped tag, e.g. "0.11". Other styles are available. See [details.md](details.md) in the Versioneer source tree for descriptions. ## Debugging Versioneer tries to avoid fatal errors: if something goes wrong, it will tend to return a version of "0+unknown". To investigate the problem, run `setup.py version`, which will run the version-lookup code in a verbose mode, and will display the full contents of `get_versions()` (including the `error` string, which may help identify what went wrong). ## Known Limitations Some situations are known to cause problems for Versioneer. This details the most significant ones. More can be found on Github [issues page](https://github.com/warner/python-versioneer/issues). ### Subprojects Versioneer has limited support for source trees in which `setup.py` is not in the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are two common reasons why `setup.py` might not be in the root: * Source trees which contain multiple subprojects, such as [Buildbot](https://github.com/buildbot/buildbot), which contains both "master" and "slave" subprojects, each with their own `setup.py`, `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI distributions (and upload multiple independently-installable tarballs). * Source trees whose main purpose is to contain a C library, but which also provide bindings to Python (and perhaps other langauges) in subdirectories. Versioneer will look for `.git` in parent directories, and most operations should get the right version string. However `pip` and `setuptools` have bugs and implementation details which frequently cause `pip install .` from a subproject directory to fail to find a correct version string (so it usually defaults to `0+unknown`). `pip install --editable .` should work correctly. `setup.py install` might work too. Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in some later version. [Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking this issue. The discussion in [PR #61](https://github.com/warner/python-versioneer/pull/61) describes the issue from the Versioneer side in more detail. [pip PR#3176](https://github.com/pypa/pip/pull/3176) and [pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve pip to let Versioneer work correctly. Versioneer-0.16 and earlier only looked for a `.git` directory next to the `setup.cfg`, so subprojects were completely unsupported with those releases. ### Editable installs with setuptools <= 18.5 `setup.py develop` and `pip install --editable .` allow you to install a project into a virtualenv once, then continue editing the source code (and test) without re-installing after every change. "Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a convenient way to specify executable scripts that should be installed along with the python package. These both work as expected when using modern setuptools. When using setuptools-18.5 or earlier, however, certain operations will cause `pkg_resources.DistributionNotFound` errors when running the entrypoint script, which must be resolved by re-installing the package. This happens when the install happens with one version, then the egg_info data is regenerated while a different version is checked out. Many setup.py commands cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into a different virtualenv), so this can be surprising. [Bug #83](https://github.com/warner/python-versioneer/issues/83) describes this one, but upgrading to a newer version of setuptools should probably resolve it. ### Unicode version strings While Versioneer works (and is continually tested) with both Python 2 and Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. Newer releases probably generate unicode version strings on py2. It's not clear that this is wrong, but it may be surprising for applications when then write these strings to a network connection or include them in bytes-oriented APIs like cryptographic checksums. [Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates this question. ## Updating Versioneer To upgrade your project to a new release of Versioneer, do the following: * install the new Versioneer (`pip install -U versioneer` or equivalent) * edit `setup.cfg`, if necessary, to include any new configuration settings indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details. * re-run `versioneer install` in your source tree, to replace `SRC/_version.py` * commit any changed files ## Future Directions This tool is designed to make it easily extended to other version-control systems: all VCS-specific components are in separate directories like src/git/ . The top-level `versioneer.py` script is assembled from these components by running make-versioneer.py . In the future, make-versioneer.py will take a VCS name as an argument, and will construct a version of `versioneer.py` that is specific to the given VCS. It might also take the configuration arguments that are currently provided manually during installation by editing setup.py . Alternatively, it might go the other direction and include code from all supported VCS systems, reducing the number of intermediate scripts. ## License To make Versioneer easier to embed, all its code is dedicated to the public domain. The `_version.py` that it creates is also in the public domain. Specifically, both are released under the Creative Commons "Public Domain Dedication" license (CC0-1.0), as described in https://creativecommons.org/publicdomain/zero/1.0/ . python-versioneer-0.18/UPGRADING.md000066400000000000000000000030511303224731000167760ustar00rootroot00000000000000# Upgrading Versioneer In Your Project Some releases of Versioneer change the way your setup.py and setup.cfg must be configured. This document contains a list of releases where, when upgrading from an older release, you must make changes in your project. ## Upgrading to 0.16 or 0.17 or 0.18 Nothing special. ## Upgrading to 0.15 Starting with this version, Versioneer is configured with a `[versioneer]` section in your `setup.cfg` file. Earlier versions required the `setup.py` to set attributes on the `versioneer` module immediately after import. The new version will refuse to run (raising an exception during import) until you have provided the necessary `setup.cfg` section. In addition, the Versioneer package provides an executable named `versioneer`, and the installation process is driven by running `versioneer install`. In 0.14 and earlier, the executable was named `versioneer-installer` and was run without an argument. ## Upgrading to 0.14 0.14 changes the format of the version string. 0.13 and earlier used hyphen-separated strings like "0.11-2-g1076c97-dirty". 0.14 and beyond use a plus-separated "local version" section strings, with dot-separated components, like "0.11+2.g1076c97". PEP440-strict tools did not like the old format, but should be ok with the new one. ## Upgrading from 0.11 to 0.12 Nothing special. ## Upgrading from 0.10 to 0.11 You must add a `versioneer.VCS = "git"` to your `setup.py` before re-running `setup.py setup_versioneer`. This will enable the use of additional version-control systems (SVN, etc) in the future. python-versioneer-0.18/details.md000066400000000000000000000261141303224731000171100ustar00rootroot00000000000000 ## What environments does Versioneer support? Versioneer may be called upon to calculate version information from one of four different environments. The first, "from-vcs", is used when run from a checked-out source tree, and asks the version-control tools for information (e.g. `git describe`). This provides the most data: it can examine the commit history, find recent tags, and detect uncommitted changes (a "dirty" tree). In general, source distributions (`setup.py sdist`) are created from this environment, and the calculated version string is embedded into the generated tarball (by replacing `_version.py` with a "short form" that contains literal strings instead of code to run git). When these tarballs are unpacked, they provide the second environment, "from-file". This environment is also created when you use `setup.py build` and then import code from the generated `build/` directory. All the version strings come from the previous "from-vcs" environment that created the tarball, frozen at that point. `_version.py` might record the fact that the sdist was created from a dirty tree, however it is not possible to detect additional changes. Sometimes you use the VCS tools to make a tarball directly, like `git archive`, without using `setup.py sdist`. Unpacking such a tarball results in the third environment, "from-keyword". The resulting source tree will contain expanded keywords in the `_version.py` file, which tells it a git revision, and an exact tag (if any), but cannot generally detect things like commits-since-recent-tag, or recent-tag at all. As with from-file, this does not give Versioneer enough information to detect additional changes, and the "dirty" status is always False. In general, you should only use `git archive` on tagged revisions. Creating archives from untagged revisions will result in a version string that's simply a copy of the full SHA1 hash. If all these methods fail, Versioneer attempts to pull a version string from the name of the parent directory, since tarballs are frequently built this way. This environment is called "from-parentdir". This can provide the main version string, but not a full-revision hash. "dirty" is always False. If even that fails, Versioneer will either report a version of "0+unknown", and will signal an error. ## What does get_version() return? It returns `get_versions()["version"]`. See below for what that means. `get_version()` and `get_versions()` are the main functions through which Versioneer provides version data to your program. Your `setup.py` can do `from versioneer import get_version`, and your top-level runtime modules can do `from ._version import get_version`. ## What does get_versions() return? `get_versions()` returns a small dictionary of rendered version information, which always contains four keys: | key | description | | --- | --- | | `version` | The version string as selected by `version-style` | | `full-revisionid` | A full-length hex SHA1 (for git), or equivalent (for other VCS systems), or None. | | `dirty` | A boolean, True if the source tree has local changes. None if unknown. | | `error` | None, or a error description string | `version` will always be a string (`str` on py3, `unicode` on py2): if Versioneer is unable to compute a version, it will be set to `"0+unknown"`. `full-revisionid` will be a str/unicode, or None if that information is not available. `dirty` will be a boolean, or None if unavailable. `error` will be None, or a str/unicode if there was an error. If the `error` key is non-None, that indicates that Versioneer was unable to obtain a satisfactory version string. There are several possibilities: * the closest tag found did not start with the configured `tag_prefix` * from-keyword mode did not find any tags (e.g. an archive created from a bare SHA1, instead of from a tag) * the output of `git describe` was unparseable * all modes failed: the source tree has no `.git` directory, expanded keywords, pre-built version data ("from-file"), or useful parent directory name. When `error` occurs, `version` will be set to "0+unknown", `full-revisionid` will be set (in from-vcs mode) or None (in other modes), and `dirty` will be None. If you want to prevent builds from happening without solid version information, use a snippet like this in your `__init__.py` or `setup.py`: ```python v = get_versions() if v["error"]: raise RuntimeError(v["error"]) ``` `get_versions()["version"]` is the most useful value, intended for `setup.py` and runtime version introspection to support a CLI command's `--version` argument. This is available in all modes, but has the most fidelity in from-vcs environments. `get_versions()["full-revisionid"]` is probably useful for an extended form of CLI `--version`, and for including in machine-generated error/crash reports. In from-parentdir mode, its value will be `None`, but in the other modes (from-vcs, from-file, from-keyword) it will be the git SHA1 hash (a 40-character lowercase hexadecimal string), or the equivalent for other VCS systems. `get_versions()["dirty"]` might be useful when running tests, to remind someone viewing a transcript that there are uncommitted changes which might affect the results. In most cases, this information will also be present in `["version"]` (it will contain a `-dirty` suffix). It may also be useful for `setup.py` decision making: ```python if versioneer.get_versions()["dirty"]: raise MustCommitError("please commit everything before making tarballs") ``` `dirty` is most meaningful in from-vcs mode. In from-file mode, it records the dirty status of the tree from which the setup.py build/sdist command was run, and is not affected by subsequent changes to the generated tree. In from-keyword and from-parentdir mode, it will always be `False`. ## How do I select a version `style`? In from-vcs mode (inside a git checkout), Versioneer can get a lot of data about the state of the tree: the current tag (if any), the closest historical tag, the number of commits since that tag, the exact revision ID, and the 'dirty' state. These pieces are used by a renderer function to compute the `['version']` in the small dictionary that will be returned by `get_versions()`. The renderer function is controlled by a configuration value called `style`. You can use this to select the kind of version string you want to use. The available forms are: | key | description | | --- | ----------- | | `default` | same as `pep440` | | `pep440` | `TAG[+DISTANCE.gSHORTHASH[.dirty]]`, a PEP-440 compatible version string which uses the "local version identifier" to record the complete non-tag information. This format provides compliant versions even under unusual/error circumstances. It returns `0+untagged.DISTANCE.gHASH[.dirty]` before any tags have been set, `0+unknown` if the tree does not contain enough information to report a verion (e.g. the .git directory has been removed), and `0.unparseable[.dirty]` if `git describe` emits something weird. If TAG includes a plus sign, then this will use a dot as a separator instead (`TAG[.DISTANCE.gSHORTHASH[.dirty]]`).| | `pep440-pre` | `TAG[.post.devDISTANCE]`, a PEP-440 compatible version string which loses information but has the useful property that non-tagged versions qualify for `pip install --pre` (by virtue of the `.dev` component). This form does not record the commit hash, nor the `-dirty` flag. | | `pep440-post` | `TAG[.postDISTANCE[.dev0]+gSHORTHASH]`, a PEP-440 compatible version string which allows all commits to get installable versions, and retains the commit hash. | `pep440-old` | `TAG[.postDISTANCE[.dev0]]`, a PEP-440 compatible version string which loses information but enables downstream projects to depend upon post-release versions (by counting commits). The ".dev0" suffix indicates a dirty tree. This form does not record the commit hash. If nothing has been tagged, this will be `0.postDISTANCE[.dev0]`. Note that PEP-0440 rules indicate that `X.dev0` sorts as "older" than `X`, so our -dirty flag is expressed somewhat backwards (usually "dirty" indicates newer changes than the base commit), but PEP-0440 offers no positive post-".postN" component. You should never be releasing software with -dirty anyways. | | `git-describe` | `TAG[-DISTANCE-gSHORTHASH][-dirty]`, equivalent to `git describe --tags --dirty --always`. The distance and shorthash are only included if the commit is not tagged. If nothing was tagged, this will be the short revisionid, plus "-dirty" if dirty. | | `git-describe-long` | `TAG-DISTANCE-gSHORTHASH[-dirty]`, equivalent to `git describe --tags --dirty --always --long`. The distance and shorthash are included unconditionally. As with `git-describe`, if nothing was tagged, this will be the short revisionid, possibly with "-dirty". | ## Pieces used by from-vcs Internally, the from-vcs function is expected to return the following values. The renderer uses these to compute the version string. | key | description | | --- | ----------- | | `long` | a full-length id (hex SHA1 for git) for the current revision | | `short` | a truncated form of `full-revisionid`, typically 7 characters for git (but might be more in large repositories if necessary to uniquely identify the commit) | | `error` | a string, if something was unparseable | | `closest-tag` | a string (or None if nothing has been tagged), with the name of the closest ancestor tag. The "tag prefix" is stripped off. | | `distance` | an integer, the number of commits since the most recent tag. If the current revision is tagged, this will be 0. If nothing has been tagged, this will be the total number of commits. | | `dirty` | a boolean, indicating that the working directory has modified files | If a value is not available (e.g. the source tree does not contain enough information to provide it), the dictionary will not contain that key. The from-keywords mode will only produce `exact-tag` and `full-revisionid`. If the git-archive tarball was created from a non-tagged revision, `exact-tag` will be None. These tarballs use keyword expansion, and there is no git-attributes keyword that replicates the tag-searching features of git-describe. `dirty` modification to the source tree can only be detected from a git checkout. A build or sdist created from a dirty tree will be marked as dirty, however an sdist created from a clean tree which is subsequently modified will not be reported as dirty. ## What version strings will we get in each environment? (note: this is not yet accurate) | key | file | keywords | git-describe | parentdir | | --- | ------------------ | ----------------- | ------------------------ | --------- | | pep440 | TAG[+DIST.gHASH] | TAG or 0.unknown? | TAG[+DIST.gHASH[.dirty]] | TAG or ? | | pep440-pre | TAG[.post.devDIST] | TAG or ? | TAG[.post.devDIST] | TAG or ? | | pep440-old | TAG[.postDIST] | TAG or ? | TAG[.postDIST[.dev0]] | TAG or ? | | git-describe | TAG[-DIST-gHASH] | TAG or ? | TAG[-DIST-gHASH][-dirty] | TAG or ? | | long | TAG-DIST-gHASH | TAG-gHASH or ? | TAG-DIST-gHASH[-dirty] | ? | python-versioneer-0.18/developers.md000066400000000000000000000016411303224731000176310ustar00rootroot00000000000000 ## To add support for a new VCS So, you want to extend Versioneer to support your favorite version control system? Great! Here's what to do: * 1: `mkdir src/NEW-VCS/` * 2: create work-alikes for everything in `src/git/` * 3: add NEW-VCS to the loop in setup.py `generate_versioneer()` * 4: add clauses for NEW-VCS to `src/get_versions.py`, for both the from-keywords and from-vcs sections * 5: add `test/test_NEWVCS.py`, copying the general style of `test_git.py` but using NEWVCS instead of git. * 6: add a line to .travis.yml to execute your `test_NEWVCS.py` upon checkins Then file a pull request! ## To make a release * test, etc * edit setup.py to set VERSION=, commit -m "release X.X" * push origin master X.X * python setup.py bdist_wheel --universal sdist register upload (if setup.py doesn't acknowledge `bdist_wheel`, and the "wheel" package is installed, look for stale versions of setuptools and delete them) python-versioneer-0.18/setup.py000077500000000000000000000150611303224731000166550ustar00rootroot00000000000000#!/usr/bin/env python import os, base64, tempfile, io from os import path from setuptools import setup, Command from setuptools.command.build_py import build_py from setuptools.dist import Distribution as _Distribution LONG=""" Versioneer is a tool to automatically update version strings (in setup.py and the conventional 'from PROJECT import _version' pattern) by asking your version-control system about the current tree. """ # as nice as it'd be to versioneer ourselves, that sounds messy. VERSION = "0.18" def ver(s): return s.replace("@VERSIONEER-VERSION@", VERSION) def get(fn, add_ver=False, unquote=False, do_strip=False, do_readme=False): with open(fn) as f: text = f.read() # If we're in Python <3 and have a separate Unicode type, we would've # read a non-unicode string. Else, all strings will be unicode strings. try: __builtins__.unicode except AttributeError: pass else: text = text.decode('ASCII') if add_ver: text = ver(text) if unquote: text = text.replace("%", "%%") if do_strip: lines = [line for line in text.split("\n") if not line.endswith("# --STRIP DURING BUILD")] text = "\n".join(lines) if do_readme: text = text.replace("@README@", get("README.md")) return text def u(s): # so u("foo") yields unicode on all of py2.6/py2.7/py3.2/py3.3 return s.encode("ascii").decode("ascii") def get_vcs_list(): project_path = path.join(path.abspath(path.dirname(__file__)), 'src') return [filename for filename in os.listdir(project_path) if path.isdir(path.join(project_path, filename))] def generate_long_version_py(VCS): s = io.StringIO() s.write(get("src/%s/long_header.py" % VCS, add_ver=True, do_strip=True)) for piece in ["src/subprocess_helper.py", "src/from_parentdir.py", "src/%s/from_keywords.py" % VCS, "src/%s/from_vcs.py" % VCS, "src/render.py", "src/%s/long_get_versions.py" % VCS]: s.write(get(piece, unquote=True, do_strip=True)) return s.getvalue() def generate_versioneer_py(): s = io.StringIO() s.write(get("src/header.py", add_ver=True, do_readme=True)) s.write(get("src/subprocess_helper.py", do_strip=True)) for VCS in get_vcs_list(): s.write(u("LONG_VERSION_PY['%s'] = '''\n" % VCS)) s.write(generate_long_version_py(VCS)) s.write(u("'''\n")) s.write(u("\n\n")) s.write(get("src/%s/from_keywords.py" % VCS, do_strip=True)) s.write(get("src/%s/from_vcs.py" % VCS, do_strip=True)) s.write(get("src/%s/install.py" % VCS, do_strip=True)) s.write(get("src/from_parentdir.py", do_strip=True)) s.write(get("src/from_file.py", add_ver=True, do_strip=True)) s.write(get("src/render.py", do_strip=True)) s.write(get("src/get_versions.py", do_strip=True)) s.write(get("src/cmdclass.py", do_strip=True)) s.write(get("src/setupfunc.py", do_strip=True)) return s.getvalue().encode("utf-8") class make_versioneer(Command): description = "create standalone versioneer.py" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): with open("versioneer.py", "w") as f: f.write(generate_versioneer_py().decode("utf8")) return 0 class make_long_version_py_git(Command): description = "create standalone _version.py (for git)" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): assert os.path.exists("versioneer.py") long_version = generate_long_version_py("git") with open("git_version.py", "w") as f: f.write(long_version % {"DOLLAR": "$", "STYLE": "pep440", "TAG_PREFIX": "tag-", "PARENTDIR_PREFIX": "parentdir_prefix", "VERSIONFILE_SOURCE": "versionfile_source", }) return 0 class my_build_py(build_py): def run(self): v = generate_versioneer_py() v_b64 = base64.b64encode(v).decode("ascii") lines = [v_b64[i:i+60] for i in range(0, len(v_b64), 60)] v_b64 = "\n".join(lines)+"\n" with open("src/installer.py") as f: s = f.read() s = ver(s.replace("@VERSIONEER-INSTALLER@", v_b64)) tempdir = tempfile.mkdtemp() installer = os.path.join(tempdir, "versioneer.py") with open(installer, "w") as f: f.write(s) self.py_modules = [os.path.splitext(os.path.basename(installer))[0]] self.package_dir.update({'': os.path.dirname(installer)}) rc = build_py.run(self) os.unlink(installer) os.rmdir(tempdir) return rc # python's distutils treats module-less packages as binary-specific (not # "pure"), so "setup.py bdist_wheel" creates binary-specific wheels. Override # this so we get cross-platform wheels instead. More info at: # https://bitbucket.org/pypa/wheel/issue/116/packages-with-only-filesdata_files-get class Distribution(_Distribution): def is_pure(self): return True setup( name = "versioneer", license = "public domain", version = VERSION, description = "Easy VCS-based management of project version strings", author = "Brian Warner", author_email = "warner-versioneer@lothar.com", url = "https://github.com/warner/python-versioneer", # "fake" is replaced with versioneer-installer in build_scripts. We need # a non-empty list to provoke "setup.py build" into making scripts, # otherwise it skips that step. py_modules = ["fake"], entry_points={ 'console_scripts': [ 'versioneer = versioneer:main', ], }, long_description = LONG, distclass=Distribution, cmdclass = { "build_py": my_build_py, "make_versioneer": make_versioneer, "make_long_version_py_git": make_long_version_py_git, }, classifiers=[ "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], ) python-versioneer-0.18/src/000077500000000000000000000000001303224731000157245ustar00rootroot00000000000000python-versioneer-0.18/src/__init__.py000066400000000000000000000000001303224731000200230ustar00rootroot00000000000000python-versioneer-0.18/src/cmdclass.py000066400000000000000000000167711303224731000201030ustar00rootroot00000000000000import os, sys # --STRIP DURING BUILD LONG_VERSION_PY = {} # --STRIP DURING BUILD def get_version(): pass # --STRIP DURING BUILD def get_versions(): pass # --STRIP DURING BUILD def get_root(): pass # --STRIP DURING BUILD def get_config_from_root(): pass # --STRIP DURING BUILD def write_to_version_file(): pass # --STRIP DURING BUILD def get_cmdclass(): """Get the custom setuptools/distutils subclasses used by Versioneer.""" if "versioneer" in sys.modules: del sys.modules["versioneer"] # this fixes the "python setup.py develop" case (also 'install' and # 'easy_install .'), in which subdependencies of the main project are # built (using setup.py bdist_egg) in the same python process. Assume # a main project A and a dependency B, which use different versions # of Versioneer. A's setup.py imports A's Versioneer, leaving it in # sys.modules by the time B's setup.py is executed, causing B to run # with the wrong versioneer. Setuptools wraps the sub-dep builds in a # sandbox that restores sys.modules to it's pre-build state, so the # parent is protected against the child's "import versioneer". By # removing ourselves from sys.modules here, before the child build # happens, we protect the child from the parent's versioneer too. # Also see https://github.com/warner/python-versioneer/issues/52 cmds = {} # we add "version" to both distutils and setuptools from distutils.core import Command class cmd_version(Command): description = "report generated version string" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): vers = get_versions(verbose=True) print("Version: %s" % vers["version"]) print(" full-revisionid: %s" % vers.get("full-revisionid")) print(" dirty: %s" % vers.get("dirty")) print(" date: %s" % vers.get("date")) if vers["error"]: print(" error: %s" % vers["error"]) cmds["version"] = cmd_version # we override "build_py" in both distutils and setuptools # # most invocation pathways end up running build_py: # distutils/build -> build_py # distutils/install -> distutils/build ->.. # setuptools/bdist_wheel -> distutils/install ->.. # setuptools/bdist_egg -> distutils/install_lib -> build_py # setuptools/install -> bdist_egg ->.. # setuptools/develop -> ? # pip install: # copies source tree to a tempdir before running egg_info/etc # if .git isn't copied too, 'git describe' will fail # then does setup.py bdist_wheel, or sometimes setup.py install # setup.py egg_info -> ? # we override different "build_py" commands for both environments if "setuptools" in sys.modules: from setuptools.command.build_py import build_py as _build_py else: from distutils.command.build_py import build_py as _build_py class cmd_build_py(_build_py): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() _build_py.run(self) # now locate _version.py in the new build/ directory and replace # it with an updated value if cfg.versionfile_build: target_versionfile = os.path.join(self.build_lib, cfg.versionfile_build) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) cmds["build_py"] = cmd_build_py if "cx_Freeze" in sys.modules: # cx_freeze enabled? from cx_Freeze.dist import build_exe as _build_exe # nczeczulin reports that py2exe won't like the pep440-style string # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. # setup(console=[{ # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION # "product_version": versioneer.get_version(), # ... class cmd_build_exe(_build_exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _build_exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["build_exe"] = cmd_build_exe del cmds["build_py"] if 'py2exe' in sys.modules: # py2exe enabled? try: from py2exe.distutils_buildexe import py2exe as _py2exe # py3 except ImportError: from py2exe.build_exe import py2exe as _py2exe # py2 class cmd_py2exe(_py2exe): def run(self): root = get_root() cfg = get_config_from_root(root) versions = get_versions() target_versionfile = cfg.versionfile_source print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, versions) _py2exe.run(self) os.unlink(target_versionfile) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) cmds["py2exe"] = cmd_py2exe # we override different "sdist" commands for both environments if "setuptools" in sys.modules: from setuptools.command.sdist import sdist as _sdist else: from distutils.command.sdist import sdist as _sdist class cmd_sdist(_sdist): def run(self): versions = get_versions() self._versioneer_generated_versions = versions # unless we update this, the command will keep using the old # version self.distribution.metadata.version = versions["version"] return _sdist.run(self) def make_release_tree(self, base_dir, files): root = get_root() cfg = get_config_from_root(root) _sdist.make_release_tree(self, base_dir, files) # now locate _version.py in the new base_dir directory # (remembering that it may be a hardlink) and replace it with an # updated value target_versionfile = os.path.join(base_dir, cfg.versionfile_source) print("UPDATING %s" % target_versionfile) write_to_version_file(target_versionfile, self._versioneer_generated_versions) cmds["sdist"] = cmd_sdist return cmds python-versioneer-0.18/src/from_file.py000066400000000000000000000030501303224731000202360ustar00rootroot00000000000000SHORT_VERSION_PY = """ # This file was generated by 'versioneer.py' (@VERSIONEER-VERSION@) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json version_json = ''' %s ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) """ import os # --STRIP DURING BUILD import json # --STRIP DURING BUILD import re # --STRIP DURING BUILD class NotThisMethod(Exception): pass # --STRIP DURING BUILD def versions_from_file(filename): """Try to determine the version from _version.py if present.""" try: with open(filename) as f: contents = f.read() except EnvironmentError: raise NotThisMethod("unable to read _version.py") mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) if not mo: raise NotThisMethod("no version_json in _version.py") return json.loads(mo.group(1)) def write_to_version_file(filename, versions): """Write the given version number to the given _version.py file.""" os.unlink(filename) contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", ": ")) with open(filename, "w") as f: f.write(SHORT_VERSION_PY % contents) print("set %s to '%s'" % (filename, versions["version"])) python-versioneer-0.18/src/from_parentdir.py000066400000000000000000000020641303224731000213130ustar00rootroot00000000000000import os # --STRIP DURING BUILD class NotThisMethod(Exception): pass # --STRIP DURING BUILD def versions_from_parentdir(parentdir_prefix, root, verbose): """Try to determine the version from the parent directory name. Source tarballs conventionally unpack into a directory that includes both the project name and a version string. We will also support searching up two directory levels for an appropriately named parent directory """ rootdirs = [] for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % (str(rootdirs), parentdir_prefix)) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") python-versioneer-0.18/src/get_versions.py000066400000000000000000000062731303224731000210150ustar00rootroot00000000000000import os, sys # --STRIP DURING BUILD def get_root(): pass # --STRIP DURING BUILD def get_config_from_root(): pass # --STRIP DURING BUILD def versions_from_file(): pass # --STRIP DURING BUILD def versions_from_parentdir(): pass # --STRIP DURING BUILD def render(): pass # --STRIP DURING BUILD HANDLERS = {} # --STRIP DURING BUILD class NotThisMethod(Exception): pass # --STRIP DURING BUILD class VersioneerBadRootError(Exception): """The project root directory is unknown or missing key files.""" def get_versions(verbose=False): """Get the project version from whatever source is available. Returns dict with two keys: 'version' and 'full'. """ if "versioneer" in sys.modules: # see the discussion in cmdclass.py:get_cmdclass() del sys.modules["versioneer"] root = get_root() cfg = get_config_from_root(root) assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" handlers = HANDLERS.get(cfg.VCS) assert handlers, "unrecognized VCS '%s'" % cfg.VCS verbose = verbose or cfg.verbose assert cfg.versionfile_source is not None, \ "please set versioneer.versionfile_source" assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" versionfile_abs = os.path.join(root, cfg.versionfile_source) # extract version from first of: _version.py, VCS command (e.g. 'git # describe'), parentdir. This is meant to work for developers using a # source checkout, for users of a tarball created by 'setup.py sdist', # and for users of a tarball/zipball created by 'git archive' or github's # download-from-tag feature or the equivalent in other VCSes. get_keywords_f = handlers.get("get_keywords") from_keywords_f = handlers.get("keywords") if get_keywords_f and from_keywords_f: try: keywords = get_keywords_f(versionfile_abs) ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) if verbose: print("got version from expanded keyword %s" % ver) return ver except NotThisMethod: pass try: ver = versions_from_file(versionfile_abs) if verbose: print("got version from file %s %s" % (versionfile_abs, ver)) return ver except NotThisMethod: pass from_vcs_f = handlers.get("pieces_from_vcs") if from_vcs_f: try: pieces = from_vcs_f(cfg.tag_prefix, root, verbose) ver = render(pieces, cfg.style) if verbose: print("got version from VCS %s" % ver) return ver except NotThisMethod: pass try: if cfg.parentdir_prefix: ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) if verbose: print("got version from parentdir %s" % ver) return ver except NotThisMethod: pass if verbose: print("unable to compute version") return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} def get_version(): """Get the short version string for this project.""" return get_versions()["version"] python-versioneer-0.18/src/git/000077500000000000000000000000001303224731000165075ustar00rootroot00000000000000python-versioneer-0.18/src/git/__init__.py000066400000000000000000000000001303224731000206060ustar00rootroot00000000000000python-versioneer-0.18/src/git/from_keywords.py000066400000000000000000000100701303224731000217510ustar00rootroot00000000000000import re # --STRIP DURING BUILD def register_vcs_handler(*args): # --STRIP DURING BUILD def nil(f): # --STRIP DURING BUILD return f # --STRIP DURING BUILD return nil # --STRIP DURING BUILD class NotThisMethod(Exception): pass # --STRIP DURING BUILD @register_vcs_handler("git", "get_keywords") def git_get_keywords(versionfile_abs): """Extract version information from the given file.""" # the code embedded in _version.py can just fetch the value of these # keywords. When used from setup.py, we don't want to import _version.py, # so we do it with a regexp instead. This function is not used from # _version.py. keywords = {} try: f = open(versionfile_abs, "r") for line in f.readlines(): if line.strip().startswith("git_refnames ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["refnames"] = mo.group(1) if line.strip().startswith("git_full ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["full"] = mo.group(1) if line.strip().startswith("git_date ="): mo = re.search(r'=\s*"(.*)"', line) if mo: keywords["date"] = mo.group(1) f.close() except EnvironmentError: pass return keywords @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" if not keywords: raise NotThisMethod("no keywords at all, weird") date = keywords.get("date") if date is not None: # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because # it's been around since git-1.5.3, and it's too difficult to # discover which version we're using, or to work around using an # older one. date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) refnames = keywords["refnames"].strip() if refnames.startswith("$Format"): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") refs = set([r.strip() for r in refnames.strip("()").split(",")]) # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d # expansion behaves like git log --decorate=short and strips out the # refs/heads/ and refs/tags/ prefixes that would let us distinguish # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". tags = set([r for r in refs if re.search(r'\d', r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: print("likely tags: %s" % ",".join(sorted(tags))) for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] if verbose: print("picking %s" % r) return {"version": r, "full-revisionid": keywords["full"].strip(), "dirty": False, "error": None, "date": date} # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") return {"version": "0+unknown", "full-revisionid": keywords["full"].strip(), "dirty": False, "error": "no suitable tags", "date": None} python-versioneer-0.18/src/git/from_vcs.py000066400000000000000000000077521303224731000207120ustar00rootroot00000000000000import sys # --STRIP DURING BUILD import re # --STRIP DURING BUILD # --STRIP DURING BUILD # --STRIP DURING BUILD def register_vcs_handler(*args): # --STRIP DURING BUILD def nil(f): # --STRIP DURING BUILD return f # --STRIP DURING BUILD return nil # --STRIP DURING BUILD # --STRIP DURING BUILD # --STRIP DURING BUILD def run_command(): pass # --STRIP DURING BUILD # --STRIP DURING BUILD # --STRIP DURING BUILD class NotThisMethod(Exception): # --STRIP DURING BUILD pass # --STRIP DURING BUILD @register_vcs_handler("git", "pieces_from_vcs") def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* expanded, and _version.py hasn't already been rewritten with a short version string, meaning we're inside a checked out source tree. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) raise NotThisMethod("'git rev-parse --git-dir' returned error") # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", "--always", "--long", "--match", "%s*" % tag_prefix], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() pieces = {} pieces["long"] = full_out pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out # look for -dirty suffix dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: git_describe = git_describe[:git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces # tag full_tag = mo.group(1) if not full_tag.startswith(tag_prefix): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" % (full_tag, tag_prefix)) return pieces pieces["closest-tag"] = full_tag[len(tag_prefix):] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) # commit: short hex revision ID pieces["short"] = mo.group(3) else: # HEX: no tags pieces["closest-tag"] = None count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces python-versioneer-0.18/src/git/install.py000066400000000000000000000024511303224731000205310ustar00rootroot00000000000000import sys # --STRIP DURING BUILD def run_command(): pass # --STRIP DURING BUILD def do_vcs_install(manifest_in, versionfile_source, ipy): """Git-specific installation logic for Versioneer. For Git, this means creating/changing .gitattributes to mark _version.py for export-subst keyword substitution. """ GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] files = [manifest_in, versionfile_source] if ipy: files.append(ipy) try: me = __file__ if me.endswith(".pyc") or me.endswith(".pyo"): me = os.path.splitext(me)[0] + ".py" versioneer_file = os.path.relpath(me) except NameError: versioneer_file = "versioneer.py" files.append(versioneer_file) present = False try: f = open(".gitattributes", "r") for line in f.readlines(): if line.strip().startswith(versionfile_source): if "export-subst" in line.strip().split()[1:]: present = True f.close() except EnvironmentError: pass if not present: f = open(".gitattributes", "a+") f.write("%s export-subst\n" % versionfile_source) f.close() files.append(".gitattributes") run_command(GITS, ["add", "--"] + files) python-versioneer-0.18/src/git/long_get_versions.py000066400000000000000000000037431303224731000226160ustar00rootroot00000000000000import os # --STRIP DURING BUILD def get_config(): pass # --STRIP DURING BUILD def get_keywords(): pass # --STRIP DURING BUILD def git_versions_from_keywords(): pass # --STRIP DURING BUILD def git_pieces_from_vcs(): pass # --STRIP DURING BUILD def versions_from_parentdir(): pass # --STRIP DURING BUILD class NotThisMethod(Exception): pass # --STRIP DURING BUILD def render(): pass # --STRIP DURING BUILD def get_versions(): """Get version information or return default if unable to do so.""" # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have # __file__, we can work backwards from there to the root. Some # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which # case we can only use expanded keywords. cfg = get_config() verbose = cfg.verbose try: return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass try: root = os.path.realpath(__file__) # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. for i in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to find root of source tree", "date": None} try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) return render(pieces, cfg.style) except NotThisMethod: pass try: if cfg.parentdir_prefix: return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) except NotThisMethod: pass return {"version": "0+unknown", "full-revisionid": None, "dirty": None, "error": "unable to compute version", "date": None} python-versioneer-0.18/src/git/long_header.py000066400000000000000000000041731303224731000213350ustar00rootroot00000000000000# This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build # directories (produced by setup.py build) will contain a much shorter file # that just contains the computed version number. # This file is released into the public domain. Generated by # versioneer-@VERSIONEER-VERSION@ (https://github.com/warner/python-versioneer) """Git implementation of _version.py.""" import errno import os import re import subprocess import sys def get_keywords(): """Get the keywords needed to look up the version information.""" # these strings will be replaced by git during git-archive. # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_config(): """Create, populate and return the VersioneerConfig() object.""" # these strings are filled in when 'setup.py versioneer' creates # _version.py cfg = VersioneerConfig() cfg.VCS = "git" cfg.style = "%(STYLE)s" cfg.tag_prefix = "%(TAG_PREFIX)s" cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" cfg.verbose = False return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate python-versioneer-0.18/src/header.py000066400000000000000000000100201303224731000175170ustar00rootroot00000000000000 # Version: @VERSIONEER-VERSION@ """The Versioneer - like a rocketeer, but for versions. @README@ """ from __future__ import print_function try: import configparser except ImportError: import ConfigParser as configparser import errno import json import os import re import subprocess import sys class VersioneerConfig: """Container for Versioneer configuration parameters.""" def get_root(): """Get the project root directory. We require that all commands are run from the project root, i.e. the directory that contains setup.py, setup.cfg, and versioneer.py . """ root = os.path.realpath(os.path.abspath(os.getcwd())) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): # allow 'python path/to/setup.py COMMAND' root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) setup_py = os.path.join(root, "setup.py") versioneer_py = os.path.join(root, "versioneer.py") if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): err = ("Versioneer was unable to run the project root directory. " "Versioneer requires setup.py to be executed from " "its immediate directory (like 'python setup.py COMMAND'), " "or in a way that lets it use sys.argv[0] to find the root " "(like 'python path/to/setup.py COMMAND').") raise VersioneerBadRootError(err) try: # Certain runtime workflows (setup.py install/develop in a setuptools # tree) execute all dependencies in a single python process, so # "versioneer" may be imported multiple times, and python's shared # module-import table will cache the first one. So we can't use # os.path.dirname(__file__), as that will find whichever # versioneer.py was first imported, even in later projects. me = os.path.realpath(os.path.abspath(__file__)) me_dir = os.path.normcase(os.path.splitext(me)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: print("Warning: build in %s is using versioneer.py from %s" % (os.path.dirname(me), versioneer_py)) except NameError: pass return root def get_config_from_root(root): """Read the project setup.cfg file to determine Versioneer config.""" # This might raise EnvironmentError (if setup.cfg is missing), or # configparser.NoSectionError (if it lacks a [versioneer] section), or # configparser.NoOptionError (if it lacks "VCS="). See the docstring at # the top of versioneer.py for instructions on writing your setup.cfg . setup_cfg = os.path.join(root, "setup.cfg") parser = configparser.SafeConfigParser() with open(setup_cfg, "r") as f: parser.readfp(f) VCS = parser.get("versioneer", "VCS") # mandatory def get(parser, name): if parser.has_option("versioneer", name): return parser.get("versioneer", name) return None cfg = VersioneerConfig() cfg.VCS = VCS cfg.style = get(parser, "style") or "" cfg.versionfile_source = get(parser, "versionfile_source") cfg.versionfile_build = get(parser, "versionfile_build") cfg.tag_prefix = get(parser, "tag_prefix") if cfg.tag_prefix in ("''", '""'): cfg.tag_prefix = "" cfg.parentdir_prefix = get(parser, "parentdir_prefix") cfg.verbose = get(parser, "verbose") return cfg class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" # these dictionaries contain VCS-specific tools LONG_VERSION_PY = {} HANDLERS = {} def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f return decorate python-versioneer-0.18/src/installer.py000066400000000000000000000026651303224731000203040ustar00rootroot00000000000000#!/usr/bin/env python import os, sys, base64 VERSIONEER_b64 = """ @VERSIONEER-INSTALLER@ """ newver = "@VERSIONEER-VERSION@" def main(): if len(sys.argv) < 2: print("Usage: versioneer install") sys.exit(1) command = sys.argv[1] if command in ("version", "--version"): print("versioneer (installer) %s" % newver) sys.exit(0) if command != "install": print("Usage: versioneer install") sys.exit(1) v = base64.b64decode(VERSIONEER_b64.encode('ASCII')) if os.path.exists("versioneer.py"): for line in open("versioneer.py").readlines()[:5]: if line.startswith("# Version: "): oldver = line[len("# Version: "):].strip() if oldver != newver: print("replacing old versioneer.py (%s)" % oldver) break else: print("overwriting existing versioneer.py") with open("versioneer.py", "wb") as f: f.write(v) print("versioneer.py (%s) installed into local tree" % newver) print("Now running 'versioneer.py setup' to install the generated files..") if " " in sys.executable: import subprocess # Do not import unless absolutely necessary to avoid compatibility issues subprocess.call([sys.executable, "versioneer.py", "setup"]) else: os.execl(sys.executable, sys.executable, "versioneer.py", "setup") if __name__ == '__main__': main() python-versioneer-0.18/src/render.py000066400000000000000000000116751303224731000175670ustar00rootroot00000000000000 def plus_or_dot(pieces): """Return a + if we don't already have one, else return a .""" if "+" in pieces.get("closest-tag", ""): return "." return "+" def render_pep440(pieces): """Build up version string, with post-release "local version identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty Exceptions: 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += plus_or_dot(pieces) rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" else: # exception #1 rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered def render_pep440_pre(pieces): """TAG[.post.devDISTANCE] -- No -dirty. Exceptions: 1: no tags. 0.post.devDISTANCE """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += ".post.dev%d" % pieces["distance"] else: # exception #1 rendered = "0.post.dev%d" % pieces["distance"] return rendered def render_pep440_post(pieces): """TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that .dev0 sorts backwards (a dirty tree will appear "older" than the corresponding clean one), but you shouldn't be releasing software with -dirty anyways. Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += plus_or_dot(pieces) rendered += "g%s" % pieces["short"] else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" rendered += "+g%s" % pieces["short"] return rendered def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. Eexceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"] or pieces["dirty"]: rendered += ".post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" else: # exception #1 rendered = "0.post%d" % pieces["distance"] if pieces["dirty"]: rendered += ".dev0" return rendered def render_git_describe(pieces): """TAG[-DISTANCE-gHEX][-dirty]. Like 'git describe --tags --dirty --always'. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] if pieces["distance"]: rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render_git_describe_long(pieces): """TAG-DISTANCE-gHEX[-dirty]. Like 'git describe --tags --dirty --always -long'. The distance/hash is unconditional. Exceptions: 1: no tags. HEX[-dirty] (note: no 'g' prefix) """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) else: # exception #1 rendered = pieces["short"] if pieces["dirty"]: rendered += "-dirty" return rendered def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: return {"version": "unknown", "full-revisionid": pieces.get("long"), "dirty": None, "error": pieces["error"], "date": None} if not style or style == "default": style = "pep440" # the default if style == "pep440": rendered = render_pep440(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": rendered = render_git_describe(pieces) elif style == "git-describe-long": rendered = render_git_describe_long(pieces) else: raise ValueError("unknown style '%s'" % style) return {"version": rendered, "full-revisionid": pieces["long"], "dirty": pieces["dirty"], "error": None, "date": pieces.get("date")} python-versioneer-0.18/src/setupfunc.py000066400000000000000000000141271303224731000203170ustar00rootroot00000000000000 from __future__ import print_function # --STRIP DURING BUILD import os, sys # --STRIP DURING BUILD def get_root(): pass # --STRIP DURING BUILD def get_config_from_root(): pass # --STRIP DURING BUILD LONG_VERSION_PY = {} # --STRIP DURING BUILD def do_vcs_install(): pass # --STRIP DURING BUILD configparser = None # --STRIP DURING BUILD CONFIG_ERROR = """ setup.cfg is missing the necessary Versioneer configuration. You need a section like: [versioneer] VCS = git style = pep440 versionfile_source = src/myproject/_version.py versionfile_build = myproject/_version.py tag_prefix = parentdir_prefix = myproject- You will also need to edit your setup.py to use the results: import versioneer setup(version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), ...) Please read the docstring in ./versioneer.py for configuration instructions, edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. """ SAMPLE_CONFIG = """ # See the docstring in versioneer.py for instructions. Note that you must # re-run 'versioneer.py setup' after changing this section, and commit the # resulting files. [versioneer] #VCS = git #style = pep440 #versionfile_source = #versionfile_build = #tag_prefix = #parentdir_prefix = """ INIT_PY_SNIPPET = """ from ._version import get_versions __version__ = get_versions()['version'] del get_versions """ def do_setup(): """Main VCS-independent setup function for installing Versioneer.""" root = get_root() try: cfg = get_config_from_root(root) except (EnvironmentError, configparser.NoSectionError, configparser.NoOptionError) as e: if isinstance(e, (EnvironmentError, configparser.NoSectionError)): print("Adding sample versioneer config to setup.cfg", file=sys.stderr) with open(os.path.join(root, "setup.cfg"), "a") as f: f.write(SAMPLE_CONFIG) print(CONFIG_ERROR, file=sys.stderr) return 1 print(" creating %s" % cfg.versionfile_source) with open(cfg.versionfile_source, "w") as f: LONG = LONG_VERSION_PY[cfg.VCS] f.write(LONG % {"DOLLAR": "$", "STYLE": cfg.style, "TAG_PREFIX": cfg.tag_prefix, "PARENTDIR_PREFIX": cfg.parentdir_prefix, "VERSIONFILE_SOURCE": cfg.versionfile_source, }) ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py") if os.path.exists(ipy): try: with open(ipy, "r") as f: old = f.read() except EnvironmentError: old = "" if INIT_PY_SNIPPET not in old: print(" appending to %s" % ipy) with open(ipy, "a") as f: f.write(INIT_PY_SNIPPET) else: print(" %s unmodified" % ipy) else: print(" %s doesn't exist, ok" % ipy) ipy = None # Make sure both the top-level "versioneer.py" and versionfile_source # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so # they'll be copied into source distributions. Pip won't be able to # install the package without this. manifest_in = os.path.join(root, "MANIFEST.in") simple_includes = set() try: with open(manifest_in, "r") as f: for line in f: if line.startswith("include "): for include in line.split()[1:]: simple_includes.add(include) except EnvironmentError: pass # That doesn't cover everything MANIFEST.in can do # (http://docs.python.org/2/distutils/sourcedist.html#commands), so # it might give some false negatives. Appending redundant 'include' # lines is safe, though. if "versioneer.py" not in simple_includes: print(" appending 'versioneer.py' to MANIFEST.in") with open(manifest_in, "a") as f: f.write("include versioneer.py\n") else: print(" 'versioneer.py' already in MANIFEST.in") if cfg.versionfile_source not in simple_includes: print(" appending versionfile_source ('%s') to MANIFEST.in" % cfg.versionfile_source) with open(manifest_in, "a") as f: f.write("include %s\n" % cfg.versionfile_source) else: print(" versionfile_source already in MANIFEST.in") # Make VCS-specific changes. For git, this means creating/changing # .gitattributes to mark _version.py for export-subst keyword # substitution. do_vcs_install(manifest_in, cfg.versionfile_source, ipy) return 0 def scan_setup_py(): """Validate the contents of setup.py against Versioneer's expectations.""" found = set() setters = False errors = 0 with open("setup.py", "r") as f: for line in f.readlines(): if "import versioneer" in line: found.add("import") if "versioneer.get_cmdclass()" in line: found.add("cmdclass") if "versioneer.get_version()" in line: found.add("get_version") if "versioneer.VCS" in line: setters = True if "versioneer.versionfile_source" in line: setters = True if len(found) != 3: print("") print("Your setup.py appears to be missing some important items") print("(but I might be wrong). Please make sure it has something") print("roughly like the following:") print("") print(" import versioneer") print(" setup( version=versioneer.get_version(),") print(" cmdclass=versioneer.get_cmdclass(), ...)") print("") errors += 1 if setters: print("You should remove lines like 'versioneer.VCS = ' and") print("'versioneer.versionfile_source = ' . This configuration") print("now lives in setup.cfg, and should be removed from setup.py") print("") errors += 1 return errors if __name__ == "__main__": cmd = sys.argv[1] if cmd == "setup": errors = do_setup() errors += scan_setup_py() if errors: sys.exit(1) python-versioneer-0.18/src/subprocess_helper.py000066400000000000000000000025241303224731000220300ustar00rootroot00000000000000import sys, subprocess, errno # --STRIP DURING BUILD def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None for c in commands: try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git p = subprocess.Popen([c] + args, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=(subprocess.PIPE if hide_stderr else None)) break except EnvironmentError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue if verbose: print("unable to run %s" % dispcmd) print(e) return None, None else: if verbose: print("unable to find command, tried %s" % (commands,)) return None, None stdout = p.communicate()[0].strip() if sys.version_info[0] >= 3: stdout = stdout.decode() if p.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) return None, p.returncode return stdout, p.returncode python-versioneer-0.18/test/000077500000000000000000000000001303224731000161145ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp-script-only/000077500000000000000000000000001303224731000220225ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp-script-only/MANIFEST.in000066400000000000000000000000571303224731000235620ustar00rootroot00000000000000include src/dummy include src/rundemo-template python-versioneer-0.18/test/demoapp-script-only/README000066400000000000000000000000101303224731000226710ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp-script-only/fake.py000066400000000000000000000000011303224731000232710ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp-script-only/setup.cfg000066400000000000000000000002031303224731000236360ustar00rootroot00000000000000[versioneer] VCS = @VCS@ versionfile_source = src/demo/_version.py versionfile_build = tag_prefix = demo- parentdir_prefix = demo- python-versioneer-0.18/test/demoapp-script-only/setup.py000066400000000000000000000025251303224731000235400ustar00rootroot00000000000000 import os, tempfile from setuptools import setup from distutils.command.build_scripts import build_scripts import versioneer commands = versioneer.get_cmdclass().copy() class my_build_scripts(build_scripts): def run(self): versions = versioneer.get_versions() tempdir = tempfile.mkdtemp() generated = os.path.join(tempdir, "rundemo") with open(generated, "wb") as f: for line in open("src/rundemo-template", "rb"): if line.strip().decode("ascii") == "#versions": f.write(('versions = %r\n' % (versions,)).encode("ascii")) else: f.write(line) self.scripts = [generated] rc = build_scripts.run(self) os.unlink(generated) os.rmdir(tempdir) return rc commands["build_scripts"] = my_build_scripts setup(name="demo", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", zip_safe=True, scripts=["src/dummy"], # this will be replaced by my_build_scripts # without py_modules= or packages=, distutils thinks this module is not # "pure", and will put a platform indicator in the .whl name even # though we call bdist_wheel with --universal. py_modules=["fake"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp-script-only/src/000077500000000000000000000000001303224731000226115ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp-script-only/src/demo/000077500000000000000000000000001303224731000235355ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp-script-only/src/demo/placeholder000066400000000000000000000000001303224731000257300ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp-script-only/src/dummy000066400000000000000000000005321303224731000236670ustar00rootroot00000000000000This is a fake script, used to ensure that setup.py's scripts= list is non-empty. The real script is generated (by modifying a template) during the "setup.py build_scripts" command (run by "setup.py build"). If scripts= was empty, then build_scripts wouldn't get run (as distutils would mistakenly believe that this package produced no scripts). python-versioneer-0.18/test/demoapp-script-only/src/rundemo-template000066400000000000000000000002271303224731000260170ustar00rootroot00000000000000#!/usr/bin/env python #versions print("__version__:%s" % versions['version']) for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) python-versioneer-0.18/test/demoapp/000077500000000000000000000000001303224731000175415ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp/MANIFEST.in000066400000000000000000000000001303224731000212650ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp/README000066400000000000000000000000101303224731000204100ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp/bin/000077500000000000000000000000001303224731000203115ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp/bin/rundemo000066400000000000000000000003671303224731000217130ustar00rootroot00000000000000#!/usr/bin/env python import demo from demo import _version print("__version__:%s" % demo.__version__) print("_version:%s" % str(_version)) versions = _version.get_versions() for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) python-versioneer-0.18/test/demoapp/setup.cfg000066400000000000000000000002251303224731000213610ustar00rootroot00000000000000 [versioneer] VCS = @VCS@ versionfile_source = src/demo/_version.py versionfile_build = demo/_version.py tag_prefix = demo- parentdir_prefix = demo- python-versioneer-0.18/test/demoapp/setup.py000066400000000000000000000006031303224731000212520ustar00rootroot00000000000000 from setuptools import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demo", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", zip_safe=True, packages=["demo"], package_dir={"": "src"}, scripts=["bin/rundemo"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp/src/000077500000000000000000000000001303224731000203305ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp/src/demo/000077500000000000000000000000001303224731000212545ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp/src/demo/__init__.py000066400000000000000000000000011303224731000233540ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp2-distutils-subproject/000077500000000000000000000000001303224731000240235ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/000077500000000000000000000000001303224731000262035ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/MANIFEST.in000066400000000000000000000000001303224731000277270ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/README000066400000000000000000000000101303224731000270520ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/bin/000077500000000000000000000000001303224731000267535ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/bin/rundemo000066400000000000000000000003671303224731000303550ustar00rootroot00000000000000#!/usr/bin/env python import demo from demo import _version print("__version__:%s" % demo.__version__) print("_version:%s" % str(_version)) versions = _version.get_versions() for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/setup.cfg000066400000000000000000000002331303224731000300220ustar00rootroot00000000000000 [versioneer] VCS = git versionfile_source = src/demo/_version.py versionfile_build = demo/_version.py tag_prefix = demoapp2- parentdir_prefix = demoapp2- python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/setup.py000066400000000000000000000005661303224731000277240ustar00rootroot00000000000000 from distutils.core import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demoapp2", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", packages=["demo"], package_dir={"": "src"}, scripts=["bin/rundemo"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/src/000077500000000000000000000000001303224731000267725ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/src/demo/000077500000000000000000000000001303224731000277165ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils-subproject/subproject/src/demo/__init__.py000066400000000000000000000000011303224731000320160ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp2-distutils/000077500000000000000000000000001303224731000216455ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils/MANIFEST.in000066400000000000000000000000001303224731000233710ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils/README000066400000000000000000000000101303224731000225140ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp2-distutils/bin/000077500000000000000000000000001303224731000224155ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils/bin/rundemo000066400000000000000000000003671303224731000240170ustar00rootroot00000000000000#!/usr/bin/env python import demo from demo import _version print("__version__:%s" % demo.__version__) print("_version:%s" % str(_version)) versions = _version.get_versions() for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) python-versioneer-0.18/test/demoapp2-distutils/setup.cfg000066400000000000000000000002331303224731000234640ustar00rootroot00000000000000 [versioneer] VCS = git versionfile_source = src/demo/_version.py versionfile_build = demo/_version.py tag_prefix = demoapp2- parentdir_prefix = demoapp2- python-versioneer-0.18/test/demoapp2-distutils/setup.py000066400000000000000000000005661303224731000233660ustar00rootroot00000000000000 from distutils.core import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demoapp2", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", packages=["demo"], package_dir={"": "src"}, scripts=["bin/rundemo"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp2-distutils/src/000077500000000000000000000000001303224731000224345ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils/src/demo/000077500000000000000000000000001303224731000233605ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-distutils/src/demo/__init__.py000066400000000000000000000000011303224731000254600ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp2-setuptools-subproject/000077500000000000000000000000001303224731000242205ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/000077500000000000000000000000001303224731000264005ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/MANIFEST.in000066400000000000000000000000001303224731000301240ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/README000066400000000000000000000000101303224731000272470ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/setup.cfg000066400000000000000000000002331303224731000302170ustar00rootroot00000000000000 [versioneer] VCS = git versionfile_source = src/demo/_version.py versionfile_build = demo/_version.py tag_prefix = demoapp2- parentdir_prefix = demoapp2- python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/setup.py000066400000000000000000000007571303224731000301230ustar00rootroot00000000000000 from setuptools import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demoapp2", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", zip_safe=True, packages=["demo"], package_dir={"": "src"}, entry_points={ 'console_scripts': [ 'rundemo = demo.main:run' ], }, install_requires=["demolib==1.0"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/src/000077500000000000000000000000001303224731000271675ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/src/demo/000077500000000000000000000000001303224731000301135ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/src/demo/__init__.py000066400000000000000000000000011303224731000322130ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp2-setuptools-subproject/subproject/src/demo/main.py000066400000000000000000000005711303224731000314140ustar00rootroot00000000000000#!/usr/bin/env python import demo from demo import _version from demolib import __version__ as libversion def run(*args, **kwargs): print("__version__:%s" % demo.__version__) print("_version:%s" % str(_version)) versions = _version.get_versions() for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) print("demolib:%s" % libversion) python-versioneer-0.18/test/demoapp2-setuptools/000077500000000000000000000000001303224731000220425ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools/MANIFEST.in000066400000000000000000000000001303224731000235660ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools/README000066400000000000000000000000101303224731000227110ustar00rootroot00000000000000read me python-versioneer-0.18/test/demoapp2-setuptools/setup.cfg000066400000000000000000000002331303224731000236610ustar00rootroot00000000000000 [versioneer] VCS = git versionfile_source = src/demo/_version.py versionfile_build = demo/_version.py tag_prefix = demoapp2- parentdir_prefix = demoapp2- python-versioneer-0.18/test/demoapp2-setuptools/setup.py000066400000000000000000000007571303224731000235650ustar00rootroot00000000000000 from setuptools import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demoapp2", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", zip_safe=True, packages=["demo"], package_dir={"": "src"}, entry_points={ 'console_scripts': [ 'rundemo = demo.main:run' ], }, install_requires=["demolib==1.0"], cmdclass=commands, ) python-versioneer-0.18/test/demoapp2-setuptools/src/000077500000000000000000000000001303224731000226315ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools/src/demo/000077500000000000000000000000001303224731000235555ustar00rootroot00000000000000python-versioneer-0.18/test/demoapp2-setuptools/src/demo/__init__.py000066400000000000000000000000011303224731000256550ustar00rootroot00000000000000 python-versioneer-0.18/test/demoapp2-setuptools/src/demo/main.py000066400000000000000000000005711303224731000250560ustar00rootroot00000000000000#!/usr/bin/env python import demo from demo import _version from demolib import __version__ as libversion def run(*args, **kwargs): print("__version__:%s" % demo.__version__) print("_version:%s" % str(_version)) versions = _version.get_versions() for k in sorted(versions.keys()): print("%s:%s" % (k,versions[k])) print("demolib:%s" % libversion) python-versioneer-0.18/test/demolib/000077500000000000000000000000001303224731000175275ustar00rootroot00000000000000python-versioneer-0.18/test/demolib/MANIFEST.in000066400000000000000000000000001303224731000212530ustar00rootroot00000000000000python-versioneer-0.18/test/demolib/README000066400000000000000000000000101303224731000203760ustar00rootroot00000000000000read me python-versioneer-0.18/test/demolib/setup.cfg000066400000000000000000000002371303224731000213520ustar00rootroot00000000000000 [versioneer] VCS = git versionfile_source = src/demolib/_version.py versionfile_build = demolib/_version.py tag_prefix = demolib- parentdir_prefix = demolib- python-versioneer-0.18/test/demolib/setup.py000066400000000000000000000005521303224731000212430ustar00rootroot00000000000000 from setuptools import setup import versioneer commands = versioneer.get_cmdclass().copy() setup(name="demolib", version=versioneer.get_version(), description="Demo", url="url", author="author", author_email="email", zip_safe=True, packages=["demolib"], package_dir={"": "src"}, cmdclass=commands, ) python-versioneer-0.18/test/demolib/src/000077500000000000000000000000001303224731000203165ustar00rootroot00000000000000python-versioneer-0.18/test/demolib/src/demolib/000077500000000000000000000000001303224731000217315ustar00rootroot00000000000000python-versioneer-0.18/test/demolib/src/demolib/__init__.py000066400000000000000000000000011303224731000240310ustar00rootroot00000000000000 python-versioneer-0.18/test/git/000077500000000000000000000000001303224731000166775ustar00rootroot00000000000000python-versioneer-0.18/test/git/common.py000066400000000000000000000027731303224731000205520ustar00rootroot00000000000000import os, sys from subprocess_helper import run_command GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] class Common: def command(self, cmd, *args, **kwargs): workdir = kwargs.pop("workdir", self.projdir) assert not kwargs, kwargs.keys() output, rc = run_command([cmd], list(args), workdir, True) if output is None: self.fail("problem running command %s" % cmd) return output def git(self, *args, **kwargs): workdir = kwargs.pop("workdir", self.gitdir) assert not kwargs, kwargs.keys() env = os.environ.copy() env["EMAIL"] = "foo@example.com" env["GIT_AUTHOR_NAME"] = "foo" env["GIT_COMMITTER_NAME"] = "foo" output, rc = run_command(GITS, args=list(args), cwd=workdir, verbose=True, env=env) if output is None: self.fail("problem running git (workdir: %s)" % workdir) return output def python(self, *args, **kwargs): workdir = kwargs.pop("workdir", self.projdir) exe = kwargs.pop("python", sys.executable) assert not kwargs, kwargs.keys() output, rc = run_command([exe], list(args), workdir, True) if output is None: self.fail("problem running python (workdir: %s)" % workdir) return output def project_file(self, *path): return os.path.join(self.projdir, *path) def subpath(self, *path): return os.path.join(self.testdir, *path) python-versioneer-0.18/test/git/test_git.py000066400000000000000000000605471303224731000211070ustar00rootroot00000000000000#! /usr/bin/python from __future__ import print_function import os, sys import shutil import tarfile import unittest import tempfile from pkg_resources import parse_version, SetuptoolsLegacyVersion sys.path.insert(0, "src") import common from render import render from git import from_vcs, from_keywords from subprocess_helper import run_command class ParseGitDescribe(unittest.TestCase): def setUp(self): self.fakeroot = tempfile.mkdtemp() self.fakegit = os.path.join(self.fakeroot, ".git") os.mkdir(self.fakegit) def test_pieces(self): def pv(git_describe, do_error=False, expect_pieces=False): def fake_run_command(exes, args, cwd=None, hide_stderr=None): if args[0] == "describe": if do_error == "describe": return None, 0 return git_describe+"\n", 0 if args[0] == "rev-parse": if do_error == "rev-parse": return None, 0 return "longlong\n", 0 if args[0] == "rev-list": return "42\n", 0 if args[0] == "show": return "12345\n", 0 self.fail("git called in weird way: %s" % (args,)) return from_vcs.git_pieces_from_vcs( "v", self.fakeroot, verbose=False, run_command=fake_run_command) self.assertRaises(from_vcs.NotThisMethod, pv, "ignored", do_error="describe") self.assertRaises(from_vcs.NotThisMethod, pv, "ignored", do_error="rev-parse") self.assertEqual(pv("1f"), {"closest-tag": None, "dirty": False, "error": None, "distance": 42, "long": "longlong", "short": "longlon", "date": "12345"}) self.assertEqual(pv("1f-dirty"), {"closest-tag": None, "dirty": True, "error": None, "distance": 42, "long": "longlong", "short": "longlon", "date": "12345"}) self.assertEqual(pv("v1.0-0-g1f"), {"closest-tag": "1.0", "dirty": False, "error": None, "distance": 0, "long": "longlong", "short": "1f", "date": "12345"}) self.assertEqual(pv("v1.0-0-g1f-dirty"), {"closest-tag": "1.0", "dirty": True, "error": None, "distance": 0, "long": "longlong", "short": "1f", "date": "12345"}) self.assertEqual(pv("v1.0-1-g1f"), {"closest-tag": "1.0", "dirty": False, "error": None, "distance": 1, "long": "longlong", "short": "1f", "date": "12345"}) self.assertEqual(pv("v1.0-1-g1f-dirty"), {"closest-tag": "1.0", "dirty": True, "error": None, "distance": 1, "long": "longlong", "short": "1f", "date": "12345"}) def tearDown(self): os.rmdir(self.fakegit) os.rmdir(self.fakeroot) class Keywords(unittest.TestCase): def parse(self, refnames, full, prefix=""): return from_keywords.git_versions_from_keywords( {"refnames": refnames, "full": full}, prefix, False) def test_parse(self): v = self.parse(" (HEAD, 2.0,master , otherbranch ) ", " full ") self.assertEqual(v["version"], "2.0") self.assertEqual(v["full-revisionid"], "full") self.assertEqual(v["dirty"], False) self.assertEqual(v["error"], None) def test_prefer_short(self): v = self.parse(" (HEAD, 2.0rc1, 2.0, 2.0rc2) ", " full ") self.assertEqual(v["version"], "2.0") self.assertEqual(v["full-revisionid"], "full") self.assertEqual(v["dirty"], False) self.assertEqual(v["error"], None) def test_prefix(self): v = self.parse(" (HEAD, projectname-2.0) ", " full ", "projectname-") self.assertEqual(v["version"], "2.0") self.assertEqual(v["full-revisionid"], "full") self.assertEqual(v["dirty"], False) self.assertEqual(v["error"], None) def test_unexpanded(self): self.assertRaises(from_keywords.NotThisMethod, self.parse, " $Format$ ", " full ", "projectname-") def test_no_tags(self): v = self.parse("(HEAD, master)", "full") self.assertEqual(v["version"], "0+unknown") self.assertEqual(v["full-revisionid"], "full") self.assertEqual(v["dirty"], False) self.assertEqual(v["error"], "no suitable tags") def test_no_prefix(self): v = self.parse("(HEAD, master, 1.23)", "full", "missingprefix-") self.assertEqual(v["version"], "0+unknown") self.assertEqual(v["full-revisionid"], "full") self.assertEqual(v["dirty"], False) self.assertEqual(v["error"], "no suitable tags") expected_renders = """ closest-tag: 1.0 distance: 0 dirty: False pep440: 1.0 pep440-pre: 1.0 pep440-post: 1.0 pep440-old: 1.0 git-describe: 1.0 git-describe-long: 1.0-0-g250b7ca closest-tag: 1.0 distance: 0 dirty: True pep440: 1.0+0.g250b7ca.dirty pep440-pre: 1.0 pep440-post: 1.0.post0.dev0+g250b7ca pep440-old: 1.0.post0.dev0 git-describe: 1.0-dirty git-describe-long: 1.0-0-g250b7ca-dirty closest-tag: 1.0 distance: 1 dirty: False pep440: 1.0+1.g250b7ca pep440-pre: 1.0.post.dev1 pep440-post: 1.0.post1+g250b7ca pep440-old: 1.0.post1 git-describe: 1.0-1-g250b7ca git-describe-long: 1.0-1-g250b7ca closest-tag: 1.0 distance: 1 dirty: True pep440: 1.0+1.g250b7ca.dirty pep440-pre: 1.0.post.dev1 pep440-post: 1.0.post1.dev0+g250b7ca pep440-old: 1.0.post1.dev0 git-describe: 1.0-1-g250b7ca-dirty git-describe-long: 1.0-1-g250b7ca-dirty closest-tag: 1.0+plus distance: 1 dirty: False pep440: 1.0+plus.1.g250b7ca pep440-pre: 1.0+plus.post.dev1 pep440-post: 1.0+plus.post1.g250b7ca pep440-old: 1.0+plus.post1 git-describe: 1.0+plus-1-g250b7ca git-describe-long: 1.0+plus-1-g250b7ca closest-tag: 1.0+plus distance: 1 dirty: True pep440: 1.0+plus.1.g250b7ca.dirty pep440-pre: 1.0+plus.post.dev1 pep440-post: 1.0+plus.post1.dev0.g250b7ca pep440-old: 1.0+plus.post1.dev0 git-describe: 1.0+plus-1-g250b7ca-dirty git-describe-long: 1.0+plus-1-g250b7ca-dirty closest-tag: None distance: 1 dirty: False pep440: 0+untagged.1.g250b7ca pep440-pre: 0.post.dev1 pep440-post: 0.post1+g250b7ca pep440-old: 0.post1 git-describe: 250b7ca git-describe-long: 250b7ca closest-tag: None distance: 1 dirty: True pep440: 0+untagged.1.g250b7ca.dirty pep440-pre: 0.post.dev1 pep440-post: 0.post1.dev0+g250b7ca pep440-old: 0.post1.dev0 git-describe: 250b7ca-dirty git-describe-long: 250b7ca-dirty """ class RenderPieces(unittest.TestCase): def do_render(self, pieces): out = {} for style in ["pep440", "pep440-pre", "pep440-post", "pep440-old", "git-describe", "git-describe-long"]: out[style] = render(pieces, style)["version"] DEFAULT = "pep440" self.assertEqual(render(pieces, ""), render(pieces, DEFAULT)) self.assertEqual(render(pieces, "default"), render(pieces, DEFAULT)) return out def parse_expected(self): base_pieces = {"long": "250b7ca731388d8f016db2e06ab1d6289486424b", "short": "250b7ca", "error": None} more_pieces = {} expected = {} for line in expected_renders.splitlines(): line = line.strip() if not line: if more_pieces and expected: pieces = base_pieces.copy() pieces.update(more_pieces) yield (pieces, expected) more_pieces = {} expected = {} continue name, value = line.split(":") name = name.strip() value = value.strip() if name == "distance": more_pieces["distance"] = int(value) elif name == "dirty": more_pieces["dirty"] = bool(value.lower() == "true") elif name == "closest-tag": more_pieces["closest-tag"] = value if value == "None": more_pieces["closest-tag"] = None else: expected[name] = value if more_pieces and expected: pieces = base_pieces.copy() pieces.update(more_pieces) yield (pieces, expected) def test_render(self): for (pieces, expected) in self.parse_expected(): got = self.do_render(pieces) for key in expected: self.assertEqual(got[key], expected[key], (pieces, key, got[key], expected[key])) VERBOSE = False class Repo(common.Common, unittest.TestCase): # There are three tree states we're interested in: # S1: sitting on the initial commit, no tags # S2: dirty tree after the initial commit # S3: sitting on the 1.0 tag # S4: dirtying the tree after 1.0 # S5: making a new commit after 1.0, clean tree # S6: dirtying the tree after the post-1.0 commit # # Then we're interested in 5 kinds of trees: # TA: source tree (with .git) # TB: source tree without .git (should get 'unknown') # TC: source tree without .git unpacked into prefixdir # TD: git-archive tarball # TE: unpacked sdist tarball # # In three runtime situations: # RA1: setup.py --version # RA2: ...path/to/setup.py --version (from outside the source tree) # RB: setup.py build; rundemo --version # # We can only detect dirty files in real git trees, so we don't examine # S2/S4/S6 for TB/TC/TD/TE, or RB. # note that the repo being manipulated is always named "demoapp", # regardless of which source directory we copied it from (test/demoapp/ # or test/demoapp-script-only/) def test_full(self): self.run_test("test/demoapp", False, ".") def test_script_only(self): # This test looks at an application that consists entirely of a # script: no libraries (so its setup.py has packages=[]). This sort # of app cannot be run from source: you must 'setup.py build' to get # anything executable. So of the 3 runtime situations examined by # Repo.test_full above, we only care about RB. (RA1 is valid too, but # covered by Repo). self.run_test("test/demoapp-script-only", True, ".") def test_project_in_subdir(self): # This test sets of the git repository so that the python project -- # i.e. setup.py -- is not located in the root directory self.run_test("test/demoapp", False, "project") def run_test(self, demoapp_dir, script_only, project_sub_dir): # The test dir should live under /tmp/ or /var/ or somewhere that # isn't the child of the versioneer repo's .git directory, since that # will confuse the tests that check what happens when there is no # .git parent. So if you change this to use a fixed directory (say, # when debugging problems), use /tmp/_test rather than ./_test . self.testdir = tempfile.mkdtemp() if VERBOSE: print("testdir: %s" % (self.testdir,)) if os.path.exists(self.testdir): shutil.rmtree(self.testdir) # Our tests run from a git repo that lives here. All self.git() # operations run from this directory unless overridden. self.gitdir = os.path.join(self.testdir, "demoapp") # Inside that git repo, the project (with setup.py, setup.cfg, and # versioneer.py) lives inside this directory. All self.python() and # self.command() operations run from this directory unless # overridden. self.project_sub_dir = project_sub_dir self.projdir = os.path.join(self.testdir, self.gitdir, self.project_sub_dir) os.mkdir(self.testdir) shutil.copytree(demoapp_dir, self.projdir) setup_cfg_fn = self.project_file("setup.cfg") with open(setup_cfg_fn, "r") as f: setup_cfg = f.read() setup_cfg = setup_cfg.replace("@VCS@", "git") with open(setup_cfg_fn, "w") as f: f.write(setup_cfg) shutil.copyfile("versioneer.py", self.project_file("versioneer.py")) self.git("init") self.git("add", "--all") self.git("commit", "-m", "comment") full = self.git("rev-parse", "HEAD") v = self.python("setup.py", "--version") self.assertEqual(v, "0+untagged.1.g%s" % full[:7]) v = self.python(self.project_file("setup.py"), "--version", workdir=self.testdir) self.assertEqual(v, "0+untagged.1.g%s" % full[:7]) out = self.python("versioneer.py", "setup").splitlines() self.assertEqual(out[0], "creating src/demo/_version.py") if script_only: self.assertEqual(out[1], " src/demo/__init__.py doesn't exist, ok") else: self.assertEqual(out[1], " appending to src/demo/__init__.py") self.assertEqual(out[2], " appending 'versioneer.py' to MANIFEST.in") self.assertEqual(out[3], " appending versionfile_source ('src/demo/_version.py') to MANIFEST.in") # Many folks have a ~/.gitignore with ignores .pyc files, but if they # don't, it will show up in the status here. Ignore it. def remove_pyc(s): return [f for f in s if not (f.startswith("?? ") and (f.endswith(".pyc") or f.endswith("__pycache__/"))) ] out = set(remove_pyc(self.git("status", "--porcelain").splitlines())) def pf(fn): return os.path.normpath(os.path.join(self.project_sub_dir, fn)) expected = set(["A %s" % pf(".gitattributes"), "M %s" % pf("MANIFEST.in"), "A %s" % pf("src/demo/_version.py"), ]) if not script_only: expected.add("M %s" % pf("src/demo/__init__.py")) self.assertEqual(out, expected) if not script_only: f = open(self.project_file("src/demo/__init__.py")) i = f.read().splitlines() f.close() self.assertEqual(i[-3], "from ._version import get_versions") self.assertEqual(i[-2], "__version__ = get_versions()['version']") self.assertEqual(i[-1], "del get_versions") self.git("commit", "-m", "add _version stuff") # "versioneer.py setup" should be idempotent out = self.python("versioneer.py", "setup").splitlines() self.assertEqual(out[0], "creating src/demo/_version.py") if script_only: self.assertEqual(out[1], " src/demo/__init__.py doesn't exist, ok") else: self.assertEqual(out[1], " src/demo/__init__.py unmodified") self.assertEqual(out[2], " 'versioneer.py' already in MANIFEST.in") self.assertEqual(out[3], " versionfile_source already in MANIFEST.in") out = set(remove_pyc(self.git("status", "--porcelain").splitlines())) self.assertEqual(out, set([])) UNABLE = "unable to compute version" NOTAG = "no suitable tags" # S1: the tree is sitting on a pre-tagged commit full = self.git("rev-parse", "HEAD") short = "0+untagged.2.g%s" % full[:7] self.do_checks("S1", {"TA": [short, full, False, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, False, None], "TD": ["0+unknown", full, False, NOTAG], "TE": [short, full, False, None], }) # TD: expanded keywords only tell us about tags and full revisionids, # not how many patches we are beyond a tag. So any TD git-archive # tarball from a non-tagged version will give us an error. "dirty" is # False, since the tree from which the tarball was created is # necessarily clean. # S2: dirty the pre-tagged tree f = open(self.project_file("setup.py"), "a") f.write("# dirty\n") f.close() full = self.git("rev-parse", "HEAD") short = "0+untagged.2.g%s.dirty" % full[:7] self.do_checks("S2", {"TA": [short, full, True, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, True, None], "TD": ["0+unknown", full, False, NOTAG], "TE": [short, full, True, None], }) # S3: we commit that change, then make the first tag (1.0) self.git("add", self.project_file("setup.py")) self.git("commit", "-m", "dirty") self.git("tag", "demo-1.0") # also add an unrelated tag, to test exclusion. git-describe appears # to return the highest lexicographically-sorted tag, so make sure # the unrelated one sorts earlier self.git("tag", "aaa-999") full = self.git("rev-parse", "HEAD") short = "1.0" if VERBOSE: print("FULL %s" % full) # the tree is now sitting on the 1.0 tag self.do_checks("S3", {"TA": [short, full, False, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, False, None], "TD": [short, full, False, None], "TE": [short, full, False, None], }) # S4: now we dirty the tree f = open(self.project_file("setup.py"), "a") f.write("# dirty\n") f.close() full = self.git("rev-parse", "HEAD") short = "1.0+0.g%s.dirty" % full[:7] self.do_checks("S4", {"TA": [short, full, True, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, True, None], "TD": ["1.0", full, False, None], "TE": [short, full, True, None], }) # S5: now we make one commit past the tag self.git("add", self.project_file("setup.py")) self.git("commit", "-m", "dirty") full = self.git("rev-parse", "HEAD") short = "1.0+1.g%s" % full[:7] self.do_checks("S5", {"TA": [short, full, False, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, False, None], "TD": ["0+unknown", full, False, NOTAG], "TE": [short, full, False, None], }) # S6: dirty the post-tag tree f = open(self.project_file("setup.py"), "a") f.write("# more dirty\n") f.close() full = self.git("rev-parse", "HEAD") short = "1.0+1.g%s.dirty" % full[:7] self.do_checks("S6", {"TA": [short, full, True, None], "TB": ["0+unknown", None, None, UNABLE], "TC": [short, full, True, None], "TD": ["0+unknown", full, False, NOTAG], "TE": [short, full, True, None], }) def do_checks(self, state, exps): if os.path.exists(self.subpath("out")): shutil.rmtree(self.subpath("out")) # TA: project tree self.check_version(self.projdir, state, "TA", exps["TA"]) # TB: .git-less copy of project tree target = self.subpath("out/demoapp-TB") shutil.copytree(self.projdir, target) if os.path.exists(os.path.join(target, ".git")): shutil.rmtree(os.path.join(target, ".git")) self.check_version(target, state, "TB", exps["TB"]) # TC: project tree in versionprefix-named parentdir target = self.subpath("out/demo-1.1") shutil.copytree(self.projdir, target) if os.path.exists(os.path.join(target, ".git")): shutil.rmtree(os.path.join(target, ".git")) self.check_version(target, state, "TC", ["1.1", None, False, None]) # XXX # TD: project subdir of an unpacked git-archive tarball target = self.subpath("out/TD/demoapp-TD") self.git("archive", "--format=tar", "--prefix=demoapp-TD/", "--output=../demo.tar", "HEAD") os.mkdir(self.subpath("out/TD")) t = tarfile.TarFile(self.subpath("demo.tar")) t.extractall(path=self.subpath("out/TD")) t.close() self.check_version(os.path.join(target, self.project_sub_dir), state, "TD", exps["TD"]) # TE: unpacked setup.py sdist tarball dist_path = os.path.join(self.projdir, "dist") if os.path.exists(dist_path): shutil.rmtree(dist_path) self.python("setup.py", "sdist", "--formats=tar") files = os.listdir(dist_path) self.assertTrue(len(files)==1, files) distfile = files[0] self.assertEqual(distfile, "demo-%s.tar" % exps["TE"][0]) fn = os.path.join(dist_path, distfile) os.mkdir(self.subpath("out/TE")) t = tarfile.TarFile(fn) t.extractall(path=self.subpath("out/TE")) t.close() target = self.subpath("out/TE/demo-%s" % exps["TE"][0]) self.assertTrue(os.path.isdir(target)) self.check_version(target, state, "TE", exps["TE"]) def check_version(self, workdir, state, tree, exps): exp_version, exp_full, exp_dirty, exp_error = exps if VERBOSE: print("== starting %s %s" % (state, tree)) # RA: setup.py --version if VERBOSE: # setup.py version invokes cmd_version, which uses verbose=True # and has more boilerplate. print(self.python("setup.py", "version", workdir=workdir)) # setup.py --version gives us get_version() with verbose=False. v = self.python("setup.py", "--version", workdir=workdir) self.compare(v, exp_version, state, tree, "RA1") self.assertPEP440(v, state, tree, "RA1") # and test again from outside the tree v = self.python(os.path.join(workdir, "setup.py"), "--version", workdir=self.testdir) self.compare(v, exp_version, state, tree, "RA2") self.assertPEP440(v, state, tree, "RA2") # RB: setup.py build; rundemo --version if os.path.exists(os.path.join(workdir, "build")): shutil.rmtree(os.path.join(workdir, "build")) self.python("setup.py", "build", "--build-lib=build/lib", "--build-scripts=build/lib", workdir=workdir) build_lib = os.path.join(workdir, "build", "lib") out = self.python("rundemo", "--version", workdir=build_lib) data = dict([line.split(":",1) for line in out.splitlines()]) self.compare(data["__version__"], exp_version, state, tree, "RB") self.assertPEP440(data["__version__"], state, tree, "RB") self.compare(data["version"], exp_version, state, tree, "RB") self.compare(data["dirty"], str(exp_dirty), state, tree, "RB") self.compare(data["full-revisionid"], str(exp_full), state, tree, "RB") self.compare(data["error"], str(exp_error), state, tree, "RB") def compare(self, got, expected, state, tree, runtime): where = "/".join([state, tree, runtime]) self.assertEqual(got, expected, "%s: got '%s' != expected '%s'" % (where, got, expected)) if VERBOSE: print(" good %s" % where) def assertPEP440(self, got, state, tree, runtime): where = "/".join([state, tree, runtime]) pv = parse_version(got) self.assertFalse(isinstance(pv, SetuptoolsLegacyVersion), "%s: '%s' was not pep440-compatible" % (where, got)) self.assertEqual(str(pv), got, "%s: '%s' pep440-normalized to '%s'" % (where, got, str(pv))) if __name__ == '__main__': ver, rc = run_command(common.GITS, ["--version"], ".", True) print("git --version: %s" % ver.strip()) unittest.main() python-versioneer-0.18/test/git/test_invocations.py000066400000000000000000001101541303224731000226460ustar00rootroot00000000000000from __future__ import print_function import os, sys, shutil, unittest, tempfile, tarfile, virtualenv, warnings sys.path.insert(0, "src") from from_file import versions_from_file import common pyver_major = "py%d" % sys.version_info[0] pyver = "py%d.%d" % sys.version_info[:2] if not hasattr(unittest, "skip"): # py26 def _skip(reason): def _skip_decorator(f): def _skipped_test(*args, **kwargs): print("skipping: %s" % reason) return _skipped_test return _skip_decorator unittest.skip = _skip if not hasattr(unittest, "expectedFailure"): def _expectedFailure(reason="expected to fail"): def _ef_decorator(f): def _ef(*args, **kwargs): print("skipping: %s" % reason) return _ef return _ef_decorator unittest.expectedFailure = _expectedFailure class _Invocations(common.Common): def setUp(self): if False: # when debugging, put the generated files in a predictable place self.testdir = os.path.abspath("t") if os.path.exists(self.testdir): return os.mkdir(self.testdir) else: self.testdir = tempfile.mkdtemp() os.mkdir(self.subpath("cache")) os.mkdir(self.subpath("cache", "distutils")) os.mkdir(self.subpath("cache", "setuptools")) self.gitdir = None self.projdir = None def make_venv(self, mode): if not os.path.exists(self.subpath("venvs")): os.mkdir(self.subpath("venvs")) venv_dir = self.subpath("venvs/%s" % mode) # python3 on OS-X uses a funky two-part executable and an environment # variable to communicate between them. If this variable is still set # by the time a virtualenv's 'pip' or 'python' is run, and if that # command spawns another sys.executable underneath it, that second # child may use the wrong python, and can install things into the # real system library instead of the virtualenv. Invoking # virtualenv.create_environment() clears this as a side-effect, but # to make things safe I'll just clear this now. See # https://github.com/pypa/virtualenv/issues/322 and # https://bugs.python.org/issue22490 for some hints. I tried # switching to 'venv' on py3, but only py3.4 includes pip, and even # then it's an ancient version. os.environ.pop("__PYVENV_LAUNCHER__", None) virtualenv.logger = virtualenv.Logger([]) # hush # virtualenv causes DeprecationWarning/ResourceWarning on py3 with warnings.catch_warnings(): warnings.simplefilter("ignore") virtualenv.create_environment(venv_dir) return venv_dir def run_in_venv(self, venv, workdir, command, *args): bins = {"python": os.path.join(venv, "bin", "python"), "pip": os.path.join(venv, "bin", "pip"), "rundemo": os.path.join(venv, "bin", "rundemo"), "easy_install": os.path.join(venv, "bin", "easy_install"), } if command == "pip": args = ["--no-cache-dir"] + list(args) maj, min = sys.version_info[0:2] if ((maj == 2 and min >= 7) or (maj == 3 and min >= 4) or maj > 3): # We prefer pip --isolated, but py2.6/py3.2/py3.3 (at least # on travis) can't handle the --no-user-cfg that it uses args = ["--isolated"] + list(args) return self.command(bins[command], *args, workdir=workdir) def check_in_venv(self, venv): out = self.run_in_venv(venv, venv, "rundemo") v = dict([line.split(":", 1) for line in out.splitlines()]) self.assertEqual(v["version"], "2.0") return v def check_in_venv_withlib(self, venv): v = self.check_in_venv(venv) self.assertEqual(v["demolib"], "1.0") # "demolib" has a version of 1.0 and is built with distutils # "demoapp2-distutils" is v2.0, uses distutils, and has no deps # "demoapp2-setuptools" is v2.0, uses setuptools, and depends on demolib # repos and unpacked git-archive tarballs come in two flavors: normal (in # which the setup.py/setup.cfg/versioneer.py files live in the root of # the source tree), and "subproject" (where they live in a subdirectory). # sdists are always "normal" (although they might have come from either # normal or subproject -style source trees), and wheels/eggs don't have # these files at all. # TODO: git-archive subproject-flavor def make_demolib_sdist(self): # create an sdist of demolib-1.0 . for the *lib*, we only use the # tarball, never the repo. demolib_sdist = self.subpath("cache", "demolib-1.0.tar") if os.path.exists(demolib_sdist): return demolib_sdist libdir = self.subpath("build-demolib") shutil.copytree("test/demolib", libdir) shutil.copy("versioneer.py", libdir) self.git("init", workdir=libdir) self.python("versioneer.py", "setup", workdir=libdir) self.git("add", "--all", workdir=libdir) self.git("commit", "-m", "commemt", workdir=libdir) self.git("tag", "demolib-1.0", workdir=libdir) self.python("setup.py", "sdist", "--format=tar", workdir=libdir) created = os.path.join(libdir, "dist", "demolib-1.0.tar") self.assertTrue(os.path.exists(created)) shutil.copyfile(created, demolib_sdist) return demolib_sdist def make_linkdir(self): # create/populate a fake pypi directory for use with --find-links linkdir = self.subpath("linkdir") if os.path.exists(linkdir): return linkdir os.mkdir(linkdir) demolib_sdist = self.make_demolib_sdist() shutil.copy(demolib_sdist, linkdir) return linkdir def make_empty_indexdir(self): indexdir = self.subpath("indexdir") if os.path.exists(indexdir): return indexdir os.mkdir(indexdir) return indexdir def make_distutils_repo(self): # create a clean repo of demoapp2-distutils at 2.0 repodir = self.subpath("demoapp2-distutils-repo") if os.path.exists(repodir): shutil.rmtree(repodir) shutil.copytree("test/demoapp2-distutils", repodir) shutil.copy("versioneer.py", repodir) self.git("init", workdir=repodir) self.python("versioneer.py", "setup", workdir=repodir) self.git("add", "--all", workdir=repodir) self.git("commit", "-m", "commemt", workdir=repodir) self.git("tag", "demoapp2-2.0", workdir=repodir) return repodir def make_distutils_repo_subproject(self): # create a clean repo of demoapp2-distutils at 2.0 repodir = self.subpath("demoapp2-distutils-repo-subproject") if os.path.exists(repodir): shutil.rmtree(repodir) shutil.copytree("test/demoapp2-distutils-subproject", repodir) projectdir = os.path.join(repodir, "subproject") shutil.copy("versioneer.py", projectdir) self.git("init", workdir=repodir) self.python("versioneer.py", "setup", workdir=projectdir) self.git("add", "--all", workdir=repodir) self.git("commit", "-m", "commemt", workdir=repodir) self.git("tag", "demoapp2-2.0", workdir=repodir) return projectdir def make_distutils_wheel_with_pip(self): # create an wheel of demoapp2-distutils at 2.0 wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major demoapp2_distutils_wheel = self.subpath("cache", "distutils", wheelname) if os.path.exists(demoapp2_distutils_wheel): return demoapp2_distutils_wheel repodir = self.make_distutils_repo() venv = self.make_venv("make-distutils-wheel-with-pip") self.run_in_venv(venv, repodir, "pip", "wheel", "--wheel-dir", "wheelhouse", "--no-index",# "--find-links", linkdir, ".") created = os.path.join(repodir, "wheelhouse", wheelname) self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_distutils_wheel) return demoapp2_distutils_wheel def make_distutils_sdist(self): # create an sdist tarball of demoapp2-distutils at 2.0 demoapp2_distutils_sdist = self.subpath("cache", "distutils", "demoapp2-2.0.tar") if os.path.exists(demoapp2_distutils_sdist): return demoapp2_distutils_sdist repodir = self.make_distutils_repo() self.python("setup.py", "sdist", "--format=tar", workdir=repodir) created = os.path.join(repodir, "dist", "demoapp2-2.0.tar") self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_distutils_sdist) return demoapp2_distutils_sdist def make_distutils_sdist_subproject(self): demoapp2_distutils_sdist = self.subpath("cache", "distutils", "demoapp2-subproject-2.0.tar") if os.path.exists(demoapp2_distutils_sdist): return demoapp2_distutils_sdist projectdir = self.make_distutils_repo_subproject() self.python("setup.py", "sdist", "--format=tar", workdir=projectdir) created = os.path.join(projectdir, "dist", "demoapp2-2.0.tar") # if that gets the version wrong, it will make the wrong tarball, and # this check will fail self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_distutils_sdist) return demoapp2_distutils_sdist def make_distutils_unpacked(self): sdist = self.make_distutils_sdist() unpack_into = self.subpath("demoapp2-distutils-unpacked") if os.path.exists(unpack_into): shutil.rmtree(unpack_into) os.mkdir(unpack_into) t = tarfile.TarFile(sdist) t.extractall(path=unpack_into) t.close() unpacked = os.path.join(unpack_into, "demoapp2-2.0") self.assertTrue(os.path.exists(unpacked)) return unpacked def make_distutils_subproject_unpacked(self): sdist = self.make_distutils_sdist_subproject() unpack_into = self.subpath("demoapp2-distutils-unpacked-subproject") if os.path.exists(unpack_into): shutil.rmtree(unpack_into) os.mkdir(unpack_into) t = tarfile.TarFile(sdist) t.extractall(path=unpack_into) t.close() unpacked = os.path.join(unpack_into, "demoapp2-2.0") self.assertTrue(os.path.exists(unpacked)) return unpacked def make_setuptools_repo(self): # create a clean repo of demoapp2-setuptools at 2.0 repodir = self.subpath("demoapp2-setuptools-repo") if os.path.exists(repodir): shutil.rmtree(repodir) shutil.copytree("test/demoapp2-setuptools", repodir) shutil.copy("versioneer.py", repodir) self.git("init", workdir=repodir) self.python("versioneer.py", "setup", workdir=repodir) self.git("add", "--all", workdir=repodir) self.git("commit", "-m", "commemt", workdir=repodir) self.git("tag", "demoapp2-2.0", workdir=repodir) return repodir def make_setuptools_repo_subproject(self): # create a clean repo of demoapp2-setuptools at 2.0 repodir = self.subpath("demoapp2-setuptools-repo-subproject") if os.path.exists(repodir): shutil.rmtree(repodir) shutil.copytree("test/demoapp2-setuptools-subproject", repodir) projectdir = os.path.join(repodir, "subproject") shutil.copy("versioneer.py", projectdir) self.git("init", workdir=repodir) self.python("versioneer.py", "setup", workdir=projectdir) self.git("add", "--all", workdir=repodir) self.git("commit", "-m", "commemt", workdir=repodir) self.git("tag", "demoapp2-2.0", workdir=repodir) return projectdir def make_setuptools_sdist(self): # create an sdist tarball of demoapp2-setuptools at 2.0 demoapp2_setuptools_sdist = self.subpath("cache", "setuptools", "demoapp2-2.0.tar") if os.path.exists(demoapp2_setuptools_sdist): return demoapp2_setuptools_sdist repodir = self.make_setuptools_repo() self.python("setup.py", "sdist", "--format=tar", workdir=repodir) created = os.path.join(repodir, "dist", "demoapp2-2.0.tar") self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_setuptools_sdist) return demoapp2_setuptools_sdist def make_setuptools_sdist_subproject(self): demoapp2_setuptools_sdist = self.subpath("cache", "setuptools", "demoapp2-subproject-2.0.tar") if os.path.exists(demoapp2_setuptools_sdist): return demoapp2_setuptools_sdist projectdir = self.make_setuptools_repo_subproject() self.python("setup.py", "sdist", "--format=tar", workdir=projectdir) created = os.path.join(projectdir, "dist", "demoapp2-2.0.tar") self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_setuptools_sdist) return demoapp2_setuptools_sdist def make_setuptools_unpacked(self): sdist = self.make_setuptools_sdist() unpack_into = self.subpath("demoapp2-setuptools-unpacked") if os.path.exists(unpack_into): shutil.rmtree(unpack_into) os.mkdir(unpack_into) t = tarfile.TarFile(sdist) t.extractall(path=unpack_into) t.close() unpacked = os.path.join(unpack_into, "demoapp2-2.0") self.assertTrue(os.path.exists(unpacked)) return unpacked def make_setuptools_subproject_unpacked(self): sdist = self.make_setuptools_sdist_subproject() unpack_into = self.subpath("demoapp2-setuptools-unpacked-subproject") if os.path.exists(unpack_into): shutil.rmtree(unpack_into) os.mkdir(unpack_into) t = tarfile.TarFile(sdist) t.extractall(path=unpack_into) t.close() unpacked = os.path.join(unpack_into, "demoapp2-2.0") self.assertTrue(os.path.exists(unpacked)) return unpacked def make_setuptools_egg(self): # create an egg of demoapp2-setuptools at 2.0 demoapp2_setuptools_egg = self.subpath("cache", "setuptools", "demoapp2-2.0-%s.egg" % pyver) if os.path.exists(demoapp2_setuptools_egg): return demoapp2_setuptools_egg repodir = self.make_setuptools_repo() self.python("setup.py", "bdist_egg", workdir=repodir) created = os.path.join(repodir, "dist", "demoapp2-2.0-%s.egg" % pyver) self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_setuptools_egg) return demoapp2_setuptools_egg def make_setuptools_wheel_with_setup_py(self): # create an wheel of demoapp2-setuptools at 2.0 wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major demoapp2_setuptools_wheel = self.subpath("cache", "setuptools", wheelname) if os.path.exists(demoapp2_setuptools_wheel): # there are two ways to make this .whl, and we need to exercise # both, so don't actually cache the results os.unlink(demoapp2_setuptools_wheel) repodir = self.make_setuptools_repo() self.python("setup.py", "bdist_wheel", workdir=repodir) created = os.path.join(repodir, "dist", wheelname) self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_setuptools_wheel) return demoapp2_setuptools_wheel def make_setuptools_wheel_with_pip(self): # create an wheel of demoapp2-setuptools at 2.0 wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major demoapp2_setuptools_wheel = self.subpath("cache", "setuptools", wheelname) if os.path.exists(demoapp2_setuptools_wheel): # there are two ways to make this .whl, and we need to exercise # both, so don't actually cache the results os.unlink(demoapp2_setuptools_wheel) linkdir = self.make_linkdir() repodir = self.make_setuptools_repo() venv = self.make_venv("make-setuptools-wheel-with-pip") self.run_in_venv(venv, repodir, "pip", "wheel", "--wheel-dir", "wheelhouse", "--no-index", "--find-links", linkdir, ".") created = os.path.join(repodir, "wheelhouse", wheelname) self.assertTrue(os.path.exists(created), created) shutil.copyfile(created, demoapp2_setuptools_wheel) return demoapp2_setuptools_wheel class DistutilsRepo(_Invocations, unittest.TestCase): def test_build(self): repodir = self.make_distutils_repo() self.python("setup.py", "build", workdir=repodir) # test that the built _version.py is correct. Ideally we'd actually # run PYTHONPATH=.../build/lib build/scripts-PYVER/rundemo and check # the output, but that's more fragile than I want to deal with today fn = os.path.join(repodir, "build", "lib", "demo", "_version.py") data = versions_from_file(fn) self.assertEqual(data["version"], "2.0") def test_install(self): repodir = self.make_distutils_repo() venv = self.make_venv("distutils-repo-install") self.run_in_venv(venv, repodir, "python", "setup.py", "install") self.check_in_venv(venv) def test_install_subproject(self): projectdir = self.make_distutils_repo_subproject() venv = self.make_venv("distutils-repo-install-subproject") self.run_in_venv(venv, projectdir, "python", "setup.py", "install") self.check_in_venv(venv) def test_pip_wheel(self): self.make_distutils_wheel_with_pip() # asserts version as a side-effect def test_sdist(self): sdist = self.make_distutils_sdist() # asserts version as a side-effect t = tarfile.TarFile(sdist) # make sure we used distutils/sdist, not setuptools/sdist self.assertFalse("demoapp2-2.0/src/demoapp2.egg-info/PKG-INFO" in t.getnames()) t.close() def test_sdist_subproject(self): sdist = self.make_distutils_sdist_subproject() t = tarfile.TarFile(sdist) # make sure we used distutils/sdist, not setuptools/sdist self.assertFalse("demoapp2-2.0/src/demoapp2.egg-info/PKG-INFO" in t.getnames()) t.close() def test_pip_install(self): repodir = self.make_distutils_repo() venv = self.make_venv("distutils-repo-pip-install") self.run_in_venv(venv, repodir, "pip", "install", ".") self.check_in_venv(venv) @unittest.expectedFailure def test_pip_install_subproject(self): projectdir = self.make_distutils_repo_subproject() venv = self.make_venv("distutils-repo-pip-install-subproject") self.run_in_venv(venv, projectdir, "pip", "install", ".") self.check_in_venv(venv) def test_pip_install_from_afar(self): repodir = self.make_distutils_repo() venv = self.make_venv("distutils-repo-pip-install-from-afar") self.run_in_venv(venv, venv, "pip", "install", repodir) self.check_in_venv(venv) @unittest.expectedFailure def test_pip_install_from_afar_subproject(self): projectdir = self.make_distutils_repo_subproject() venv = self.make_venv("distutils-repo-pip-install-from-afar-subproject") self.run_in_venv(venv, venv, "pip", "install", projectdir) self.check_in_venv(venv) def test_pip_install_editable(self): repodir = self.make_distutils_repo() venv = self.make_venv("distutils-repo-pip-install-editable") self.run_in_venv(venv, repodir, "pip", "install", "--editable", ".") self.check_in_venv(venv) def test_pip_install_editable_subproject(self): projectdir = self.make_distutils_repo_subproject() venv = self.make_venv("distutils-repo-pip-install-editable-subproject") self.run_in_venv(venv, projectdir, "pip", "install", "--editable", ".") self.check_in_venv(venv) class SetuptoolsRepo(_Invocations, unittest.TestCase): def test_install(self): repodir = self.make_setuptools_repo() demolib = self.make_demolib_sdist() venv = self.make_venv("setuptools-repo-install") # "setup.py install" doesn't take --no-index or --find-links, so we # pre-install the dependency self.run_in_venv(venv, venv, "pip", "install", demolib) self.run_in_venv(venv, repodir, "python", "setup.py", "install") self.check_in_venv_withlib(venv) def test_install_subproject(self): projectdir = self.make_setuptools_repo_subproject() demolib = self.make_demolib_sdist() venv = self.make_venv("setuptools-repo-install-subproject") # "setup.py install" doesn't take --no-index or --find-links, so we # pre-install the dependency self.run_in_venv(venv, venv, "pip", "install", demolib) self.run_in_venv(venv, projectdir, "python", "setup.py", "install") self.check_in_venv_withlib(venv) @unittest.skip("setuptools 'easy_install .': known to be broken") def test_easy_install(self): # This case still fails: the 'easy_install' command modifies the # repo's setup.cfg (copying our --index-url and --find-links # arguments into [easy_install]index_url= settings, so that any # dependencies setup_requires= builds will use them), which means the # repo is always "dirty", which creates an .egg with the wrong # version. I have not yet found a clean way to hook the easy_install # command to fix this: there is very little linkage between the # parent command (which could calculate the version before setup.cfg # is modified) and the command which builds the .egg. Leave it broken # for now. linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() repodir = self.make_setuptools_repo() venv = self.make_venv("setuptools-repo-easy-install") self.run_in_venv(venv, repodir, "python", "setup.py", "easy_install", "--index-url", indexdir, "--find-links", linkdir, "." ) self.check_in_venv_withlib(venv) def test_develop(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() repodir = self.make_setuptools_repo() venv = self.make_venv("setuptools-repo-develop") # "setup.py develop" takes --find-links and --index-url but not # --no-index self.run_in_venv(venv, repodir, "python", "setup.py", "develop", "--index-url", indexdir, "--find-links", linkdir, ) self.check_in_venv_withlib(venv) def test_develop_subproject(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() projectdir = self.make_setuptools_repo_subproject() venv = self.make_venv("setuptools-repo-develop-subproject") # "setup.py develop" takes --find-links and --index-url but not # --no-index self.run_in_venv(venv, projectdir, "python", "setup.py", "develop", "--index-url", indexdir, "--find-links", linkdir, ) self.check_in_venv_withlib(venv) def test_egg(self): self.make_setuptools_egg() # asserts version as a side-effect def test_pip_wheel(self): self.make_setuptools_wheel_with_pip() # asserts version as a side-effect def test_bdist_wheel(self): self.make_setuptools_wheel_with_setup_py() # asserts version as a side-effect def test_sdist(self): sdist = self.make_setuptools_sdist() # asserts version as a side-effect t = tarfile.TarFile(sdist) # make sure we used setuptools/sdist, not distutils/sdist self.assertTrue("demoapp2-2.0/src/demoapp2.egg-info/PKG-INFO" in t.getnames()) t.close() def test_sdist_subproject(self): sdist = self.make_setuptools_sdist_subproject() t = tarfile.TarFile(sdist) # make sure we used setuptools/sdist, not distutils/sdist self.assertTrue("demoapp2-2.0/src/demoapp2.egg-info/PKG-INFO" in t.getnames()) t.close() def test_pip_install(self): linkdir = self.make_linkdir() repodir = self.make_setuptools_repo() venv = self.make_venv("setuptools-repo-pip-install") self.run_in_venv(venv, repodir, "pip", "install", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) @unittest.expectedFailure def test_pip_install_subproject(self): linkdir = self.make_linkdir() projectdir = self.make_setuptools_repo_subproject() venv = self.make_venv("setuptools-repo-pip-install-subproject") self.run_in_venv(venv, projectdir, "pip", "install", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) def test_pip_install_from_afar(self): linkdir = self.make_linkdir() repodir = self.make_setuptools_repo() venv = self.make_venv("setuptools-repo-pip-install-from-afar") self.run_in_venv(venv, venv, "pip", "install", repodir, "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) @unittest.expectedFailure def test_pip_install_from_afar_subproject(self): linkdir = self.make_linkdir() projectdir = self.make_setuptools_repo_subproject() venv = self.make_venv("setuptools-repo-pip-install-from-afar-subproject") self.run_in_venv(venv, venv, "pip", "install", projectdir, "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) def test_pip_install_editable(self): linkdir = self.make_linkdir() repodir = self.make_setuptools_repo() venv = self.make_venv("setuptools-repo-pip-install-editable") self.run_in_venv(venv, repodir, "pip", "install", "--editable", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) def test_pip_install_editable_subproject(self): linkdir = self.make_linkdir() projectdir = self.make_setuptools_repo_subproject() venv = self.make_venv("setuptools-repo-pip-install-editable-subproject") self.run_in_venv(venv, projectdir, "pip", "install", "--editable", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) class DistutilsSdist(_Invocations, unittest.TestCase): def test_pip_install(self): sdist = self.make_distutils_sdist() venv = self.make_venv("distutils-sdist-pip-install") self.run_in_venv(venv, venv, "pip", "install", sdist) self.check_in_venv(venv) def test_pip_install_subproject(self): sdist = self.make_distutils_sdist_subproject() venv = self.make_venv("distutils-sdist-pip-install-subproject") self.run_in_venv(venv, venv, "pip", "install", sdist) self.check_in_venv(venv) def test_easy_install(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() sdist = self.make_distutils_sdist() venv = self.make_venv("distutils-sdist-easy-install") self.run_in_venv(venv, venv, "easy_install", "--index-url", indexdir, "--find-links", linkdir, sdist) self.check_in_venv(venv) class SetuptoolsSdist(_Invocations, unittest.TestCase): def test_pip_install(self): linkdir = self.make_linkdir() sdist = self.make_setuptools_sdist() venv = self.make_venv("setuptools-sdist-pip-install") self.run_in_venv(venv, venv, "pip", "install", "--no-index", "--find-links", linkdir, sdist) self.check_in_venv_withlib(venv) def test_pip_install_subproject(self): linkdir = self.make_linkdir() sdist = self.make_setuptools_sdist_subproject() venv = self.make_venv("setuptools-sdist-pip-install-subproject") self.run_in_venv(venv, venv, "pip", "install", "--no-index", "--find-links", linkdir, sdist) self.check_in_venv_withlib(venv) def test_easy_install(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() sdist = self.make_setuptools_sdist() venv = self.make_venv("setuptools-sdist-easy-install") self.run_in_venv(venv, venv, "easy_install", "--index-url", indexdir, "--find-links", linkdir, sdist) self.check_in_venv_withlib(venv) class SetuptoolsWheel(_Invocations, unittest.TestCase): def test_pip_install(self): linkdir = self.make_linkdir() wheel = self.make_setuptools_wheel_with_setup_py() venv = self.make_venv("setuptools-wheel-pip-install") self.run_in_venv(venv, venv, "pip", "install", "--no-index", "--find-links", linkdir, wheel) self.check_in_venv_withlib(venv) class Egg(_Invocations, unittest.TestCase): def test_easy_install(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() egg = self.make_setuptools_egg() venv = self.make_venv("setuptools-egg-easy-install") self.run_in_venv(venv, venv, "easy_install", "--index-url", indexdir, "--find-links", linkdir, egg) self.check_in_venv_withlib(venv) class DistutilsUnpacked(_Invocations, unittest.TestCase): def test_build(self): unpacked = self.make_distutils_unpacked() self.python("setup.py", "build", workdir=unpacked) # test that the built _version.py is correct. Ideally we'd actually # run PYTHONPATH=.../build/lib build/scripts-PYVER/rundemo and check # the output, but that's more fragile than I want to deal with today fn = os.path.join(unpacked, "build", "lib", "demo", "_version.py") data = versions_from_file(fn) self.assertEqual(data["version"], "2.0") def test_install(self): unpacked = self.make_distutils_unpacked() venv = self.make_venv("distutils-unpacked-install") self.run_in_venv(venv, unpacked, "python", "setup.py", "install") self.check_in_venv(venv) def test_install_subproject(self): unpacked = self.make_distutils_subproject_unpacked() venv = self.make_venv("distutils-subproject-unpacked-install") self.run_in_venv(venv, unpacked, "python", "setup.py", "install") self.check_in_venv(venv) def test_pip_wheel(self): unpacked = self.make_distutils_unpacked() wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major venv = self.make_venv("distutils-unpacked-pip-wheel") self.run_in_venv(venv, unpacked, "pip", "wheel", "--wheel-dir", "wheelhouse", "--no-index",# "--find-links", linkdir, ".") created = os.path.join(unpacked, "wheelhouse", wheelname) self.assertTrue(os.path.exists(created), created) def test_pip_install(self): repodir = self.make_distutils_unpacked() venv = self.make_venv("distutils-unpacked-pip-install") self.run_in_venv(venv, repodir, "pip", "install", ".") self.check_in_venv(venv) def test_pip_install_subproject(self): unpacked = self.make_distutils_subproject_unpacked() venv = self.make_venv("distutils-subproject-unpacked-pip-install") self.run_in_venv(venv, unpacked, "pip", "install", ".") self.check_in_venv(venv) def test_pip_install_from_afar(self): repodir = self.make_distutils_unpacked() venv = self.make_venv("distutils-unpacked-pip-install-from-afar") self.run_in_venv(venv, venv, "pip", "install", repodir) self.check_in_venv(venv) class SetuptoolsUnpacked(_Invocations, unittest.TestCase): def test_install(self): unpacked = self.make_setuptools_unpacked() demolib = self.make_demolib_sdist() venv = self.make_venv("setuptools-unpacked-install") # "setup.py install" doesn't take --no-index or --find-links, so we # pre-install the dependency self.run_in_venv(venv, venv, "pip", "install", demolib) self.run_in_venv(venv, unpacked, "python", "setup.py", "install") self.check_in_venv_withlib(venv) def test_install_subproject(self): unpacked = self.make_setuptools_subproject_unpacked() demolib = self.make_demolib_sdist() venv = self.make_venv("setuptools-subproject-unpacked-install") # "setup.py install" doesn't take --no-index or --find-links, so we # pre-install the dependency self.run_in_venv(venv, venv, "pip", "install", demolib) self.run_in_venv(venv, unpacked, "python", "setup.py", "install") self.check_in_venv_withlib(venv) def test_easy_install(self): linkdir = self.make_linkdir() indexdir = self.make_empty_indexdir() unpacked = self.make_setuptools_unpacked() venv = self.make_venv("setuptools-unpacked-easy-install") self.run_in_venv(venv, unpacked, "python", "setup.py", "easy_install", "--index-url", indexdir, "--find-links", linkdir, "." ) self.check_in_venv_withlib(venv) def test_wheel(self): unpacked = self.make_setuptools_unpacked() self.python("setup.py", "bdist_wheel", workdir=unpacked) wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major wheel = os.path.join(unpacked, "dist", wheelname) self.assertTrue(os.path.exists(wheel)) def test_pip_wheel(self): unpacked = self.make_setuptools_unpacked() linkdir = self.make_linkdir() wheelname = "demoapp2-2.0-%s-none-any.whl" % pyver_major venv = self.make_venv("setuptools-unpacked-pip-wheel") self.run_in_venv(venv, unpacked, "pip", "wheel", "--wheel-dir", "wheelhouse", "--no-index", "--find-links", linkdir, ".") created = os.path.join(unpacked, "wheelhouse", wheelname) self.assertTrue(os.path.exists(created), created) def test_pip_install(self): linkdir = self.make_linkdir() repodir = self.make_setuptools_unpacked() venv = self.make_venv("setuptools-unpacked-pip-install") self.run_in_venv(venv, repodir, "pip", "install", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) def test_pip_install_subproject(self): linkdir = self.make_linkdir() unpacked = self.make_setuptools_subproject_unpacked() venv = self.make_venv("setuptools-subproject-unpacked-pip-install") self.run_in_venv(venv, unpacked, "pip", "install", ".", "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) def test_pip_install_from_afar(self): linkdir = self.make_linkdir() repodir = self.make_setuptools_unpacked() venv = self.make_venv("setuptools-unpacked-pip-install-from-afar") self.run_in_venv(venv, venv, "pip", "install", repodir, "--no-index", "--find-links", linkdir) self.check_in_venv_withlib(venv) if __name__ == '__main__': unittest.main() python-versioneer-0.18/test/run_pyflakes_src.py000066400000000000000000000011741303224731000220420ustar00rootroot00000000000000from __future__ import print_function import os from pyflakes.api import main def get_filenames(): for dirpath, dirnames, filenames in os.walk("src"): if dirpath.endswith("__pycache__"): continue for rel_fn in filenames: if not rel_fn.endswith(".py"): continue fn = os.path.join(dirpath, rel_fn) if fn in [os.path.join("src", "header.py"), os.path.join("src", "git", "long_header.py"), ]: continue print("pyflakes on:", fn) yield fn main(args=list(get_filenames())) python-versioneer-0.18/test/test_config.py000066400000000000000000000043661303224731000210030ustar00rootroot00000000000000import unittest import os, tempfile, shutil try: import configparser except ImportError: import ConfigParser as configparser from versioneer import get_config_from_root base = """ [versioneer] VCS = git style = pep440 versionfile_source = petmail/_version.py versionfile_build = petmail/_version.py tag_prefix = v parentdir_prefix = petmail- """ class Parser(unittest.TestCase): def parse(self, contents): root = tempfile.mkdtemp() try: with open(os.path.join(root, "setup.cfg"), "w") as f: f.write(contents) return get_config_from_root(root) finally: shutil.rmtree(root) def test_base(self): cfg = self.parse(base) self.assertEqual(cfg.VCS, "git") self.assertEqual(cfg.style, "pep440") self.assertEqual(cfg.versionfile_source, "petmail/_version.py") self.assertEqual(cfg.versionfile_build, "petmail/_version.py") self.assertEqual(cfg.tag_prefix, "v") self.assertEqual(cfg.parentdir_prefix, "petmail-") self.assertEqual(cfg.verbose, None) def test_empty(self): self.assertRaises(configparser.NoSectionError, self.parse, "") def test_mostly_empty(self): self.assertRaises(configparser.NoOptionError, self.parse, "[versioneer]\n") def test_minimal(self): cfg = self.parse("[versioneer]\nvcs = git\n") self.assertEqual(cfg.VCS, "git") self.assertEqual(cfg.style, "") self.assertEqual(cfg.versionfile_source, None) self.assertEqual(cfg.versionfile_build, None) self.assertEqual(cfg.tag_prefix, None) self.assertEqual(cfg.parentdir_prefix, None) self.assertEqual(cfg.verbose, None) def test_empty_tag_prefixes(self): # all three of these should give an empty tag_prefix: # tag_prefix = # tag_prefix = '' # tag_prefix = "" cfg = self.parse("[versioneer]\nVCS=git\ntag_prefix=") self.assertEqual(cfg.tag_prefix, "") cfg = self.parse("[versioneer]\nVCS=git\ntag_prefix=''") self.assertEqual(cfg.tag_prefix, "") cfg = self.parse("[versioneer]\nVCS=git\ntag_prefix=\"\"") self.assertEqual(cfg.tag_prefix, "") python-versioneer-0.18/test/test_file.py000066400000000000000000000015311303224731000204440ustar00rootroot00000000000000import os, shutil, tempfile, unittest from versioneer import versions_from_file class Parser(unittest.TestCase): def test_lf(self): root = tempfile.mkdtemp() try: fn = os.path.join(root, "_version.py") with open(fn, "wb") as f: f.write(b"version_json = '''\n{}\n''' # END VERSION_JSON\n") data = versions_from_file(fn) self.assertEqual(data, {}) finally: shutil.rmtree(root) def test_cflf(self): root = tempfile.mkdtemp() try: fn = os.path.join(root, "_version.py") with open(fn, "wb") as f: f.write(b"version_json = '''\r\n{}\r\n''' # END VERSION_JSON\r\n") data = versions_from_file(fn) self.assertEqual(data, {}) finally: shutil.rmtree(root) python-versioneer-0.18/test/test_render.py000066400000000000000000000134551303224731000210140ustar00rootroot00000000000000import unittest from versioneer import render class Testing_renderer_case_mixin(object): """ This is a mixin object which can be combined with a unittest.TestCase which defines a style and an expected dictionary. See Test_pep440 for and example. """ def define_pieces(self, closest_tag, distance=0, dirty=False): return {"error": '', "closest-tag": closest_tag, "distance": distance, "dirty": dirty, "short": "abc" if distance else '', "long": "abcdefg" if distance else '', "date": "2016-05-31T13:02:11+0200"} def assert_rendered(self, pieces, test_case_name): version = render(pieces, self.style)['version'] expected = self.expected[test_case_name] msg = ('Versions differ for {0} style with "{1}" case: expected {2}, ' 'got {3}'.format(self.style, test_case_name, expected, version)) self.assertEqual(version, expected, msg) # Naming structure: # test_(un)tagged__commits_(clean|dirty) def test_tagged_0_commits_clean(self): self.assert_rendered(self.define_pieces('v1.2.3'), 'tagged_0_commits_clean') def test_tagged_1_commits_clean(self): self.assert_rendered(self.define_pieces('v1.2.3', distance=1), 'tagged_1_commits_clean') def test_tagged_0_commits_dirty(self): self.assert_rendered(self.define_pieces('v1.2.3', dirty=True), 'tagged_0_commits_dirty') def test_tagged_1_commits_dirty(self): self.assert_rendered(self.define_pieces('v1.2.3', distance=1, dirty=True), 'tagged_1_commits_dirty') def test_untagged_0_commits_clean(self): self.assert_rendered(self.define_pieces(None), 'untagged_0_commits_clean') def test_untagged_1_commits_clean(self): self.assert_rendered(self.define_pieces(None, distance=1), 'untagged_1_commits_clean') def test_untagged_0_commits_dirty(self): self.assert_rendered(self.define_pieces(None, dirty=True), 'untagged_0_commits_dirty') def test_untagged_1_commits_dirty(self): self.assert_rendered(self.define_pieces(None, distance=1, dirty=True), 'untagged_1_commits_dirty') def test_error_getting_parts(self): self.assert_rendered({'error': 'Not a git repo'}, 'error_getting_parts') class Test_pep440(unittest.TestCase, Testing_renderer_case_mixin): style = 'pep440' expected = {'tagged_0_commits_clean': 'v1.2.3', 'tagged_0_commits_dirty': 'v1.2.3+0.g.dirty', 'tagged_1_commits_clean': 'v1.2.3+1.gabc', 'tagged_1_commits_dirty': 'v1.2.3+1.gabc.dirty', 'untagged_0_commits_clean': '0+untagged.0.g', 'untagged_0_commits_dirty': '0+untagged.0.g.dirty', 'untagged_1_commits_clean': '0+untagged.1.gabc', 'untagged_1_commits_dirty': '0+untagged.1.gabc.dirty', 'error_getting_parts': 'unknown' } class Test_pep440_old(unittest.TestCase, Testing_renderer_case_mixin): style = 'pep440-old' expected = {'tagged_0_commits_clean': 'v1.2.3', 'tagged_0_commits_dirty': 'v1.2.3.post0.dev0', 'tagged_1_commits_clean': 'v1.2.3.post1', 'tagged_1_commits_dirty': 'v1.2.3.post1.dev0', 'untagged_0_commits_clean': '0.post0', 'untagged_0_commits_dirty': '0.post0.dev0', 'untagged_1_commits_clean': '0.post1', 'untagged_1_commits_dirty': '0.post1.dev0', 'error_getting_parts': 'unknown' } class Test_pep440_post(unittest.TestCase, Testing_renderer_case_mixin): style = 'pep440-post' expected = {'tagged_0_commits_clean': 'v1.2.3', 'tagged_0_commits_dirty': 'v1.2.3.post0.dev0+g', 'tagged_1_commits_clean': 'v1.2.3.post1+gabc', 'tagged_1_commits_dirty': 'v1.2.3.post1.dev0+gabc', 'untagged_0_commits_clean': '0.post0+g', 'untagged_0_commits_dirty': '0.post0.dev0+g', 'untagged_1_commits_clean': '0.post1+gabc', 'untagged_1_commits_dirty': '0.post1.dev0+gabc', 'error_getting_parts': 'unknown' } class Test_pep440_pre(unittest.TestCase, Testing_renderer_case_mixin): style = 'pep440-pre' expected = {'tagged_0_commits_clean': 'v1.2.3', 'tagged_0_commits_dirty': 'v1.2.3', 'tagged_1_commits_clean': 'v1.2.3.post.dev1', 'tagged_1_commits_dirty': 'v1.2.3.post.dev1', 'untagged_0_commits_clean': '0.post.dev0', 'untagged_0_commits_dirty': '0.post.dev0', 'untagged_1_commits_clean': '0.post.dev1', 'untagged_1_commits_dirty': '0.post.dev1', 'error_getting_parts': 'unknown' } class Test_git_describe(unittest.TestCase, Testing_renderer_case_mixin): style = 'git-describe' expected = {'tagged_0_commits_clean': 'v1.2.3', 'tagged_0_commits_dirty': 'v1.2.3-dirty', 'tagged_1_commits_clean': 'v1.2.3-1-gabc', 'tagged_1_commits_dirty': 'v1.2.3-1-gabc-dirty', 'untagged_0_commits_clean': '', 'untagged_0_commits_dirty': '-dirty', 'untagged_1_commits_clean': 'abc', 'untagged_1_commits_dirty': 'abc-dirty', 'error_getting_parts': 'unknown' } if __name__ == '__main__': unittest.main() python-versioneer-0.18/tox.ini000066400000000000000000000033151303224731000164520ustar00rootroot00000000000000# Tox (http://tox.testrun.org/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. # env names corresponding to py${TRAVIS_PYTHON_VERSION}, see .travis.yml [tox] envlist = py2.6,py2.7,py3.2,py3.3,py3.4,py3.5,py3.6,pypypy,pypypy3 skip_missing_interpreters = True [testenv] basepython = py2.6: python2.6 py2.7: python2.7 py3.2: python3.2 py3.3: python3.3 py3.4: python3.4 py3.5: python3.5 py3.6: python3.6 pypypy: pypy pypypy3: pypy3 # virtualenv>=14.0.0 is incompatible with python 3.2 # flake8>=3.0.0 is incompatible with 2.6,3.2,3.3 deps = pyflakes py2.6,py3.2,py3.3: flake8<3.0.0 py2.7,py3.4,py3.5,py3.6,pypypy,pypypy3: flake8 wheel setuptools py3.2: virtualenv<14.0.0 py2.6,py2.7,py3.3,py3.4,py3.5,py3.6,pypypy,pypypy3: virtualenv discover flake8-docstrings pep8 commands = pip --version easy_install --version virtualenv --version # this creates versioneer.py in the current directory, which is used by # tests python setup.py make_versioneer python -m discover test python test/git/test_git.py -v python test/git/test_invocations.py -v # this creates git_version.py, which is used by tests python setup.py make_long_version_py_git pyflakes setup.py versioneer.py git_version.py # pyflakes all of src except src/git/long_header.py and src/header.py python test/run_pyflakes_src.py pyflakes test flake8 git_version.py versioneer.py pep8 git_version.py versioneer.py