Skip to main content

vcver Python

What is vcver?

vcver is an approach for versioning that heavily relies on the version control system of choice for determining version strings.

There are two categories of version strings:

develop versions, of the form:

{main_version}.dev{commit_count}+{branch}.{scm_change_id}

With development branches, it is desired to not override versions published from a blessed subset of “released” branches. As such, if the current branch is not a release branch, a version of 0 is used instead of the main_version:

0.dev{commit_count}+{branch}.{scm_change_id}

and a release version, of the form:

{main_version}

Each part is described as follows:

  • main_version is retrieved from the last tagged commit with a leading v (e.g. v1.0), but is converted to a 0 if the branch is not a release branch.

  • commit_count is the number of commits from main_version

  • branch is the branch that the repository was built against, removing characters that are incompatible with PEP440 (anything that is not alphanumeric or a dot)

  • scm_change_id is a unique id in the form of version control, used to identify the change that was used to build this version.

For example, in a git repository, on a master branch with the most recent tag of v1.1, the dev version would look something like:

1.1.dev10+master.abc123

On a develop branch:

0.dev13+develop.def456

And a release version:

1.1

These are compatible with PEP440.

Example

Add a MANIFEST.in to your package, if you do not already have one. Then add the following:

include VERSION

It’s also recommended to ignore this file in your version control.

Then, follow this pattern in your setup.py:

# OPTIONAL, but recommended:
# this block is useful for specifying when a build should
# use the 'release' version. it allows specifying a release version
# with an additional argument in the setup.py:
# $ python setup.py upload --release
import sys
is_release = False
if "--release" in sys.argv:
    sys.argv.remove("--release")
    is_release = True

# OPTIONAL, but recommended:
# vcver writes a version file relative to the
# current working directory by default.
# It's recommended to provide it with your
# setup.py directory instead (in case someone
# runs your setup.py from a different directory)
base = os.path.dirname(os.path.abspath(__file__))

setup(name='aiohttp-transmute',
    # add the following two lines,
    # and do not specify a version.
    setup_requires=["vcver"],
    # vcver will only produce a release
    # version if "is_release" is True.
    vcver={
        "is_release": is_release,
        "path": base,
        # OPTIONAL ARGS

        # version_format overrides the standard version format
        version_format="{main_version}.{commit_count}",

        # release_version_format overrides the release version format
        release_version_format="{commit_count}",

        # scm_type: if you do not want autodetection of the SCM, you can
        # specify it.
        scm_type="git",

        # release_branch_regex: override the default release branch
        # (default release branch depends on the SCM used.)
        release_branch_regex="(master|hotfix|release)",

        # version_file: override the name of the version file.
        version_file="GENERATED_VERSION"
    },
    ...
)

Now your package will publish with a VC-based version!

If you followed the full example, you can specify the release version by adding –release:

python setup.py upload --release

FAQ / Other Details

Why a dev and release version?

The dev and release versions have different goals:

  • dev: to provide as much information as possible to quickly identify where the current version originated from in regard to version control.

  • release: to provide a clear version that helps the consumer understand what changed.

For most consumers, the number of commits since the last release, the branch it was released against, or the build commit itself are irrelevant. The consumer wants to know about the size of the change or type of changes, and that can be done by the major / minor / patch versions specified in the git tag, or the changelog. Adding version control information proves to be confusing with that regard, providing multiple numbers that are not relevant to figuring out the amount of change.

Why zero out versions from non-release branches?

Sometimes, a non-release version can be published accidentally, or it may be desired to publish development versions side by side by versions published by release branches. In this situations, ensuring that the release versions always take precedence over non-release version is valuable, to ensure that development versions are not accidentally picked up by those expecting stable releases.

If this behavior is not desired, custom version strings can be specified with “main_version” instead of “main_version”. “main_version” is preserved regardless of the branch used.

How to make sure others can consume your package

If you followed the example, you already have this.

Once vcver is called, a VERSION file is created in the current working directory, which is typically the same directory as where the setup.py lives (you can make it more accurate, see the example)

vcver will attempt to find a VERSION file if the working directory is not a version control repository. Make sure your package includes a VERSION file by creating/modifying the MANIFEST.in:

include VERSION

Customizable Version Strings

Both the version format and release format is configurable, with the arguments version_format and release_version_format, respectively.

In addition to the values above, the following values are provided:

  • tag_version: the raw version of main_version, which does not zero out for non-release branches.

Pre-PEP440 Version

Some (much older) versions of setuptools are unable to consume the dev version string, due to the plus in the version string.

If you need backwards compatibility and you would still like vc versioning, the following format is recommended:

     {main_version}.dev{commit_count}.{branch}.{scm_change_id}

This can be changed by an argument into vcver:
# in the setup call of setup.py
vcver={"version_format": "{main_version}.dev{commit_count}.{branch}.{scm_change_id}"}

Compatibility with Semantic Versioning

Semantic versioning is a standard to provided a meaning to the major, minor, and patch versions of a version string. Compatibility with semver is possible if new major / minor versions are tagged according the semver spec.

Special Thanks

  • Zillow, where this particular approach of SCM-based versioning was developed

  • Taylor McKay, who implemented the original Python version at Zillow

  • Mohammad Sarhan, who designed and implemented the original Java version at Zillow, and has a public gradle variant

Metadata

Release files for vcver 0.2.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vcver 0.2.12
File Size Uploaded
vcver-0.2.12.tar.gz 13.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vcver 0.2.12
File Interpreter ABI Platform
vcver-0.2.12-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 26.6 kB

Release files / vcver-0.2.12.tar.gz

Download URL vcver-0.2.12.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6ff8181d87bd943c8e0dc939acf6a1358aa68eb4e2db537591982452a3005553
BLAKE2b-256 checksum
How to use checksums
f3be335cfdacb2bdbf8de1bb0fc3e75d35af2f38d978e89ce9c35c2c83b39ab6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.9.2

Release files / vcver-0.2.12-py2.py3-none-any.whl

Download URL vcver-0.2.12-py2.py3-none-any.whl
Size 13.4 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
48cbe2afefc60dd2ceca5f766ca40a3f26c60e9e778a9b48783efb1a2b3de2cc
BLAKE2b-256 checksum
How to use checksums
cc048719edaba58aa968af2540d5f3b344e901d6007c1e3c5786c397387474f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.9.2
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page