setuptools-git-versioning 3.0.1__py3-none-any.whl → 3.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- setuptools_git_versioning/__init__.py +3 -0
- setuptools_git_versioning/archival.py +225 -0
- setuptools_git_versioning/defaults.py +1 -0
- setuptools_git_versioning/dynamic_metadata.py +51 -0
- setuptools_git_versioning/scikit_metadata.py +66 -0
- setuptools_git_versioning/version.py +56 -23
- {setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/METADATA +31 -2
- setuptools_git_versioning-3.2.0.dist-info/RECORD +19 -0
- {setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/WHEEL +1 -1
- {setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/entry_points.txt +3 -0
- setuptools_git_versioning-3.0.1.dist-info/RECORD +0 -16
- {setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/licenses/LICENSE +0 -0
- {setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/top_level.txt +0 -0
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
|
+
from setuptools_git_versioning.archival import parse_archival_file, version_from_archival
|
|
5
6
|
from setuptools_git_versioning.git import (
|
|
6
7
|
count_since,
|
|
7
8
|
get_all_tags,
|
|
@@ -37,5 +38,7 @@ __all__ = [
|
|
|
37
38
|
"get_version",
|
|
38
39
|
"infer_version",
|
|
39
40
|
"is_dirty",
|
|
41
|
+
"parse_archival_file",
|
|
42
|
+
"version_from_archival",
|
|
40
43
|
"version_from_git",
|
|
41
44
|
]
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os # noqa: TC003
|
|
5
|
+
import re
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from email.parser import HeaderParser
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from setuptools_git_versioning.defaults import (
|
|
12
|
+
DEFAULT_DEV_TEMPLATE,
|
|
13
|
+
DEFAULT_DIRTY_TEMPLATE,
|
|
14
|
+
DEFAULT_TEMPLATE,
|
|
15
|
+
)
|
|
16
|
+
from setuptools_git_versioning.factories import create_branch_formatter, create_tag_formatter
|
|
17
|
+
from setuptools_git_versioning.log import DEBUG, INFO
|
|
18
|
+
from setuptools_git_versioning.subst import resolve_substitutions
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from typing import Callable
|
|
22
|
+
|
|
23
|
+
from packaging.version import Version
|
|
24
|
+
|
|
25
|
+
ARCHIVAL_FILENAME = ".git_archival.txt"
|
|
26
|
+
DESCRIBE_UNSUPPORTED = "%(describe"
|
|
27
|
+
FORMAT_UNSUBSTITUTED = "$Format"
|
|
28
|
+
DESCRIBE_PARTS = 3 # tag-N-gSHA
|
|
29
|
+
|
|
30
|
+
REF_TAG_RE = re.compile(r"(?<=\btag: )([^,]+)\b")
|
|
31
|
+
REF_HEAD_RE = re.compile(r"HEAD\s*->\s*([^,]+)")
|
|
32
|
+
FULL_SHA_RE = re.compile(r"^([0-9a-f]{40}|[0-9a-f]{64})$") # SHA-1 or SHA-256
|
|
33
|
+
|
|
34
|
+
log = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ArchivalData:
|
|
39
|
+
tag: str
|
|
40
|
+
ccount: int
|
|
41
|
+
sha: str
|
|
42
|
+
full_sha: str
|
|
43
|
+
dirty: bool
|
|
44
|
+
branch: str | None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def parse_archival_file(path: str | os.PathLike) -> dict[str, str]:
|
|
48
|
+
"""Read a .git_archival.txt file and return its key/value pairs.
|
|
49
|
+
|
|
50
|
+
Keys are normalized to lowercase so lookups behave consistently
|
|
51
|
+
regardless of whether the file uses `node:` or `Node:` etc.
|
|
52
|
+
"""
|
|
53
|
+
content = Path(path).read_text(encoding="utf-8")
|
|
54
|
+
log.log(DEBUG, "'%s' content:\n%s", ARCHIVAL_FILENAME, content)
|
|
55
|
+
message = HeaderParser().parsestr(content)
|
|
56
|
+
|
|
57
|
+
# HeaderParser treats the first blank line as the end of headers.
|
|
58
|
+
# Anything after it ends up in the message body and is silently
|
|
59
|
+
# dropped from .items(). Warn the user instead of losing fields.
|
|
60
|
+
payload = message.get_payload()
|
|
61
|
+
if isinstance(payload, str) and payload.strip():
|
|
62
|
+
log.warning(
|
|
63
|
+
"'%s' contains content after a blank line; those fields will be ignored",
|
|
64
|
+
ARCHIVAL_FILENAME,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return {key.lower(): value for key, value in message.items()}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _parse_describe(describe: str) -> tuple[str, int, str | None, bool]:
|
|
71
|
+
"""Parse a `git describe`-style string into (tag, ccount, short_sha, dirty)."""
|
|
72
|
+
dirty = False
|
|
73
|
+
if describe.endswith("-dirty"):
|
|
74
|
+
dirty = True
|
|
75
|
+
describe = describe[: -len("-dirty")]
|
|
76
|
+
|
|
77
|
+
parts = describe.rsplit("-", 2)
|
|
78
|
+
if len(parts) < DESCRIBE_PARTS:
|
|
79
|
+
return describe, 0, None, dirty
|
|
80
|
+
|
|
81
|
+
tag, ccount_str, gnode = parts
|
|
82
|
+
try:
|
|
83
|
+
ccount = int(ccount_str)
|
|
84
|
+
except ValueError:
|
|
85
|
+
return describe, 0, None, dirty
|
|
86
|
+
|
|
87
|
+
short_sha = gnode[1:] if gnode.startswith("g") else gnode
|
|
88
|
+
return tag, ccount, short_sha, dirty
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _branch_from_ref_names(ref_names: str) -> str | None:
|
|
92
|
+
match = REF_HEAD_RE.search(ref_names)
|
|
93
|
+
if match:
|
|
94
|
+
return match.group(1).strip()
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_data_from_archival_file(data: dict[str, str]) -> ArchivalData | None:
|
|
99
|
+
"""Convert parsed archival data into structured version info, or None.
|
|
100
|
+
|
|
101
|
+
Returns None when the file looks unsubstituted or otherwise unusable so
|
|
102
|
+
the caller can fall through to live git.
|
|
103
|
+
"""
|
|
104
|
+
if any(FORMAT_UNSUBSTITUTED in value for value in data.values()):
|
|
105
|
+
log.warning(
|
|
106
|
+
"'%s' contains unprocessed '$Format:...$' placeholders, skipping",
|
|
107
|
+
ARCHIVAL_FILENAME,
|
|
108
|
+
)
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
node = data.get("node", "").strip()
|
|
112
|
+
full_sha = node if FULL_SHA_RE.match(node) else ""
|
|
113
|
+
ref_names = data.get("ref-names", "")
|
|
114
|
+
branch = _branch_from_ref_names(ref_names)
|
|
115
|
+
describe = data.get("describe-name", "").strip()
|
|
116
|
+
|
|
117
|
+
describe_tag: str | None = None
|
|
118
|
+
ccount = 0
|
|
119
|
+
short_sha = ""
|
|
120
|
+
dirty = False
|
|
121
|
+
|
|
122
|
+
if describe and DESCRIBE_UNSUPPORTED not in describe:
|
|
123
|
+
describe_tag, ccount, parsed_sha, dirty = _parse_describe(describe)
|
|
124
|
+
if parsed_sha:
|
|
125
|
+
short_sha = parsed_sha
|
|
126
|
+
elif describe:
|
|
127
|
+
log.warning(
|
|
128
|
+
"git archive did not expand %(describe...) (git <2.32), falling back to ref-names",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if describe_tag is not None:
|
|
132
|
+
tag = describe_tag
|
|
133
|
+
else:
|
|
134
|
+
tags = REF_TAG_RE.findall(ref_names)
|
|
135
|
+
if not tags:
|
|
136
|
+
log.log(
|
|
137
|
+
INFO,
|
|
138
|
+
"'%s' has no usable describe-name or tag in ref-names",
|
|
139
|
+
ARCHIVAL_FILENAME,
|
|
140
|
+
)
|
|
141
|
+
return None
|
|
142
|
+
tag = tags[0].strip()
|
|
143
|
+
|
|
144
|
+
# Prefer the full SHA when available so {sha} matches the live-git
|
|
145
|
+
# path's `full_sha[:8]` rendering. Fall back to the short SHA from
|
|
146
|
+
# describe-name only when no valid `node` field is present.
|
|
147
|
+
if full_sha:
|
|
148
|
+
short_sha = full_sha[:8]
|
|
149
|
+
elif short_sha:
|
|
150
|
+
full_sha = short_sha
|
|
151
|
+
|
|
152
|
+
return ArchivalData(
|
|
153
|
+
tag=tag,
|
|
154
|
+
ccount=ccount,
|
|
155
|
+
sha=short_sha[:8],
|
|
156
|
+
full_sha=full_sha,
|
|
157
|
+
dirty=dirty,
|
|
158
|
+
branch=branch,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def version_from_archival( # noqa: PLR0913
|
|
163
|
+
project_root: str | os.PathLike,
|
|
164
|
+
*,
|
|
165
|
+
package_name: str | None = None,
|
|
166
|
+
template: str = DEFAULT_TEMPLATE,
|
|
167
|
+
dev_template: str = DEFAULT_DEV_TEMPLATE,
|
|
168
|
+
dirty_template: str = DEFAULT_DIRTY_TEMPLATE,
|
|
169
|
+
tag_formatter: Callable[[str], str] | str | None = None,
|
|
170
|
+
branch_formatter: Callable[[str], str] | str | None = None,
|
|
171
|
+
) -> Version | None:
|
|
172
|
+
"""Return a Version derived from .git_archival.txt, or None if unavailable."""
|
|
173
|
+
archival_path = Path(project_root).joinpath(ARCHIVAL_FILENAME)
|
|
174
|
+
if not archival_path.exists():
|
|
175
|
+
log.log(DEBUG, "No '%s' present at '%s'", ARCHIVAL_FILENAME, project_root)
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
log.log(INFO, "File '%s' is found, reading its content", archival_path)
|
|
179
|
+
data = parse_archival_file(archival_path)
|
|
180
|
+
info = get_data_from_archival_file(data)
|
|
181
|
+
if info is None:
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
log.log(DEBUG, "Parsed archival data: %r", info)
|
|
185
|
+
|
|
186
|
+
tag = info.tag
|
|
187
|
+
if tag_formatter is not None:
|
|
188
|
+
tag_format_callback = create_tag_formatter(tag_formatter, package_name=package_name, root=project_root)
|
|
189
|
+
tag = tag_format_callback(tag)
|
|
190
|
+
log.log(DEBUG, "Tag after formatting: %r", tag)
|
|
191
|
+
|
|
192
|
+
if info.dirty:
|
|
193
|
+
log.log(INFO, "Using template from 'dirty_template' option")
|
|
194
|
+
chosen = dirty_template
|
|
195
|
+
elif info.ccount > 0:
|
|
196
|
+
log.log(INFO, "Using template from 'dev_template' option")
|
|
197
|
+
chosen = dev_template
|
|
198
|
+
else:
|
|
199
|
+
log.log(INFO, "Using template from 'template' option")
|
|
200
|
+
chosen = template
|
|
201
|
+
|
|
202
|
+
# When ref-names is absent or doesn't reveal a current branch, default
|
|
203
|
+
# to the literal "HEAD" so `{branch}` substitution mirrors what
|
|
204
|
+
# `git rev-parse --abbrev-ref HEAD` produces in detached-HEAD state.
|
|
205
|
+
branch = info.branch if info.branch is not None else "HEAD"
|
|
206
|
+
if branch_formatter is not None:
|
|
207
|
+
branch_format_callback = create_branch_formatter(branch_formatter, package_name=package_name, root=project_root)
|
|
208
|
+
branch = branch_format_callback(branch)
|
|
209
|
+
log.log(INFO, "Branch after formatting: %r", branch)
|
|
210
|
+
|
|
211
|
+
rendered = resolve_substitutions(
|
|
212
|
+
chosen,
|
|
213
|
+
sha=info.sha,
|
|
214
|
+
tag=tag,
|
|
215
|
+
ccount=info.ccount,
|
|
216
|
+
branch=branch,
|
|
217
|
+
full_sha=info.full_sha,
|
|
218
|
+
)
|
|
219
|
+
log.log(INFO, "Version number after resolving substitutions: %r", rendered)
|
|
220
|
+
|
|
221
|
+
# Deferred to avoid a top-level circular import:
|
|
222
|
+
# `version.py` imports `version_from_archival` from this module.
|
|
223
|
+
from setuptools_git_versioning.version import sanitize_version
|
|
224
|
+
|
|
225
|
+
return sanitize_version(rendered)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Version provider for the dynamic-metadata protocol."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from setuptools_git_versioning.defaults import set_default_options
|
|
9
|
+
from setuptools_git_versioning.setup import read_toml
|
|
10
|
+
from setuptools_git_versioning.version import version_from_git
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Mapping
|
|
14
|
+
|
|
15
|
+
__all__ = ["dynamic_metadata"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def dynamic_metadata(
|
|
19
|
+
settings: Mapping[str, Any],
|
|
20
|
+
project: Mapping[str, Any],
|
|
21
|
+
) -> dict[str, str]:
|
|
22
|
+
if settings:
|
|
23
|
+
msg = (
|
|
24
|
+
"Inline configuration under [[tool.dynamic-metadata]] is not supported. "
|
|
25
|
+
"Configure setuptools-git-versioning under [tool.setuptools-git-versioning] instead."
|
|
26
|
+
)
|
|
27
|
+
raise ValueError(msg)
|
|
28
|
+
|
|
29
|
+
root = Path.cwd()
|
|
30
|
+
|
|
31
|
+
config = read_toml(root=root)
|
|
32
|
+
if not config:
|
|
33
|
+
msg = (
|
|
34
|
+
"Missing [tool.setuptools-git-versioning] section in pyproject.toml. "
|
|
35
|
+
"Add it (with at minimum 'enabled = true') to use this provider."
|
|
36
|
+
)
|
|
37
|
+
raise ValueError(msg)
|
|
38
|
+
|
|
39
|
+
if not config.pop("enabled", True):
|
|
40
|
+
msg = (
|
|
41
|
+
"[tool.setuptools-git-versioning] has 'enabled = false' but the "
|
|
42
|
+
"metadata provider for setuptools-git-versioning was selected. "
|
|
43
|
+
"Either remove the provider or set 'enabled = true'."
|
|
44
|
+
)
|
|
45
|
+
raise ValueError(msg)
|
|
46
|
+
|
|
47
|
+
set_default_options(config)
|
|
48
|
+
|
|
49
|
+
name = project.get("name")
|
|
50
|
+
package_name = name if isinstance(name, str) else None
|
|
51
|
+
return {"version": str(version_from_git(package_name, **config, root=root))}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Deprecated version provider for the classic scikit-build-core protocol."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from setuptools_git_versioning.dynamic_metadata import dynamic_metadata as _dynamic_metadata
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Mapping
|
|
13
|
+
|
|
14
|
+
__all__ = ["dynamic_metadata", "get_requires_for_dynamic_metadata"]
|
|
15
|
+
|
|
16
|
+
warnings.warn(
|
|
17
|
+
"setuptools_git_versioning.scikit_metadata is deprecated; "
|
|
18
|
+
"migrate to [[tool.dynamic-metadata]] with provider = 'setuptools_git_versioning.dynamic_metadata' "
|
|
19
|
+
"on a backend supporting dynamic-metadata such as scikit-build-core>=1.0.",
|
|
20
|
+
DeprecationWarning,
|
|
21
|
+
stacklevel=2,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def dynamic_metadata(
|
|
26
|
+
field: str,
|
|
27
|
+
settings: Mapping[str, Any] | None = None,
|
|
28
|
+
) -> str:
|
|
29
|
+
if field != "version":
|
|
30
|
+
msg = f"Only the 'version' field is supported, got {field!r}"
|
|
31
|
+
raise ValueError(msg)
|
|
32
|
+
|
|
33
|
+
if settings:
|
|
34
|
+
msg = (
|
|
35
|
+
"Inline configuration under [tool.scikit-build.metadata.version] is not supported. "
|
|
36
|
+
"Configure setuptools-git-versioning under [tool.setuptools-git-versioning] instead."
|
|
37
|
+
)
|
|
38
|
+
raise ValueError(msg)
|
|
39
|
+
|
|
40
|
+
return _dynamic_metadata({}, {"name": _read_project_name(Path.cwd())})["version"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _read_project_name(root: Path) -> str | None:
|
|
44
|
+
pyproject = root / "pyproject.toml"
|
|
45
|
+
if not pyproject.is_file():
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
import tomllib
|
|
50
|
+
|
|
51
|
+
with pyproject.open("rb") as file:
|
|
52
|
+
data = tomllib.load(file)
|
|
53
|
+
except ImportError:
|
|
54
|
+
import tomli
|
|
55
|
+
|
|
56
|
+
with pyproject.open("rb") as file:
|
|
57
|
+
data = tomli.load(file)
|
|
58
|
+
|
|
59
|
+
name = data.get("project", {}).get("name")
|
|
60
|
+
return name if isinstance(name, str) else None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_requires_for_dynamic_metadata(
|
|
64
|
+
_settings: Mapping[str, Any] | None = None,
|
|
65
|
+
) -> list[str]:
|
|
66
|
+
return ["setuptools-git-versioning"]
|
|
@@ -5,12 +5,13 @@ import logging
|
|
|
5
5
|
import os # noqa: TC003
|
|
6
6
|
import re
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Callable
|
|
8
|
+
from typing import Callable, cast
|
|
9
9
|
|
|
10
10
|
# avoid importing 'packaging' because setuptools-git-versioning can be installed using sdist
|
|
11
11
|
# where 'packaging' is not installed yet
|
|
12
12
|
from packaging.version import Version
|
|
13
13
|
|
|
14
|
+
from setuptools_git_versioning.archival import version_from_archival
|
|
14
15
|
from setuptools_git_versioning.defaults import (
|
|
15
16
|
DEFAULT_DEV_TEMPLATE,
|
|
16
17
|
DEFAULT_DIRTY_TEMPLATE,
|
|
@@ -95,6 +96,7 @@ def version_from_git( # noqa: PLR0915, PLR0912, PLR0913, C901
|
|
|
95
96
|
version_callback: str | Callable[[], str] | None = None,
|
|
96
97
|
version_file: str | os.PathLike | None = None,
|
|
97
98
|
count_commits_from_version_file: bool = False,
|
|
99
|
+
prefer_tag: bool = False,
|
|
98
100
|
tag_formatter: Callable[[str], str] | str | None = None,
|
|
99
101
|
branch_formatter: Callable[[str], str] | str | None = None,
|
|
100
102
|
tag_filter: Callable[[str], str | None] | str | None = None,
|
|
@@ -114,12 +116,28 @@ def version_from_git( # noqa: PLR0915, PLR0912, PLR0913, C901
|
|
|
114
116
|
# running on sdist package, do not sanitize
|
|
115
117
|
return Version(version_str)
|
|
116
118
|
|
|
119
|
+
archival_version = version_from_archival(
|
|
120
|
+
project_root,
|
|
121
|
+
package_name=package_name,
|
|
122
|
+
template=template,
|
|
123
|
+
dev_template=dev_template,
|
|
124
|
+
dirty_template=dirty_template,
|
|
125
|
+
tag_formatter=tag_formatter,
|
|
126
|
+
branch_formatter=branch_formatter,
|
|
127
|
+
)
|
|
128
|
+
if archival_version is not None:
|
|
129
|
+
log.log(INFO, "Resolved version from '.git_archival.txt': %s", archival_version)
|
|
130
|
+
return archival_version
|
|
131
|
+
|
|
117
132
|
if version_callback is not None:
|
|
118
133
|
if version_file is not None:
|
|
119
134
|
msg = "Either 'version_file' or 'version_callback' can be passed, but not both at the same time"
|
|
120
135
|
raise ValueError(msg)
|
|
121
136
|
return get_version_from_callback(version_callback, package_name, root=root)
|
|
122
137
|
|
|
138
|
+
ccount: int | None = 0
|
|
139
|
+
on_tag = False
|
|
140
|
+
tag_sha = None
|
|
123
141
|
head_sha = get_sha(root=root)
|
|
124
142
|
log.log(INFO, "HEAD SHA-256: %r", head_sha)
|
|
125
143
|
|
|
@@ -132,15 +150,21 @@ def version_from_git( # noqa: PLR0915, PLR0912, PLR0913, C901
|
|
|
132
150
|
tag = get_tag(sort_by=sort_by, root=root, filter_callback=filter_callback)
|
|
133
151
|
if not tag:
|
|
134
152
|
log.log(INFO, "No tags found")
|
|
135
|
-
tag_sha = None
|
|
136
|
-
on_tag = False
|
|
137
153
|
else:
|
|
138
|
-
tag_sha = get_sha(tag, root=root)
|
|
154
|
+
tag_sha = cast("str", get_sha(tag, root=root))
|
|
139
155
|
log.log(INFO, "Tag SHA-256: %r", tag_sha)
|
|
140
156
|
|
|
141
157
|
on_tag = head_sha is not None and head_sha == tag_sha
|
|
142
158
|
log.log(INFO, "HEAD is tagged: %r", on_tag)
|
|
143
159
|
|
|
160
|
+
ccount = count_since(tag_sha, root=root)
|
|
161
|
+
log.log(INFO, "Commits count between HEAD and last tag: %r", ccount)
|
|
162
|
+
|
|
163
|
+
if tag_formatter is not None:
|
|
164
|
+
tag_format_callback = create_tag_formatter(tag_formatter, package_name=package_name, root=root)
|
|
165
|
+
tag = tag_format_callback(tag)
|
|
166
|
+
log.log(DEBUG, "Tag after formatting: %r", tag)
|
|
167
|
+
|
|
144
168
|
if version_file:
|
|
145
169
|
log.log(INFO, "Checking for 'version_file'")
|
|
146
170
|
|
|
@@ -152,35 +176,44 @@ def version_from_git( # noqa: PLR0915, PLR0912, PLR0913, C901
|
|
|
152
176
|
version_file_path,
|
|
153
177
|
starting_version,
|
|
154
178
|
)
|
|
155
|
-
|
|
179
|
+
file_tag = None
|
|
156
180
|
else:
|
|
157
181
|
log.log(INFO, "Reading version_file '%s' content", version_file)
|
|
158
|
-
|
|
182
|
+
file_tag = version_file_path.read_text().strip() or None
|
|
159
183
|
|
|
160
|
-
if not
|
|
184
|
+
if not file_tag:
|
|
161
185
|
log.log(INFO, "File %r is empty", version_file)
|
|
162
186
|
else:
|
|
163
|
-
log.log(DEBUG, "File content: %r",
|
|
164
|
-
if not count_commits_from_version_file:
|
|
165
|
-
return sanitize_version(tag)
|
|
187
|
+
log.log(DEBUG, "File content: %r", file_tag)
|
|
166
188
|
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
if prefer_tag and file_tag and tag:
|
|
190
|
+
log.log(
|
|
191
|
+
INFO,
|
|
192
|
+
"Both 'version_file' and a Git tag (%r) are present, and 'prefer_tag' is enabled: using the tag",
|
|
193
|
+
tag,
|
|
194
|
+
)
|
|
195
|
+
if file_tag and sanitize_version(file_tag) != sanitize_version(tag):
|
|
196
|
+
log.warning(
|
|
197
|
+
"Git tag %r and 'version_file' content %r are different: using the tag. "
|
|
198
|
+
"Update the version file to silence this warning",
|
|
199
|
+
tag,
|
|
200
|
+
file_tag,
|
|
201
|
+
)
|
|
169
202
|
|
|
170
|
-
|
|
171
|
-
|
|
203
|
+
elif file_tag:
|
|
204
|
+
tag = file_tag
|
|
172
205
|
|
|
173
|
-
|
|
174
|
-
|
|
206
|
+
if not count_commits_from_version_file:
|
|
207
|
+
return sanitize_version(tag)
|
|
175
208
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
log.log(INFO, "Commits count between HEAD and last tag: %r", ccount)
|
|
209
|
+
file_sha = get_latest_file_commit(version_file, root=root)
|
|
210
|
+
log.log(DEBUG, "File SHA-256: %r", file_sha)
|
|
179
211
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
212
|
+
ccount = count_since(file_sha, root=root) if file_sha else None
|
|
213
|
+
log.log(INFO, "Commits count between HEAD and last version file change: %r", ccount)
|
|
214
|
+
|
|
215
|
+
elif not head_sha:
|
|
216
|
+
log.log(INFO, "Not a git repo, or repo without any branch")
|
|
184
217
|
|
|
185
218
|
if not tag:
|
|
186
219
|
log.log(INFO, "No source for version, return starting_version %r", starting_version)
|
{setuptools_git_versioning-3.0.1.dist-info → setuptools_git_versioning-3.2.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: setuptools-git-versioning
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: Use git repo data for building a version number according to PEP-440
|
|
5
5
|
Author-email: dolfinus <martinov.m.s.8@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
24
|
Classifier: Operating System :: OS Independent
|
|
24
25
|
Requires-Python: >=3.7
|
|
25
26
|
Description-Content-Type: text/x-rst
|
|
@@ -81,7 +82,8 @@ between ``setuptools-git-versioning`` and other tools.
|
|
|
81
82
|
|
|
82
83
|
- Only Git v2 is supported
|
|
83
84
|
|
|
84
|
-
-
|
|
85
|
+
- Setuptools and build backends supporting `dynamic-metadata <https://dynamic-metadata.readthedocs.io>`_
|
|
86
|
+
(e.g. `scikit-build-core <https://scikit-build-core.readthedocs.io>`_ 1.0+) are supported.
|
|
85
87
|
|
|
86
88
|
- Currently does not support automatic exporting of package version to a file for runtime use
|
|
87
89
|
(but you can use ``setuptools-git-versioning > file`` redirect instead)
|
|
@@ -173,3 +175,30 @@ and then add new argument ``setuptools_git_versioning`` with config options:
|
|
|
173
175
|
)
|
|
174
176
|
|
|
175
177
|
Commands are the same as above, plus ``python -m setup.py`` returns the same version.
|
|
178
|
+
|
|
179
|
+
``dynamic-metadata``
|
|
180
|
+
~~~~~~~~~~~~~~~~~~~~
|
|
181
|
+
|
|
182
|
+
For build backends supporting `dynamic-metadata <https://dynamic-metadata.readthedocs.io>`_ 0.4+,
|
|
183
|
+
select the registered provider in ``[[tool.dynamic-metadata]]``. For example, with
|
|
184
|
+
`scikit-build-core <https://scikit-build-core.readthedocs.io>`_ 1.0+:
|
|
185
|
+
|
|
186
|
+
.. code:: toml
|
|
187
|
+
|
|
188
|
+
[build-system]
|
|
189
|
+
requires = [ "scikit-build-core>=1.0", "dynamic-metadata>=0.4", "setuptools-git-versioning>=3.2,<4", ]
|
|
190
|
+
build-backend = "scikit_build_core.build"
|
|
191
|
+
|
|
192
|
+
[project]
|
|
193
|
+
name = "mypackage"
|
|
194
|
+
dynamic = ["version"]
|
|
195
|
+
|
|
196
|
+
[[tool.dynamic-metadata]]
|
|
197
|
+
provider = "setuptools_git_versioning.dynamic_metadata"
|
|
198
|
+
|
|
199
|
+
[tool.setuptools-git-versioning]
|
|
200
|
+
enabled = true
|
|
201
|
+
|
|
202
|
+
The provider sets only ``version`` and reads options from ``[tool.setuptools-git-versioning]``.
|
|
203
|
+
Inline settings in ``[[tool.dynamic-metadata]]`` are not supported.
|
|
204
|
+
The provider itself has no runtime dependency on ``dynamic-metadata``.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
setuptools_git_versioning/__init__.py,sha256=HBPrkDXm4rugE32DxfzvPZwFkZodvB9d1Pt4m9MwmNw,1003
|
|
2
|
+
setuptools_git_versioning/__main__.py,sha256=6mSX6LsqmyKDEmobvZRfrxXO0kDuZH3aENzvxbunOtA,55
|
|
3
|
+
setuptools_git_versioning/archival.py,sha256=A9udXlJFsLHv2Vk7U6CP_jyv816NwPD6hie_fkloLY8,7524
|
|
4
|
+
setuptools_git_versioning/cli.py,sha256=DQ6_OFbKXUM30dnP0wWWJbAVjt5RIjxFxUw3sfdBtFs,1132
|
|
5
|
+
setuptools_git_versioning/defaults.py,sha256=b6v4LbK8Js_WQmsqzSouP2eTgc1TAttkM6sD1i1gFCI,822
|
|
6
|
+
setuptools_git_versioning/dynamic_metadata.py,sha256=IUNeuWpKmmjVDvB7yNY_8bTdCDaIw2DZM_Maty4twXM,1618
|
|
7
|
+
setuptools_git_versioning/factories.py,sha256=tGJpYVJeGJC2vE5mFvuoogl3sG0H3xJbkqpPApGZXjs,4462
|
|
8
|
+
setuptools_git_versioning/git.py,sha256=qjh-zQOx_nngl3HmlypG5kXb2vCjw75HC9IxKEUSqDY,3529
|
|
9
|
+
setuptools_git_versioning/log.py,sha256=R4VPodnnRkuybYc5L2CKENyTtESXedTyz3CvqxJCJPA,515
|
|
10
|
+
setuptools_git_versioning/scikit_metadata.py,sha256=9XeDmR163oBoEM8NtHpHNYmhT5EigC1VNlneEfV9MVU,1934
|
|
11
|
+
setuptools_git_versioning/setup.py,sha256=bQGeT96GFodgmemaOo19uuwyRiNIySleGDB1T46FQOY,5357
|
|
12
|
+
setuptools_git_versioning/subst.py,sha256=thLbkXUmUvsZR84o1S7D5uXsYmK4xSldGGPBGQdwccM,2174
|
|
13
|
+
setuptools_git_versioning/version.py,sha256=ZQtW-QolkWhc066V4wSwQ0tOhSRFb53xamzjs7uZMwg,9459
|
|
14
|
+
setuptools_git_versioning-3.2.0.dist-info/licenses/LICENSE,sha256=YP7W0rZutEgY8ypJZeFLuZDSYsaZC-P6YxGZDjiFuL4,1060
|
|
15
|
+
setuptools_git_versioning-3.2.0.dist-info/METADATA,sha256=pc4-IlDYGjHiIWXyZZy3hXoen9I8J1uF6RpkAAMc2n8,7066
|
|
16
|
+
setuptools_git_versioning-3.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
17
|
+
setuptools_git_versioning-3.2.0.dist-info/entry_points.txt,sha256=e-Eyt_a42w9hc-6tjRpitRnP4TxvlLwelNPI5k-jdEA,405
|
|
18
|
+
setuptools_git_versioning-3.2.0.dist-info/top_level.txt,sha256=aP9te4bjCBVXzZRQhwrT_IdcSxOe1Dd8Mb_oFCeNyEI,26
|
|
19
|
+
setuptools_git_versioning-3.2.0.dist-info/RECORD,,
|
|
@@ -4,5 +4,8 @@ setuptools-git-versioning = setuptools_git_versioning.cli:main
|
|
|
4
4
|
[distutils.setup_keywords]
|
|
5
5
|
setuptools_git_versioning = setuptools_git_versioning:parse_config
|
|
6
6
|
|
|
7
|
+
[dynamic_metadata.provider]
|
|
8
|
+
setuptools_git_versioning.dynamic_metadata = setuptools_git_versioning.dynamic_metadata
|
|
9
|
+
|
|
7
10
|
[setuptools.finalize_distribution_options]
|
|
8
11
|
setuptools_git_versioning = setuptools_git_versioning:infer_version
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
setuptools_git_versioning/__init__.py,sha256=7sEdMWbjUWJXVTeY_g1POOmwW8jBph58H6PbuaQ8PQY,857
|
|
2
|
-
setuptools_git_versioning/__main__.py,sha256=6mSX6LsqmyKDEmobvZRfrxXO0kDuZH3aENzvxbunOtA,55
|
|
3
|
-
setuptools_git_versioning/cli.py,sha256=DQ6_OFbKXUM30dnP0wWWJbAVjt5RIjxFxUw3sfdBtFs,1132
|
|
4
|
-
setuptools_git_versioning/defaults.py,sha256=PVsZd2w7pGi8jMIpnpkdlBoacDYypiG3bQK2Lh6FPBA,797
|
|
5
|
-
setuptools_git_versioning/factories.py,sha256=tGJpYVJeGJC2vE5mFvuoogl3sG0H3xJbkqpPApGZXjs,4462
|
|
6
|
-
setuptools_git_versioning/git.py,sha256=qjh-zQOx_nngl3HmlypG5kXb2vCjw75HC9IxKEUSqDY,3529
|
|
7
|
-
setuptools_git_versioning/log.py,sha256=R4VPodnnRkuybYc5L2CKENyTtESXedTyz3CvqxJCJPA,515
|
|
8
|
-
setuptools_git_versioning/setup.py,sha256=bQGeT96GFodgmemaOo19uuwyRiNIySleGDB1T46FQOY,5357
|
|
9
|
-
setuptools_git_versioning/subst.py,sha256=thLbkXUmUvsZR84o1S7D5uXsYmK4xSldGGPBGQdwccM,2174
|
|
10
|
-
setuptools_git_versioning/version.py,sha256=9D8_BOoTk9_o1WqNTZYPCK4tXd33Zx4OjCdHa7rdd30,8258
|
|
11
|
-
setuptools_git_versioning-3.0.1.dist-info/licenses/LICENSE,sha256=YP7W0rZutEgY8ypJZeFLuZDSYsaZC-P6YxGZDjiFuL4,1060
|
|
12
|
-
setuptools_git_versioning-3.0.1.dist-info/METADATA,sha256=3HPqdILZxsUZN7wNXiX-3o0k2l7NF1LDBonLPEP2Wxw,5951
|
|
13
|
-
setuptools_git_versioning-3.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
14
|
-
setuptools_git_versioning-3.0.1.dist-info/entry_points.txt,sha256=FU3QTN1qtkjTNeRGVcJZgo9jwV2z7syLEy3Fj9YUR9M,288
|
|
15
|
-
setuptools_git_versioning-3.0.1.dist-info/top_level.txt,sha256=aP9te4bjCBVXzZRQhwrT_IdcSxOe1Dd8Mb_oFCeNyEI,26
|
|
16
|
-
setuptools_git_versioning-3.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|