Single source of truth for Python project version in presence of pyproject.toml

Question:

The pyproject.toml specification affords the ability to specify the project version, e.g.

[project]
name = "foo"
version = "0.0.1"

However, it is also a common Python idiom to put __version__ = "0.0.1" in foo/__init__.py so that users can query it.

Is there a standard way of extracting the version from the pyproject.toml and getting it into the foo/__init__.py?

Asked By: user14717

||

Answers:

There are two approaches you can take here.

  1. Keep version in pyproject.toml and get it from the package metadata in the source code. So, in your foo/__init__.py or wherever:

    from importlib.metadata import version
    __version__ = version(__package__)
    

    importlib.metadata.version is available since Python 3.8. For earlier Python versions, you can do similar with the importlib_metadata backport.

  2. Keep the version in the source code and instruct the build system to get it from there. For a setuptools build backend, it looks like this in pyproject.toml:

    [project]
    dynamic = ["version"]
    
    [tool.setuptools.dynamic]
    version = {attr = "foo.__version__"}
    

My recommendation is actually ( ) … neither! Don’t keep a __version__ attribute in the source code at all. It’s an outdated habit which we can do without these days. Version is already a required field in the package metadata, it’s redundant to keep the same string as an attribute in the package/module namespace.

Answered By: wim
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.