setuptools_scm icon indicating copy to clipboard operation
setuptools_scm copied to clipboard

`UserWarning: tag '0.0' no version found` in a fresh Git repo when `tag_regex` is defined

Open TheTaylorHicks opened this issue 2 years ago • 6 comments

Trying to use setuptools_scm==7.1.0 on a brand new repository with no tags fails if tag_regex has been specified that does not match the default fallback version 0.0, like the example below:

^(?P<prefix>packagename[-_])(?P<version>[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$

After a little troubleshooting and inspecting the source code, the problem seems to be that if no tags are found in the parent git repo matching the provided regex, setuptools_scm.git._git_parse_inner attempts to fake a tag 0.0 to provide to setuptools_scm.version.meta as a default.

This later causes a panic when setuptools_scm.version.tag_to_version attempts to match 0.0 against the configured regular expression and returns None.

For context, I'm trying to introduce setuptools_scm to a pre-existing monorepo containing multiple Python projects that need to be individually versioned. As such, I can't use an optional prefix as tags without a prefix would have a chance to override the version of every package in the repository.

TheTaylorHicks avatar Feb 15 '23 07:02 TheTaylorHicks

sampleproject/pyproject.toml

[project]
name = "sampleproject"
dynamic = ["version"]
requires-python = ">=3.7"

[tool.setuptools_scm]
root = ".."
write_to = "sampleproject/src/sample/_version.py"
tag_regex = "^(?P<prefix>sampleproject[-_])(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$"
fallback_version = "0.0.0"

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

$ export SETUPTOOLS_SCM_DEBUG=1; pip3 install sampleproject/

Defaulting to user installation because normal site-packages is not writeable
Processing ./sampleproject
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [125 lines of output]
      finalize hook {'name': None, 'version': None, 'author': None, 'author_email': None, 'maintainer': None, 'maintainer_email': None, 'url': None, 'license': None, 'description': None, 'long_description': None, 'keywords': None, 'platforms': None, 'classifiers': None, 'download_url': None, 'provides': None, 'requires': None, 'obsoletes': None}
      abs root {'root': '..', 'relative_to': 'pyproject.toml'}
      file pyproject.toml
      root '/workspaces/setuptools_scm_test'
      relative_to 'pyproject.toml'
      dist name: sampleproject
      version_from_ep setuptools_scm.parse_scm /workspaces/setuptools_scm_test
      looking for ep setuptools_scm.parse_scm /workspaces/setuptools_scm_test
      found ep EntryPoint(name='.git', value='setuptools_scm.git:parse', group='setuptools_scm.parse_scm') in /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git rev-parse --show-prefix
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      out:
      
      
      real root /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git describe --dirty --tags --long --match "*[0-9]*"
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      err:
           fatal: No names found, cannot describe anything.
      
      ret: 128
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git rev-parse --verify --quiet HEAD
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      out:
           c89112a048f30200569cd48efcd796c7833f062d
      
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git rev-list HEAD
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      out:
           c89112a048f30200569cd48efcd796c7833f062d
          a3a2a2c86e1e71761ea9581d3026313732c137bb
      
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git status --porcelain --untracked-files=no
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git rev-parse --abbrev-ref HEAD
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      out:
           master
      
      ----
      cmd:
           git --git-dir /workspaces/setuptools_scm_test/.git -c log.showSignature=false log -n 1 HEAD --format=%cI
       in: /workspaces/setuptools_scm_test
      GIT_ASKPASS /vscode/vscode-server/bin/linux-x64/e8a3071ea4344d9d48ef8a4df2c097372b0c5161/extensions/git/dist/askpass.sh
      GIT_EDITOR code --wait
      out:
           2023-02-15T07:09:11+00:00
      
      tag 0.0
      tag '0.0' parsed to None
      /tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/version.py:84: UserWarning: tag '0.0' no version found
        warnings.warn(f"tag {tag!r} no version found")
      Traceback (most recent call last):
        File "/usr/local/lib/python3.8/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
          main()
        File "/usr/local/lib/python3.8/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
        File "/usr/local/lib/python3.8/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
          return hook(config_settings)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 338, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=['wheel'])
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 320, in _get_build_requires
          self.run_setup()
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/build_meta.py", line 335, in run_setup
          exec(code, locals())
        File "<string>", line 1, in <module>
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/__init__.py", line 108, in setup
          return distutils.core.setup(**attrs)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/_distutils/core.py", line 147, in setup
          _setup_distribution = dist = klass(attrs)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/dist.py", line 488, in __init__
          _Distribution.__init__(
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/_distutils/dist.py", line 283, in __init__
          self.finalize_options()
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools/dist.py", line 912, in finalize_options
          ep(self)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/integration.py", line 127, in infer_version
          _assign_version(dist, config)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/integration.py", line 60, in _assign_version
          maybe_version = _get_version(config)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/__init__.py", line 153, in _get_version
          parsed_version = _do_parse(config)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/__init__.py", line 100, in _do_parse
          version = _version_from_entrypoints(config) or _version_from_entrypoints(
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/_entrypoints.py", line 66, in _version_from_entrypoints
          version: ScmVersion | None = _call_entrypoint_fn(root, config, ep.load())
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/_entrypoints.py", line 40, in _call_entrypoint_fn
          return fn(root, config=config)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/git.py", line 181, in parse
          return _git_parse_inner(
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/git.py", line 224, in _git_parse_inner
          return meta(
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/version.py", line 226, in meta
          parsed_version = _parse_tag(tag, preformatted, config)
        File "/tmp/pip-build-env-tt745vl_/overlay/lib/python3.8/site-packages/setuptools_scm/version.py", line 203, in _parse_tag
          assert version is not None
      AssertionError
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

TheTaylorHicks avatar Feb 15 '23 07:02 TheTaylorHicks

Good catch, the tag regex ought not to be applied to the fallback version when none is found

RonnyPfannschmidt avatar Feb 15 '23 08:02 RonnyPfannschmidt

For what it's worth, this issue happens whether the user has specified a fallback_version or not.

The culprit is a hard-coded default in git.py.

TheTaylorHicks avatar Feb 15 '23 08:02 TheTaylorHicks

I'm currently working around the issue by specifying a custom git_describe_command that calls out to a shell script that provides its own default value if git describe returns an error.

sampleproject/pyproject.toml

[project]
name = "sampleproject"
dynamic = ["version"]
requires-python = ">=3.7"

[tool.setuptools_scm]
root = ".."
write_to = "sampleproject/src/sample/_version.py"
tag_regex = "^(?P<prefix>sampleproject[-_])(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$"
git_describe_command = ["common/scripts/git-describe.bash", "sampleproject"]

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

common/scripts/git-describe.bash

#!/usr/bin/env bash
set -euo pipefail

if [[ $# != 1 || $@ == "--help" ||  $@ == "-h" ]]
then 
	echo "Usage: $0 TAG_PREFIX"
	exit 1
fi 

TAG_PREFIX=$1
git describe --dirty --tags --long --match '*[0-9]*' || echo "${TAG_PREFIX}-0.0.0-1-g$(git rev-parse --short HEAD)$(git diff --quiet || echo -dirty)"

TheTaylorHicks avatar Feb 15 '23 08:02 TheTaylorHicks

IMHO, I got this UserWarning which effectively translated to a full runtime error while having two tags, one matching the pattern and one not. IMHO, the whole point of this tag_regex was to filter the list of tags in order to determine which ones are safe to be used. Still, what happens is that it picks the bad one first and instead of ignoring it and picking the next one, it fails ugly.

My pattern is tag_regex = "^(?P<prefix>v)?(?P<version>[0-9]+.[0-9.]+)(?P<suffix>.*)?$"

* Getting build dependencies for sdist...
/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/version.py:95: UserWarning: tag 'v6' no version found
  warnings.warn(f"tag {tag!r} no version found")
Traceback (most recent call last):
  File "/Users/ssbarnea/c/a/ansible-lint/.tox/pkg/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
    main()
  File "/Users/ssbarnea/c/a/ansible-lint/.tox/pkg/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 335, in main
    json_out['return_val'] = hook(**hook_input['kwargs'])
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ssbarnea/c/a/ansible-lint/.tox/pkg/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 287, in get_requires_for_build_sdist
    return hook(config_settings)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/build_meta.py", line 358, in get_requires_for_build_sdist
    return self._get_build_requires(config_settings, requirements=[])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/build_meta.py", line 325, in _get_build_requires
    self.run_setup()
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/build_meta.py", line 341, in run_setup
    exec(code, locals())
  File "<string>", line 1, in <module>
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/__init__.py", line 103, in setup
    return distutils.core.setup(**attrs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 147, in setup
    _setup_distribution = dist = klass(attrs)
                                 ^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/dist.py", line 303, in __init__
    _Distribution.__init__(self, dist_attrs)
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 283, in __init__
    self.finalize_options()
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools/dist.py", line 680, in finalize_options
    ep(self)
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_integration/setuptools.py", line 121, in infer_version
    _assign_version(dist, config)
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_integration/setuptools.py", line 53, in _assign_version
    maybe_version = _get_version(config, force_write_version_files=True)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_get_version_impl.py", line 93, in _get_version
    parsed_version = parse_version(config)
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_get_version_impl.py", line 56, in parse_version
    or parse_scm_version(config)
       ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_get_version_impl.py", line 35, in parse_scm_version
    return _entrypoints.version_from_entrypoint(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_entrypoints.py", line 55, in version_from_entrypoint
    maybe_version: version.ScmVersion | None = fn(root, config=config)
                                               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/git.py", line 211, in parse
    return _git_parse_inner(
           ^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/git.py", line 255, in _git_parse_inner
    version = version_from_describe(wd, config, describe_command)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/git.py", line 243, in version_from_describe
    return describe_res.parse_success(parse=parse_describe)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/_run_cmd.py", line 77, in parse_success
    return parse(self.stdout)
           ^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/git.py", line 241, in parse_describe
    return meta(tag=tag, distance=distance, dirty=dirty, node=node, config=config)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/version.py", line 210, in meta
    parsed_version = _parse_tag(tag, preformatted, config)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/var/folders/32/1xrphgzd4xv777syxjtkpdw80000gn/T/build-env-nffze1n6/lib/python3.12/site-packages/setuptools_scm/version.py", line 193, in _parse_tag
    assert version is not None
AssertionError

ERROR Backend subprocess exited when trying to invoke get_requires_for_build_sdist

Any suggestings?

ssbarnea avatar Nov 07 '23 15:11 ssbarnea

@ssbarnea custom describe command in the git case - theres no direct control over the tag thats picked for describe, so both have to be adapted atm

RonnyPfannschmidt avatar Dec 11 '23 18:12 RonnyPfannschmidt