From 35f1681dc11a62633f29ba3470dbb8894f10d45d Mon Sep 17 00:00:00 2001 From: jack1142 <6032823+jack1142@users.noreply.github.com> Date: Sun, 3 Apr 2022 03:51:34 +0200 Subject: [PATCH] Include tag distance and commit hash in dev versions when possible (#5664) * Include tag distance and commit hash in dev versions when possible * Fix test --- .github/workflows/scripts/bump_version.py | 7 +++-- redbot/__init__.py | 32 ++++++++++++++++---- redbot/_version.py | 36 +++++++++++++++++++++++ setup.cfg | 1 - setup.py | 11 +++++-- tests/core/test_version.py | 4 +++ 6 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 redbot/_version.py diff --git a/.github/workflows/scripts/bump_version.py b/.github/workflows/scripts/bump_version.py index fed5dccfd..ee744a73f 100644 --- a/.github/workflows/scripts/bump_version.py +++ b/.github/workflows/scripts/bump_version.py @@ -4,10 +4,11 @@ import sys from typing import Match import redbot +from redbot._version import __version__ if int(os.environ.get("JUST_RETURN_VERSION", 0)): - print(f"::set-output name=version::{redbot.__version__}") + print(f"::set-output name=version::{__version__}") sys.exit(0) @@ -33,7 +34,7 @@ def repl(match: Match[str]) -> str: return f'__version__ = "{version_info}"' -with open("redbot/__init__.py", encoding="utf-8") as fp: +with open("redbot/_version.py", encoding="utf-8") as fp: new_contents, found = re.subn( pattern=r'^__version__ = "(?P[^"]*)"$', repl=repl, @@ -46,7 +47,7 @@ if not found: print("Couldn't find `__version__` line!") sys.exit(1) -with open("redbot/__init__.py", "w", encoding="utf-8", newline="\n") as fp: +with open("redbot/_version.py", "w", encoding="utf-8", newline="\n") as fp: fp.write(new_contents) print(f"::set-output name=new_version::{version_info}") diff --git a/redbot/__init__.py b/redbot/__init__.py index 18b9b35d7..ff5ea7eae 100644 --- a/redbot/__init__.py +++ b/redbot/__init__.py @@ -12,6 +12,8 @@ from typing import ( Union as _Union, ) +from redbot._version import _get_version + MIN_PYTHON_VERSION = (3, 8, 1) @@ -42,6 +44,7 @@ class VersionInfo: r"(?:(?Pa|b|rc)(?P0|[1-9]\d*))?" r"(?:\.post(?P0|[1-9]\d*))?" r"(?:\.dev(?P0|[1-9]\d*))?" + r"(?:\+(?Pg[a-z0-9]+(?:\.dirty)?))?" r"$", flags=_re.IGNORECASE, ) @@ -61,6 +64,7 @@ class VersionInfo: serial: _Optional[int] = None, post_release: _Optional[int] = None, dev_release: _Optional[int] = None, + local_version: _Optional[str] = None, ) -> None: self.major: int = major self.minor: int = minor @@ -73,6 +77,17 @@ class VersionInfo: self.serial: _Optional[int] = serial self.post_release: _Optional[int] = post_release self.dev_release: _Optional[int] = dev_release + self.local_version: _Optional[str] = local_version + + @property + def short_commit_hash(self) -> _Optional[str]: + if self.local_version is None: + return None + return self.local_version[1:].split(".", 1)[0] + + @property + def dirty(self) -> bool: + return self.local_version is not None and self.local_version.endswith(".dirty") @classmethod def from_str(cls, version_str: str) -> "VersionInfo": @@ -99,6 +114,7 @@ class VersionInfo: for key in ("serial", "post_release", "dev_release"): if match[key] is not None: kwargs[key] = int(match[key]) + kwargs["local_version"] = match["local_version"] return cls(**kwargs) @classmethod @@ -121,15 +137,18 @@ class VersionInfo: "serial": self.serial, "post_release": self.post_release, "dev_release": self.dev_release, + "local_version": self.local_version, } def _generate_comparison_tuples( self, other: "VersionInfo" ) -> _List[ - _Tuple[int, int, int, int, _Union[int, float], _Union[int, float], _Union[int, float]] + _Tuple[int, int, int, int, _Union[int, float], _Union[int, float], _Union[int, float], int] ]: tups: _List[ - _Tuple[int, int, int, int, _Union[int, float], _Union[int, float], _Union[int, float]] + _Tuple[ + int, int, int, int, _Union[int, float], _Union[int, float], _Union[int, float], int + ] ] = [] for obj in (self, other): tups.append( @@ -141,6 +160,7 @@ class VersionInfo: obj.serial if obj.serial is not None else _inf, obj.post_release if obj.post_release is not None else -_inf, obj.dev_release if obj.dev_release is not None else _inf, + int(obj.dirty), ) ) return tups @@ -168,14 +188,16 @@ class VersionInfo: ret += f".post{self.post_release}" if self.dev_release is not None: ret += f".dev{self.dev_release}" + if self.local_version is not None: + ret += f"+{self.local_version}" return ret def __repr__(self) -> str: return ( "VersionInfo(major={major}, minor={minor}, micro={micro}, " "releaselevel={releaselevel}, serial={serial}, post={post_release}, " - "dev={dev_release})".format(**self.to_json()) - ) + "dev={dev_release}, local={local_version})" + ).format(**self.to_json()) def _update_event_loop_policy(): @@ -223,7 +245,7 @@ def _early_init(): _ensure_no_colorama() -__version__ = "3.5.0.dev1" +__version__ = _get_version() version_info = VersionInfo.from_str(__version__) # Filter fuzzywuzzy slow sequence matcher warning diff --git a/redbot/_version.py b/redbot/_version.py new file mode 100644 index 000000000..8d455e47f --- /dev/null +++ b/redbot/_version.py @@ -0,0 +1,36 @@ +def _get_version(*, ignore_installed: bool = False) -> str: + if not __version__.endswith(".dev1"): + return __version__ + try: + import os + import subprocess + + path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + output = subprocess.check_output( + ("git", "describe", "--tags", "--long", "--dirty"), cwd=path + ) + _, count, commit, *dirty = output.decode("utf-8").strip().split("-", 3) + dirty_suffix = f".{dirty[0]}" if dirty else "" + return f"{__version__[:-1]}{count}+{commit}{dirty_suffix}" + except Exception: + # `ignore_installed` is `True` when building with setuptools. + if ignore_installed: + # we don't want any failure to raise here but we should print it + import traceback + + traceback.print_exc() + else: + try: + from importlib.metadata import version + + return version("Red-DiscordBot") + except Exception: + # we don't want any failure to raise here but we should print it + import traceback + + traceback.print_exc() + + return __version__ + + +__version__ = "3.5.0.dev1" diff --git a/setup.cfg b/setup.cfg index 5e9870412..935806314 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,5 @@ [metadata] name = Red-DiscordBot -version = attr: redbot.__version__ description = A highly customisable Discord bot license = GPL-3.0 long_description = file: README.md diff --git a/setup.py b/setup.py index ce0537a46..69e1d67e0 100644 --- a/setup.py +++ b/setup.py @@ -2,9 +2,16 @@ import os import sys from setuptools import setup +# Since we're importing `redbot` package, we have to ensure that it's in sys.path. +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) + +from redbot._version import _get_version + +version = _get_version(ignore_installed=True) + if os.getenv("TOX_RED", False) and sys.version_info >= (3, 10): # We want to be able to test Python versions that we do not support yet. - setup(python_requires=">=3.8.1") + setup(python_requires=">=3.8.1", version=version) else: # Metadata and options defined in setup.cfg - setup() + setup(version=version) diff --git a/tests/core/test_version.py b/tests/core/test_version.py index e5b210b18..06242cd27 100644 --- a/tests/core/test_version.py +++ b/tests/core/test_version.py @@ -20,6 +20,10 @@ version_tests = ( "3.0.0rc1.dev1", "3.0.0rc1", "3.0.0", + "3.0.1.dev1", + "3.0.1.dev2+gdbaf31e", + "3.0.1.dev2+gdbaf31e.dirty", + "3.0.1.dev3+gae98d77", "3.0.1", "3.0.1.post1.dev1", "3.0.1.post1",