Skip to content

Commit

Permalink
Merge pull request #731 from RonnyPfannschmidt/cli-setup-root-option
Browse files Browse the repository at this point in the history
fix #691 - support root in pyproject.toml even for cli
  • Loading branch information
RonnyPfannschmidt authored Jun 26, 2022
2 parents 6990979 + 1d920c7 commit 21e58d4
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 24 deletions.
21 changes: 11 additions & 10 deletions src/setuptools_scm/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
from setuptools_scm.integration import find_files


def main() -> None:
opts = _get_cli_opts()
root = opts.root or "."
def main(args: list[str] | None = None) -> None:
opts = _get_cli_opts(args)
inferred_root: str = opts.root or "."

pyproject = opts.config or _find_pyproject(root)
pyproject = opts.config or _find_pyproject(inferred_root)

try:
root = opts.root or os.path.relpath(os.path.dirname(pyproject))
config = Configuration.from_file(pyproject, root=root)

config = Configuration.from_file(pyproject, root=opts.root)
except (LookupError, FileNotFoundError) as ex:
# no pyproject.toml OR no [tool.setuptools_scm]
print(
Expand All @@ -27,10 +27,11 @@ def main() -> None:
f" Reason: {ex}.",
file=sys.stderr,
)
config = Configuration(root=root)
config = Configuration(inferred_root)

version = _get_version(config)
assert version is not None
if version is None:
raise SystemExit("ERROR: no version found for", opts)
if opts.strip_dev:
version = version.partition(".dev")[0]
print(version)
Expand All @@ -40,7 +41,7 @@ def main() -> None:
print(fname)


def _get_cli_opts() -> argparse.Namespace:
def _get_cli_opts(args: list[str] | None) -> argparse.Namespace:
prog = "python -m setuptools_scm"
desc = "Print project version according to SCM metadata"
parser = argparse.ArgumentParser(prog, description=desc)
Expand Down Expand Up @@ -68,7 +69,7 @@ def _get_cli_opts() -> argparse.Namespace:
# We avoid `metavar` to prevent printing repetitive information
desc = "List files managed by the SCM"
sub.add_parser("ls", help=desc[0].lower() + desc[1:], description=desc)
return parser.parse_args()
return parser.parse_args(args)


def _find_pyproject(parent: str) -> str:
Expand Down
35 changes: 30 additions & 5 deletions src/setuptools_scm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
DEFAULT_TAG_REGEX = r"^(?:[\w-]+-)?(?P<version>[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$"
DEFAULT_VERSION_SCHEME = "guess-next-dev"
DEFAULT_LOCAL_SCHEME = "node-and-date"
_ROOT = "root"


def _check_tag_regex(value: str | Pattern[str] | None) -> Pattern[str]:
Expand Down Expand Up @@ -213,27 +214,51 @@ def from_file(

with open(name, encoding="UTF-8") as strm:
data = strm.read()

defn = _load_toml(data)
try:
section = defn.get("tool", {})["setuptools_scm"]
except LookupError as e:
raise LookupError(
f"{name} does not contain a tool.setuptools_scm section"
) from e

project = defn.get("project", {})
dist_name = cls._cleanup_from_file_args_data(
project, dist_name, kwargs, section
)
return cls(dist_name=dist_name, relative_to=name, **section, **kwargs)

@staticmethod
def _cleanup_from_file_args_data(
project: dict[str, Any],
dist_name: str | None,
kwargs: dict[str, Any],
section: dict[str, Any],
) -> str | None:
"""drops problematic details and figures the distribution name"""
if "dist_name" in section:
if dist_name is None:
dist_name = section.pop("dist_name")
else:
assert dist_name == section["dist_name"]
del section["dist_name"]
if dist_name is None:
if "project" in defn:
# minimal pep 621 support for figuring the pretend keys
dist_name = defn["project"].get("name")
# minimal pep 621 support for figuring the pretend keys
dist_name = project.get("name")
if dist_name is None:
dist_name = _read_dist_name_from_setup_cfg()

return cls(dist_name=dist_name, **section, **kwargs)
if _ROOT in kwargs:
if kwargs[_ROOT] is None:
kwargs.pop(_ROOT, None)
elif _ROOT in section:
if section[_ROOT] != kwargs[_ROOT]:
warnings.warn(
f"root {section[_ROOT]} is overridden"
f" by the cli arg {kwargs[_ROOT]}"
)
section.pop("root", None)
return dist_name


def _read_dist_name_from_setup_cfg() -> str | None:
Expand Down
26 changes: 19 additions & 7 deletions testing/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import os
from pathlib import Path
from typing import Any
from typing import Generator

import pytest

import setuptools_scm.utils
from .wd_wrapper import WorkDir


Expand Down Expand Up @@ -39,13 +39,25 @@ def pytest_addoption(parser: Any) -> None:
)


@pytest.fixture(autouse=True)
def debug_mode() -> Generator[None, None, None]:
from setuptools_scm import utils
class DebugMode:
def __init__(self, monkeypatch: pytest.MonkeyPatch):
self.__monkeypatch = monkeypatch
self.__module = setuptools_scm.utils

__monkeypatch: pytest.MonkeyPatch

def enable(self) -> None:
self.__monkeypatch.setattr(self.__module, "DEBUG", True)

utils.DEBUG = True
yield
utils.DEBUG = False
def disable(self) -> None:
self.__monkeypatch.setattr(self.__module, "DEBUG", False)


@pytest.fixture(autouse=True)
def debug_mode(monkeypatch: pytest.MonkeyPatch) -> DebugMode:
debug_mode = DebugMode(monkeypatch)
debug_mode.enable()
return debug_mode


@pytest.fixture
Expand Down
50 changes: 50 additions & 0 deletions testing/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import annotations

import io
from contextlib import redirect_stdout

import pytest

from .conftest import DebugMode
from .test_git import wd as wd_fixture # NOQA evil fixture reuse
from .wd_wrapper import WorkDir
from setuptools_scm._cli import main


PYPROJECT_TOML = "pyproject.toml"
PYPROJECT_SIMPLE = "[tool.setuptools_scm]"
PYPROJECT_ROOT = '[tool.setuptools_scm]\nroot=".."'


def get_output(args: list[str]) -> str:

with redirect_stdout(io.StringIO()) as out:
main(args)
return out.getvalue()


def test_cli_find_pyproject(
wd: WorkDir, monkeypatch: pytest.MonkeyPatch, debug_mode: DebugMode
) -> None:
debug_mode.disable()
wd.commit_testfile()
wd.write(PYPROJECT_TOML, PYPROJECT_SIMPLE)
monkeypatch.chdir(wd.cwd)

out = get_output([])
assert out.startswith("0.1.dev1+")

with pytest.raises(SystemExit, match="no version found for"):
get_output(["--root=.."])

wd.write(PYPROJECT_TOML, PYPROJECT_ROOT)
with pytest.raises(SystemExit, match="no version found for"):
print(get_output(["-c", PYPROJECT_TOML]))

with pytest.raises(SystemExit, match="no version found for"):

get_output(["-c", PYPROJECT_TOML, "--root=.."])

with pytest.warns(UserWarning, match="root .. is overridden by the cli arg ."):
out = get_output(["-c", PYPROJECT_TOML, "--root=."])
assert out.startswith("0.1.dev1+")
7 changes: 5 additions & 2 deletions testing/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import pytest

from .conftest import DebugMode
from .wd_wrapper import WorkDir
from setuptools_scm import Configuration
from setuptools_scm import format_version
Expand All @@ -31,14 +32,16 @@
)


@pytest.fixture
def wd(wd: WorkDir, monkeypatch: pytest.MonkeyPatch) -> WorkDir:
@pytest.fixture(name="wd")
def wd(wd: WorkDir, monkeypatch: pytest.MonkeyPatch, debug_mode: DebugMode) -> WorkDir:
debug_mode.disable()
monkeypatch.delenv("HOME", raising=False)
wd("git init")
wd("git config user.email test@example.com")
wd('git config user.name "a test"')
wd.add_command = "git add ."
wd.commit_command = "git commit -m test-{reason}"
debug_mode.enable()
return wd


Expand Down

0 comments on commit 21e58d4

Please sign in to comment.