Configuration
The [tool.versioningit]
table in pyproject.toml
is divided into
seven subtables, each describing how one of the seven steps of the version
extraction & calculation should be carried out. Each subtable consists of an
optional method
key specifying the method (entry point or function)
that should be used to carry out that step, plus zero or more extra keys that
will be passed as parameters to the method when it’s called. If the method
key is omitted, the default method for the step is used.
Specifying the Method
A method can be specified in two different ways, depending on where it’s
implemented. A method that is built in to versioningit
or provided by an
installed third-party extension is specified by giving its name as a string,
e.g.:
[tool.versioningit.vcs]
# The method key:
method = "git" # <- The method name
# Parameters to pass to the method:
match = ["v*"]
default-tag = "1.0.0"
Alternatively, a method can be implemented as a function in a Python source
file in your project directory (either part of the main Python package or in an
auxiliary file); see “Writing Your Own Methods” for more information. To tell
versioningit
to use such a method, set the method
key to a table with a
module
key giving the dotted name of the module in which the method is
defined and a value
key giving the name of the callable object in the
module that implements the method. For example, if you created a custom
next-version
method that’s named my_next_version()
and is located in
mypackage/mymodule.py
, you would write:
[tool.versioningit.next-version]
method = { module = "mypackage.module", value = "my_next_version" }
# Put any parameters here
Note that this assumes that mypackage/
is located at the root of the
project directory (i.e., the directory containing the pyproject.toml
file); if is located inside another directory, like src/
, you will need
to add a module-dir
key to the method table giving the path to that
directory relative to the project root, like so:
[tool.versioningit.next-version]
method = { module = "mypackage.module", value = "my_next_version", module-dir = "src" }
# Put any parameters here
As a special case, if there are no parameters for a given step, the respective subtable can be replaced by the method specification, e.g.:
[tool.versioningit]
# Use the "git" method for the vcs step with no parameters:
vcs = "git"
# Use a custom function for the next-version step with no parameters:
next-version = { module = "mypackage.module", value = "my_next_version" }
The [tool.versioningit.vcs]
Subtable
The vcs
subtable specifies the version control system used by the project
and how to extract the tag and related information from it. versioningit
provides three vcs
methods: "git"
(the default), "git-archive"
, and
"hg"
.
"git"
The "git"
method relies on the project directory being located inside a Git
repository with one or more commits. Git 1.8.0 or higher must be installed,
though some optional features require more recent Git versions.
The "git"
method takes the following parameters, all optional:
match
list of stringsA set of fileglob patterns to pass to the
--match
option ofgit describe
to make Git only consider tags matching the given pattern(s). Defaults to an empty list.Note
Specifying more than one match pattern requires Git 2.13.0 or higher.
exclude
list of stringsA set of fileglob patterns to pass to the
--exclude
option ofgit describe
to make Git not consider tags matching the given pattern(s). Defaults to an empty list.Note
This option requires Git 2.13.0 or higher.
default-tag
stringIf
git describe
cannot find a tag,versioningit
will raise aversioningit.errors.NoTagError
unlessdefault-tag
is set, in which case it will act as though the initial commit is tagged with the value ofdefault-tag
"git-archive"
The "git-archive"
method is a variation of the "git"
method that also
supports determining the version when installing from a properly-prepared Git
archive. The method takes the following parameters:
describe-subst
string(required) Set this to
"$Format:%(describe)$"
and add the linepyproject.toml export-subst
to your repository’s.gitattributes
file. This will cause any Git archive made from your repository from this point forward to contain the minimum necessary information to determine a version.match
andexclude
options are set by including them in the format placeholder like so:# Match 'v*' tags: describe-subst = "$Format:%(describe:match=v*)$" # Match 'v*' and 'r*' tags: describe-subst = "$Format:%(describe:match=v*,match=r*)$" # Match 'v*' tags, exclude '*-final' tags: describe-subst = "$Format:%(describe:match=v*,exclude=*-final)$"
By default, only annotated tags are considered, and lightweight tags are ignored; this can be changed by including the “tags” option in the placeholder like so:
# Honor all tags: describe-subst = "$Format:%(describe:tags)$" # Honor all tags, exclude '*rc' tags: describe-subst = "$Format:%(describe:tags,exclude=*rc)$"
Options other than “match”, “exclude”, and “tags” are not supported by
versioningit
and will result in an error.default-tag
string(optional) If
git describe
cannot find a tag,versioningit
will raise aversioningit.errors.NoTagError
unlessdefault-tag
is set, in which case it will act as though the initial commit is tagged with the value ofdefault-tag
.Note that this parameter has no effect when installing from a Git archive; if the repository that the archive was produced from had no relevant tags for the archived commit (causing the value of
describe-subst
to be set to the empty string),versioningit
will raise an error when trying to install the archive.
Note that, in order to provide a consistent set of information regardless of
whether installing from a repository or an archive, the "git-archive"
method provides the format
step with only a subset of the fields that the
"git"
method does; see below for more information.
Changed in version 1.0.0: The “match” and “exclude” settings are now parsed from the
describe-subst
parameter, which is now required, and the old match
and exclude
parameters are now ignored. Also, support for the “tags”
option was added.
Note
In order to avoid DOS attacks, Git will not expand more than one
%(describe)s
placeholder per archive, and so you should not have any
other $Format:%(describe)$
placeholders in your repository.
Note
This method will not work correctly if you have a tag that resembles git
describe
output, i.e., that is of the form
<anything>-<number>-g<hex-chars>
. So don’t do that.
"hg"
The "hg"
method supports installing from a Mercurial repository or archive.
When installing from a repository, Mercurial 5.2 or higher must be installed.
The "hg"
method takes the following parameters, all optional:
pattern
stringA revision pattern (See
hg help revisions.patterns
) to pass to thelatesttag()
template function. Note that this parameter has no effect when installing from a Mercurial archive.default-tag
stringIf there is no latest tag,
versioningit
will raise aversioningit.errors.NoTagError
unlessdefault-tag
is set, in which case it will act as though the initial commit is tagged with the value ofdefault-tag
The [tool.versioningit.tag2version]
Subtable
The tag2version
subtable specifies how to extract the version from the tag
found by the vcs
step. versioningit
provides one tag2version
method, "basic"
(the default), which proceeds as follows:
If the
rmprefix
parameter is set to a string and the tag begins with that string, the given string is removed from the tag.If the
rmsuffix
parameter is set to a string and the tag ends with that string, the given string is removed from the tag.If the
regex
parameter is set to a string (a Python regex) and the regex matches the tag (usingre.search
), the tag is replaced with the contents of the capturing group named “version
”, or the entire matched text if there is no group by that name. If the regex does not match the tag, the behavior depends on therequire-match
parameter: if true, an error is raised; if false or unset, the tag is left as-is.Finally, any remaining leading
v
’s are removed from the tag.
A warning is emitted if the resulting version is not PEP 440-compliant.
The [tool.versioningit.next-version]
Subtable
The next-version
subtable specifies how to calculate the next release
version from the version extracted from the VCS tag. versioningit
provides
the following next-version
methods; none of them take any parameters.
minor
(default) Strips the input version down to just the epoch segment (if any) and release segment (i.e., the
N(.N)*
bit), increments the second component of the release segment, and replaces the following components with a single zero. For example, if the version extracted from the VCS tag is1.2.3.4
, the"minor"
method will calculate a new version of1.3.0
.minor-release
Like
minor
, except that if the input version is a prerelease or development release, the base version is returned; e.g.,1.2.3a0
becomes1.2.3
. This method requires the input version to be PEP 440-compliant.smallest
Like
minor
, except that it increments the last component of the release segment. For example, if the version extracted from the VCS tag is1.2.3.4
, the"smallest"
method will calculate a new version of1.2.3.5
.smallest-release
Like
smallest
, except that if the input version is a prerelease or development release, the base version is returned; e.g.,1.2.3a0
becomes1.2.3
. This method requires the input version to be PEP 440-compliant.null
Returns the input version unchanged. Useful if your repo version is something horrible and unparsable.
A warning is emitted if the resulting version is not PEP 440-compliant.
The [tool.versioningit.format]
Subtable
The format
subtable specifies how to format the project’s final version
based on the information calculated in previous steps. (Note that, if the
repository’s current state is an exact tag match, this step will be skipped and
the version returned by the tag2version
step will be used as the final
version.) versioningit
provides one format
method, "basic"
(the
default).
The data returned by the vcs
step includes a repository state (describing
the relationship of the repository’s current contents to the most recent tag)
and a collection of format fields. The "basic"
format
method takes
the name of that state, looks up the format
parameter with the same name
(falling back to a default, given below) to get a format template string,
and formats the template using the given format fields plus {base_version}
,
{next_version}
, and {branch}
fields. A warning is emitted if the
resulting version is not PEP 440-compliant.
For the built-in vcs
methods, the repository states are:
|
One or more commits have been made on the current branch since the latest tag |
|
No commits have been made on the branch since the latest tag, but the repository has uncommitted changes |
|
One or more commits have been made on the branch since the latest tag, and the repository has uncommitted changes |
For the built-in vcs
methods, the available format fields are:
|
The author date of the HEAD commit [1] ( |
|
The version extracted from the most recent tag |
|
The name of the current branch (with non-alphanumeric
characters converted to periods), or |
|
The current date & time, or the date & time specified by
the environment variable |
|
The committer date of the HEAD commit [1] ( |
|
The number of commits since the most recent tag |
|
The next release version, calculated by the
|
|
The abbreviated hash of the HEAD commit |
|
The full hash of the HEAD commit ( |
|
The first letter of the name of the VCS (i.e., “ |
|
The name of the VCS (i.e., “ |
Changed in version 2.0.0: The {version}
field was renamed to {base_version}
. The old name
remains usable but is deprecated.
The default parameters for the format
step are:
[tool.versioningit.format]
distance = "{base_version}.post{distance}+{vcs}{rev}"
dirty = "{base_version}+d{build_date:%Y%m%d}"
distance-dirty = "{base_version}.post{distance}+{vcs}{rev}.d{build_date:%Y%m%d}"
The [tool.versioningit.template-fields]
Subtable
Added in version 2.0.0.
The template-fields
subtable controls the fields available for the
templates of the write
and onbuild
steps. versioningit
provides
one template-fields
method, "basic"
(the default), which provides the
following template fields:
{version}
— the project’s final version{version_tuple}
— a string representation of a tuple of{version}
’s components; see below for how to configure how the version is split upAll of the same fields available in the
format
step with the “basic”format
method (see above), but with{branch}
not sanitized and without the{version}
alias of{base_version}
Important
If tool.versioningit.default-version
(see below)
is set and an error occurs during version calculation, leading to
versioningit
recovering by using the given default version, there may
not be enough information afterwards to populate all of the template
fields, and you will get an error if you try to use an unpopulated field in
a write
or onbuild
template.
If default-version
is set, the only fields you can rely on to always be
present are {version}
and {version_tuple}
.
The "basic"
method takes one optional parameter, a version-tuple
subtable (i.e., [tool.versioningit.template-fields.version-tuple]
), used to
control how the project’s version is converted into the {version_tuple}
field. This subtable can contain the following fields:
split-on
string(optional) A Python regex that will be used to split apart the project version with
re.split
. AnyNone
or empty items returned by the split are discarded. Any items that consist entirely of digits are converted to integers (i.e., they will not be enclosed in quotes in{version_tuple}
). Defaults to[-_.+!]
.This field is ignored when
pep440
is true.pep440
boolean(optional) If true (default: false), the project version will be parsed & normalized as a PEP 440 version (If is not valid, an error will occur), and
{version_tuple}
will consist of the following items, in order:The version’s epoch (as an integer), if
epoch
is true or ifepoch
is unspecified and the epoch is nonzeroThe individual components of the release version as integers, including trailing zero components
If the version is a prerelease, the phase identifier and prerelease number (e.g.,
"a0"
or"rc1"
)If the version is a postrelease, “
post
” and the postrelease numberIf the version is a dev release, “
dev
” and the dev release numberIf the version has a local version label, “
+
” and the label
epoch
boolean(optional) Whether to include the version’s epoch in
{version_tuple}
. If unspecified, the epoch is included iff it is nonzero.This option only has an effect when
pep440
is true.double-quote
boolean(optional) Whether to enclose string components in double quotes (
True
, the default) or single quotes (False
)
Here are some examples of how a version can be converted to a
{version_tuple}
:
|
|
|
|
|
---|---|---|---|---|
1.2.3 |
(default) |
Any |
— |
|
1.2.3a0 |
(default) |
|
— |
|
1.2.3a0 |
(default) |
|
— |
|
1.2.3.post1 |
(default) |
Any |
— |
|
1.2.3-1 |
(default) |
|
— |
|
1.2.3-1 |
(default) |
|
— |
|
1.2.3+local.2022 |
(default) |
|
— |
|
1.2.3+local.2022 |
|
|
— |
|
1.2.3+local.2022 |
(default) |
|
— |
|
1.2.3b1.dev3 |
(default) |
|
— |
|
1.2.3 |
(default) |
|
|
|
1!2.3.4 |
(default) |
|
— |
|
1!2.3.4 |
(default) |
|
|
|
0.1.0.0.0 |
(default) |
Any |
— |
|
1.2.3j |
(default) |
|
— |
|
1.2.3j |
(default) |
|
— |
ERROR — Not a PEP 440 version |
1.2.3~local.2022 |
|
|
— |
|
1.2.3~local.2022 |
|
|
— |
ERROR — Not a PEP 440 version |
The [tool.versioningit.write]
Subtable
The write
subtable enables an optional feature, writing the final version
and/or other fields to a file. Unlike the other subtables, if the write
subtable is omitted, the corresponding step will not be carried out.
versioningit
provides one write
method, "basic"
(the default),
which takes the following parameters:
file
string(required) The path to the file to which to write the version, relative to the root of your project directory. This path should use forward slashes (
/
) as the path separator, even on Windows.Note
This file should not be committed to version control, but it should be included in your project’s built sdists and wheels.
Note
If you’re using Hatch and you followed the advice above by adding the file to your
.gitignore
or.hgignore
, then you will need to tell Hatch to include the file in sdists & wheels like so:[tool.hatch.build] # Replace the path below with the value you gave to the "file" key: artifacts = ["src/mypackage/_version.py"]
encoding
string(optional) The encoding with which to write the file. Defaults to UTF-8.
template
: string(optional) The content to write to the file (minus the final newline, which
versioningit
adds automatically), as a string containing some number of{fieldname}
placeholders. The available placeholders are determined by thetemplate-fields
step (see above).If this parameter is omitted, the default is determined based on the
file
parameter’s file extension. For.txt
files and files without an extension, the default is:{version}
while for
.py
files, the default is:__version__ = "{version}"
If
template
is omitted andfile
has any other extension, an error is raised.
Note
When testing out your configuration with the versioningit
command (See
Command), you will need to pass the --write
option if you want
the [tool.versioningit.write]
subtable to take effect.
Enabling & Configuring the onbuild
Step
Added in version 1.1.0.
versioningit
provides custom setuptools and Hatch hooks for enabling an
optional feature (called the “onbuild
step”) in which your project’s
version and/or other fields are inserted into a file in sdists & wheels at
build time while leaving your local project directory alone.
The steps for enabling the onbuild
step differ depending on whether you’re
using setuptools or Hatch as your build backend. The configuration options for
the step are the same between the backends, but where you put the configuration
and how you tell the backend to enable the hooks differs.
Using onbuild
with setuptools
There are two steps to enabling the onbuild
step with setuptools. First,
add a [tool.versioningit.onbuild]
table to your pyproject.toml
containing your desired configuration for the step (see below). Second, you need to tell setuptools to use
versioningit
’s custom command classes. How to do this depends on what file
you’ve placed your project’s setuptools configuration in.
If you’re configuring setuptools via
setup.cfg
, you can simply add the following field to its[options]
table:[options] cmdclass = sdist = versioningit.cmdclass.sdist build_py = versioningit.cmdclass.build_py
If you’ve instead placed all your setuptools configuration in
pyproject.toml
, then add the following table to it:[tool.setuptools.cmdclass] build_py = "versioningit.cmdclass.build_py" sdist = "versioningit.cmdclass.sdist"
If you’re still configuring setuptools through
setup.py
, you’ll need to passversioningit.get_cmdclasses()
as thecmdclass
argument tosetup()
, like so:from setuptools import setup from versioningit import get_cmdclasses setup( cmdclass=get_cmdclasses(), # Other arguments go here )
If you’re already using other custom build_py
and/or sdist
command
classes, you’ll need to combine them with versioningit
’s command classes.
One option is to pass your custom classes to get_cmdclasses()
in
setup.py
so that versioningit
will use them as parent classes; see
the function’s documentation for more information. If that doesn’t work, you
may have to manually modify or subclass your command classes and add a call to
run_onbuild()
at the appropriate location; see the function’s documentation
for more information, but you’ll largely be on your own at this point.
Added in version 2.2.0: sdist
and build_py
classes added for use in setup.cfg
and
pyproject.toml
Using onbuild
with Hatch
Added in version 3.0.0: Support for using the onbuild
step with Hatch
In order to enable & configure the onbuild
step when using versioningit
with Hatch, simply place all of your desired configuration for the step under a
[tool.hatch.build.hooks.versioningit-onbuild]
table. Do not use the
[tool.versioningit.onbuild]
table with Hatch; it will be ignored, and its
presence will generate a warning.
Note
The versioningit-onbuild
build hook is only usable when also using
versioningit
as a Hatch version source. Trying to use the build hook
with a different version source will result in an error.
Note
The versioningit-onbuild
build hook is only supported when building an
sdist or wheel. Using other Hatch builders (such as the application
builder) with versioningit-onbuild
is not supported or endorsed in
any way.
onbuild
Configuration Options
versioningit
provides one onbuild
method, "replace-version"
(the
default). It scans a given file for a line matching a given regex and inserts
the project version (or other templated string) into the first line that
matches. The method takes the following parameters:
source-file
string(required) The path to the file to modify, relative to the root of your project directory. This path should use forward slashes (
/
) as the path separator, even on Windows.build-file
string(required) The path to the file to modify when building a wheel. This path should be the location of the file when your project is installed, relative to the root of the installation directory. For example, if
source-file
is"src/mypackage/__init__.py"
, wheresrc/
is your project dir, setbuild-file
to"mypackage/__init__.py"
. If you do not use asrc/
-layout or other remapping of package files, setbuild-file
to the same value assource-file
.This path should use forward slashes (
/
) as the path separator, even on Windows.encoding
string(optional) The encoding with which to read & write the file. Defaults to UTF-8.
regex
string(optional) A Python regex that is tested against each line of the file using
re.search
. The first line that matches is updated as follows:If the regex contains a capturing group named “
version
”, the substring matched by the group is replaced with the expansion ofreplacement
(see below). Ifversion
did not participate in the match, an error is raised.Otherwise, the entire substring of the line matched by the regex is replaced by the expansion of
replacement
.
The default regex is:
^\s*__version__\s*=\s*(?P<version>.*)
require-match
boolean(optional) If
regex
does not match any lines in the file andappend-line
is not set, an error will be raised ifrequire-match
is true (default: false).replacement
string(optional) The string used to replace the relevant portion of the matched line. The string is first expanded by replacing any occurrences of
{fieldname}
placeholders with the values provided by thetemplate-fields
step (see above), and then any backreferences to capturing groups in the regex are expanded.The default value is
"{version}"
(that is, the version enclosed in double quotes).append-line
string(optional) If
regex
does not match any lines in the file andappend-line
is set, any occurrences of{fieldname}
inappend-line
are replaced with the values provided by thetemplate-fields
step, and the resulting line is appended to the end of the file.
Thus, with the default settings, "replace-version"
finds the first line in
the given file of the form “__version__ = ...
” and replaces the part after
the =
with the project version in double quotes; if there is no such line,
the file is left unmodified.
Note
If you use this feature and run python setup.py directly (as
opposed to building with build
or similar), you must invoke
setup.py
from the root project directory (the one containing your
setup.py
).
Tip
You are encouraged to test your onbuild
configuration by building an
sdist and wheel for your project and examining the files within to ensure
that they look how you want. An sdist can be expanded by running
tar zxf filename
, and a wheel can be expanded by running
unzip filename
.
tool.versioningit.default-version
The final key in the [tool.versioningit]
table is default-version
,
which is a string rather than a subtable. When this key is set and an error
occurs during version calculation, versioningit
will set your package’s
version to the given default version. When this key is not set, any errors
that occur inside versioningit
will cause the build/install process to
fail.
Note that default-version
is not applied if an error occurs while parsing
the [tool.versioningit]
table; however, such errors can be caught ahead of
time by running the versioningit
command (See “Command”).
Log Level Environment Variable
When versioningit
is invoked via the setuptools or Hatch plugin interface,
it logs various information to stderr. By default, only messages at
WARNING
level or higher are displayed, but this can be changed by setting
the VERSIONINGIT_LOG_LEVEL
environment variable to the name of a
Python logging level (case insensitive) or the equivalent integer value.