Skip to content

Commit

Permalink
feat: auto min version
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
  • Loading branch information
henryiii committed Jul 6, 2024
1 parent 3287d2c commit bfdd3df
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
15 changes: 15 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ probably keep in sync with your build-system requirements.
minimum-version = "0.2"
```

In your `pyproject.toml`, you can specify the special string
`"build-system.requirements"`, which will read the minimum version from your
build-system requirements directly; you must specify a minimum there to use this
automatic feature.

```toml
[build-system]
requires = ["scikit-build-core>=0.10"]

[tool.scikit-build]
minimum-version = "build-system.requirements"
```

:::{warning}

The following behaviors are affected by `minimum-version`:
Expand All @@ -110,6 +123,8 @@ The following behaviors are affected by `minimum-version`:
- `minimum-version` 0.5+ (or unset) strips binaries by default.
- `minimum-version` 0.8+ (or unset) `cmake.minimum-version` and
`ninja.minimum-version` are replaced with `cmake.version` and `ninja.version`.
- `minimum-version` 0.10+ (or unset) `cmake.targets` and
`cmake.verbose` are replaced with `build.targets` and `build.verbose`.

:::

Expand Down
53 changes: 53 additions & 0 deletions src/scikit_build_core/settings/auto_requires.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from packaging.requirements import Requirement
from packaging.utils import canonicalize_name
from packaging.version import Version

if TYPE_CHECKING:
from collections.abc import Iterable

Check warning on line 10 in src/scikit_build_core/settings/auto_requires.py

View check run for this annotation

Codecov / codecov/patch

src/scikit_build_core/settings/auto_requires.py#L10

Added line #L10 was not covered by tests

from packaging.specifiers import Specifier

Check warning on line 12 in src/scikit_build_core/settings/auto_requires.py

View check run for this annotation

Codecov / codecov/patch

src/scikit_build_core/settings/auto_requires.py#L12

Added line #L12 was not covered by tests

__all__ = ["get_min_requires"]


def __dir__() -> list[str]:
return __all__


def get_min_requires(package: str, reqlist: Iterable[str]) -> Version | None:
"""
Read the build requirements from a pyproject.toml file
and return the minimum version required for the given package.
Returns None if no minimum version is discovered.
"""

norm_package = canonicalize_name(package)

requires = [Requirement(req) for req in reqlist]

for req in requires:
if canonicalize_name(req.name) == norm_package:
specset = req.specifier
versions = (min_from_spec(v) for v in specset)
return min((v for v in versions if v is not None), default=None)

return None


def min_from_spec(spec: Specifier) -> Version | None:
"""
Return the minimum version from a specifier.
Returns None if no minimum version is discovered.
">" technically doesn't include the minimum, but any
larger version is acceptable, so it is treated as the
minimum.
"""

if spec.operator in {">=", ">", "==", "~="}:
return Version(spec.version)
return None
18 changes: 18 additions & 0 deletions src/scikit_build_core/settings/skbuild_read_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .._compat import tomllib
from .._logging import logger, rich_print
from ..errors import CMakeConfigError
from .auto_requires import get_min_requires
from .skbuild_model import CMakeSettings, NinjaSettings, ScikitBuildSettings
from .sources import ConfSource, EnvSource, SourceChain, TOMLSource

Expand Down Expand Up @@ -327,8 +328,25 @@ def __init__(
) -> None:
self.state = state

# Handle overrides
pyproject = copy.deepcopy(pyproject)
process_overides(pyproject.get("tool", {}).get("scikit-build", {}), state, env)

# Support for minimum-version='build-system.requires'
tmp_min_v = (
pyproject.get("tool", {})
.get("scikit-build", {})
.get("minimum-version", None)
)
if tmp_min_v == "build-system.requires":
reqlist = pyproject["build-system"]["requires"]
min_v = get_min_requires("scikit-build-core", reqlist)
if min_v is None:
rich_print(

Check warning on line 345 in src/scikit_build_core/settings/skbuild_read_settings.py

View check run for this annotation

Codecov / codecov/patch

src/scikit_build_core/settings/skbuild_read_settings.py#L345

Added line #L345 was not covered by tests
"[red][bold]ERROR:[/bold] scikit-build-core needs a min version in build-system.requires to use minimum-version='build-system.requires'"
)
raise SystemExit(7)

Check warning on line 348 in src/scikit_build_core/settings/skbuild_read_settings.py

View check run for this annotation

Codecov / codecov/patch

src/scikit_build_core/settings/skbuild_read_settings.py#L348

Added line #L348 was not covered by tests
pyproject["tool"]["scikit-build"]["minimum-version"] = str(min_v)
toml_srcs = [TOMLSource("tool", "scikit-build", settings=pyproject)]

if extra_settings is not None:
Expand Down
27 changes: 27 additions & 0 deletions tests/test_auto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pytest
from packaging.version import Version

from scikit_build_core.settings.auto_requires import get_min_requires


def test_auto_requires_pkg_no_spec():
reqlist = ["scikit-build-core"]

assert get_min_requires("scikit-build-core", reqlist) is None
assert get_min_requires("other", reqlist) is None


@pytest.mark.parametrize(
("spec", "version"),
[
("==1.0", Version("1.0")),
(">=1.0", Version("1.0")),
(">1.0", Version("1.0")),
("~=1.0", Version("1.0")),
(">=0.3,<0.4", Version("0.3")),
("", None),
],
)
def test_auto_requires_pkg_version(spec: str, version: Version):
reqlist = [f"scikit_build_core{spec}"]
assert get_min_requires("scikit-build-core", reqlist) == version
22 changes: 22 additions & 0 deletions tests/test_skbuild_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,25 @@ def test_backcompat_cmake_build_both_specified(

with pytest.raises(SystemExit):
SettingsReader.from_file(pyproject_toml, {"build.verbose": "1"})


def test_auto_minimum_version(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(
scikit_build_core.settings.skbuild_read_settings, "__version__", "0.10.0"
)
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
textwrap.dedent(
"""\
[build-system]
requires = ["scikit-build-core>=0.8"]
[tool.scikit-build]
minimum-version = "build-system.requires"
"""
),
encoding="utf-8",
)

reader = SettingsReader.from_file(pyproject_toml, {})
assert reader.settings.minimum_version == Version("0.8")

0 comments on commit bfdd3df

Please sign in to comment.