-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build: remove versioningit build-req from sdist
- Replace `tool.versioningit.onbuild` hook with a custom implementation which replaces the entire `streamlink._version` module (similar to before) and which additionally removes `versioningit` from the `build-system.requires` field in `pyproject.toml` and which sets a static version string in `setup.py` - Rewrite `streamlink._version` module - Add and update comments - Update docs - Add tests
- Loading branch information
1 parent
80a7645
commit 1376283
Showing
6 changed files
with
181 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import re | ||
from contextlib import contextmanager | ||
from pathlib import Path | ||
from typing import Any, Dict, Generator, Generic, TypeVar, Union | ||
|
||
|
||
# noinspection PyUnusedLocal | ||
def onbuild( | ||
build_dir: Union[str, Path], | ||
is_source: bool, | ||
template_fields: Dict[str, Any], | ||
params: Dict[str, Any], | ||
): | ||
""" | ||
Remove the ``versioningit`` build-requirement from Streamlink's source distribution. | ||
Also set the static version string in the :mod:`streamlink._version` module when building the sdist/bdist. | ||
The version string already gets set by ``versioningit`` when building, so the sdist doesn't need to have | ||
``versioningit`` added as a build-requirement. Previously, the generated version string was only applied | ||
to the :mod:`streamlink._version` module while ``versioningit`` was still set as a build-requirement. | ||
This custom onbuild hook gets called via the ``tool.versioningit.onbuild`` config in ``pyproject.toml``, | ||
since ``versioningit`` does only support modifying one file via its default onbuild hook configuration. | ||
""" | ||
|
||
base_dir: Path = Path(build_dir).resolve() | ||
pkg_dir: Path = base_dir / "src" if is_source else base_dir | ||
version: str = template_fields["version"] | ||
cmproxy: Proxy[str] | ||
|
||
# Remove versioningit from ``build-system.requires`` in ``pyproject.toml`` | ||
if is_source: | ||
with update_file(base_dir / "pyproject.toml") as cmproxy: | ||
cmproxy.set(re.sub( | ||
r"^(\s*)(\"versioningit\b.+?\",).*$", | ||
"\\1# \\2", | ||
cmproxy.get(), | ||
flags=re.MULTILINE, | ||
count=1, | ||
)) | ||
|
||
# Set the static version string that gets passed directly to setuptools via ``setup.py``. | ||
# This is much easier compared to adding the ``project.version`` field and removing "version" from ``project.dynamic`` | ||
# in ``pyproject.toml``. | ||
if is_source: | ||
with update_file(base_dir / "setup.py") as cmproxy: | ||
cmproxy.set(re.sub( | ||
r"^(\s*)# (version=\"\",).*$", | ||
f"\\1version=\"{version}\",", | ||
cmproxy.get(), | ||
flags=re.MULTILINE, | ||
count=1, | ||
)) | ||
|
||
# Overwrite the entire ``streamlink._version`` module | ||
with update_file(pkg_dir / "streamlink" / "_version.py") as cmproxy: | ||
cmproxy.set(f"__version__ = \"{version}\"\n") | ||
|
||
|
||
TProxyItem = TypeVar("TProxyItem") | ||
|
||
|
||
class Proxy(Generic[TProxyItem]): | ||
def __init__(self, data: TProxyItem): | ||
self._data = data | ||
|
||
def get(self) -> TProxyItem: | ||
return self._data | ||
|
||
def set(self, data: TProxyItem) -> None: | ||
self._data = data | ||
|
||
|
||
@contextmanager | ||
def update_file(file: Path) -> Generator[Proxy[str], None, None]: | ||
with file.open("r+", encoding="utf-8") as fh: | ||
proxy = Proxy(fh.read()) | ||
yield proxy | ||
fh.seek(0) | ||
fh.write(proxy.get()) | ||
fh.truncate() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import re | ||
import shutil | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
from build_backend.onbuild import onbuild | ||
|
||
|
||
PROJECT_ROOT = Path(__file__).parents[1] | ||
|
||
|
||
@pytest.fixture() | ||
def template_fields(request: pytest.FixtureRequest) -> dict: | ||
template_fields = { | ||
"version": "1.2.3+fake", | ||
} | ||
template_fields.update(getattr(request, "param", {})) | ||
|
||
return template_fields | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
def build(request: pytest.FixtureRequest, tmp_path: Path, template_fields: dict) -> Path: | ||
param = getattr(request, "param", {}) | ||
is_source = param.get("is_source", True) | ||
pkg_dir = tmp_path / "src" if is_source else tmp_path | ||
|
||
(pkg_dir / "streamlink").mkdir(parents=True) | ||
shutil.copy(PROJECT_ROOT / "pyproject.toml", tmp_path / "pyproject.toml") | ||
shutil.copy(PROJECT_ROOT / "setup.py", tmp_path / "setup.py") | ||
shutil.copy(PROJECT_ROOT / "src" / "streamlink" / "_version.py", pkg_dir / "streamlink" / "_version.py") | ||
|
||
onbuild(tmp_path, is_source, template_fields, {}) | ||
|
||
return tmp_path | ||
|
||
|
||
@pytest.mark.parametrize("build", [pytest.param({"is_source": True}, id="is_source=True")], indirect=True) | ||
def test_sdist(build: Path): | ||
assert re.search( | ||
r"^(\s*)# (\"versioningit\b.+?\",).*$", | ||
(build / "pyproject.toml").read_text(encoding="utf-8"), | ||
re.MULTILINE, | ||
), "versioningit is not a build-requirement" | ||
assert re.search( | ||
r"^(\s*)(version=\"1\.2\.3\+fake\",).*$", | ||
(build / "setup.py").read_text(encoding="utf-8"), | ||
re.MULTILINE, | ||
), "setup() call defines a static version string" | ||
assert (build / "src" / "streamlink" / "_version.py").read_text(encoding="utf-8") \ | ||
== "__version__ = \"1.2.3+fake\"\n", \ | ||
"streamlink._version exports a static version string" | ||
|
||
|
||
@pytest.mark.parametrize("build", [pytest.param({"is_source": False}, id="is_source=False")], indirect=True) | ||
def test_bdist(build: Path): | ||
assert (build / "pyproject.toml").read_text(encoding="utf-8") \ | ||
== (PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8"), \ | ||
"Doesn't touch pyproject.toml (irrelevant for non-sdist)" | ||
assert (build / "setup.py").read_text(encoding="utf-8") \ | ||
== (PROJECT_ROOT / "setup.py").read_text(encoding="utf-8"), \ | ||
"Doesn't touch setup.py (irrelevant for non-sdist)" | ||
assert (build / "streamlink" / "_version.py").read_text(encoding="utf-8") \ | ||
== "__version__ = \"1.2.3+fake\"\n", \ | ||
"streamlink._version exports a static version string" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
# Always get the current version in "editable" installs | ||
# `pip install -e .` / `python setup.py develop` | ||
# This module will get replaced by versioningit when building a source distribution | ||
# and instead of trying to get the version string from git, a static version string will be set | ||
|
||
def _get_version() -> str: | ||
""" | ||
Get the current version from git in "editable" installs | ||
""" | ||
from pathlib import Path | ||
from versioningit import get_version | ||
import streamlink | ||
|
||
return get_version( | ||
project_dir=Path(streamlink.__file__).parents[2], | ||
) | ||
return get_version(project_dir=Path(streamlink.__file__).parents[2]) | ||
|
||
|
||
# The following _get_version() call will get replaced by versioningit with a static version string when building streamlink | ||
# `pip install .` / `pip wheel .` / `python setup.py build` / `python setup.py bdist_wheel` / etc. | ||
__version__ = _get_version() |