Skip to content

Commit b9fe9aa

Browse files
committed
Add script for infering version from pyproject.toml
1 parent d5cc869 commit b9fe9aa

File tree

6 files changed

+108
-4
lines changed

6 files changed

+108
-4
lines changed

CHANGELOG.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ Changelog
44
1.10
55
----
66

7+
.. changelog::
8+
:version: 1.10.1
9+
10+
.. change::
11+
:tags: core, feature
12+
13+
Add ``setuptools-git-versioning`` script to infer version from ``pyproject.toml`` config
14+
715
.. changelog::
816
:version: 1.10.0
917
:released: 18.07.2022

README.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ Just add ``setuptools-git-versioning`` to ``build-sytem`` part of your ``pyproje
8585
[tool.setuptools-git-versioning]
8686
enabled = true
8787
88+
And check the package version generated:
89+
90+
.. code:: bash
91+
$ python -m setuptools_git_versioning
92+
0.0.1
93+
94+
# or
95+
96+
$ setuptools-git-versioning
97+
0.0.1
98+
8899
``setup.py``
89100
~~~~~~~~~~~~~~
90101

@@ -101,3 +112,9 @@ Just add ``setuptools-git-versioning`` to ``setup_requires`` part of your ``setu
101112
},
102113
setup_requires=["setuptools-git-versioning"],
103114
)
115+
116+
And check the package version generated:
117+
118+
.. code:: bash
119+
$ python setup.py --version
120+
0.0.1

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def parse_requirements(file_content):
5858
"setuptools.finalize_distribution_options": [
5959
"setuptools_git_versioning = setuptools_git_versioning:infer_version",
6060
],
61+
"console_scripts": ["setuptools-git-versioning=setuptools_git_versioning:__main__"],
6162
},
6263
include_package_data=True,
6364
zip_safe=False,

setuptools_git_versioning.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
import os
66
import re
77
import subprocess
8+
import textwrap
89
import warnings
910
from collections.abc import Mapping
1011
from datetime import datetime
11-
from distutils.errors import DistutilsSetupError
1212
from pathlib import Path
13-
from typing import Any, Callable
13+
from typing import TYPE_CHECKING, Any, Callable
1414

1515
from setuptools.dist import Distribution
1616

17+
if TYPE_CHECKING:
18+
from packaging.version import Version
19+
1720
DEFAULT_TEMPLATE = "{tag}"
1821
DEFAULT_DEV_TEMPLATE = "{tag}.post{ccount}+git.{sha}"
1922
DEFAULT_DIRTY_TEMPLATE = "{tag}.post{ccount}+git.{sha}.dirty"
@@ -146,6 +149,8 @@ def read_toml(file_name: str | os.PathLike) -> dict:
146149

147150
# TODO: remove along with version_config
148151
def parse_config(dist: Distribution, attr: Any, value: Any) -> None:
152+
from distutils.errors import DistutilsOptionError
153+
149154
if attr == "version_config" and value is not None:
150155
warnings.warn(
151156
"`version_config` option is deprecated "
@@ -156,14 +161,16 @@ def parse_config(dist: Distribution, attr: Any, value: Any) -> None:
156161
)
157162

158163
if getattr(dist, "setuptools_git_versioning", None) is not None:
159-
raise DistutilsSetupError(
164+
raise DistutilsOptionError(
160165
"You can set either `version_config` or `setuptools_git_versioning` "
161166
"but not both of them at the same time"
162167
)
163168

164169

165170
# real version is generated here
166171
def infer_version(dist: Distribution) -> None:
172+
from distutils.errors import DistutilsOptionError, DistutilsSetupError
173+
167174
value = getattr(dist, "setuptools_git_versioning", None) or getattr(dist, "version_config", None)
168175

169176
if isinstance(value, bool):
@@ -190,7 +197,7 @@ def infer_version(dist: Distribution) -> None:
190197
return
191198

192199
if not isinstance(value, Mapping):
193-
raise DistutilsSetupError(f"Wrong config format. Expected dict, got: {value}")
200+
raise DistutilsOptionError(f"Wrong config format. Expected dict, got: {value}")
194201

195202
if not value or not value.get("enabled", True):
196203
# Nothing to do here
@@ -439,3 +446,35 @@ def version_from_git(
439446
local_sanitized = LOCAL_REGEXP.sub(".", local)
440447
public_sanitized = VERSION_PREFIX_REGEXP.sub("", public) # for version "v1.0.0" drop leading "v" symbol
441448
return public_sanitized + sep + local_sanitized
449+
450+
451+
def main(config: dict | None = None) -> Version:
452+
value = config or read_toml("pyproject.toml")
453+
454+
if not value or not value.get("enabled", True):
455+
raise RuntimeError(
456+
textwrap.dedent(
457+
"""
458+
'setuptools-git-versioning' command can be used only with 'pyproject.toml'
459+
file setup (see https://setuptools-git-versioning.readthedocs.io/en/stable/install.html)
460+
""",
461+
),
462+
)
463+
464+
if not isinstance(value, Mapping):
465+
raise RuntimeError(f"Wrong config format. Expected dict, got: {value}")
466+
467+
config = load_config_from_dict(value)
468+
result = version_from_git(**config)
469+
470+
from packaging.version import Version
471+
472+
return Version(result)
473+
474+
475+
def __main__():
476+
print(main().public)
477+
478+
479+
if __name__ == "__main__":
480+
__main__()

tests/lib/util.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ def get_version_setup_py(cwd, **kwargs): # type: (str, **Any) -> str
256256
return execute(cwd, f"{sys.executable} setup.py --version", **kwargs).strip()
257257

258258

259+
def get_version_module(cwd, **kwargs): # type: (str, **Any) -> str
260+
return execute(cwd, f"{sys.executable} -m setuptools_git_versioning", **kwargs).strip()
261+
262+
263+
def get_version_script(cwd, **kwargs): # type: (str, **Any) -> str
264+
return execute(cwd, "setuptools-git-versioning", **kwargs).strip()
265+
266+
259267
def get_version(cwd, isolated=False, **kwargs): # type: (str, bool, **Any) -> str
260268
cmd = f"{sys.executable} -m build -s"
261269
if not isolated:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import pytest
2+
import subprocess
3+
4+
from tests.lib.util import get_version_script, get_version_module, create_pyproject_toml, create_setup_py
5+
6+
7+
def test_command_pyproject_toml(repo):
8+
create_pyproject_toml(repo)
9+
10+
assert get_version_module(repo) == "0.0.1"
11+
assert get_version_script(repo) == "0.0.1"
12+
13+
14+
def test_command_pyproject_toml_disabled(repo):
15+
create_pyproject_toml(repo, {"enabled": False})
16+
17+
with pytest.raises(subprocess.CalledProcessError):
18+
get_version_module(repo)
19+
20+
with pytest.raises(subprocess.CalledProcessError):
21+
get_version_script(repo)
22+
23+
24+
def test_command_setup_py_fail(repo):
25+
create_setup_py(repo)
26+
27+
with pytest.raises(subprocess.CalledProcessError):
28+
get_version_module(repo)
29+
30+
with pytest.raises(subprocess.CalledProcessError):
31+
get_version_script(repo)

0 commit comments

Comments
 (0)