diff --git a/source/guides/single-sourcing-package-version.rst b/source/guides/single-sourcing-package-version.rst index acab9358e..b6555d8c0 100644 --- a/source/guides/single-sourcing-package-version.rst +++ b/source/guides/single-sourcing-package-version.rst @@ -75,17 +75,47 @@ number of your project: :file:`MANIFEST.in`). #. Set the value in :file:`setup.py`, and have the project code use the - ``pkg_resources`` API. + ``importlib.metadata`` API to fetch the value at runtime. + (``importlib.metadata`` was introduced in Python 3.8 and is available to + older versions as the ``importlib-metadata`` project.) An installed + project's version can be fetched with the API as follows:: - :: + try: + from importlib import metadata + except ImportError: + # Running on pre-3.8 Python; use importlib-metadata package + import importlib_metadata as metadata - import pkg_resources - assert pkg_resources.get_distribution('pip').version == '1.2.0' + assert metadata.version('pip') == '1.2.0' - Be aware that the ``pkg_resources`` API only knows about what's in the + Be aware that the ``importlib.metadata`` API only knows about what's in the installation metadata, which is not necessarily the code that's currently imported. + If a project uses this method to fetch its version at runtime, then its + ``install_requires`` value needs to be edited to install + ``importlib-metadata`` on pre-3.8 versions of Python like so:: + + setup( + ... + install_requires=[ + ... + 'importlib-metadata ~= 1.0 ; python_version < "3.8"', + ... + ], + ... + ) + + An older (and less efficient) alternative to ``importlib.metadata`` is the + ``pkg_resources`` API provided by ``setuptools``:: + + import pkg_resources + assert pkg_resources.get_distribution('pip').version == '1.2.0' + + If a project uses ``pkg_resources`` to fetch its own version at runtime, + then ``setuptools`` must be added to the project's ``install_requires`` + list. + Example using this technique: `setuptools `_.