Search code examples
python-3.xsetuptoolspython-wheelsetuptools-scm

Running application installed from bdist_wheel package using setuptools_scm fails with version lookup error


TL;DR

I am trying to create built-distribution package for a project that uses setuptools-scm. I generated the wheel package running python setup.py sdist bdist_wheel. I am able to install the .whl package using pip install .... But when I try to run the program, it throws the following error:

Traceback (most recent call last):
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/bin/mymodule", line 5, in <module>
    from mymodule.cli import main
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/mymodule/cli.py", line 4, in <module>
    from mymodule.contexts import ContextConfig
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/mymodule/contexts/__init__.py", line 2, in <module>
    from mymodule.contexts.context_config import ContextConfig
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/mymodule/contexts/context_config.py", line 8, in <module>
    from mymodule.commons import local_config_file_path, user_config_file_path
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/mymodule/commons/__init__.py", line 19, in <module>
    version = get_version(root="../..", relative_to=__file__)
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/setuptools_scm/__init__.py", line 144, in get_version
    return _get_version(config)
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/setuptools_scm/__init__.py", line 148, in _get_version
    parsed_version = _do_parse(config)
  File "/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages/setuptools_scm/__init__.py", line 110, in _do_parse
    raise LookupError(
LookupError: setuptools-scm was unable to detect version for '/home/zobayer/Projects/opensource/staging/myproject/venv/lib64/python3.8/site-packages'.

Here's a simplistic view of the directory tree (without expanding .git\)

myproject
├── .git
├── mymodule
│   ├── cli.py
│   ├── commons
│   │   ├── command.py
│   │   ├── helpers.py
│   │   └── __init__.py
│   ├── contexts
│   │   ├── context_config.py
│   │   └── __init__.py
│   ├── __init__.py
│   └── version.py
├── LICENSE
├── MANIFEST.in
├── pyproject.toml
├── README.md
├── requirements.txt
├── setup.cfg
├── setup.py
└── tox.ini

Here mymodule/version.py is not tracked. The repo was clean and tagged. Using setuptools 49.1.0 and setuptools_scm 4.1.2, I have configured the following:

setup.py (omitted metadata fields)

setup(
    name="myproject",
    use_scm_version=True,
    setup_requires=["wheel", "setuptools-scm"],
    packages=find_packages(exclude=["docs*", "tests*"]),
    include_package_data=True,
    install_requires=install_dependencies,
)

setup.cfg

[metadata]
license_files = LICENSE

[options]
setup_requires =
    wheel==0.34.2
    setuptools_scm==4.1.2

pyproject.toml

[build-system]
requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
write_to = "mymodule/version.py"
write_to_template = "# -*- coding: utf-8 -*-\n\n__version__ = '{version}'\n"
version_scheme = "release-branch-semver"

I'd like to note here, the installation works with pip install -e . and application runs as expected.

I have tried updating the root and relative_to parameters when calling get_version, and updating use_scm_version to use configuration dictionary to no avail. I looked into official issues in github, but I could not resolve this issue. At this point I am convinced that I misunderstood setuptools_scm and probably misconfigured it.


Solution

  • You shouldn't be using setuptools-scm in actual code, it's meant to be used for packaging only. It looks for a VCS repository to read version from its metadata (git tags etc), so clearly it will fail when the package is installed. If you are trying to get the version of an installed package, use importlib.metadata (part of standard library since 3.8, for older versions there's a backport: importlib-metadata). Example:

    >>> from importlib.metadata import version
    >>> version('myproject')
    '0.0.1'
    

    You can also use pkg_resources (part of setuptools) to query metadata for version, but beware that it is superseded by importlib.metadata now:

    >>> import pkg_resources
    >>> pkg_resources.get_distribution('myproject').version
    '0.0.1'