Skip to content

Project metadata#

The project metadata is stored in the project table in pyproject.toml, which is based on PEP 621.

On top of that, we also support some additional features.

Dynamic project version#

pdm-backend can determine the version of the project dynamically. To do this, you need to leave the version field out from your pyproject.toml and add version to the list of project.dynamic:

1
2
3
4
[project]
...
- version = "0.1.0" remove this line
+ dynamic = ["version"]

Then in [tool.pdm.version] table, specify how to get the version info. There are three ways supported:

Read from a static string in the given file path#

1
2
3
[tool.pdm.version]
source = "file"
path = "mypackage/__init__.py"

In this way, the file MUST contain a line like:

1
__version__ = "0.1.0" # Single quotes and double quotes are both OK, comments are allowed.

Read from SCM tag, supporting git and hg#

1
2
[tool.pdm.version]
source = "scm"

When building from a source tree where SCM is not available, you can use the env var PDM_BUILD_SCM_VERSION to pretend the version is set.

1
PDM_BUILD_SCM_VERSION=0.1.0 python -m build

Added in version 2.2.0

Alternatively, you can specify a default version in the configuration:

1
2
[tool.pdm.version]
fallback_version = "0.0.0"

To control which scm tags are used to generate the version, you can use two fields: tag_filter and tag_regex.

1
2
3
4
[tool.pdm.version]
source = "scm"
tag_filter = "test/*"
tag_regex = '^test/(?:\D*)?(?P<version>([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|c|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$)$'

tag_filter filters the set of tags which are considered as candidates to capture your project's version. For git repositories, this field is a glob matched against the tag. For hg repositories, it is a regular expression used with the latesttag function.

tag_regex configures how you extract a version from a tag. It is applied after tag_filter extracts candidate tags to extract the version from that tag. It is a python style regular expression.

Added in version 2.2.0

To customize the format of the version string, specify the version_format option with a format function:

1
2
3
[tool.pdm.version]
source = "scm"
version_format = "mypackage.version:format_version"
1
2
3
4
5
6
7
8
# mypackage/version.py
from pdm.backend.hooks.version import SCMVersion

def format_version(version: SCMVersion) -> str:
    if version.distance is None:
        return str(version.version)
    else:
        return f"{version.version}.post{version.distance}"

Get with a specific function#

1
2
3
[tool.pdm.version]
source = "call"
getter = "mypackage.version:get_version"

You can also supply it with literal arguments:

1
getter = "mypackage.version:get_version('dev')"

Writing dynamic version to file#

You can instruct pdm-backend to write back the dynamic version to a file. It is supported for all sources but file.

1
2
3
[tool.pdm.version]
source = "scm"
write_to = "foo/version.txt"

By default, pdm-backend will just write the SCM version itself. You can provide a template as a Python-formatted string to create a syntactically correct Python assignment:

1
2
3
4
[tool.pdm.version]
source = "scm"
write_to = "foo/_version.py"
write_template = "__version__ = '{}'"

Note

The path in write_to is relative to the root of the wheel file, hence the package-dir part should be stripped.

Note

pdm-backend will rewrite the whole file each time, so you can't have additional contents in that file.

Variables expansion#

Environment variables#

You can refer to environment variables in form of ${VAR} in the dependency strings, both work for dependencies and optional-dependencies:

1
2
3
4
[project]
dependencies = [
    "foo @ https://${USERNAME}:${PASSWORD}/mypypi.org/packages/foo-0.1.0-py3-none-any.whl"
]

When you build the project, the variables will be expanded with the current values of the environment variables.

Relative paths#

You can add a dependency with the relative paths to the project root. To do this, pdm-backend provides a special variable ${PROJECT_ROOT} to refer to the project root, and the dependency must be defined with the file:// URL:

1
2
3
4
[project]
dependencies = [
    "foo @ file:///${PROJECT_ROOT}/foo-0.1.0-py3-none-any.whl"
]

To refer to a package beyond the project root:

1
2
3
4
[project]
dependencies = [
    "foo @ file:///${PROJECT_ROOT}/../packages/foo-0.1.0-py3-none-any.whl"
]

Note

The triple slashes /// is required for the compatibility of Windows and POSIX systems.

Note

The relative paths will be expanded into the absolute paths on the local machine. So it makes no sense to include them in a distribution, since others who install the package will not have the same paths.