Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/integrations.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
# Integrations

## dynamic-metadata

Any PEP 517 backend that supports the `tool.dynamic-metadata` array (as described in
[scikit-build/dynamic-metadata](https://github.com/scikit-build/dynamic-metadata)),
such as scikit-build-core 1.0+, can infer its version from VCS metadata using the
`vcs_versioning.dynamic_metadata` provider shipped with vcs-versioning:

```toml title="pyproject.toml"
[build-system]
requires = ["scikit-build-core", "vcs-versioning"]
build-backend = "scikit_build_core.build"

[project]
name = "my-package"
dynamic = ["version"]

[tool.vcs-versioning]
# normal vcs-versioning options go here, e.g.
# local_scheme = "no-local-version"

[[tool.dynamic-metadata]]
provider = "vcs_versioning.dynamic_metadata"
```

The provider always populates `version`. Version-scheme settings are read from
`[tool.vcs-versioning]`. You may also pass options inline in the
`[[tool.dynamic-metadata]]` table — any key there is forwarded as an override, so
this is equivalent to the `local_scheme` above:

```toml
[[tool.dynamic-metadata]]
provider = "vcs_versioning.dynamic_metadata"
local_scheme = "no-local-version"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho dynamic metadata should have a wy to pass in the root pyproject directly - and the vcs-versioning provider should use its own tool section for the configuration - creating additional placees for putting the same thing is against the zen of python as far as im concerned

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does, hooks run in the same directory as build-system.build-backend so it's fine to read it. That's why the docs say both work. You can disable this (don't pass through config, require to be empty), but users will likely expect to have all the config in each tool.dynamic-metadata section. And if you use it multiple times (like building readme's out of fragments), you have to have it in each entry.

```

## ReadTheDocs

### Avoid having a dirty Git index
Expand Down
1 change: 1 addition & 0 deletions vcs-versioning/changelog.d/1465.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a ``vcs_versioning.dynamic_metadata`` provider for the [dynamic-metadata](https://github.com/scikit-build/dynamic-metadata) system.
46 changes: 46 additions & 0 deletions vcs-versioning/src/vcs_versioning/dynamic_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""scikit-build ``dynamic-metadata`` provider for vcs-versioning.

Use this module as a provider for `scikit-build/dynamic-metadata
<https://github.com/scikit-build/dynamic-metadata>`_ so any backend supporting
that can fill in a VCS-derived ``version``::

[[tool.dynamic-metadata]]
provider = "vcs_versioning.dynamic_metadata"
Comment thread
RonnyPfannschmidt marked this conversation as resolved.
Outdated

Configuration is read from ``[tool.vcs-versioning]``; any keys in the
``[[tool.dynamic-metadata]]`` table are passed through as overrides.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from collections.abc import Mapping

from vcs_versioning import PyProjectData, infer_version_string
from vcs_versioning.overrides import GlobalOverrides

__all__ = ["dynamic_metadata"]


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


def dynamic_metadata(
settings: Mapping[str, Any],
project: Mapping[str, Any],
) -> dict[str, Any]:
"""Return the ``version`` field for a dynamic-metadata consumer."""
dist_name = project.get("name")
# dynamic-metadata runs hooks with cwd at the project root.
with GlobalOverrides.from_env("VCS_VERSIONING", dist_name=dist_name):
pyproject = PyProjectData.from_file("pyproject.toml")
version = infer_version_string(
dist_name=dist_name,
pyproject_data=pyproject,
overrides=dict(settings) or None,
force_write_version_files=True,
)
return {"version": version}
49 changes: 49 additions & 0 deletions vcs-versioning/testing_vcs/test_dynamic_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Tests for the scikit-build dynamic-metadata provider."""

from __future__ import annotations

from pathlib import Path

import pytest
from vcs_versioning import test_api
from vcs_versioning.dynamic_metadata import dynamic_metadata


def test_pretend_version(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
(tmp_path / "pyproject.toml").write_text(
"""
[project]
name = "test-package"
dynamic = ["version"]

[tool.vcs-versioning]
""",
encoding="utf-8",
)
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("VCS_VERSIONING_PRETEND_VERSION_FOR_TEST_PACKAGE", "1.2.3")

assert dynamic_metadata({}, {"name": "test-package"}) == {"version": "1.2.3"}


def test_inline_override_drops_local_segment(
wd: test_api.WorkDir, monkeypatch: pytest.MonkeyPatch
) -> None:
wd.setup_git(monkeypatch)
wd.create_basic_pyproject_toml(name="test-package")
wd.add_and_commit()
wd.create_tag("1.0.0")
wd.commit_testfile()
monkeypatch.chdir(wd.cwd)

# Default local scheme adds a +g<node> local segment.
default = dynamic_metadata({}, {"name": "test-package"})
assert "+" in default["version"]

# Inline settings are forwarded to infer_version_string as overrides.
overridden = dynamic_metadata(
{"local_scheme": "no-local-version"},
{"name": "test-package"},
)
assert "+" not in overridden["version"]
assert overridden["version"].startswith("1.0.1.dev1")