Skip to content

Commit 5b1c77b

Browse files
Merge pull request #901 from RonnyPfannschmidt/fix-549-fallback-when-scm-missing
Fix 549 fallback when scm missing
2 parents 2e5c2f8 + 978564b commit 5b1c77b

File tree

6 files changed

+47
-28
lines changed

6 files changed

+47
-28
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ features
3838
* support passing log levels to SETUPTOOLS_SCM_DEBUG
3939
* support using rich.logging as console log handler if installed
4040
* fix #527: type annotation in default version template
41+
* fix #549: use fallbacks when scm search raises CommandNotFoundError
4142

4243
bugfixes
4344
--------

src/setuptools_scm/_entrypoints.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
from . import version
1414

1515
if TYPE_CHECKING:
16-
from ._config import Configuration
1716
from . import _types as _t
17+
from ._config import Configuration, ParseFunction
1818

1919

2020
log = _log.log.getChild("entrypoints")
@@ -27,21 +27,14 @@ def load(self) -> Any:
2727
pass
2828

2929

30-
def _version_from_entrypoints(
31-
config: Configuration, fallback: bool = False
30+
def version_from_entrypoint(
31+
config: Configuration, entrypoint: str, root: _t.PathT
3232
) -> version.ScmVersion | None:
33-
if fallback:
34-
entrypoint = "setuptools_scm.parse_scm_fallback"
35-
root = config.fallback_root
36-
else:
37-
entrypoint = "setuptools_scm.parse_scm"
38-
root = config.absolute_root
39-
4033
from .discover import iter_matching_entrypoints
4134

4235
log.debug("version_from_ep %s in %s", entrypoint, root)
4336
for ep in iter_matching_entrypoints(root, entrypoint, config):
44-
fn = ep.load()
37+
fn: ParseFunction = ep.load()
4538
maybe_version: version.ScmVersion | None = fn(root, config=config)
4639
log.debug("%s found %r", ep, maybe_version)
4740
if maybe_version is not None:

src/setuptools_scm/_get_version.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import logging
34
import re
45
import warnings
56
from pathlib import Path
@@ -8,30 +9,41 @@
89
from typing import Pattern
910

1011
from . import _config
12+
from . import _entrypoints
13+
from . import _run_cmd
1114
from . import _types as _t
1215
from ._config import Configuration
13-
from ._entrypoints import _version_from_entrypoints
1416
from ._overrides import _read_pretended_version_for
1517
from ._version_cls import _validate_version_cls
1618
from .version import format_version as _format_version
1719
from .version import ScmVersion
1820

21+
_log = logging.getLogger(__name__)
22+
1923

2024
def parse_scm_version(config: Configuration) -> ScmVersion | None:
21-
if config.parse is not None:
22-
parse_result = config.parse(config.absolute_root, config=config)
23-
if parse_result is not None and not isinstance(parse_result, ScmVersion):
24-
raise TypeError(
25-
f"version parse result was {str!r}\n"
26-
"please return a parsed version (ScmVersion)"
27-
)
28-
return parse_result
29-
else:
30-
return _version_from_entrypoints(config)
25+
try:
26+
if config.parse is not None:
27+
parse_result = config.parse(config.absolute_root, config=config)
28+
if parse_result is not None and not isinstance(parse_result, ScmVersion):
29+
raise TypeError(
30+
f"version parse result was {str!r}\n"
31+
"please return a parsed version (ScmVersion)"
32+
)
33+
return parse_result
34+
else:
35+
entrypoint = "setuptools_scm.parse_scm"
36+
root = config.absolute_root
37+
return _entrypoints.version_from_entrypoint(config, entrypoint, root)
38+
except _run_cmd.CommandNotFoundError as e:
39+
_log.exception("command %s not found while parsing the scm, using fallbacks", e)
40+
return None
3141

3242

3343
def parse_fallback_version(config: Configuration) -> ScmVersion | None:
34-
return _version_from_entrypoints(config, fallback=True)
44+
entrypoint = "setuptools_scm.parse_scm_fallback"
45+
root = config.fallback_root
46+
return _entrypoints.version_from_entrypoint(config, entrypoint, root)
3547

3648

3749
def _do_parse(config: Configuration) -> ScmVersion | None:

src/setuptools_scm/_run_cmd.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ def has_command(
189189
return res
190190

191191

192+
class CommandNotFoundError(LookupError, FileNotFoundError):
193+
pass
194+
195+
192196
def require_command(name: str) -> None:
193197
if not has_command(name, warn=False):
194-
raise OSError(f"{name!r} was not found")
198+
raise CommandNotFoundError(name)

testing/test_git.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from setuptools_scm import git
2525
from setuptools_scm import NonNormalizedVersion
2626
from setuptools_scm._file_finders.git import git_find_files
27+
from setuptools_scm._run_cmd import CommandNotFoundError
2728
from setuptools_scm._run_cmd import CompletedProcess
2829
from setuptools_scm._run_cmd import has_command
2930
from setuptools_scm._run_cmd import run
@@ -93,8 +94,12 @@ def test_root_search_parent_directories(
9394

9495
def test_git_gone(wd: WorkDir, monkeypatch: pytest.MonkeyPatch) -> None:
9596
monkeypatch.setenv("PATH", str(wd.cwd / "not-existing"))
96-
with pytest.raises(EnvironmentError, match="'git' was not found"):
97-
git.parse(str(wd.cwd), Configuration(), git.DEFAULT_DESCRIBE)
97+
98+
wd.write("pyproject.toml", "[tool.setuptools_scm]")
99+
with pytest.raises(CommandNotFoundError, match=r"git"):
100+
git.parse(wd.cwd, Configuration(), git.DEFAULT_DESCRIBE)
101+
102+
assert wd.get_version(fallback_version="1.0") == "1.0"
98103

99104

100105
@pytest.mark.issue("https://github.com/pypa/setuptools_scm/issues/298")

testing/test_mercurial.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import setuptools_scm._file_finders
99
from setuptools_scm import Configuration
10+
from setuptools_scm._run_cmd import CommandNotFoundError
1011
from setuptools_scm._run_cmd import has_command
1112
from setuptools_scm.hg import archival_to_version
1213
from setuptools_scm.hg import parse
@@ -55,8 +56,11 @@ def test_archival_to_version(expected: str, data: dict[str, str]) -> None:
5556
def test_hg_gone(wd: WorkDir, monkeypatch: pytest.MonkeyPatch) -> None:
5657
monkeypatch.setenv("PATH", str(wd.cwd / "not-existing"))
5758
config = Configuration()
58-
with pytest.raises(EnvironmentError, match="'hg' was not found"):
59-
parse(str(wd.cwd), config=config)
59+
wd.write("pyproject.toml", "[tool.setuptools_scm]")
60+
with pytest.raises(CommandNotFoundError, match=r"hg"):
61+
parse(wd.cwd, config=config)
62+
63+
assert wd.get_version(fallback_version="1.0") == "1.0"
6064

6165

6266
def test_find_files_stop_at_root_hg(

0 commit comments

Comments
 (0)