Home

Awesome

Dunamai

Dunamai is a Python 3.5+ library and command line tool for producing dynamic, standards-compliant version strings, derived from tags in your version control system. This facilitates uniquely identifying nightly or per-commit builds in continuous integration and releasing new versions of your software simply by creating a tag.

Dunamai is also available as a GitHub Action.

Features

Usage

Installation

pip install dunamai

CLI

# Suppose you are on commit g29045e8, 7 commits after the v0.2.0 tag.

# Auto-detect the version control system and generate a version:
$ dunamai from any
0.2.0.post7.dev0+g29045e8

# Or use an explicit VCS and style:
$ dunamai from git --no-metadata --style semver
0.2.0-post.7

# Custom formats:
$ dunamai from any --format "v{base}+{distance}.{commit}"
v0.2.0+7.g29045e8

# If you'd prefer to frame the version in terms of progress toward the next
# release rather than distance from the latest one, you can bump it:
$ dunamai from any --bump
0.2.1.dev7+g29045e8

# Validation of custom formats:
$ dunamai from any --format "v{base}" --style pep440
Version 'v0.2.0' does not conform to the PEP 440 style

# Validate your own freeform versions:
$ dunamai check 0.01.0 --style semver
Version '0.01.0' does not conform to the Semantic Versioning style

# More info:
$ dunamai --help
$ dunamai from --help
$ dunamai from git --help

Library

from dunamai import Version, Style

# Let's say you're on commit g644252b, which is tagged as v0.1.0.
version = Version.from_git()
assert version.serialize() == "0.1.0"

# Let's say there was a v0.1.0rc5 tag 44 commits ago
# and you have some uncommitted changes.
version = Version.from_any_vcs()
assert version.serialize() == "0.1.0rc5.post44.dev0+g644252b"
assert version.serialize(metadata=False) == "0.1.0rc5.post44.dev0"
assert version.serialize(dirty=True) == "0.1.0rc5.post44.dev0+g644252b.dirty"
assert version.serialize(style=Style.SemVer) == "0.1.0-rc.5.post.44+g644252b"

The serialize() method gives you an opinionated, PEP 440-compliant default that ensures that versions for untagged commits are compatible with Pip's --pre flag. The individual parts of the version are also available for you to use and inspect as you please:

assert version.base == "0.1.0"
assert version.stage == "rc"
assert version.revision == 5
assert version.distance == 44
assert version.commit == "g644252b"
assert version.dirty is True

# Available if the latest tag includes metadata, like v0.1.0+linux:
assert version.tagged_metadata == "linux"

Tips

By default, the "v" prefix on the tag is required, unless you specify a custom tag pattern. You can either write a regular expression:

...or use a named preset:

You can also keep the default pattern and just specify a prefix. For example, this would match tags like some-package-v1.2.3:

VCS archives

Sometimes, you may only have access to an archive of a repository (e.g., a zip file) without the full history. Dunamai can still detect a version in some of these cases:

Custom formats

Here are the available substitutions for custom formats. If you have a tag like v9!0.1.2-beta.3+other, then:

If you specify a substitution, its value will always be included in the output. For conditional formatting, you can do something like this (Bash):

distance=$(dunamai from any --format "{distance}")
if [ "$distance" = "0" ]; then
    dunamai from any --format "v{base}"
else
    dunamai from any --format "v{base}+{distance}.{dirty}"
fi

Comparison to Versioneer

Versioneer is another great library for dynamic versions, but there are some design decisions that prompted the creation of Dunamai as an alternative:

Integration

Other notes