Skip to content

Commit

Permalink
Merge pull request pypa#901 from RonnyPfannschmidt/fix-549-fallback-w…
Browse files Browse the repository at this point in the history
…hen-scm-missing

Fix 549 fallback when scm missing
  • Loading branch information
RonnyPfannschmidt authored Sep 13, 2023
2 parents 2e5c2f8 + 978564b commit 5b1c77b
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ features
* support passing log levels to SETUPTOOLS_SCM_DEBUG
* support using rich.logging as console log handler if installed
* fix #527: type annotation in default version template
* fix #549: use fallbacks when scm search raises CommandNotFoundError

bugfixes
--------
Expand Down
15 changes: 4 additions & 11 deletions src/setuptools_scm/_entrypoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from . import version

if TYPE_CHECKING:
from ._config import Configuration
from . import _types as _t
from ._config import Configuration, ParseFunction


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


def _version_from_entrypoints(
config: Configuration, fallback: bool = False
def version_from_entrypoint(
config: Configuration, entrypoint: str, root: _t.PathT
) -> version.ScmVersion | None:
if fallback:
entrypoint = "setuptools_scm.parse_scm_fallback"
root = config.fallback_root
else:
entrypoint = "setuptools_scm.parse_scm"
root = config.absolute_root

from .discover import iter_matching_entrypoints

log.debug("version_from_ep %s in %s", entrypoint, root)
for ep in iter_matching_entrypoints(root, entrypoint, config):
fn = ep.load()
fn: ParseFunction = ep.load()
maybe_version: version.ScmVersion | None = fn(root, config=config)
log.debug("%s found %r", ep, maybe_version)
if maybe_version is not None:
Expand Down
36 changes: 24 additions & 12 deletions src/setuptools_scm/_get_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import logging
import re
import warnings
from pathlib import Path
Expand All @@ -8,30 +9,41 @@
from typing import Pattern

from . import _config
from . import _entrypoints
from . import _run_cmd
from . import _types as _t
from ._config import Configuration
from ._entrypoints import _version_from_entrypoints
from ._overrides import _read_pretended_version_for
from ._version_cls import _validate_version_cls
from .version import format_version as _format_version
from .version import ScmVersion

_log = logging.getLogger(__name__)


def parse_scm_version(config: Configuration) -> ScmVersion | None:
if config.parse is not None:
parse_result = config.parse(config.absolute_root, config=config)
if parse_result is not None and not isinstance(parse_result, ScmVersion):
raise TypeError(
f"version parse result was {str!r}\n"
"please return a parsed version (ScmVersion)"
)
return parse_result
else:
return _version_from_entrypoints(config)
try:
if config.parse is not None:
parse_result = config.parse(config.absolute_root, config=config)
if parse_result is not None and not isinstance(parse_result, ScmVersion):
raise TypeError(
f"version parse result was {str!r}\n"
"please return a parsed version (ScmVersion)"
)
return parse_result
else:
entrypoint = "setuptools_scm.parse_scm"
root = config.absolute_root
return _entrypoints.version_from_entrypoint(config, entrypoint, root)
except _run_cmd.CommandNotFoundError as e:
_log.exception("command %s not found while parsing the scm, using fallbacks", e)
return None


def parse_fallback_version(config: Configuration) -> ScmVersion | None:
return _version_from_entrypoints(config, fallback=True)
entrypoint = "setuptools_scm.parse_scm_fallback"
root = config.fallback_root
return _entrypoints.version_from_entrypoint(config, entrypoint, root)


def _do_parse(config: Configuration) -> ScmVersion | None:
Expand Down
6 changes: 5 additions & 1 deletion src/setuptools_scm/_run_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ def has_command(
return res


class CommandNotFoundError(LookupError, FileNotFoundError):
pass


def require_command(name: str) -> None:
if not has_command(name, warn=False):
raise OSError(f"{name!r} was not found")
raise CommandNotFoundError(name)
9 changes: 7 additions & 2 deletions testing/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from setuptools_scm import git
from setuptools_scm import NonNormalizedVersion
from setuptools_scm._file_finders.git import git_find_files
from setuptools_scm._run_cmd import CommandNotFoundError
from setuptools_scm._run_cmd import CompletedProcess
from setuptools_scm._run_cmd import has_command
from setuptools_scm._run_cmd import run
Expand Down Expand Up @@ -93,8 +94,12 @@ def test_root_search_parent_directories(

def test_git_gone(wd: WorkDir, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("PATH", str(wd.cwd / "not-existing"))
with pytest.raises(EnvironmentError, match="'git' was not found"):
git.parse(str(wd.cwd), Configuration(), git.DEFAULT_DESCRIBE)

wd.write("pyproject.toml", "[tool.setuptools_scm]")
with pytest.raises(CommandNotFoundError, match=r"git"):
git.parse(wd.cwd, Configuration(), git.DEFAULT_DESCRIBE)

assert wd.get_version(fallback_version="1.0") == "1.0"


@pytest.mark.issue("https://github.com/pypa/setuptools_scm/issues/298")
Expand Down
8 changes: 6 additions & 2 deletions testing/test_mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import setuptools_scm._file_finders
from setuptools_scm import Configuration
from setuptools_scm._run_cmd import CommandNotFoundError
from setuptools_scm._run_cmd import has_command
from setuptools_scm.hg import archival_to_version
from setuptools_scm.hg import parse
Expand Down Expand Up @@ -55,8 +56,11 @@ def test_archival_to_version(expected: str, data: dict[str, str]) -> None:
def test_hg_gone(wd: WorkDir, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("PATH", str(wd.cwd / "not-existing"))
config = Configuration()
with pytest.raises(EnvironmentError, match="'hg' was not found"):
parse(str(wd.cwd), config=config)
wd.write("pyproject.toml", "[tool.setuptools_scm]")
with pytest.raises(CommandNotFoundError, match=r"hg"):
parse(wd.cwd, config=config)

assert wd.get_version(fallback_version="1.0") == "1.0"


def test_find_files_stop_at_root_hg(
Expand Down

0 comments on commit 5b1c77b

Please sign in to comment.