From 89695decf680d187f47dccd38db2bcbff46dcf04 Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 08:54:24 +0000 Subject: [PATCH 01/30] add project files --- .project | 2 +- src/pygitversionhelper/__init__.py | 2 +- src/pygitversionhelper/gitversionhelper.py | 244 +++++++++++++++++++++ src/pygitversionhelper/test_module.py | 43 ---- test/test_gitversionhelper.py | 24 ++ test/test_test_module.py | 32 --- 6 files changed, 270 insertions(+), 77 deletions(-) create mode 100644 src/pygitversionhelper/gitversionhelper.py delete mode 100644 src/pygitversionhelper/test_module.py create mode 100644 test/test_gitversionhelper.py delete mode 100644 test/test_test_module.py diff --git a/.project b/.project index dc36649..abb1fea 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - {{project_name}} + gitversionhelper diff --git a/src/pygitversionhelper/__init__.py b/src/pygitversionhelper/__init__.py index 0ab7e56..19105bf 100644 --- a/src/pygitversionhelper/__init__.py +++ b/src/pygitversionhelper/__init__.py @@ -19,4 +19,4 @@ except PackageNotFoundError: # pragma: no cover warnings.warn("can not read __version__, assuming local test context, setting it to ?.?.?") __version__ = "?.?.?" -from .test_module import test_function +from .gitversionhelper import gitversionhelper diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py new file mode 100644 index 0000000..fbfa342 --- /dev/null +++ b/src/pygitversionhelper/gitversionhelper.py @@ -0,0 +1,244 @@ +from __future__ import annotations + +import os +import subprocess +from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN +import re +from dataclasses import dataclass +from copy import copy + +def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: + try: + stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) + except subprocess.CalledProcessError as e: + stdout = e.output + lines = stdout.splitlines() + return [line.rstrip() for line in lines if line.rstrip()] + +class gitversionhelper: + class head: + @classmethod + def isDirty(cls): + return True if _exec(f"git status --short") else False + + class tag: + __OptDict = {"same_branch": "same_branch"} + @classmethod + def getTags(cls,sort:str = "version:refname"): + return _exec(f"git tag -l --sort={sort}") + + @classmethod + def getLastTag(cls,**kwargs): + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]]==True)): + return _exec(f"git describe --tags --abbrev=0")[0] + else: + tag = _exec("git rev-list --tags --max-count=1") + return _exec(f"git describe --tags {tag[0]}")[0] + + @classmethod + def getDistanceFromLastTag(cls,tag=None,**kwargs): + if (tag == None): + tag = cls.getLastTag(**kwargs) + return _exec(f"git rev-list {tag}..HEAD --count")[0] + + class version: + __OptDict = { "version_std": "version_std", + "formated_output": "formated_output", + "output_format": "output_format"} + DefaultInputFormat = "PEP440" + VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"}, + "PEP440" : { "regex" : packaging_VERSION_PATTERN } + } + + class MetaVersion: + """ + generic version object + """ + __OptDict = { "bump_type": "bump_type", + "bump_dev_strategy": "bump_dev_strategy"} + DefaultBumpType = "patch" + BumpTypes = ["major","minor","patch","dev"] + DefaultBumpDevStrategy = "post" + BumpDevStrategys = ["post","pre","force_post","force_pre"] + major: int = 0 + minor: int = 1 + patch: int = 0 + pre_count:int = 0 + post_count:int = 0 + raw:str = "0.1.0" + + def __init__(self,major,minor,patch,pre_count,post_count,raw): + self.major,self.minor,self.patch,self.pre_count,self.post_count,self.raw = major,minor,patch,pre_count,post_count,raw + + @classmethod + def _getBumpDevStrategy(cls,**kwargs): + """ + get selected bump_dev_strategy + """ + BumpDevStrategy = cls.DefaultBumpDevStrategy + if (cls.__OptDict["bump_dev_strategy"] in kwargs): + if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: + BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] + else: + raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") + return BumpDevStrategy + + @classmethod + def _getBumpType(cls,**kwargs): + """ + get selected bump_type + """ + BumpType = cls.DefaultBumpType + if (cls.__OptDict["bump_type"] in kwargs): + if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: + BumpType = kwargs[cls.__OptDict["bump_type"]] + else: + raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") + return BumpType + + def bump(self,**kwargs): + BumpType = self._getBumpType(**kwargs) + BumpDevStrategy=self._getBumpDevStrategy(**kwargs) + _v=copy(self) + if BumpType == "dev": + if BumpDevStrategy=="post": + if _v.pre_count > 0: + _v.pre_count = _v.pre_count + 1 + else: + _v.post_count = _v.post_count + 1 + elif BumpDevStrategy=="pre": + if _v.post_count > 0: + _v.post_count = _v.post_count + 1 + else: + _v.pre_count = _v.pre_count + 1 + elif BumpDevStrategy=="force_post": + pass + elif BumpDevStrategy=="force_pre": + pass + else: + if BumpType == "major": + _v.major = _v.major + 1 + elif BumpType == "minor": + _v.minor = _v.minor + 1 + elif BumpType == "patch": + _v.patch = _v.patch + 1 + _v.pre_count=0 + _v.post_count=0 + + _v.raw="{major}.{minor}.{patch}".format(major=_v.major,minor=_v.minor,patch=_v.patch,revpattern="",revcount="") + return _v + + def doFormatVersion(self,**kwargs): + return gitversionhelper.version.doFormatVersion(self,**kwargs) + + @classmethod + def _getVersionStd(cls,**kwargs): + """ + get selected version_std + """ + VersionStd = cls.DefaultInputFormat + if (cls.__OptDict["version_std"] in kwargs): + if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: + VersionStd = kwargs[cls.__OptDict["version_std"]] + else: + raise RuntimeError(f"invalid {cls.__OptDict['version_std']} requested") + return VersionStd + + @classmethod + def getLastVersion(cls,**kwargs): + """ + get last version from git tags + """ + VersionStd = cls._getVersionStd(**kwargs) + _r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | re.IGNORECASE) + + lastTag = gitversionhelper.tag.getLastTag(**kwargs) + + _m = re.match(_r,lastTag) + if not _m: + raise RuntimeError("no valid version found in tags") + if VersionStd == "PEP440": + ver=_m.group("release").split(".") + ver += ["0"] * (3 - len(ver)) + ver[0]=int(ver[0]) + ver[1]=int(ver[1]) + ver[2]=int(ver[2]) + major, minor, patch = tuple(ver) + pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 + post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 + elif VersionStd == "SemVer": + major, minor, patch = int(_m.group("major")),int(_m.group("minor")),int(_m.group("patch")),(_m.group("prerelease") if _m.group("prerelease") else ""), "" + pre_count = 0 + post_count = 0 + + _v = cls.MetaVersion(major, minor, patch, pre_count, post_count, lastTag) + + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]]==True)): + return cls.doFormatVersion(_v,**kwargs) + else: + return _v + + @classmethod + def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): + """ + output a formated version + """ + VersionStd = cls._getVersionStd(**kwargs) + + OutputFormat = None + revpattern="" + revcount="" + post_count = inputversion.post_count + pre_count = inputversion.pre_count + patch = inputversion.patch + if (cls.__OptDict["output_format"] in kwargs): + OutputFormat=kwargs[cls.__OptDict["output_format"]] + if OutputFormat == None: + if VersionStd == "PEP440": + OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" + if post_count > 0: + revpattern=".post" + revcount=f"{post_count}" + elif VersionStd == "SemVer": + OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" + if post_count > 0: + pre_count = pre_count + post_count + post_count = 0 + patch = patch + 1 + if pre_count > 0: + revpattern="-pre" + revcount=f"{pre_count}" + + return OutputFormat.format(major=inputversion.major,minor=inputversion.minor,patch=patch,revpattern=revpattern,revcount=revcount) + + + + + +#print(gitversionhelper.head.isDirty()) +#print(gitversionhelper.tag.getTags()) +#print(gitversionhelper.tag.getLastTag()) +#print(gitversionhelper.tag.getLastTag(same_branch=True)) +#print(gitversionhelper.tag.getDistanceFromLastTag()) +#print(gitversionhelper.tag.getDistanceFromLastTag(same_branch=True)) + +#print(gitversionhelper.version.getLastVersion()) +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440",formated_output=True)) +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440",formated_output=True,output_format="v{major}.{minor}.{patch}")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump()) +#print("") +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="SemVer")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="patch").doFormatVersion(version_std="SemVer")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="minor").doFormatVersion(version_std="SemVer")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="major").doFormatVersion(version_std="SemVer")) +#print("") +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="patch").doFormatVersion(version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="minor").doFormatVersion(version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="major").doFormatVersion(version_std="PEP440")) + +#from setuptools_git_versioning import version_from_git +#print(str(version_from_git(tag_filter="^\d+\.\d+\.\d+$",dev_template = "{tag}.post{ccount}",sort_by="v:refname")),end ="") diff --git a/src/pygitversionhelper/test_module.py b/src/pygitversionhelper/test_module.py deleted file mode 100644 index 7a9bff5..0000000 --- a/src/pygitversionhelper/test_module.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# pygitversionhelper (c) by chacha -# -# pygitversionhelper is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -"""Phasellus tellus lectus, volutpat eu dapibus ut, suscipit vel augue. - -Tips: - Aliquam non leo vel libero sagittis viverra. Quisque lobortis nunc sit amet augue euismod laoreet. -Note: - Maecenas volutpat porttitor pretium. Aliquam suscipit quis nisi non imperdiet. -Note: - Vivamus et efficitur lorem, eget imperdiet tortor. Integer vel interdum sem. -""" - -from __future__ import annotations -from typing import TYPE_CHECKING - -if TYPE_CHECKING: # Only imports the below statements during type checking - pass - -def test_function(testvar: int) -> int: - """ A test function that return testvar+1 and print "Hello world !" - - Proin eget sapien eget ipsum efficitur mollis nec ac nibh. - - Note: - Morbi id lectus maximus, condimentum nunc eget, porta felis. In tristique velit tortor. - - Args: - testvar: any integer - - Returns: - testvar+1 - """ - print("Hello world !") - return testvar+1 diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py new file mode 100644 index 0000000..9708dc5 --- /dev/null +++ b/test/test_gitversionhelper.py @@ -0,0 +1,24 @@ +# pygitversionhelper (c) by chacha +# +# pygitversionhelper is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. +# +# You should have received a copy of the license along with this +# work. If not, see . + +import unittest +from io import StringIO +from contextlib import redirect_stdout,redirect_stderr + +print(__name__) +print(__package__) + +from src import pygitversionhelper + +class Test_gitversionhelper(unittest.TestCase): + def test_version(self): + version = pygitversionhelper.gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="SemVer") + self.assertNotEqual(version,"?.?.?") + + + \ No newline at end of file diff --git a/test/test_test_module.py b/test/test_test_module.py deleted file mode 100644 index add530e..0000000 --- a/test/test_test_module.py +++ /dev/null @@ -1,32 +0,0 @@ -# pygitversionhelper (c) by chacha -# -# pygitversionhelper is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -import unittest -from io import StringIO -from contextlib import redirect_stdout,redirect_stderr - -print(__name__) -print(__package__) - -from src import pygitversionhelper - -class Testtest_module(unittest.TestCase): - def test_version(self): - self.assertNotEqual(pygitversionhelper.__version__,"?.?.?") - - def test_test_module(self): - - with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr: - self.assertEqual(pygitversionhelper.test_function(41),42) - - self.assertEqual(len(capted_stderr.getvalue()),0) - self.assertEqual(capted_stdout.getvalue().strip(),"Hello world !") - self.assertEqual(len(capted_stderr.getvalue()),0) - - - \ No newline at end of file -- 2.47.3 From 70a1c6ef8c76e19b507ce4dfc436dfc24acee41c Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 18:09:34 +0000 Subject: [PATCH 02/30] start fixing pylint warnings + add docstrings --- src/pygitversionhelper/gitversionhelper.py | 102 ++++++++++++++++++--- 1 file changed, 88 insertions(+), 14 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index fbfa342..bf3fd0b 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -1,13 +1,26 @@ from __future__ import annotations +from typing import TYPE_CHECKING import os import subprocess -from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN import re -from dataclasses import dataclass from copy import copy +from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN + +if TYPE_CHECKING: # Only imports the below statements during type checking + from typing import Union + def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: + """ + Helper function to handle system cmd execution + Args: + cmd: command line to be executed + root: root directory where the command need to be executed + Return: + a list of command's return lines + + """ try: stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) except subprocess.CalledProcessError as e: @@ -15,20 +28,53 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: lines = stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] -class gitversionhelper: - class head: +class gitversionhelper: # pylint: disable=too-few-public-methods + """ + Main gitversionhelper class + """ + class repository: + """ + class containing methods focusing on repository + """ @classmethod - def isDirty(cls): + def isDirty(cls) -> bool: + """ + Check if the repository is in dirty state + Return: + True if it is dirty + """ return True if _exec(f"git status --short") else False class tag: + """ + class containing methods focusing on tags + """ __OptDict = {"same_branch": "same_branch"} + __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] @classmethod - def getTags(cls,sort:str = "version:refname"): + def getTags(cls,sort:str = "version:refname") -> list[str]: + """ + retrieve all tags from a repository + Args: + sort: sorting constraints (git format) + Return: + the tags list + """ + if sort not in cls.__validGitTagSort: + raise RuntimeError("sort option not in allowed list") return _exec(f"git tag -l --sort={sort}") @classmethod - def getLastTag(cls,**kwargs): + def getLastTag(cls,**kwargs) -> Union[str,None]: + f""" + retrieve the last tag from a repository + Arguments: + sort: sorting constraints (git format) + Kwargs: + {cls.__OptDict["same_branch"]}: force searching only in the same branch + Return: + the tag + """ if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]]==True)): return _exec(f"git describe --tags --abbrev=0")[0] else: @@ -36,12 +82,24 @@ class gitversionhelper: return _exec(f"git describe --tags {tag[0]}")[0] @classmethod - def getDistanceFromLastTag(cls,tag=None,**kwargs): + def getDistanceFromTag(cls,tag=None,**kwargs) -> int: + f""" + retrieve the distance from tag in the repository + Arguments: + tag: reference tag, if None the most recent one will be used + Kwargs: + {cls.__OptDict["same_branch"]}: force searching only in the same branch + Return: + the tag + """ if (tag == None): tag = cls.getLastTag(**kwargs) - return _exec(f"git rev-list {tag}..HEAD --count")[0] + return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) class version: + """ + class containing methods focusing on versions + """ __OptDict = { "version_std": "version_std", "formated_output": "formated_output", "output_format": "output_format"} @@ -54,7 +112,7 @@ class gitversionhelper: """ generic version object """ - __OptDict = { "bump_type": "bump_type", + __OptDict = { "bump_type": "bump_type", "bump_dev_strategy": "bump_dev_strategy"} DefaultBumpType = "patch" BumpTypes = ["major","minor","patch","dev"] @@ -71,9 +129,13 @@ class gitversionhelper: self.major,self.minor,self.patch,self.pre_count,self.post_count,self.raw = major,minor,patch,pre_count,post_count,raw @classmethod - def _getBumpDevStrategy(cls,**kwargs): - """ + def _getBumpDevStrategy(cls,**kwargs) -> str: + f""" get selected bump_dev_strategy + Kwargs: + {cls.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) + Return: + Kwargs given {cls.__OptDict["bump_dev_strategy"]} or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy if (cls.__OptDict["bump_dev_strategy"] in kwargs): @@ -84,9 +146,13 @@ class gitversionhelper: return BumpDevStrategy @classmethod - def _getBumpType(cls,**kwargs): - """ + def _getBumpType(cls,**kwargs) -> str: + f""" get selected bump_type + Kwargs: + {cls.__OptDict["bump_type"]}: the given bump_type (can be None) + Return: + Kwargs given {cls.__OptDict["bump_type"]} or the default one. """ BumpType = cls.DefaultBumpType if (cls.__OptDict["bump_type"] in kwargs): @@ -97,6 +163,14 @@ class gitversionhelper: return BumpType def bump(self,**kwargs): + f""" + bump the version to the next one + Kwargs: + {cls.__OptDict["bump_type"]}: the given bump_type (can be None) + {cls.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) + Return: + the bumped version + """ BumpType = self._getBumpType(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs) _v=copy(self) -- 2.47.3 From 525200b1fcfe35c5c76c90ce822ddb2557e9c3ea Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 18:26:11 +0000 Subject: [PATCH 03/30] trial fix tag_filter --- pyproject.toml | 2 +- src/pygitversionhelper/gitversionhelper.py | 43 +++++++++++----------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 67182a2..5d00a65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] enabled = true dev_template = "{tag}.post{ccount}" -#tag_filter = "^\\d+\\.\\d+\\.\\d+$" +tag_filter = "^\\d+\\.\\d+\\.\\d+$" [project] name = "pygitversionhelper" diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index bf3fd0b..16db1e6 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -75,11 +75,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: the tag """ - if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]]==True)): - return _exec(f"git describe --tags --abbrev=0")[0] - else: - tag = _exec("git rev-list --tags --max-count=1") - return _exec(f"git describe --tags {tag[0]}")[0] + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + return _exec("git describe --tags --abbrev=0")[0] + tag = _exec("git rev-list --tags --max-count=1") + return _exec(f"git describe --tags {tag[0]}")[0] @classmethod def getDistanceFromTag(cls,tag=None,**kwargs) -> int: @@ -92,7 +91,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: the tag """ - if (tag == None): + if (tag is None): tag = cls.getLastTag(**kwargs) return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) @@ -125,7 +124,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count:int = 0 raw:str = "0.1.0" - def __init__(self,major,minor,patch,pre_count,post_count,raw): + def __init__(self,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): self.major,self.minor,self.patch,self.pre_count,self.post_count,self.raw = major,minor,patch,pre_count,post_count,raw @classmethod @@ -174,32 +173,32 @@ class gitversionhelper: # pylint: disable=too-few-public-methods BumpType = self._getBumpType(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs) _v=copy(self) - if BumpType == "dev": - if BumpDevStrategy=="post": + if BumpType is "dev": + if BumpDevStrategy is "post": if _v.pre_count > 0: _v.pre_count = _v.pre_count + 1 else: _v.post_count = _v.post_count + 1 - elif BumpDevStrategy=="pre": + elif BumpDevStrategy is "pre": if _v.post_count > 0: _v.post_count = _v.post_count + 1 else: _v.pre_count = _v.pre_count + 1 - elif BumpDevStrategy=="force_post": + elif BumpDevStrategy is "force_post": pass - elif BumpDevStrategy=="force_pre": + elif BumpDevStrategy is "force_pre": pass else: - if BumpType == "major": + if BumpType is "major": _v.major = _v.major + 1 - elif BumpType == "minor": + elif BumpType is "minor": _v.minor = _v.minor + 1 - elif BumpType == "patch": + elif BumpType is "patch": _v.patch = _v.patch + 1 _v.pre_count=0 _v.post_count=0 - _v.raw="{major}.{minor}.{patch}".format(major=_v.major,minor=_v.minor,patch=_v.patch,revpattern="",revcount="") + _v.raw="{major}.{minor}.{patch}{revpattern}{revcount}".format(major=_v.major,minor=_v.minor,patch=_v.patch,revpattern="",revcount="") return _v def doFormatVersion(self,**kwargs): @@ -231,7 +230,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _m = re.match(_r,lastTag) if not _m: raise RuntimeError("no valid version found in tags") - if VersionStd == "PEP440": + if VersionStd is "PEP440": ver=_m.group("release").split(".") ver += ["0"] * (3 - len(ver)) ver[0]=int(ver[0]) @@ -240,14 +239,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods major, minor, patch = tuple(ver) pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 - elif VersionStd == "SemVer": + elif VersionStd is "SemVer": major, minor, patch = int(_m.group("major")),int(_m.group("minor")),int(_m.group("patch")),(_m.group("prerelease") if _m.group("prerelease") else ""), "" pre_count = 0 post_count = 0 _v = cls.MetaVersion(major, minor, patch, pre_count, post_count, lastTag) - if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]]==True)): + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return cls.doFormatVersion(_v,**kwargs) else: return _v @@ -267,13 +266,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods patch = inputversion.patch if (cls.__OptDict["output_format"] in kwargs): OutputFormat=kwargs[cls.__OptDict["output_format"]] - if OutputFormat == None: - if VersionStd == "PEP440": + if OutputFormat is None: + if VersionStd is "PEP440": OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0: revpattern=".post" revcount=f"{post_count}" - elif VersionStd == "SemVer": + elif VersionStd is "SemVer": OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0: pre_count = pre_count + post_count -- 2.47.3 From 2d718d2e4c04adf101ab0bfb26a5d8a5a3c098c4 Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 18:32:38 +0000 Subject: [PATCH 04/30] fix: wrong cls usage in self class --- src/pygitversionhelper/gitversionhelper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 16db1e6..502d2ff 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -165,8 +165,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods f""" bump the version to the next one Kwargs: - {cls.__OptDict["bump_type"]}: the given bump_type (can be None) - {cls.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) + {self.__OptDict["bump_type"]}: the given bump_type (can be None) + {self.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) Return: the bumped version """ -- 2.47.3 From c0d5e4480cf86eb79d9f8adda9d5a32a4aec75f4 Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 18:48:18 +0000 Subject: [PATCH 05/30] fix: code quality --- src/pygitversionhelper/gitversionhelper.py | 84 ++++++++++++++-------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 502d2ff..6f60596 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -1,3 +1,16 @@ +# pygitversionhelper (c) by chacha +# +# pygitversionhelper is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. +# +# You should have received a copy of the license along with this +# work. If not, see . + +""" +This module is the main gitversionhelper file, containing all the code. +This project aim to be kept compact and focused on helping doing handy things with git when it deal with project versions/tags. +""" + from __future__ import annotations from typing import TYPE_CHECKING @@ -28,7 +41,7 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: lines = stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] -class gitversionhelper: # pylint: disable=too-few-public-methods +class gitversionhelper: # pylint: disable=too-few-public-methods """ Main gitversionhelper class """ @@ -66,12 +79,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def getLastTag(cls,**kwargs) -> Union[str,None]: - f""" + """ retrieve the last tag from a repository - Arguments: - sort: sorting constraints (git format) Kwargs: - {cls.__OptDict["same_branch"]}: force searching only in the same branch + same_branch(bool): force searching only in the same branch Return: the tag """ @@ -82,12 +93,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def getDistanceFromTag(cls,tag=None,**kwargs) -> int: - f""" + """ retrieve the distance from tag in the repository Arguments: tag: reference tag, if None the most recent one will be used Kwargs: - {cls.__OptDict["same_branch"]}: force searching only in the same branch + same_branch(bool): force searching only in the same branch Return: the tag """ @@ -103,7 +114,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods "formated_output": "formated_output", "output_format": "output_format"} DefaultInputFormat = "PEP440" - VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"}, + VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)"\ + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"\ + r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"\ + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"}, "PEP440" : { "regex" : packaging_VERSION_PATTERN } } @@ -129,12 +143,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def _getBumpDevStrategy(cls,**kwargs) -> str: - f""" + """ get selected bump_dev_strategy Kwargs: - {cls.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) + bump_dev_strategy(str): the given bump_dev_strategy (can be None) Return: - Kwargs given {cls.__OptDict["bump_dev_strategy"]} or the default one. + Kwargs given bump_dev_strategy or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy if (cls.__OptDict["bump_dev_strategy"] in kwargs): @@ -146,12 +160,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def _getBumpType(cls,**kwargs) -> str: - f""" + """ get selected bump_type Kwargs: - {cls.__OptDict["bump_type"]}: the given bump_type (can be None) + bump_type(str): the given bump_type (can be None) Return: - Kwargs given {cls.__OptDict["bump_type"]} or the default one. + Kwargs given bump_type or the default one. """ BumpType = cls.DefaultBumpType if (cls.__OptDict["bump_type"] in kwargs): @@ -162,38 +176,38 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return BumpType def bump(self,**kwargs): - f""" + """ bump the version to the next one Kwargs: - {self.__OptDict["bump_type"]}: the given bump_type (can be None) - {self.__OptDict["bump_dev_strategy"]}: the given bump_dev_strategy (can be None) + bump_type(str): the given bump_type (can be None) + bump_dev_strategy(str): the given bump_dev_strategy (can be None) Return: the bumped version """ BumpType = self._getBumpType(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs) _v=copy(self) - if BumpType is "dev": - if BumpDevStrategy is "post": + if BumpType == "dev": + if BumpDevStrategy == "post": if _v.pre_count > 0: _v.pre_count = _v.pre_count + 1 else: _v.post_count = _v.post_count + 1 - elif BumpDevStrategy is "pre": + elif BumpDevStrategy == "pre": if _v.post_count > 0: _v.post_count = _v.post_count + 1 else: _v.pre_count = _v.pre_count + 1 - elif BumpDevStrategy is "force_post": + elif BumpDevStrategy == "force_post": pass - elif BumpDevStrategy is "force_pre": + elif BumpDevStrategy == "force_pre": pass else: - if BumpType is "major": + if BumpType == "major": _v.major = _v.major + 1 - elif BumpType is "minor": + elif BumpType == "minor": _v.minor = _v.minor + 1 - elif BumpType is "patch": + elif BumpType == "patch": _v.patch = _v.patch + 1 _v.pre_count=0 _v.post_count=0 @@ -208,6 +222,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def _getVersionStd(cls,**kwargs): """ get selected version_std + Kwargs: + version_std(str): the given version_std (can be None) + Return: + Kwargs given version_std or the default one. """ VersionStd = cls.DefaultInputFormat if (cls.__OptDict["version_std"] in kwargs): @@ -218,9 +236,15 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return VersionStd @classmethod - def getLastVersion(cls,**kwargs): + def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: """ - get last version from git tags + bump the last version from tags + Kwargs: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + Return: + the last version """ VersionStd = cls._getVersionStd(**kwargs) _r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | re.IGNORECASE) @@ -254,7 +278,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): """ - output a formated version + output a formated version string + Args: + inputversion: version to be rendered + Return: + formated version string """ VersionStd = cls._getVersionStd(**kwargs) -- 2.47.3 From 46ee6dec57bc2ad97284a38df65be13a650d85df Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 18:54:36 +0000 Subject: [PATCH 06/30] fix: quality score --- src/pygitversionhelper/gitversionhelper.py | 43 ++++++++++++++-------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 6f60596..942d06c 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -8,7 +8,8 @@ """ This module is the main gitversionhelper file, containing all the code. -This project aim to be kept compact and focused on helping doing handy things with git when it deal with project versions/tags. +This project aim to be kept compact and focused on helping doing handy +things with git when it deal with project versions/tags. """ from __future__ import annotations @@ -56,8 +57,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: True if it is dirty """ - return True if _exec(f"git status --short") else False - + return True if _exec("git status --short") else False + class tag: """ class containing methods focusing on tags @@ -102,7 +103,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: the tag """ - if (tag is None): + if tag is None: tag = cls.getLastTag(**kwargs) return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) @@ -139,7 +140,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raw:str = "0.1.0" def __init__(self,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): - self.major,self.minor,self.patch,self.pre_count,self.post_count,self.raw = major,minor,patch,pre_count,post_count,raw + self.major = major + self.minor = minor + self.patch = patch + self.pre_count = pre_count + self.post_count = post_count + self.raw = raw @classmethod def _getBumpDevStrategy(cls,**kwargs) -> str: @@ -212,7 +218,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v.pre_count=0 _v.post_count=0 - _v.raw="{major}.{minor}.{patch}{revpattern}{revcount}".format(major=_v.major,minor=_v.minor,patch=_v.patch,revpattern="",revcount="") + _v.raw="{major}.{minor}.{patch}{revpattern}{revcount}".format(major=_v.major,\ + minor=_v.minor,\ + patch=_v.patch,\ + revpattern="",\ + revcount="") return _v def doFormatVersion(self,**kwargs): @@ -228,7 +238,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given version_std or the default one. """ VersionStd = cls.DefaultInputFormat - if (cls.__OptDict["version_std"] in kwargs): + if cls.__OptDict["version_std"] in kwargs: if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: VersionStd = kwargs[cls.__OptDict["version_std"]] else: @@ -247,14 +257,15 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the last version """ VersionStd = cls._getVersionStd(**kwargs) - _r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | re.IGNORECASE) + _r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | \ + re.IGNORECASE) lastTag = gitversionhelper.tag.getLastTag(**kwargs) _m = re.match(_r,lastTag) if not _m: raise RuntimeError("no valid version found in tags") - if VersionStd is "PEP440": + if VersionStd == "PEP440": ver=_m.group("release").split(".") ver += ["0"] * (3 - len(ver)) ver[0]=int(ver[0]) @@ -263,8 +274,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods major, minor, patch = tuple(ver) pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 - elif VersionStd is "SemVer": - major, minor, patch = int(_m.group("major")),int(_m.group("minor")),int(_m.group("patch")),(_m.group("prerelease") if _m.group("prerelease") else ""), "" + elif VersionStd == "SemVer": + major, minor, patch = int(_m.group("major")),\ + int(_m.group("minor")),\ + int(_m.group("patch")),\ + (_m.group("prerelease") if _m.group("prerelease") else ""), "" pre_count = 0 post_count = 0 @@ -272,8 +286,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return cls.doFormatVersion(_v,**kwargs) - else: - return _v + return _v @classmethod def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): @@ -295,12 +308,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if (cls.__OptDict["output_format"] in kwargs): OutputFormat=kwargs[cls.__OptDict["output_format"]] if OutputFormat is None: - if VersionStd is "PEP440": + if VersionStd == "PEP440": OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0: revpattern=".post" revcount=f"{post_count}" - elif VersionStd is "SemVer": + elif VersionStd == "SemVer": OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0: pre_count = pre_count + post_count -- 2.47.3 From b74269b39be96d73a0a793b27f7b0727d03c2a05 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 00:10:00 +0000 Subject: [PATCH 07/30] more tests and features --- src/pygitversionhelper/__init__.py | 2 +- src/pygitversionhelper/gitversionhelper.py | 264 +++++--- test/test_gitversionhelper.py | 675 ++++++++++++++++++++- 3 files changed, 847 insertions(+), 94 deletions(-) diff --git a/src/pygitversionhelper/__init__.py b/src/pygitversionhelper/__init__.py index 19105bf..ed207f0 100644 --- a/src/pygitversionhelper/__init__.py +++ b/src/pygitversionhelper/__init__.py @@ -19,4 +19,4 @@ except PackageNotFoundError: # pragma: no cover warnings.warn("can not read __version__, assuming local test context, setting it to ?.?.?") __version__ = "?.?.?" -from .gitversionhelper import gitversionhelper +from .gitversionhelper import gitversionhelper, gitversionhelperException diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 942d06c..e97936c 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -19,12 +19,13 @@ import os import subprocess import re from copy import copy +import logging from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN if TYPE_CHECKING: # Only imports the below statements during type checking from typing import Union - + def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: """ Helper function to handle system cmd execution @@ -42,14 +43,23 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: lines = stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] +class gitversionhelperException(Exception): + pass + class gitversionhelper: # pylint: disable=too-few-public-methods """ Main gitversionhelper class """ + class wrongArguments(gitversionhelperException): + pass class repository: """ class containing methods focusing on repository """ + class repositoryException(gitversionhelperException): + pass + class repositoryDirty(repositoryException): + pass @classmethod def isDirty(cls) -> bool: """ @@ -65,6 +75,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ __OptDict = {"same_branch": "same_branch"} __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] + + class tagException(gitversionhelperException): + pass + class tagNotFound(tagException): + pass + class moreThanOneTag(tagException): + pass + @classmethod def getTags(cls,sort:str = "version:refname") -> list[str]: """ @@ -75,7 +93,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the tags list """ if sort not in cls.__validGitTagSort: - raise RuntimeError("sort option not in allowed list") + raise gitversionhelper.wrongArguments("sort option not in allowed list") return _exec(f"git tag -l --sort={sort}") @classmethod @@ -88,14 +106,22 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the tag """ if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): - return _exec("git describe --tags --abbrev=0")[0] - tag = _exec("git rev-list --tags --max-count=1") - return _exec(f"git describe --tags {tag[0]}")[0] + res = _exec("git describe --tags --abbrev=0") + else: + res = _exec("git rev-list --tags --max-count=1") + if len(res)==1: + res = _exec(f"git describe --tags {res[0]}") + + if len(res)==0: + raise cls.tagNotFound("no tag found in commit history") + elif len(res)!=1: + raise cls.MoreThanOneTag("multiple tags on same commit is unsupported") + return res[0] @classmethod def getDistanceFromTag(cls,tag=None,**kwargs) -> int: """ - retrieve the distance from tag in the repository + retrieve the distance between HEAD and tag in the repository Arguments: tag: reference tag, if None the most recent one will be used Kwargs: @@ -114,24 +140,36 @@ class gitversionhelper: # pylint: disable=too-few-public-methods __OptDict = { "version_std": "version_std", "formated_output": "formated_output", "output_format": "output_format"} - DefaultInputFormat = "PEP440" + DefaultInputFormat = "Auto" VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)"\ r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"\ r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"\ - r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"}, - "PEP440" : { "regex" : packaging_VERSION_PATTERN } + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", + "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", + "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" + + }, + "PEP440" : { "regex" : packaging_VERSION_PATTERN, + "Auto" : None + } } + class versionException(gitversionhelperException): + pass + class noValidVersion(versionException): + pass class MetaVersion: """ generic version object """ - __OptDict = { "bump_type": "bump_type", - "bump_dev_strategy": "bump_dev_strategy"} + __OptDict = { "bump_type": "bump_type", + "bump_dev_strategy": "bump_dev_strategy"} DefaultBumpType = "patch" BumpTypes = ["major","minor","patch","dev"] DefaultBumpDevStrategy = "post" - BumpDevStrategys = ["post","pre","force_post","force_pre"] + BumpDevStrategys = ["post","pre-patch","pre-minor","pre-major"] + version_std = "None" + major: int = 0 minor: int = 1 patch: int = 0 @@ -139,13 +177,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count:int = 0 raw:str = "0.1.0" - def __init__(self,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): - self.major = major - self.minor = minor - self.patch = patch - self.pre_count = pre_count - self.post_count = post_count - self.raw = raw + def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): + self.version_std = version_std + self.major = major + self.minor = minor + self.patch = patch + self.pre_count = pre_count + self.post_count = post_count + self.raw = raw @classmethod def _getBumpDevStrategy(cls,**kwargs) -> str: @@ -161,7 +200,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] else: - raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpDevStrategy @classmethod @@ -178,10 +217,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: BumpType = kwargs[cls.__OptDict["bump_type"]] else: - raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - def bump(self,**kwargs): + def bump(self,amount:int=1,**kwargs): """ bump the version to the next one Kwargs: @@ -193,36 +232,39 @@ class gitversionhelper: # pylint: disable=too-few-public-methods BumpType = self._getBumpType(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs) _v=copy(self) + if BumpType == "dev": if BumpDevStrategy == "post": if _v.pre_count > 0: - _v.pre_count = _v.pre_count + 1 + _v.pre_count = _v.pre_count + amount else: - _v.post_count = _v.post_count + 1 - elif BumpDevStrategy == "pre": + _v.post_count = _v.post_count + amount + elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]: if _v.post_count > 0: - _v.post_count = _v.post_count + 1 + _v.post_count = _v.post_count + amount else: - _v.pre_count = _v.pre_count + 1 - elif BumpDevStrategy == "force_post": - pass - elif BumpDevStrategy == "force_pre": - pass + if _v.pre_count == 0: + if BumpDevStrategy == "pre-patch": + _v.patch = _v.patch + 1 + elif BumpDevStrategy == "pre-minor": + _v.minor = _v.minor + 1 + _v.patch = 0 + elif BumpDevStrategy == "pre-major": + _v.major = _v.major + 1 + _v.minor = 0 + _v.patch = 0 + _v.pre_count = _v.pre_count + amount else: if BumpType == "major": - _v.major = _v.major + 1 + _v.major = _v.major + amount elif BumpType == "minor": - _v.minor = _v.minor + 1 + _v.minor = _v.minor + amount elif BumpType == "patch": - _v.patch = _v.patch + 1 + _v.patch = _v.patch + amount _v.pre_count=0 _v.post_count=0 - _v.raw="{major}.{minor}.{patch}{revpattern}{revcount}".format(major=_v.major,\ - minor=_v.minor,\ - patch=_v.patch,\ - revpattern="",\ - revcount="") + _v.raw=_v.doFormatVersion(**kwargs) return _v def doFormatVersion(self,**kwargs): @@ -242,9 +284,23 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: VersionStd = kwargs[cls.__OptDict["version_std"]] else: - raise RuntimeError(f"invalid {cls.__OptDict['version_std']} requested") + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['version_std']} requested") return VersionStd + @classmethod + def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: + if gitversionhelper.repository.isDirty() is not False: + raise gitversionhelper.repository.repositoryDirty("The repository is dirty and a current version can not be generated.") + saved_kwargs = copy(kwargs) + if "formated_output" in kwargs: + del saved_kwargs["formated_output"] + _v = cls.getLastVersion(**saved_kwargs) + amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) + _v = _v.bump(amount,**kwargs) + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): + return _v.doFormatVersion(**kwargs) + return _v + @classmethod def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: """ @@ -257,35 +313,70 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the last version """ VersionStd = cls._getVersionStd(**kwargs) - _r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | \ - re.IGNORECASE) - lastTag = gitversionhelper.tag.getLastTag(**kwargs) + bAutoVersionStd = False + if VersionStd == "Auto": + bAutoVersionStd = True - _m = re.match(_r,lastTag) - if not _m: - raise RuntimeError("no valid version found in tags") - if VersionStd == "PEP440": - ver=_m.group("release").split(".") - ver += ["0"] * (3 - len(ver)) - ver[0]=int(ver[0]) - ver[1]=int(ver[1]) - ver[2]=int(ver[2]) - major, minor, patch = tuple(ver) - pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 - post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 - elif VersionStd == "SemVer": - major, minor, patch = int(_m.group("major")),\ - int(_m.group("minor")),\ - int(_m.group("patch")),\ - (_m.group("prerelease") if _m.group("prerelease") else ""), "" - pre_count = 0 - post_count = 0 - - _v = cls.MetaVersion(major, minor, patch, pre_count, post_count, lastTag) + lastTag=cls.MetaVersion.raw + try: + lastTag = gitversionhelper.tag.getLastTag(**kwargs) + except gitversionhelper.tag.tagNotFound: + logging.warning('tag not found, reseting versionning') + + bFound = False + if VersionStd == "SemVer" or (bAutoVersionStd is True) : + _r=re.compile(r"^\s*" + cls.VersionStds["SemVer"]["regex"] + r"\s*$", re.VERBOSE | \ + re.IGNORECASE) + _m = re.match(_r,lastTag) + if not _m: + pass + else: + major, minor, patch = int(_m.group("major")),\ + int(_m.group("minor")),\ + int(_m.group("patch")) + + pre_count = 0 + if _pre := _m.group("prerelease"): + if (_match := re.search (cls.VersionStds["SemVer"]["regex_preversion_num"],_pre)) is not None: + pre_count = int(_match.group("num")) + else: + pre_count = 1 + + post_count = 0 + if _post := _m.group("buildmetadata"): + if (_match := re.search (cls.VersionStds["SemVer"]["regex_build_num"],_post)) is not None: + post_count = int(_match.group("num")) + else: + post_count = 1 + bFound = True + VersionStd = "SemVer" + + if VersionStd == "PEP440" or ( (bAutoVersionStd is True) and (bFound is not True)): + _r=re.compile(r"^\s*" + cls.VersionStds["PEP440"]["regex"] + r"\s*$", re.VERBOSE | \ + re.IGNORECASE) + _m = re.match(_r,lastTag) + if not _m: + pass + else: + ver=_m.group("release").split(".") + ver += ["0"] * (3 - len(ver)) + ver[0]=int(ver[0]) + ver[1]=int(ver[1]) + ver[2]=int(ver[2]) + major, minor, patch = tuple(ver) + pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 + post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 + bFound = True + VersionStd = "PEP440" + + if bFound is not True: + raise gitversionhelper.version.noValidVersion("no valid version found in tags") + + _v = cls.MetaVersion(VersionStd,major, minor, patch, pre_count, post_count, lastTag) if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): - return cls.doFormatVersion(_v,**kwargs) + return _v.doFormatVersion(**kwargs) return _v @classmethod @@ -297,32 +388,39 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: formated version string """ - VersionStd = cls._getVersionStd(**kwargs) + VersionStd = cls._getVersionStd(**kwargs) + if VersionStd=="Auto" : + VersionStd = inputversion.version_std + OutputFormat = None revpattern="" revcount="" post_count = inputversion.post_count pre_count = inputversion.pre_count patch = inputversion.patch + if (cls.__OptDict["output_format"] in kwargs): OutputFormat=kwargs[cls.__OptDict["output_format"]] + if OutputFormat is None: + OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" + if post_count > 0 and pre_count > 0: + raise RuntimeError("pre and post release can not be present at the same time") if VersionStd == "PEP440": - OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0: revpattern=".post" revcount=f"{post_count}" - elif VersionStd == "SemVer": - OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" - if post_count > 0: - pre_count = pre_count + post_count - post_count = 0 - patch = patch + 1 - if pre_count > 0: - revpattern="-pre" + elif pre_count > 0: + revpattern=".pre" revcount=f"{pre_count}" - + elif VersionStd == "SemVer": + if post_count > 0: + revpattern="+post" + revcount=f".{post_count}" + elif pre_count > 0: + revpattern="-pre" + revcount=f".{pre_count}" return OutputFormat.format(major=inputversion.major,minor=inputversion.minor,patch=patch,revpattern=revpattern,revcount=revcount) @@ -340,19 +438,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods #print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) #print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) #print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440",formated_output=True)) -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440",formated_output=True,output_format="v{major}.{minor}.{patch}")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump()) -#print("") -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="SemVer")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="patch").doFormatVersion(version_std="SemVer")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="minor").doFormatVersion(version_std="SemVer")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="major").doFormatVersion(version_std="SemVer")) -#print("") -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="patch").doFormatVersion(version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="minor").doFormatVersion(version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="major").doFormatVersion(version_std="PEP440")) + #from setuptools_git_versioning import version_from_git #print(str(version_from_git(tag_filter="^\d+\.\d+\.\d+$",dev_template = "{tag}.post{ccount}",sort_by="v:refname")),end ="") diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 9708dc5..4029a59 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -7,7 +7,12 @@ # work. If not, see . import unittest -from io import StringIO + +import tempfile +import os +import pathlib +import re + from contextlib import redirect_stdout,redirect_stderr print(__name__) @@ -15,10 +20,672 @@ print(__package__) from src import pygitversionhelper +HelperRegex=r"^(?P\d+)\.(?P\d+)\.(?P\d+)([\.\-\+])?(?:.*)?" + class Test_gitversionhelper(unittest.TestCase): - def test_version(self): - version = pygitversionhelper.gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440").bump(bump_type="dev").doFormatVersion(version_std="SemVer") - self.assertNotEqual(version,"?.?.?") + def setUp(self): + self.TmpWorkingDir=tempfile.TemporaryDirectory() + self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) + os.chdir(self.TmpWorkingDirPath) + os.system("git init") + + def _test_version_readback(self,tag:str,**kwargs): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag {tag}") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(**kwargs) + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, tag) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + + _m = re.match(HelperRegex, tag) + self.assertEqual(int(_m.group("MAJ")),_v.major) + self.assertEqual(int(_m.group("MIN")),_v.minor) + self.assertEqual(int(_m.group("PATCH")),_v.patch) + return _v + + def _test_version_format(self,_v:pygitversionhelper.gitversionhelper.version.MetaVersion,tag:str,**kwargs): + _f=_v.doFormatVersion(**kwargs) + self.assertRegex(_f,HelperRegex) + self.assertEqual(_f, tag) + + def _test_version_readback_simple(self,tag:str,**kwargs): + _v=self._test_version_readback(tag,**kwargs) + self._test_version_format(_v,tag,**kwargs) + + def test_nominal_version_auto_1(self): + self._test_version_readback_simple("0.0.1") + def test_nominal_version_auto_2(self): + self._test_version_readback_simple("0.0.2") + def test_nominal_version_auto_3(self): + self._test_version_readback_simple("0.1.0") + def test_nominal_version_auto_4(self): + self._test_version_readback_simple("0.1.1") + def test_nominal_version_auto_5(self): + self._test_version_readback_simple("1.0.0") + def test_nominal_version_auto_6(self): + self._test_version_readback_simple("1.1.0") + def test_nominal_version_auto_7(self): + self._test_version_readback_simple("1.2.0") + def test_nominal_version_auto_8(self): + self._test_version_readback_simple("1.1.1") + def test_nominal_version_auto_9(self): + self._test_version_readback_simple("1.2.1") + def test_nominal_version_auto_PEP440_post(self): + self._test_version_readback_simple("1.2.1.post1") + def test_nominal_version_auto_PEP440_pre(self): + self._test_version_readback_simple("1.2.1.pre1") + def test_nominal_version_auto_PEP440_post_2(self): + self._test_version_readback_simple("1.2.1.post10") + def test_nominal_version_auto_PEP440_pre_2(self): + self._test_version_readback_simple("1.2.1.pre10") + + def test_nominal_version_auto_SemVer_post(self): + self._test_version_readback_simple("1.2.1+post.1") + def test_nominal_version_auto_SemVer_pre(self): + self._test_version_readback_simple("1.2.1-pre.1") + def test_nominal_version_auto_SemVer_post_2(self): + self._test_version_readback_simple("1.2.1+post.10") + def test_nominal_version_auto_Semver_pre_2(self): + self._test_version_readback_simple("1.2.1-pre.10") + + def test_nominal_version_PEP440_1(self): + self._test_version_readback_simple("0.0.1",version_std="PEP440") + def test_nominal_version_PEP440_2(self): + self._test_version_readback_simple("0.0.2",version_std="PEP440") + def test_nominal_version_PEP440_3(self): + self._test_version_readback_simple("0.1.0",version_std="PEP440") + def test_nominal_version_PEP440_4(self): + self._test_version_readback_simple("0.1.1",version_std="PEP440") + def test_nominal_version_PEP440_5(self): + self._test_version_readback_simple("1.0.0",version_std="PEP440") + def test_nominal_version_PEP440_6(self): + self._test_version_readback_simple("1.1.0",version_std="PEP440") + def test_nominal_version_PEP440_7(self): + self._test_version_readback_simple("1.2.0",version_std="PEP440") + def test_nominal_version_PEP440_8(self): + self._test_version_readback_simple("1.1.1",version_std="PEP440") + def test_nominal_version_PEP440_9(self): + self._test_version_readback_simple("1.2.1",version_std="PEP440") + def test_nominal_version_PEP440_post(self): + self._test_version_readback_simple("1.2.1.post1",version_std="PEP440") + def test_nominal_version_PEP440_pre(self): + self._test_version_readback_simple("1.2.1.pre1",version_std="PEP440") + def test_nominal_version_PEP440_post_2(self): + self._test_version_readback_simple("1.2.1.post10",version_std="PEP440") + def test_nominal_version_PEP440_pre_2(self): + self._test_version_readback_simple("1.2.1.pre10",version_std="PEP440") + + def test_nominal_version_SemVer_1(self): + self._test_version_readback_simple("0.0.1",version_std="SemVer") + def test_nominal_version_SemVer_2(self): + self._test_version_readback_simple("0.0.2",version_std="SemVer") + def test_nominal_version_SemVer_3(self): + self._test_version_readback_simple("0.1.0",version_std="SemVer") + def test_nominal_version_SemVer_4(self): + self._test_version_readback_simple("0.1.1",version_std="SemVer") + def test_nominal_version_SemVer_5(self): + self._test_version_readback_simple("1.0.0",version_std="SemVer") + def test_nominal_version_SemVer_6(self): + self._test_version_readback_simple("1.1.0",version_std="SemVer") + def test_nominal_version_SemVer_7(self): + self._test_version_readback_simple("1.2.0",version_std="SemVer") + def test_nominal_version_SemVer_8(self): + self._test_version_readback_simple("1.1.1",version_std="SemVer") + def test_nominal_version_SemVer_9(self): + self._test_version_readback_simple("1.2.1",version_std="SemVer") + def test_nominal_version_SemVer_post(self): + self._test_version_readback_simple("1.2.1+post.1",version_std="SemVer") + def test_nominal_version_SemVer_pre(self): + self._test_version_readback_simple("1.2.1-pre.1",version_std="SemVer") + def test_nominal_version_SemVer_post_2(self): + self._test_version_readback_simple("1.2.1+post.10",version_std="SemVer") + def test_nominal_version_SemVer_pre_2(self): + self._test_version_readback_simple("1.2.1-pre.10",version_std="SemVer") + + def test_nominal_version_post_PEP440_to_SemVer(self): + _v=self._test_version_readback("1.2.1.post10",version_std="PEP440") + self._test_version_format(_v,"1.2.1+post.10",version_std="SemVer") + + def test_nominal_version_post_SemVer_to_PEP440(self): + _v=self._test_version_readback("1.2.1+post.10",version_std="SemVer") + self._test_version_format(_v,"1.2.1.post10",version_std="PEP440") + + def test_nominal_version_pre_PEP440_to_SemVer(self): + _v=self._test_version_readback("1.2.1.pre10",version_std="PEP440") + self._test_version_format(_v,"1.2.1-pre.10",version_std="SemVer") + + def test_nominal_version_pre_SemVer_to_PEP440(self): + _v=self._test_version_readback("1.2.1-pre.10",version_std="SemVer") + self._test_version_format(_v,"1.2.1.pre10",version_std="PEP440") + + def test_nominal_version_post_SemVer_nonum(self): + _v=self._test_version_readback("1.2.1+post",version_std="SemVer") + self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") + + def test_nominal_version_post_SemVer_nonum_random(self): + _v=self._test_version_readback("1.2.1+toto",version_std="SemVer") + self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") + + def test_nominal_version_pre_SemVer_nonum(self): + _v=self._test_version_readback("1.2.1-pre",version_std="SemVer") + self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") + + def test_nominal_version_pre_SemVer_nonum_random(self): + _v=self._test_version_readback("1.2.1-toto",version_std="SemVer") + self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") + + def test_version_pump_SemVer(self,**kwargs): + _v = self._test_version_readback("1.0.0",version_std="SemVer") + + _v = _v.bump() + self.assertIsInstance(_v.raw, str) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + self.assertEqual(_v.raw, "1.0.1") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 1) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.1") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "1.0.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.2") + + _v = _v.bump(bump_type="minor") + self.assertEqual(_v.raw, "1.1.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.1.2") + + _v = _v.bump(bump_type="major") + self.assertEqual(_v.raw, "2.1.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.2") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2+post.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.2+post.1") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2+post.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.2+post.2") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 3) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.3") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4-pre.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 1) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4-pre.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 2) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.2") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.4-pre.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 3) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.3") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.5") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.5") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.5+post.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.5+post.1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.5+post.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.5+post.2") + + def test_version_pump_PEP440(self,**kwargs): + _v = self._test_version_readback("1.0.0",version_std="PEP440") + + _v = _v.bump() + self.assertIsInstance(_v.raw, str) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + self.assertEqual(_v.raw, "1.0.1") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 1) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.1") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "1.0.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.2") + + _v = _v.bump(bump_type="minor") + self.assertEqual(_v.raw, "1.1.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.1.2") + + _v = _v.bump(bump_type="major") + self.assertEqual(_v.raw, "2.1.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.2") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2.post1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.2.post1") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2.post2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.2.post2") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 3) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.3") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4.pre1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 1) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4.pre2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 2) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre2") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.4.pre3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 3) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre3") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.5") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.5") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.5.post1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.5.post1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.5.post2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.5.post2") + + def test_nominal_version_SemVer_zeroRev(self): + _v=self._test_version_readback("0.0.0",version_std="SemVer") + self._test_version_format(_v,"0.0.0",version_std="SemVer") + + def test_nominal_version_PEP440_zeroRev(self): + _v=self._test_version_readback("0.0.0",version_std="PEP440") + self._test_version_format(_v,"0.0.0",version_std="PEP440") + + + def test_nominal_version_PEP440_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.1.0") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + + def test_nominal_version_SemVer_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="SemVer") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.1.0") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + self._test_version_format(_v,"0.1.0",version_std="SemVer") + + def test_nominal_version_AUTO_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.1.0") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + self._test_version_format(_v,"0.1.0") + + + def test_nominal_version_AUTO_bump_commits(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag 0.2.0") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.2.0") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue22") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.2.1") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,1) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.2.1") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue223") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue224") + os.system("git add .") + os.system("git commit -m \"4th commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.2.3") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,3) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.2.3") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + os.system("git add .") + os.system("git commit -m \"5th commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.2.0+post.4") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,4) + self._test_version_format(_v,"0.2.0+post.4") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-patch") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.2.1-pre.4") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,1) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.2.1-pre.4") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-minor") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.3.0-pre.4") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.3.0-pre.4") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "1.0.0-pre.4") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,1) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"1.0.0-pre.4") + + def test_nominal_custom_format(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + + self.assertEqual("V_0_1_1____",_v.doFormatVersion(output_format="V_{major}_{minor}_{patch}____{revcount}")) + self.assertEqual("V_0_1",_v.doFormatVersion(output_format="V_{major}_{minor}")) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + os.system("git add .") + os.system("git commit -m \"5th commit\"") + + self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major").doFormatVersion(output_format="V_{major}_{minor}")) + self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major",output_format="V_{major}_{minor}",formated_output=True)) + + def tearDown(self): + os.chdir("/") \ No newline at end of file -- 2.47.3 From 014e8ac0d2fe9bf2d8c0905f02c6f462d7f1a2d6 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 00:49:33 +0000 Subject: [PATCH 08/30] fix + more unittests --- src/pygitversionhelper/gitversionhelper.py | 55 +++++++------- test/test_gitversionhelper.py | 85 +++++++++++++++++++++- 2 files changed, 112 insertions(+), 28 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index e97936c..e293ebd 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -37,10 +37,19 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: """ try: - stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) + #stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) + p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True) + if re.search("not a git repository",p.stderr): + raise gitversionhelper.repository.notAGitRepository() + if re.search("fatal:",p.stderr): + raise gitversionhelper.unknownGITFatalError() + if int(p.returncode) < 0: + raise gitversionhelper.unknownGITError + except subprocess.CalledProcessError as e: - stdout = e.output - lines = stdout.splitlines() + raise RuntimeError(e.output) + + lines = p.stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] class gitversionhelperException(Exception): @@ -52,12 +61,18 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ class wrongArguments(gitversionhelperException): pass + class unknownGITError(gitversionhelperException): + pass + class unknownGITFatalError(unknownGITError): + pass class repository: """ class containing methods focusing on repository """ class repositoryException(gitversionhelperException): pass + class notAGitRepository(repositoryException): + pass class repositoryDirty(repositoryException): pass @classmethod @@ -115,7 +130,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if len(res)==0: raise cls.tagNotFound("no tag found in commit history") elif len(res)!=1: - raise cls.MoreThanOneTag("multiple tags on same commit is unsupported") + raise cls.moreThanOneTag("multiple tags on same commit is unsupported") return res[0] @classmethod @@ -153,6 +168,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods "Auto" : None } } + __versionReseted = False class versionException(gitversionhelperException): pass class noValidVersion(versionException): @@ -294,9 +310,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods saved_kwargs = copy(kwargs) if "formated_output" in kwargs: del saved_kwargs["formated_output"] + _v = cls.getLastVersion(**saved_kwargs) - amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) - _v = _v.bump(amount,**kwargs) + + if cls.__versionReseted == False: + amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) + _v = _v.bump(amount,**kwargs) + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v @@ -319,10 +339,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods bAutoVersionStd = True lastTag=cls.MetaVersion.raw + cls.__versionReseted = False try: lastTag = gitversionhelper.tag.getLastTag(**kwargs) except gitversionhelper.tag.tagNotFound: logging.warning('tag not found, reseting versionning') + cls.__versionReseted = True + bFound = False if VersionStd == "SemVer" or (bAutoVersionStd is True) : @@ -422,23 +445,3 @@ class gitversionhelper: # pylint: disable=too-few-public-methods revpattern="-pre" revcount=f".{pre_count}" return OutputFormat.format(major=inputversion.major,minor=inputversion.minor,patch=patch,revpattern=revpattern,revcount=revcount) - - - - - -#print(gitversionhelper.head.isDirty()) -#print(gitversionhelper.tag.getTags()) -#print(gitversionhelper.tag.getLastTag()) -#print(gitversionhelper.tag.getLastTag(same_branch=True)) -#print(gitversionhelper.tag.getDistanceFromLastTag()) -#print(gitversionhelper.tag.getDistanceFromLastTag(same_branch=True)) - -#print(gitversionhelper.version.getLastVersion()) -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440")) - - -#from setuptools_git_versioning import version_from_git -#print(str(version_from_git(tag_filter="^\d+\.\d+\.\d+$",dev_template = "{tag}.post{ccount}",sort_by="v:refname")),end ="") diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 4029a59..cdbf3ea 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -685,7 +685,88 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major",output_format="V_{major}_{minor}",formated_output=True)) - + def test_nominal_emptyrepo(self): + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, "0.1.0") + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + self._test_version_format(_v,"0.1.0") + + def test_defect_dirty(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) as context: + pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + def test_defect_wrongargument_git_sortargs(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + pygitversionhelper.gitversionhelper.tag.getTags(sort="toto") + + def test_defect_git_notagfound(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.tagNotFound) as context: + pygitversionhelper.gitversionhelper.tag.getLastTag() + + """ This test is impossible to do + def test_defect_git_multipletagsfound(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag 0.1.0") + os.system(f"git tag 0.2.0") + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.moreThanOneTag) as context: + pygitversionhelper.gitversionhelper.tag.getLastTag() + """ + + def test_defect_wrongargument_bump_type(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="toto") + + def test_defect_wrongargument_bump_dev_strategy(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_dev_strategy="toto") + + + def tearDown(self): os.chdir("/") - \ No newline at end of file + +class Test_gitversionhelperNoRepo(unittest.TestCase): + def setUp(self): + self.TmpWorkingDir=tempfile.TemporaryDirectory() + self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) + os.chdir(self.TmpWorkingDirPath) + + def test_defect_norepo(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.notAGitRepository) as context: + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + def tearDown(self): + os.chdir("/") + +#print(gitversionhelper.tag.getLastTag(same_branch=True)) +#print(gitversionhelper.tag.getDistanceFromLastTag(same_branch=True)) + +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) +#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440")) \ No newline at end of file -- 2.47.3 From 96250682ec96b11e8eb54d9e8c8782177195a0a6 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 00:59:35 +0000 Subject: [PATCH 09/30] fix missing user/mail for git --- test/test_gitversionhelper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index cdbf3ea..2d12fd0 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -28,6 +28,8 @@ class Test_gitversionhelper(unittest.TestCase): self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) os.chdir(self.TmpWorkingDirPath) os.system("git init") + os.system('git config --local user.name "john doe"') + os.system('git config --local user.email "john@doe.org"') def _test_version_readback(self,tag:str,**kwargs): with open("demofile.txt", "w+t") as tmpFile: -- 2.47.3 From 6a1331d1bf36076ab11f03a426fafda888849b48 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:22:32 +0000 Subject: [PATCH 10/30] improve quality --- src/pygitversionhelper/gitversionhelper.py | 117 ++++++++++++++------- 1 file changed, 77 insertions(+), 40 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index e293ebd..8a8bcac 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -23,12 +23,13 @@ import logging from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN -if TYPE_CHECKING: # Only imports the below statements during type checking +# Only imports the below statements during type checking +if TYPE_CHECKING: from typing import Union - + def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: """ - Helper function to handle system cmd execution + helper function to handle system cmd execution Args: cmd: command line to be executed root: root directory where the command need to be executed @@ -36,54 +37,71 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: a list of command's return lines """ - try: - #stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) - p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True) - if re.search("not a git repository",p.stderr): - raise gitversionhelper.repository.notAGitRepository() - if re.search("fatal:",p.stderr): - raise gitversionhelper.unknownGITFatalError() - if int(p.returncode) < 0: - raise gitversionhelper.unknownGITError - - except subprocess.CalledProcessError as e: - raise RuntimeError(e.output) + + p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False) + if re.search("not a git repository",p.stderr): + raise gitversionhelper.repository.notAGitRepository() + if re.search("fatal:",p.stderr): + raise gitversionhelper.unknownGITFatalError() + if int(p.returncode) < 0: + raise gitversionhelper.unknownGITError lines = p.stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] class gitversionhelperException(Exception): + """ + general Module Exception + """ pass class gitversionhelper: # pylint: disable=too-few-public-methods """ - Main gitversionhelper class + main gitversionhelper class """ class wrongArguments(gitversionhelperException): + """ + wrong argument generic exception + """ pass class unknownGITError(gitversionhelperException): + """ + unknown git error generic exception + """ pass class unknownGITFatalError(unknownGITError): + """ + unknown fatal git error generic exception + """ pass class repository: """ class containing methods focusing on repository """ class repositoryException(gitversionhelperException): + """ + generic repository exeption + """ pass class notAGitRepository(repositoryException): + """ + not a git repository exception + """ pass class repositoryDirty(repositoryException): + """ + dirty repository exception + """ pass @classmethod def isDirty(cls) -> bool: """ - Check if the repository is in dirty state + check if the repository is in dirty state Return: True if it is dirty """ - return True if _exec("git status --short") else False - + return bool(_exec("git status --short")) + class tag: """ class containing methods focusing on tags @@ -92,10 +110,19 @@ class gitversionhelper: # pylint: disable=too-few-public-methods __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] class tagException(gitversionhelperException): + """ + generic tag exception + """ pass class tagNotFound(tagException): + """ + tag not found exception + """ pass class moreThanOneTag(tagException): + """ + more than one tag exception + """ pass @classmethod @@ -110,7 +137,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if sort not in cls.__validGitTagSort: raise gitversionhelper.wrongArguments("sort option not in allowed list") return _exec(f"git tag -l --sort={sort}") - + @classmethod def getLastTag(cls,**kwargs) -> Union[str,None]: """ @@ -129,7 +156,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if len(res)==0: raise cls.tagNotFound("no tag found in commit history") - elif len(res)!=1: + if len(res)!=1: raise cls.moreThanOneTag("multiple tags on same commit is unsupported") return res[0] @@ -147,7 +174,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if tag is None: tag = cls.getLastTag(**kwargs) return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) - + class version: """ class containing methods focusing on versions @@ -170,8 +197,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods } __versionReseted = False class versionException(gitversionhelperException): + """ + generic version exception + """ pass class noValidVersion(versionException): + """ + no valid version found exception + """ pass class MetaVersion: @@ -193,7 +226,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count:int = 0 raw:str = "0.1.0" - def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): + def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): #pylint: disable=R0913 self.version_std = version_std self.major = major self.minor = minor @@ -201,7 +234,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods self.pre_count = pre_count self.post_count = post_count self.raw = raw - + @classmethod def _getBumpDevStrategy(cls,**kwargs) -> str: """ @@ -236,7 +269,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - def bump(self,amount:int=1,**kwargs): + def bump(self,amount:int=1,**kwargs): # pylint: disable=R0912 """ bump the version to the next one Kwargs: @@ -285,7 +318,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def doFormatVersion(self,**kwargs): return gitversionhelper.version.doFormatVersion(self,**kwargs) - + @classmethod def _getVersionStd(cls,**kwargs): """ @@ -302,18 +335,19 @@ class gitversionhelper: # pylint: disable=too-few-public-methods else: raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['version_std']} requested") return VersionStd - + @classmethod def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: if gitversionhelper.repository.isDirty() is not False: - raise gitversionhelper.repository.repositoryDirty("The repository is dirty and a current version can not be generated.") + raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \ + " can not be generated.") saved_kwargs = copy(kwargs) if "formated_output" in kwargs: del saved_kwargs["formated_output"] - + _v = cls.getLastVersion(**saved_kwargs) - if cls.__versionReseted == False: + if not cls.__versionReseted: amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) _v = _v.bump(amount,**kwargs) @@ -322,7 +356,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return _v @classmethod - def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: + def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 """ bump the last version from tags Kwargs: @@ -345,7 +379,6 @@ class gitversionhelper: # pylint: disable=too-few-public-methods except gitversionhelper.tag.tagNotFound: logging.warning('tag not found, reseting versionning') cls.__versionReseted = True - bFound = False if VersionStd == "SemVer" or (bAutoVersionStd is True) : @@ -358,14 +391,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods major, minor, patch = int(_m.group("major")),\ int(_m.group("minor")),\ int(_m.group("patch")) - + pre_count = 0 if _pre := _m.group("prerelease"): if (_match := re.search (cls.VersionStds["SemVer"]["regex_preversion_num"],_pre)) is not None: pre_count = int(_match.group("num")) else: pre_count = 1 - + post_count = 0 if _post := _m.group("buildmetadata"): if (_match := re.search (cls.VersionStds["SemVer"]["regex_build_num"],_post)) is not None: @@ -374,7 +407,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count = 1 bFound = True VersionStd = "SemVer" - + if VersionStd == "PEP440" or ( (bAutoVersionStd is True) and (bFound is not True)): _r=re.compile(r"^\s*" + cls.VersionStds["PEP440"]["regex"] + r"\s*$", re.VERBOSE | \ re.IGNORECASE) @@ -393,10 +426,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods bFound = True VersionStd = "PEP440" - if bFound is not True: + if not bFound : raise gitversionhelper.version.noValidVersion("no valid version found in tags") - _v = cls.MetaVersion(VersionStd,major, minor, patch, pre_count, post_count, lastTag) + _v = cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, lastTag) if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) @@ -415,7 +448,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods VersionStd = cls._getVersionStd(**kwargs) if VersionStd=="Auto" : VersionStd = inputversion.version_std - + OutputFormat = None revpattern="" revcount="" @@ -425,7 +458,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if (cls.__OptDict["output_format"] in kwargs): OutputFormat=kwargs[cls.__OptDict["output_format"]] - + if OutputFormat is None: OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0 and pre_count > 0: @@ -444,4 +477,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods elif pre_count > 0: revpattern="-pre" revcount=f".{pre_count}" - return OutputFormat.format(major=inputversion.major,minor=inputversion.minor,patch=patch,revpattern=revpattern,revcount=revcount) + return OutputFormat.format( major=inputversion.major, \ + minor=inputversion.minor, \ + patch=patch, \ + revpattern=revpattern, \ + revcount=revcount) -- 2.47.3 From 39e7d8236c50dda9f3935aa93257feb278acd2ba Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:23:33 +0000 Subject: [PATCH 11/30] update: update: quality column length check 120 -> 140 --- helpers/quality_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/quality_check.py b/helpers/quality_check.py index 6d9ad9c..7616d5f 100644 --- a/helpers/quality_check.py +++ b/helpers/quality_check.py @@ -61,7 +61,7 @@ class quality_check(helper_withresults_base): '--ignore=_version.py', '--reports=y', '--score=yes', - '--max-line-length=120', + '--max-line-length=140', 'src.' + cls.pyproject['project']['name']], exit=False) with open(cls.get_result_dir()/"report.json","w+", encoding='utf-8') as Outfile: -- 2.47.3 From bce35f0a60482d3b946377c004a594978b9a853c Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:32:44 +0000 Subject: [PATCH 12/30] fix quality --- src/pygitversionhelper/gitversionhelper.py | 99 +++++++++++----------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 8a8bcac..dbf97c7 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -24,7 +24,7 @@ import logging from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN # Only imports the below statements during type checking -if TYPE_CHECKING: +if TYPE_CHECKING: from typing import Union def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: @@ -37,7 +37,7 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: a list of command's return lines """ - + p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False) if re.search("not a git repository",p.stderr): raise gitversionhelper.repository.notAGitRepository() @@ -53,7 +53,6 @@ class gitversionhelperException(Exception): """ general Module Exception """ - pass class gitversionhelper: # pylint: disable=too-few-public-methods """ @@ -63,17 +62,17 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ wrong argument generic exception """ - pass + class unknownGITError(gitversionhelperException): """ unknown git error generic exception """ - pass + class unknownGITFatalError(unknownGITError): """ unknown fatal git error generic exception """ - pass + class repository: """ class containing methods focusing on repository @@ -82,17 +81,17 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ generic repository exeption """ - pass + class notAGitRepository(repositoryException): """ not a git repository exception """ - pass + class repositoryDirty(repositoryException): """ dirty repository exception """ - pass + @classmethod def isDirty(cls) -> bool: """ @@ -101,30 +100,29 @@ class gitversionhelper: # pylint: disable=too-few-public-methods True if it is dirty """ return bool(_exec("git status --short")) - + class tag: """ class containing methods focusing on tags """ __OptDict = {"same_branch": "same_branch"} __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] - + class tagException(gitversionhelperException): """ generic tag exception """ - pass + class tagNotFound(tagException): """ tag not found exception """ - pass + class moreThanOneTag(tagException): """ more than one tag exception """ - pass - + @classmethod def getTags(cls,sort:str = "version:refname") -> list[str]: """ @@ -137,7 +135,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if sort not in cls.__validGitTagSort: raise gitversionhelper.wrongArguments("sort option not in allowed list") return _exec(f"git tag -l --sort={sort}") - + @classmethod def getLastTag(cls,**kwargs) -> Union[str,None]: """ @@ -153,7 +151,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods res = _exec("git rev-list --tags --max-count=1") if len(res)==1: res = _exec(f"git describe --tags {res[0]}") - + if len(res)==0: raise cls.tagNotFound("no tag found in commit history") if len(res)!=1: @@ -174,7 +172,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if tag is None: tag = cls.getLastTag(**kwargs) return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) - + class version: """ class containing methods focusing on versions @@ -200,13 +198,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ generic version exception """ - pass + class noValidVersion(versionException): """ no valid version found exception """ - pass - + class MetaVersion: """ generic version object @@ -218,14 +215,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods DefaultBumpDevStrategy = "post" BumpDevStrategys = ["post","pre-patch","pre-minor","pre-major"] version_std = "None" - + major: int = 0 minor: int = 1 patch: int = 0 pre_count:int = 0 post_count:int = 0 raw:str = "0.1.0" - + def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): #pylint: disable=R0913 self.version_std = version_std self.major = major @@ -234,7 +231,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods self.pre_count = pre_count self.post_count = post_count self.raw = raw - + @classmethod def _getBumpDevStrategy(cls,**kwargs) -> str: """ @@ -251,7 +248,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods else: raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpDevStrategy - + @classmethod def _getBumpType(cls,**kwargs) -> str: """ @@ -268,7 +265,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods else: raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - + def bump(self,amount:int=1,**kwargs): # pylint: disable=R0912 """ bump the version to the next one @@ -281,7 +278,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods BumpType = self._getBumpType(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs) _v=copy(self) - + if BumpType == "dev": if BumpDevStrategy == "post": if _v.pre_count > 0: @@ -312,13 +309,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v.patch = _v.patch + amount _v.pre_count=0 _v.post_count=0 - + _v.raw=_v.doFormatVersion(**kwargs) return _v - + def doFormatVersion(self,**kwargs): return gitversionhelper.version.doFormatVersion(self,**kwargs) - + @classmethod def _getVersionStd(cls,**kwargs): """ @@ -335,7 +332,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods else: raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['version_std']} requested") return VersionStd - + @classmethod def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: if gitversionhelper.repository.isDirty() is not False: @@ -344,17 +341,17 @@ class gitversionhelper: # pylint: disable=too-few-public-methods saved_kwargs = copy(kwargs) if "formated_output" in kwargs: del saved_kwargs["formated_output"] - + _v = cls.getLastVersion(**saved_kwargs) - + if not cls.__versionReseted: amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) _v = _v.bump(amount,**kwargs) - + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v - + @classmethod def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 """ @@ -367,11 +364,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the last version """ VersionStd = cls._getVersionStd(**kwargs) - + bAutoVersionStd = False if VersionStd == "Auto": bAutoVersionStd = True - + lastTag=cls.MetaVersion.raw cls.__versionReseted = False try: @@ -379,7 +376,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods except gitversionhelper.tag.tagNotFound: logging.warning('tag not found, reseting versionning') cls.__versionReseted = True - + bFound = False if VersionStd == "SemVer" or (bAutoVersionStd is True) : _r=re.compile(r"^\s*" + cls.VersionStds["SemVer"]["regex"] + r"\s*$", re.VERBOSE | \ @@ -391,14 +388,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods major, minor, patch = int(_m.group("major")),\ int(_m.group("minor")),\ int(_m.group("patch")) - + pre_count = 0 if _pre := _m.group("prerelease"): if (_match := re.search (cls.VersionStds["SemVer"]["regex_preversion_num"],_pre)) is not None: pre_count = int(_match.group("num")) else: pre_count = 1 - + post_count = 0 if _post := _m.group("buildmetadata"): if (_match := re.search (cls.VersionStds["SemVer"]["regex_build_num"],_post)) is not None: @@ -407,7 +404,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count = 1 bFound = True VersionStd = "SemVer" - + if VersionStd == "PEP440" or ( (bAutoVersionStd is True) and (bFound is not True)): _r=re.compile(r"^\s*" + cls.VersionStds["PEP440"]["regex"] + r"\s*$", re.VERBOSE | \ re.IGNORECASE) @@ -425,16 +422,16 @@ class gitversionhelper: # pylint: disable=too-few-public-methods post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 bFound = True VersionStd = "PEP440" - + if not bFound : raise gitversionhelper.version.noValidVersion("no valid version found in tags") - + _v = cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, lastTag) - + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v - + @classmethod def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): """ @@ -444,21 +441,21 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Return: formated version string """ - + VersionStd = cls._getVersionStd(**kwargs) if VersionStd=="Auto" : VersionStd = inputversion.version_std - + OutputFormat = None revpattern="" revcount="" post_count = inputversion.post_count pre_count = inputversion.pre_count patch = inputversion.patch - - if (cls.__OptDict["output_format"] in kwargs): + + if cls.__OptDict["output_format"] in kwargs: OutputFormat=kwargs[cls.__OptDict["output_format"]] - + if OutputFormat is None: OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0 and pre_count > 0: @@ -481,4 +478,4 @@ class gitversionhelper: # pylint: disable=too-few-public-methods minor=inputversion.minor, \ patch=patch, \ revpattern=revpattern, \ - revcount=revcount) + revcount=revcount) \ No newline at end of file -- 2.47.3 From df74016945db9bce60004228fb28d0993fa1df41 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:39:25 +0000 Subject: [PATCH 13/30] improve quality --- src/pygitversionhelper/gitversionhelper.py | 38 +++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index dbf97c7..371283e 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -152,10 +152,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if len(res)==1: res = _exec(f"git describe --tags {res[0]}") - if len(res)==0: + if len(res)==0: raise cls.tagNotFound("no tag found in commit history") - if len(res)!=1: - raise cls.moreThanOneTag("multiple tags on same commit is unsupported") + if len(res)!=1: + raise cls.moreThanOneTag("multiple tags on same commit is unsupported") return res[0] @classmethod @@ -187,7 +187,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" - + }, "PEP440" : { "regex" : packaging_VERSION_PATTERN, "Auto" : None @@ -224,7 +224,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raw:str = "0.1.0" def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): #pylint: disable=R0913 - self.version_std = version_std + self.version_std = version_std self.major = major self.minor = minor self.patch = patch @@ -242,7 +242,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given bump_dev_strategy or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy - if (cls.__OptDict["bump_dev_strategy"] in kwargs): + if cls.__OptDict["bump_dev_strategy"] in kwargs: if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] else: @@ -259,7 +259,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given bump_type or the default one. """ BumpType = cls.DefaultBumpType - if (cls.__OptDict["bump_type"] in kwargs): + if cls.__OptDict["bump_type"] in kwargs: if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: BumpType = kwargs[cls.__OptDict["bump_type"]] else: @@ -314,6 +314,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return _v def doFormatVersion(self,**kwargs): + """ + output a formated version string + Return: + formated version string + """ return gitversionhelper.version.doFormatVersion(self,**kwargs) @classmethod @@ -335,6 +340,15 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: + """ + get the current version or bump depending of repository state + Kwargs: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + Return: + the last version + """ if gitversionhelper.repository.isDirty() is not False: raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \ " can not be generated.") @@ -355,7 +369,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 """ - bump the last version from tags + get the last version from tags Kwargs: version_std(str): the given version_std (can be None) same_branch(bool): force searching only in the same branch @@ -365,9 +379,9 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ VersionStd = cls._getVersionStd(**kwargs) - bAutoVersionStd = False + bAutoVersionStd = False if VersionStd == "Auto": - bAutoVersionStd = True + bAutoVersionStd = True lastTag=cls.MetaVersion.raw cls.__versionReseted = False @@ -377,7 +391,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods logging.warning('tag not found, reseting versionning') cls.__versionReseted = True - bFound = False + bFound = False if VersionStd == "SemVer" or (bAutoVersionStd is True) : _r=re.compile(r"^\s*" + cls.VersionStds["SemVer"]["regex"] + r"\s*$", re.VERBOSE | \ re.IGNORECASE) @@ -478,4 +492,4 @@ class gitversionhelper: # pylint: disable=too-few-public-methods minor=inputversion.minor, \ patch=patch, \ revpattern=revpattern, \ - revcount=revcount) \ No newline at end of file + revcount=revcount) -- 2.47.3 From f3f3459ccf2dd31279708a7a3c5a26fa5cb5ecea Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:42:53 +0000 Subject: [PATCH 14/30] improve quality --- src/pygitversionhelper/gitversionhelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 371283e..cf59b87 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -187,7 +187,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" - + }, "PEP440" : { "regex" : packaging_VERSION_PATTERN, "Auto" : None -- 2.47.3 From 05093566d6772adafeecd9257f76070c8fe7f591 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 01:59:21 +0000 Subject: [PATCH 15/30] fix doc + try **kwargs --- src/pygitversionhelper/gitversionhelper.py | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index cf59b87..7c21a44 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -33,7 +33,7 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: Args: cmd: command line to be executed root: root directory where the command need to be executed - Return: + Returns: a list of command's return lines """ @@ -96,7 +96,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def isDirty(cls) -> bool: """ check if the repository is in dirty state - Return: + Returns: True if it is dirty """ return bool(_exec("git status --short")) @@ -129,7 +129,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods retrieve all tags from a repository Args: sort: sorting constraints (git format) - Return: + Returns: the tags list """ if sort not in cls.__validGitTagSort: @@ -142,7 +142,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods retrieve the last tag from a repository Kwargs: same_branch(bool): force searching only in the same branch - Return: + Returns: the tag """ if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): @@ -166,7 +166,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods tag: reference tag, if None the most recent one will be used Kwargs: same_branch(bool): force searching only in the same branch - Return: + Returns: the tag """ if tag is None: @@ -238,7 +238,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods get selected bump_dev_strategy Kwargs: bump_dev_strategy(str): the given bump_dev_strategy (can be None) - Return: + Returns: Kwargs given bump_dev_strategy or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy @@ -255,7 +255,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods get selected bump_type Kwargs: bump_type(str): the given bump_type (can be None) - Return: + Returns: Kwargs given bump_type or the default one. """ BumpType = cls.DefaultBumpType @@ -272,7 +272,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs: bump_type(str): the given bump_type (can be None) bump_dev_strategy(str): the given bump_dev_strategy (can be None) - Return: + Returns: the bumped version """ BumpType = self._getBumpType(**kwargs) @@ -316,7 +316,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def doFormatVersion(self,**kwargs): """ output a formated version string - Return: + Returns: formated version string """ return gitversionhelper.version.doFormatVersion(self,**kwargs) @@ -327,7 +327,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods get selected version_std Kwargs: version_std(str): the given version_std (can be None) - Return: + Returns: Kwargs given version_std or the default one. """ VersionStd = cls.DefaultInputFormat @@ -346,7 +346,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods version_std(str): the given version_std (can be None) same_branch(bool): force searching only in the same branch formated_output(bool) : output a formated version string - Return: + Returns: the last version """ if gitversionhelper.repository.isDirty() is not False: @@ -370,11 +370,12 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 """ get the last version from tags - Kwargs: - version_std(str): the given version_std (can be None) - same_branch(bool): force searching only in the same branch - formated_output(bool) : output a formated version string - Return: + Parameters: + **kwargs: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + Returns: the last version """ VersionStd = cls._getVersionStd(**kwargs) @@ -452,7 +453,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods output a formated version string Args: inputversion: version to be rendered - Return: + Returns: formated version string """ -- 2.47.3 From 4e43629dfdc0915ac5e9c9262a0dcb0c49e68a1e Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 02:26:12 +0000 Subject: [PATCH 16/30] test docstrings --- src/pygitversionhelper/gitversionhelper.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 7c21a44..ddd4ec2 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -368,13 +368,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods @classmethod def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 - """ - get the last version from tags - Parameters: - **kwargs: - version_std(str): the given version_std (can be None) - same_branch(bool): force searching only in the same branch - formated_output(bool) : output a formated version string + """get the last version from tags + Keyword Arguments: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string Returns: the last version """ -- 2.47.3 From 2598a412273208d73a928f45e15ca417eb064c13 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 09:25:43 +0000 Subject: [PATCH 17/30] fix kwargs --- src/pygitversionhelper/gitversionhelper.py | 39 +++++++++++----------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index ddd4ec2..4fd6266 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -140,7 +140,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def getLastTag(cls,**kwargs) -> Union[str,None]: """ retrieve the last tag from a repository - Kwargs: + Keyword Arguments: same_branch(bool): force searching only in the same branch Returns: the tag @@ -164,7 +164,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods retrieve the distance between HEAD and tag in the repository Arguments: tag: reference tag, if None the most recent one will be used - Kwargs: + Keyword Arguments: same_branch(bool): force searching only in the same branch Returns: the tag @@ -208,20 +208,21 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ generic version object """ + __OptDict = { "bump_type": "bump_type", "bump_dev_strategy": "bump_dev_strategy"} DefaultBumpType = "patch" BumpTypes = ["major","minor","patch","dev"] DefaultBumpDevStrategy = "post" BumpDevStrategys = ["post","pre-patch","pre-minor","pre-major"] - version_std = "None" - major: int = 0 - minor: int = 1 - patch: int = 0 - pre_count:int = 0 - post_count:int = 0 - raw:str = "0.1.0" + version_std: str = "None" + major: int = 0 + minor: int = 1 + patch: int = 0 + pre_count:int = 0 + post_count:int = 0 + raw:str = "0.1.0" def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): #pylint: disable=R0913 self.version_std = version_std @@ -236,13 +237,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def _getBumpDevStrategy(cls,**kwargs) -> str: """ get selected bump_dev_strategy - Kwargs: + Keyword Arguments: bump_dev_strategy(str): the given bump_dev_strategy (can be None) Returns: Kwargs given bump_dev_strategy or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy - if cls.__OptDict["bump_dev_strategy"] in kwargs: + if cls.__OptDict["bump_dev_strategy"] in Keyword Arguments: if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] else: @@ -253,13 +254,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def _getBumpType(cls,**kwargs) -> str: """ get selected bump_type - Kwargs: + Keyword Arguments: bump_type(str): the given bump_type (can be None) Returns: Kwargs given bump_type or the default one. """ BumpType = cls.DefaultBumpType - if cls.__OptDict["bump_type"] in kwargs: + if cls.__OptDict["bump_type"] in Keyword Arguments: if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: BumpType = kwargs[cls.__OptDict["bump_type"]] else: @@ -269,7 +270,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def bump(self,amount:int=1,**kwargs): # pylint: disable=R0912 """ bump the version to the next one - Kwargs: + Keyword Arguments: bump_type(str): the given bump_type (can be None) bump_dev_strategy(str): the given bump_dev_strategy (can be None) Returns: @@ -325,13 +326,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def _getVersionStd(cls,**kwargs): """ get selected version_std - Kwargs: + Keyword Arguments: version_std(str): the given version_std (can be None) Returns: Kwargs given version_std or the default one. """ VersionStd = cls.DefaultInputFormat - if cls.__OptDict["version_std"] in kwargs: + if cls.__OptDict["version_std"] in Keyword Arguments: if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: VersionStd = kwargs[cls.__OptDict["version_std"]] else: @@ -342,7 +343,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: """ get the current version or bump depending of repository state - Kwargs: + Keyword Arguments: version_std(str): the given version_std (can be None) same_branch(bool): force searching only in the same branch formated_output(bool) : output a formated version string @@ -353,7 +354,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \ " can not be generated.") saved_kwargs = copy(kwargs) - if "formated_output" in kwargs: + if "formated_output" in Keyword Arguments: del saved_kwargs["formated_output"] _v = cls.getLastVersion(**saved_kwargs) @@ -466,7 +467,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods pre_count = inputversion.pre_count patch = inputversion.patch - if cls.__OptDict["output_format"] in kwargs: + if cls.__OptDict["output_format"] in Keyword Arguments: OutputFormat=kwargs[cls.__OptDict["output_format"]] if OutputFormat is None: -- 2.47.3 From 04578b30665b7b53d47216aa9a1d509ceca4f369 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 19:34:26 +0000 Subject: [PATCH 18/30] fix typing + add formated_output option to bump add more unittest --- src/pygitversionhelper/gitversionhelper.py | 134 +++-- test/test_gitversionhelper.py | 660 +++++++++++++++------ 2 files changed, 577 insertions(+), 217 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 4fd6266..6731bd1 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -7,9 +7,21 @@ # work. If not, see . """ +This project try to help doing handy operations with git when +dealing with project versioning and tags on python project - +or at leat for project using PEP440 versionning or SemVer. + +Goal is to keep it compact and not covering too much other things. +This is the reason it is one single file with nested classes. +=> Design is on purpose poorly expandable to keep the scope maintainable. + +This library is maid for repository using tag as version. + + This module is the main gitversionhelper file, containing all the code. -This project aim to be kept compact and focused on helping doing handy -things with git when it deal with project versions/tags. + +Read the read me for more information. +Check the unittest s for usage samples. """ from __future__ import annotations @@ -37,15 +49,13 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: a list of command's return lines """ - - p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False) + p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False, timeout=2) if re.search("not a git repository",p.stderr): raise gitversionhelper.repository.notAGitRepository() if re.search("fatal:",p.stderr): - raise gitversionhelper.unknownGITFatalError() + raise gitversionhelper.unknownGITFatalError(p.stderr) if int(p.returncode) < 0: - raise gitversionhelper.unknownGITError - + raise gitversionhelper.unknownGITError(p.stderr) lines = p.stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] @@ -124,7 +134,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ @classmethod - def getTags(cls,sort:str = "version:refname") -> list[str]: + def getTags(cls,sort:str = "taggerdate",**kwargs) -> list[str]: """ retrieve all tags from a repository Args: @@ -132,12 +142,17 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Returns: the tags list """ + if sort not in cls.__validGitTagSort: raise gitversionhelper.wrongArguments("sort option not in allowed list") - return _exec(f"git tag -l --sort={sort}") + + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + currentBranch = _exec("git rev-parse --abbrev-ref HEAD") + return list(reversed(_exec(f"git tag --merged {currentBranch[0]} --sort={sort}"))) + return list(reversed(_exec(f"git tag -l --sort={sort}"))) @classmethod - def getLastTag(cls,**kwargs) -> Union[str,None]: + def getLastTag(cls,**kwargs) -> str | None: """ retrieve the last tag from a repository Keyword Arguments: @@ -146,9 +161,9 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the tag """ if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): - res = _exec("git describe --tags --abbrev=0") + res = _exec("git describe --tags --first-parent --abbrev=0") else: - res = _exec("git rev-list --tags --max-count=1") + res = _exec("git rev-list --tags --date-order --max-count=1") if len(res)==1: res = _exec(f"git describe --tags {res[0]}") @@ -159,7 +174,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return res[0] @classmethod - def getDistanceFromTag(cls,tag=None,**kwargs) -> int: + def getDistanceFromTag(cls,tag:str=None,**kwargs) -> int: """ retrieve the distance between HEAD and tag in the repository Arguments: @@ -179,7 +194,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ __OptDict = { "version_std": "version_std", "formated_output": "formated_output", - "output_format": "output_format"} + "output_format": "output_format", + "ignore_unknown_tags": "ignore_unknown_tags"} DefaultInputFormat = "Auto" VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)"\ r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"\ @@ -209,8 +225,9 @@ class gitversionhelper: # pylint: disable=too-few-public-methods generic version object """ - __OptDict = { "bump_type": "bump_type", - "bump_dev_strategy": "bump_dev_strategy"} + __OptDict = { "bump_type": "bump_type", + "bump_dev_strategy": "bump_dev_strategy", + "formated_output": "formated_output"} DefaultBumpType = "patch" BumpTypes = ["major","minor","patch","dev"] DefaultBumpDevStrategy = "post" @@ -243,7 +260,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given bump_dev_strategy or the default one. """ BumpDevStrategy = cls.DefaultBumpDevStrategy - if cls.__OptDict["bump_dev_strategy"] in Keyword Arguments: + if cls.__OptDict["bump_dev_strategy"] in kwargs: if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] else: @@ -260,14 +277,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given bump_type or the default one. """ BumpType = cls.DefaultBumpType - if cls.__OptDict["bump_type"] in Keyword Arguments: + if cls.__OptDict["bump_type"] in kwargs: if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: BumpType = kwargs[cls.__OptDict["bump_type"]] else: raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - def bump(self,amount:int=1,**kwargs): # pylint: disable=R0912 + def bump(self,amount:int=1,**kwargs) -> MetaVersion | str : # pylint: disable=R0912 """ bump the version to the next one Keyword Arguments: @@ -310,11 +327,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v.patch = _v.patch + amount _v.pre_count=0 _v.post_count=0 - _v.raw=_v.doFormatVersion(**kwargs) + + if ((self.__OptDict["formated_output"] in kwargs) and (kwargs[self.__OptDict["formated_output"]] is True)): + return _v.doFormatVersion(**kwargs) return _v - def doFormatVersion(self,**kwargs): + def doFormatVersion(self,**kwargs) -> str: """ output a formated version string Returns: @@ -323,7 +342,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return gitversionhelper.version.doFormatVersion(self,**kwargs) @classmethod - def _getVersionStd(cls,**kwargs): + def _getVersionStd(cls,**kwargs) -> str: """ get selected version_std Keyword Arguments: @@ -332,7 +351,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Kwargs given version_std or the default one. """ VersionStd = cls.DefaultInputFormat - if cls.__OptDict["version_std"] in Keyword Arguments: + if cls.__OptDict["version_std"] in kwargs: if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: VersionStd = kwargs[cls.__OptDict["version_std"]] else: @@ -340,7 +359,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return VersionStd @classmethod - def getCurrentVersion(cls,**kwargs) -> Union[str,MetaVersion]: + def getCurrentVersion(cls,**kwargs) -> MetaVersion | str : """ get the current version or bump depending of repository state Keyword Arguments: @@ -354,48 +373,39 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \ " can not be generated.") saved_kwargs = copy(kwargs) - if "formated_output" in Keyword Arguments: + if "formated_output" in kwargs: del saved_kwargs["formated_output"] _v = cls.getLastVersion(**saved_kwargs) if not cls.__versionReseted: amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) - _v = _v.bump(amount,**kwargs) + _v = _v.bump(amount,**saved_kwargs) if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v @classmethod - def getLastVersion(cls,**kwargs) -> Union[str,MetaVersion]: # pylint: disable=R0914, R0912, R0915 + def _parseTag(cls,tag,**kwargs): """get the last version from tags + Arguments: + tag: the tag to be parsed Keyword Arguments: version_std(str): the given version_std (can be None) - same_branch(bool): force searching only in the same branch - formated_output(bool) : output a formated version string + ignore_unknown_tags(bool): skip tags with not decoded versions (default to False) Returns: the last version """ VersionStd = cls._getVersionStd(**kwargs) - bAutoVersionStd = False if VersionStd == "Auto": bAutoVersionStd = True - - lastTag=cls.MetaVersion.raw - cls.__versionReseted = False - try: - lastTag = gitversionhelper.tag.getLastTag(**kwargs) - except gitversionhelper.tag.tagNotFound: - logging.warning('tag not found, reseting versionning') - cls.__versionReseted = True - bFound = False if VersionStd == "SemVer" or (bAutoVersionStd is True) : _r=re.compile(r"^\s*" + cls.VersionStds["SemVer"]["regex"] + r"\s*$", re.VERBOSE | \ re.IGNORECASE) - _m = re.match(_r,lastTag) + _m = re.match(_r,tag) if not _m: pass else: @@ -422,7 +432,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if VersionStd == "PEP440" or ( (bAutoVersionStd is True) and (bFound is not True)): _r=re.compile(r"^\s*" + cls.VersionStds["PEP440"]["regex"] + r"\s*$", re.VERBOSE | \ re.IGNORECASE) - _m = re.match(_r,lastTag) + _m = re.match(_r,tag) if not _m: pass else: @@ -438,16 +448,50 @@ class gitversionhelper: # pylint: disable=too-few-public-methods VersionStd = "PEP440" if not bFound : - raise gitversionhelper.version.noValidVersion("no valid version found in tags") + raise gitversionhelper.version.noValidVersion("no valid version found in tags") + return cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, tag) - _v = cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, lastTag) + @classmethod + def getLastVersion(cls,**kwargs) -> MetaVersion | str : # pylint: disable=R0914, R0912, R0915 + """get the last version from tags + Keyword Arguments: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + ignore_unknown_tags(bool): skip tags with not decoded versions (default to False) + Returns: + the last version + """ + lastTag=cls.MetaVersion.raw + cls.__versionReseted = False + try: + lastTag = gitversionhelper.tag.getLastTag(**kwargs) + except gitversionhelper.tag.tagNotFound: + logging.warning('tag not found, reseting versionning') + cls.__versionReseted = True + + _v=None + try: + _v=cls._parseTag(lastTag,**kwargs) + except gitversionhelper.version.noValidVersion: + if ((cls.__OptDict["ignore_unknown_tags"] in kwargs) and (kwargs[cls.__OptDict["ignore_unknown_tags"]] is True)): + tags = gitversionhelper.tag.getTags(sort= "taggerdate",**kwargs) + _v=None + for _tag in tags: + try: + _v=cls._parseTag(_tag,**kwargs) + break; + except: + continue + if _v is None: + raise gitversionhelper.version.noValidVersion() if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v @classmethod - def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): + def doFormatVersion(cls,inputversion:MetaVersion,**kwargs) -> str: """ output a formated version string Args: @@ -467,7 +511,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods pre_count = inputversion.pre_count patch = inputversion.patch - if cls.__OptDict["output_format"] in Keyword Arguments: + if cls.__OptDict["output_format"] in kwargs: OutputFormat=kwargs[cls.__OptDict["output_format"]] if OutputFormat is None: diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 2d12fd0..728f47c 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -12,6 +12,7 @@ import tempfile import os import pathlib import re +import time from contextlib import redirect_stdout,redirect_stderr @@ -66,129 +67,129 @@ class Test_gitversionhelper(unittest.TestCase): _v=self._test_version_readback(tag,**kwargs) self._test_version_format(_v,tag,**kwargs) - def test_nominal_version_auto_1(self): + def test_nominal__version__auto_1(self): self._test_version_readback_simple("0.0.1") - def test_nominal_version_auto_2(self): + def test_nominal__version__auto_2(self): self._test_version_readback_simple("0.0.2") - def test_nominal_version_auto_3(self): + def test_nominal__version__auto_3(self): self._test_version_readback_simple("0.1.0") - def test_nominal_version_auto_4(self): + def test_nominal__version__auto_4(self): self._test_version_readback_simple("0.1.1") - def test_nominal_version_auto_5(self): + def test_nominal__version__auto_5(self): self._test_version_readback_simple("1.0.0") - def test_nominal_version_auto_6(self): + def test_nominal__version__auto_6(self): self._test_version_readback_simple("1.1.0") - def test_nominal_version_auto_7(self): + def test_nominal__version__auto_7(self): self._test_version_readback_simple("1.2.0") - def test_nominal_version_auto_8(self): + def test_nominal__version__auto_8(self): self._test_version_readback_simple("1.1.1") - def test_nominal_version_auto_9(self): + def test_nominal__version__auto_9(self): self._test_version_readback_simple("1.2.1") - def test_nominal_version_auto_PEP440_post(self): + def test_nominal__version__auto_PEP440_post(self): self._test_version_readback_simple("1.2.1.post1") - def test_nominal_version_auto_PEP440_pre(self): + def test_nominal__version__auto_PEP440_pre(self): self._test_version_readback_simple("1.2.1.pre1") - def test_nominal_version_auto_PEP440_post_2(self): + def test_nominal__version__auto_PEP440_post_2(self): self._test_version_readback_simple("1.2.1.post10") - def test_nominal_version_auto_PEP440_pre_2(self): + def test_nominal__version__auto_PEP440_pre_2(self): self._test_version_readback_simple("1.2.1.pre10") - def test_nominal_version_auto_SemVer_post(self): + def test_nominal__version__auto_SemVer_post(self): self._test_version_readback_simple("1.2.1+post.1") - def test_nominal_version_auto_SemVer_pre(self): + def test_nominal__version__auto_SemVer_pre(self): self._test_version_readback_simple("1.2.1-pre.1") - def test_nominal_version_auto_SemVer_post_2(self): + def test_nominal__version__auto_SemVer_post_2(self): self._test_version_readback_simple("1.2.1+post.10") - def test_nominal_version_auto_Semver_pre_2(self): + def test_nominal__version__auto_Semver_pre_2(self): self._test_version_readback_simple("1.2.1-pre.10") - def test_nominal_version_PEP440_1(self): + def test_nominal__version__PEP440_1(self): self._test_version_readback_simple("0.0.1",version_std="PEP440") - def test_nominal_version_PEP440_2(self): + def test_nominal__version__PEP440_2(self): self._test_version_readback_simple("0.0.2",version_std="PEP440") - def test_nominal_version_PEP440_3(self): + def test_nominal__version__PEP440_3(self): self._test_version_readback_simple("0.1.0",version_std="PEP440") - def test_nominal_version_PEP440_4(self): + def test_nominal__version__PEP440_4(self): self._test_version_readback_simple("0.1.1",version_std="PEP440") - def test_nominal_version_PEP440_5(self): + def test_nominal__version__PEP440_5(self): self._test_version_readback_simple("1.0.0",version_std="PEP440") - def test_nominal_version_PEP440_6(self): + def test_nominal__version__PEP440_6(self): self._test_version_readback_simple("1.1.0",version_std="PEP440") - def test_nominal_version_PEP440_7(self): + def test_nominal__version__PEP440_7(self): self._test_version_readback_simple("1.2.0",version_std="PEP440") - def test_nominal_version_PEP440_8(self): + def test_nominal__version__PEP440_8(self): self._test_version_readback_simple("1.1.1",version_std="PEP440") - def test_nominal_version_PEP440_9(self): + def test_nominal__version__PEP440_9(self): self._test_version_readback_simple("1.2.1",version_std="PEP440") - def test_nominal_version_PEP440_post(self): + def test_nominal__version__PEP440_post(self): self._test_version_readback_simple("1.2.1.post1",version_std="PEP440") - def test_nominal_version_PEP440_pre(self): + def test_nominal__version__PEP440_pre(self): self._test_version_readback_simple("1.2.1.pre1",version_std="PEP440") - def test_nominal_version_PEP440_post_2(self): + def test_nominal__version__PEP440_post_2(self): self._test_version_readback_simple("1.2.1.post10",version_std="PEP440") - def test_nominal_version_PEP440_pre_2(self): + def test_nominal__version__PEP440_pre_2(self): self._test_version_readback_simple("1.2.1.pre10",version_std="PEP440") - def test_nominal_version_SemVer_1(self): + def test_nominal__version__SemVer_1(self): self._test_version_readback_simple("0.0.1",version_std="SemVer") - def test_nominal_version_SemVer_2(self): + def test_nominal__version__SemVer_2(self): self._test_version_readback_simple("0.0.2",version_std="SemVer") - def test_nominal_version_SemVer_3(self): + def test_nominal__version__SemVer_3(self): self._test_version_readback_simple("0.1.0",version_std="SemVer") - def test_nominal_version_SemVer_4(self): + def test_nominal__version__SemVer_4(self): self._test_version_readback_simple("0.1.1",version_std="SemVer") - def test_nominal_version_SemVer_5(self): + def test_nominal__version__SemVer_5(self): self._test_version_readback_simple("1.0.0",version_std="SemVer") - def test_nominal_version_SemVer_6(self): + def test_nominal__version__SemVer_6(self): self._test_version_readback_simple("1.1.0",version_std="SemVer") - def test_nominal_version_SemVer_7(self): + def test_nominal__version__SemVer_7(self): self._test_version_readback_simple("1.2.0",version_std="SemVer") - def test_nominal_version_SemVer_8(self): + def test_nominal__version__SemVer_8(self): self._test_version_readback_simple("1.1.1",version_std="SemVer") - def test_nominal_version_SemVer_9(self): + def test_nominal__version__SemVer_9(self): self._test_version_readback_simple("1.2.1",version_std="SemVer") - def test_nominal_version_SemVer_post(self): + def test_nominal__version__SemVer_post(self): self._test_version_readback_simple("1.2.1+post.1",version_std="SemVer") - def test_nominal_version_SemVer_pre(self): + def test_nominal__version__SemVer_pre(self): self._test_version_readback_simple("1.2.1-pre.1",version_std="SemVer") - def test_nominal_version_SemVer_post_2(self): + def test_nominal__version__SemVer_post_2(self): self._test_version_readback_simple("1.2.1+post.10",version_std="SemVer") - def test_nominal_version_SemVer_pre_2(self): + def test_nominal__version__SemVer_pre_2(self): self._test_version_readback_simple("1.2.1-pre.10",version_std="SemVer") - def test_nominal_version_post_PEP440_to_SemVer(self): + def test_nominal__version__post_PEP440_to_SemVer(self): _v=self._test_version_readback("1.2.1.post10",version_std="PEP440") self._test_version_format(_v,"1.2.1+post.10",version_std="SemVer") - def test_nominal_version_post_SemVer_to_PEP440(self): + def test_nominal__version__post_SemVer_to_PEP440(self): _v=self._test_version_readback("1.2.1+post.10",version_std="SemVer") self._test_version_format(_v,"1.2.1.post10",version_std="PEP440") - def test_nominal_version_pre_PEP440_to_SemVer(self): + def test_nominal__version__pre_PEP440_to_SemVer(self): _v=self._test_version_readback("1.2.1.pre10",version_std="PEP440") self._test_version_format(_v,"1.2.1-pre.10",version_std="SemVer") - def test_nominal_version_pre_SemVer_to_PEP440(self): + def test_nominal__version__pre_SemVer_to_PEP440(self): _v=self._test_version_readback("1.2.1-pre.10",version_std="SemVer") self._test_version_format(_v,"1.2.1.pre10",version_std="PEP440") - def test_nominal_version_post_SemVer_nonum(self): + def test_nominal__version__post_SemVer_nonum(self): _v=self._test_version_readback("1.2.1+post",version_std="SemVer") self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") - def test_nominal_version_post_SemVer_nonum_random(self): + def test_nominal__version__post_SemVer_nonum_random(self): _v=self._test_version_readback("1.2.1+toto",version_std="SemVer") self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") - def test_nominal_version_pre_SemVer_nonum(self): + def test_nominal__version__pre_SemVer_nonum(self): _v=self._test_version_readback("1.2.1-pre",version_std="SemVer") self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") - def test_nominal_version_pre_SemVer_nonum_random(self): + def test_nominal__version__pre_SemVer_nonum_random(self): _v=self._test_version_readback("1.2.1-toto",version_std="SemVer") self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") - def test_version_pump_SemVer(self,**kwargs): + def test_nominal__version___pump_SemVer(self,**kwargs): _v = self._test_version_readback("1.0.0",version_std="SemVer") _v = _v.bump() @@ -314,7 +315,7 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(_v.post_count, 2) self.assertEqual(_v.doFormatVersion(), "2.1.5+post.2") - def test_version_pump_PEP440(self,**kwargs): + def test_nominal__version___pump_PEP440(self,**kwargs): _v = self._test_version_readback("1.0.0",version_std="PEP440") _v = _v.bump() @@ -440,16 +441,16 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(_v.post_count, 2) self.assertEqual(_v.doFormatVersion(), "2.1.5.post2") - def test_nominal_version_SemVer_zeroRev(self): + def test_nominal__version___SemVer_zeroRev(self): _v=self._test_version_readback("0.0.0",version_std="SemVer") self._test_version_format(_v,"0.0.0",version_std="SemVer") - def test_nominal_version_PEP440_zeroRev(self): + def test_nominal__version___PEP440_zeroRev(self): _v=self._test_version_readback("0.0.0",version_std="PEP440") self._test_version_format(_v,"0.0.0",version_std="PEP440") - def test_nominal_version_PEP440_noRev_noTag(self): + def test_nominal__version___PEP440_noRev_noTag(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") @@ -459,20 +460,13 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.1.0",version_std="PEP440") self.assertEqual(_v.raw, "0.1.0") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,0) - self._test_version_format(_v,"0.1.0",version_std="PEP440") - def test_nominal_version_SemVer_noRev_noTag(self): + def test_nominal__version___SemVer_noRev_noTag(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") @@ -482,20 +476,13 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="SemVer") self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.1.0",version_std="SemVer") self.assertEqual(_v.raw, "0.1.0") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,0) - self._test_version_format(_v,"0.1.0",version_std="SemVer") - def test_nominal_version_AUTO_noRev_noTag(self): + def test_nominal__version___AUTO_noRev_noTag(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") @@ -505,21 +492,14 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getLastVersion() self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.1.0") self.assertEqual(_v.raw, "0.1.0") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,0) - self._test_version_format(_v,"0.1.0") - def test_nominal_version_AUTO_bump_commits(self): + def test_nominal__version___AUTO_bump_commits(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -529,20 +509,13 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.2.0") self.assertEqual(_v.raw, "0.2.0") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,2) self.assertEqual(_v.patch,0) self.assertEqual(_v.pre_count,0) - self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.2.0") + self.assertEqual(_v.post_count,0) with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue22") @@ -552,20 +525,13 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.2.1") self.assertEqual(_v.raw, "0.2.1") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,2) self.assertEqual(_v.patch,1) self.assertEqual(_v.pre_count,0) - self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.2.1") + self.assertEqual(_v.post_count,0) with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue223") @@ -580,20 +546,13 @@ class Test_gitversionhelper(unittest.TestCase): _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) - self.assertEqual(_v.raw, "0.2.3") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - + self._test_version_format(_v,"0.2.3") + self.assertEqual(_v.raw, "0.2.3") self.assertEqual(_v.major,0) self.assertEqual(_v.minor,2) self.assertEqual(_v.patch,3) self.assertEqual(_v.pre_count,0) self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.2.3") with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue225") @@ -604,75 +563,48 @@ class Test_gitversionhelper(unittest.TestCase): self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) self.assertIsInstance(_v.raw, str) - self.assertEqual(_v.raw, "0.2.0+post.4") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - + self._test_version_format(_v,"0.2.0+post.4") + self.assertEqual(_v.raw, "0.2.0+post.4") self.assertEqual(_v.major,0) self.assertEqual(_v.minor,2) self.assertEqual(_v.patch,0) self.assertEqual(_v.pre_count,0) self.assertEqual(_v.post_count,4) - self._test_version_format(_v,"0.2.0+post.4") _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-patch") self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) - self.assertEqual(_v.raw, "0.2.1-pre.4") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - + self._test_version_format(_v,"0.2.1-pre.4") + self.assertEqual(_v.raw, "0.2.1-pre.4") self.assertEqual(_v.major,0) self.assertEqual(_v.minor,2) self.assertEqual(_v.patch,1) self.assertEqual(_v.pre_count,4) - self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.2.1-pre.4") + self.assertEqual(_v.post_count,0) _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-minor") self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.3.0-pre.4") self.assertEqual(_v.raw, "0.3.0-pre.4") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - self.assertEqual(_v.major,0) self.assertEqual(_v.minor,3) self.assertEqual(_v.patch,0) self.assertEqual(_v.pre_count,4) self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.3.0-pre.4") _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major") self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) - self.assertEqual(_v.raw, "1.0.0-pre.4") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) - + self._test_version_format(_v,"1.0.0-pre.4") + self.assertEqual(_v.raw, "1.0.0-pre.4") self.assertEqual(_v.major,1) self.assertEqual(_v.minor,0) self.assertEqual(_v.patch,0) self.assertEqual(_v.pre_count,4) self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"1.0.0-pre.4") - def test_nominal_custom_format(self): + def test_nominal__version___custom_format(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") self.assertEqual("V_0_1_1____",_v.doFormatVersion(output_format="V_{major}_{minor}_{patch}____{revcount}")) @@ -687,25 +619,19 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major",output_format="V_{major}_{minor}",formated_output=True)) - def test_nominal_emptyrepo(self): + def test_nominal__git__emptyrepo(self): _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) - self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.1.0") self.assertEqual(_v.raw, "0.1.0") - self.assertIsInstance(_v.major, int) - self.assertIsInstance(_v.minor, int) - self.assertIsInstance(_v.patch, int) - self.assertIsInstance(_v.pre_count, int) - self.assertIsInstance(_v.post_count, int) self.assertEqual(_v.major,0) self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,0) self.assertEqual(_v.pre_count,0) self.assertEqual(_v.post_count,0) - self._test_version_format(_v,"0.1.0") - def test_defect_dirty(self): + def test_defect__git__dirty(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") with open("demofile.txt", "w+t") as tmpFile: @@ -714,11 +640,11 @@ class Test_gitversionhelper(unittest.TestCase): with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) as context: pygitversionhelper.gitversionhelper.version.getCurrentVersion() - def test_defect_wrongargument_git_sortargs(self): + def test_defect__git__wrongargument_sortargs(self): with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: pygitversionhelper.gitversionhelper.tag.getTags(sort="toto") - def test_defect_git_notagfound(self): + def test_defect__git__notagfound(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -727,7 +653,7 @@ class Test_gitversionhelper(unittest.TestCase): pygitversionhelper.gitversionhelper.tag.getLastTag() """ This test is impossible to do - def test_defect_git_multipletagsfound(self): + def test_defect__git_multipletagsfound(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -737,19 +663,416 @@ class Test_gitversionhelper(unittest.TestCase): with self.assertRaises(pygitversionhelper.gitversionhelper.tag.moreThanOneTag) as context: pygitversionhelper.gitversionhelper.tag.getLastTag() """ - - def test_defect_wrongargument_bump_type(self): + + def test_defect__wrongargument_bump_type(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="toto") - - def test_defect_wrongargument_bump_dev_strategy(self): + + def test_defect__wrongargument_bump_dev_strategy(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_dev_strategy="toto") + + def test_nominal__tag__getDistanceFromTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + self.assertEqual(2,pygitversionhelper.gitversionhelper.tag.getDistanceFromTag()) + self.assertEqual(4,pygitversionhelper.gitversionhelper.tag.getDistanceFromTag("0.2.0")) + + def test_nominal__tag__getTags(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getTags_two_branch(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getTags_two_branch_samebranch(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + + os.system("git switch master") + + self.assertEqual(set(["0.3.0","0.2.0"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + + os.system("git switch dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.2") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + os.system("git switch master") + + self.assertEqual(set(["0.3.0","0.2.0"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getLastTag_two_branches(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + os.system(f"git tag 0.1.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + os.system(f"git tag 0.2.0") + + """ + print("===") + os.system(f"git status") + print("===") + os.system(f"git describe --tags --abbrev=0") + print("===") + os.system(f"git rev-list --all") + print("===") + os.system(f"git rev-list --tags") + print("===") + os.system(f"git log --oneline --decorate=short") + print("===") + os.system(f"git describe --tags") + print("===") + """ + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.2.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + os.system(f"git tag 0.3.0") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + os.system("git switch master") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + os.system("git merge --no-ff dev -m \"merge dev into master\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + os.system(f"git tag 0.4.0") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.4.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.4.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,4) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.4.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.4.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,4) + self.assertEqual(_v.patch,0) + + def test_defect__tag__invalidtag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + os.system(f"git tag INVALIDTAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + def test_defect__tag__invalidtag_inbetween(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.0.1") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.0.1",version_std="PEP440") + self.assertEqual(_v.raw, "0.0.1") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,1) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTAG2") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA3") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA4") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() - + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.0.1",version_std="PEP440") + self.assertEqual(_v.raw, "0.0.1") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,1) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.1.2") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue6") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA5") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue7") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.1.3") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.3",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.3") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,3) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.3",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.3") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,3) + def tearDown(self): os.chdir("/") @@ -759,16 +1082,9 @@ class Test_gitversionhelperNoRepo(unittest.TestCase): self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) os.chdir(self.TmpWorkingDirPath) - def test_defect_norepo(self): + def test_defect__norepo(self): with self.assertRaises(pygitversionhelper.gitversionhelper.repository.notAGitRepository) as context: _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() def tearDown(self): - os.chdir("/") - -#print(gitversionhelper.tag.getLastTag(same_branch=True)) -#print(gitversionhelper.tag.getDistanceFromLastTag(same_branch=True)) - -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=True,version_std="PEP440")) -#print(gitversionhelper.version.getLastVersion(same_branch=False,version_std="PEP440")) \ No newline at end of file + os.chdir("/") \ No newline at end of file -- 2.47.3 From a2235005092d81820ce19b8aaf198e2bc25a28d2 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 19:38:29 +0000 Subject: [PATCH 19/30] cleanup code --- src/pygitversionhelper/gitversionhelper.py | 5 ---- test/test_gitversionhelper.py | 27 ++++++++++------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 6731bd1..67cbb13 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -25,7 +25,6 @@ Check the unittest s for usage samples. """ from __future__ import annotations -from typing import TYPE_CHECKING import os import subprocess @@ -35,10 +34,6 @@ import logging from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN -# Only imports the below statements during type checking -if TYPE_CHECKING: - from typing import Union - def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: """ helper function to handle system cmd execution diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 728f47c..107c165 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -12,9 +12,6 @@ import tempfile import os import pathlib import re -import time - -from contextlib import redirect_stdout,redirect_stderr print(__name__) print(__package__) @@ -189,7 +186,7 @@ class Test_gitversionhelper(unittest.TestCase): _v=self._test_version_readback("1.2.1-toto",version_std="SemVer") self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") - def test_nominal__version___pump_SemVer(self,**kwargs): + def test_nominal__version___pump_SemVer(self): _v = self._test_version_readback("1.0.0",version_std="SemVer") _v = _v.bump() @@ -315,7 +312,7 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(_v.post_count, 2) self.assertEqual(_v.doFormatVersion(), "2.1.5+post.2") - def test_nominal__version___pump_PEP440(self,**kwargs): + def test_nominal__version___pump_PEP440(self): _v = self._test_version_readback("1.0.0",version_std="PEP440") _v = _v.bump() @@ -637,11 +634,11 @@ class Test_gitversionhelper(unittest.TestCase): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue225") - with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) : pygitversionhelper.gitversionhelper.version.getCurrentVersion() def test_defect__git__wrongargument_sortargs(self): - with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : pygitversionhelper.gitversionhelper.tag.getTags(sort="toto") def test_defect__git__notagfound(self): @@ -649,7 +646,7 @@ class Test_gitversionhelper(unittest.TestCase): tmpFile.write("testvalue") os.system("git add .") os.system("git commit -m \"first commit\"") - with self.assertRaises(pygitversionhelper.gitversionhelper.tag.tagNotFound) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.tagNotFound) : pygitversionhelper.gitversionhelper.tag.getLastTag() """ This test is impossible to do @@ -666,12 +663,12 @@ class Test_gitversionhelper(unittest.TestCase): def test_defect__wrongargument_bump_type(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") - with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="toto") def test_defect__wrongargument_bump_dev_strategy(self): _v=self._test_version_readback("0.1.1",version_std="PEP440") - with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_dev_strategy="toto") def test_nominal__tag__getDistanceFromTag(self): @@ -956,7 +953,7 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git commit -m \"2nd commit\"") os.system(f"git tag INVALIDTAG") - with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : _v = pygitversionhelper.gitversionhelper.version.getLastVersion() def test_defect__tag__invalidtag_inbetween(self): @@ -972,7 +969,7 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git commit -m \"commit\"") os.system(f"git tag INVALIDTAG") - with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : _v = pygitversionhelper.gitversionhelper.version.getLastVersion() _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) @@ -1001,7 +998,7 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git commit -m \"commit\"") os.system(f"git tag INVALIDTA4") - with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : _v = pygitversionhelper.gitversionhelper.version.getLastVersion() _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) @@ -1040,7 +1037,7 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git commit -m \"commit\"") os.system(f"git tag INVALIDTA5") - with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : _v = pygitversionhelper.gitversionhelper.version.getLastVersion() _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) @@ -1083,7 +1080,7 @@ class Test_gitversionhelperNoRepo(unittest.TestCase): os.chdir(self.TmpWorkingDirPath) def test_defect__norepo(self): - with self.assertRaises(pygitversionhelper.gitversionhelper.repository.notAGitRepository) as context: + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.notAGitRepository) : _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() def tearDown(self): -- 2.47.3 From 7d9f2a77920925a4c94616abcbf442e1f93c3607 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 20:11:14 +0000 Subject: [PATCH 20/30] improve coverage and unittest and quality --- src/pygitversionhelper/gitversionhelper.py | 46 +++++++++++++--------- test/test_gitversionhelper.py | 33 ++++++++++++++-- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 67cbb13..363d4ad 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -47,9 +47,9 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False, timeout=2) if re.search("not a git repository",p.stderr): raise gitversionhelper.repository.notAGitRepository() - if re.search("fatal:",p.stderr): + if re.search("fatal:",p.stderr): #pragma: nocover raise gitversionhelper.unknownGITFatalError(p.stderr) - if int(p.returncode) < 0: + if int(p.returncode) < 0: #pragma: nocover raise gitversionhelper.unknownGITError(p.stderr) lines = p.stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] @@ -137,10 +137,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Returns: the tags list """ - + if sort not in cls.__validGitTagSort: raise gitversionhelper.wrongArguments("sort option not in allowed list") - + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): currentBranch = _exec("git rev-parse --abbrev-ref HEAD") return list(reversed(_exec(f"git tag --merged {currentBranch[0]} --sort={sort}"))) @@ -164,7 +164,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if len(res)==0: raise cls.tagNotFound("no tag found in commit history") - if len(res)!=1: + if len(res)!=1: #pragma: nocover raise cls.moreThanOneTag("multiple tags on same commit is unsupported") return res[0] @@ -196,9 +196,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"\ r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"\ r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", - "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", - "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" - + "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", + "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" }, "PEP440" : { "regex" : packaging_VERSION_PATTERN, "Auto" : None @@ -215,6 +214,11 @@ class gitversionhelper: # pylint: disable=too-few-public-methods no valid version found exception """ + class PreAndPostVersionUnsupported(versionException): + """ + pre and post release can not be present at the same time + """ + class MetaVersion: """ generic version object @@ -279,7 +283,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - def bump(self,amount:int=1,**kwargs) -> MetaVersion | str : # pylint: disable=R0912 + def bump(self,amount:int=1,**kwargs) -> cls | str : # pylint: disable=R0912 """ bump the version to the next one Keyword Arguments: @@ -298,7 +302,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v.pre_count = _v.pre_count + amount else: _v.post_count = _v.post_count + amount - elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]: + #elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]: + else: if _v.post_count > 0: _v.post_count = _v.post_count + amount else: @@ -308,7 +313,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods elif BumpDevStrategy == "pre-minor": _v.minor = _v.minor + 1 _v.patch = 0 - elif BumpDevStrategy == "pre-major": + #elif BumpDevStrategy == "pre-major": + else: _v.major = _v.major + 1 _v.minor = 0 _v.patch = 0 @@ -318,12 +324,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v.major = _v.major + amount elif BumpType == "minor": _v.minor = _v.minor + amount - elif BumpType == "patch": + #elif BumpType == "patch": + else: _v.patch = _v.patch + amount _v.pre_count=0 _v.post_count=0 _v.raw=_v.doFormatVersion(**kwargs) - + if ((self.__OptDict["formated_output"] in kwargs) and (kwargs[self.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) return _v @@ -382,7 +389,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return _v @classmethod - def _parseTag(cls,tag,**kwargs): + def _parseTag(cls,tag,**kwargs): # pylint: disable=R0914, R0912, R0915 """get the last version from tags Arguments: tag: the tag to be parsed @@ -468,7 +475,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v=None try: _v=cls._parseTag(lastTag,**kwargs) - except gitversionhelper.version.noValidVersion: + except gitversionhelper.version.noValidVersion as _ex: if ((cls.__OptDict["ignore_unknown_tags"] in kwargs) and (kwargs[cls.__OptDict["ignore_unknown_tags"]] is True)): tags = gitversionhelper.tag.getTags(sort= "taggerdate",**kwargs) _v=None @@ -476,10 +483,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods try: _v=cls._parseTag(_tag,**kwargs) break; - except: + except gitversionhelper.version.noValidVersion: continue if _v is None: - raise gitversionhelper.version.noValidVersion() + raise gitversionhelper.version.noValidVersion() from _ex if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) @@ -512,7 +519,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if OutputFormat is None: OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0 and pre_count > 0: - raise RuntimeError("pre and post release can not be present at the same time") + raise gitversionhelper.version.PreAndPostVersionUnsupported() if VersionStd == "PEP440": if post_count > 0: revpattern=".post" @@ -520,7 +527,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods elif pre_count > 0: revpattern=".pre" revcount=f"{pre_count}" - elif VersionStd == "SemVer": + #elif VersionStd == "SemVer": + else: if post_count > 0: revpattern="+post" revcount=f".{post_count}" diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 107c165..eec9e1d 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -12,6 +12,7 @@ import tempfile import os import pathlib import re +import copy print(__name__) print(__package__) @@ -36,7 +37,7 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git add .") os.system("git commit -m \"first commit\"") os.system(f"git tag {tag}") - + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(**kwargs) self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) @@ -53,6 +54,7 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(int(_m.group("MAJ")),_v.major) self.assertEqual(int(_m.group("MIN")),_v.minor) self.assertEqual(int(_m.group("PATCH")),_v.patch) + return _v def _test_version_format(self,_v:pygitversionhelper.gitversionhelper.version.MetaVersion,tag:str,**kwargs): @@ -63,6 +65,17 @@ class Test_gitversionhelper(unittest.TestCase): def _test_version_readback_simple(self,tag:str,**kwargs): _v=self._test_version_readback(tag,**kwargs) self._test_version_format(_v,tag,**kwargs) + + def test_nominal__version__formated_output(self): + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("PEP440", + 1, + 0, + 0, + 0, + 0, + "1.0.0") + self.assertEqual("1.0.1", _v.bump(formated_output=True)) + self.assertEqual("2.0.0", _v.bump(formated_output=True,bump_type="major")) def test_nominal__version__auto_1(self): self._test_version_readback_simple("0.0.1") @@ -636,6 +649,14 @@ class Test_gitversionhelper(unittest.TestCase): with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) : pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + + def test_defect__version_post_and_pre(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + _v=self._test_version_readback("0.1.1.pre1.post1",version_std="PEP440") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + _v=self._test_version_readback("0.1.1-pre.1+post.1",version_std="SemVer") def test_defect__git__wrongargument_sortargs(self): with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : @@ -649,7 +670,7 @@ class Test_gitversionhelper(unittest.TestCase): with self.assertRaises(pygitversionhelper.gitversionhelper.tag.tagNotFound) : pygitversionhelper.gitversionhelper.tag.getLastTag() - """ This test is impossible to do + """ This test is impossible to do because current implementation can only return one tag def test_defect__git_multipletagsfound(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") @@ -657,8 +678,8 @@ class Test_gitversionhelper(unittest.TestCase): os.system("git commit -m \"first commit\"") os.system(f"git tag 0.1.0") os.system(f"git tag 0.2.0") - with self.assertRaises(pygitversionhelper.gitversionhelper.tag.moreThanOneTag) as context: - pygitversionhelper.gitversionhelper.tag.getLastTag() + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.moreThanOneTag) : + pygitversionhelper.gitversionhelper.tag.getLastTag(same_branch=True) """ def test_defect__wrongargument_bump_type(self): @@ -955,6 +976,10 @@ class Test_gitversionhelper(unittest.TestCase): with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) def test_defect__tag__invalidtag_inbetween(self): with open("demofile.txt", "w+t") as tmpFile: -- 2.47.3 From c9e6f4f436863de66bfc91377572cd40b02af53b Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 20:20:11 +0000 Subject: [PATCH 21/30] improve detection of wrong case: both pre and post index + test --- src/pygitversionhelper/gitversionhelper.py | 7 +++++- test/test_gitversionhelper.py | 25 +++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 363d4ad..e8735ca 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -451,6 +451,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if not bFound : raise gitversionhelper.version.noValidVersion("no valid version found in tags") + + if pre_count > 0 and post_count > 0: + raise cls.PreAndPostVersionUnsupported("can not parse a version with both pre" \ + " and post release number.") return cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, tag) @classmethod @@ -519,7 +523,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if OutputFormat is None: OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0 and pre_count > 0: - raise gitversionhelper.version.PreAndPostVersionUnsupported() + raise gitversionhelper.version.PreAndPostVersionUnsupported("cannot output a version with both pre " \ + "and post release number.") if VersionStd == "PEP440": if post_count > 0: revpattern=".post" diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index eec9e1d..869b00a 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -651,13 +651,32 @@ class Test_gitversionhelper(unittest.TestCase): pygitversionhelper.gitversionhelper.version.getCurrentVersion() - def test_defect__version_post_and_pre(self): + def test_defect__version_post_and_pre_output(self): + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("PEP440", + 0, + 0, + 1, + 1, + 1, + "0.0.1.pre1.post1") with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : - _v=self._test_version_readback("0.1.1.pre1.post1",version_std="PEP440") + _v.doFormatVersion() + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("SemVer", + 0, + 0, + 1, + 1, + 1, + "0.0.1-pre.1+post.1") with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : - _v=self._test_version_readback("0.1.1-pre.1+post.1",version_std="SemVer") + _v.doFormatVersion() + + def test_defect__version_post_and_pre_parse(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + pygitversionhelper.gitversionhelper.version._parseTag("0.0.1.pre1.post1") + def test_defect__git__wrongargument_sortargs(self): with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : pygitversionhelper.gitversionhelper.tag.getTags(sort="toto") -- 2.47.3 From a1cf4983ff6daaad2242f36d0f388d3e8b5aa6e2 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 20:21:59 +0000 Subject: [PATCH 22/30] improve code quality --- src/pygitversionhelper/gitversionhelper.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index e8735ca..75ced2d 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -283,7 +283,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") return BumpType - def bump(self,amount:int=1,**kwargs) -> cls | str : # pylint: disable=R0912 + def bump(self,amount:int=1,**kwargs) -> gitversionhelper.version.MetaVersion | str : # pylint: disable=R0912 """ bump the version to the next one Keyword Arguments: @@ -451,7 +451,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods if not bFound : raise gitversionhelper.version.noValidVersion("no valid version found in tags") - + if pre_count > 0 and post_count > 0: raise cls.PreAndPostVersionUnsupported("can not parse a version with both pre" \ " and post release number.") @@ -479,18 +479,18 @@ class gitversionhelper: # pylint: disable=too-few-public-methods _v=None try: _v=cls._parseTag(lastTag,**kwargs) - except gitversionhelper.version.noValidVersion as _ex: + except gitversionhelper.version.noValidVersion as _ex: if ((cls.__OptDict["ignore_unknown_tags"] in kwargs) and (kwargs[cls.__OptDict["ignore_unknown_tags"]] is True)): tags = gitversionhelper.tag.getTags(sort= "taggerdate",**kwargs) - _v=None + _v = None for _tag in tags: try: _v=cls._parseTag(_tag,**kwargs) - break; + break except gitversionhelper.version.noValidVersion: continue if _v is None: - raise gitversionhelper.version.noValidVersion() from _ex + raise gitversionhelper.version.noValidVersion() from _ex if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): return _v.doFormatVersion(**kwargs) -- 2.47.3 From 961f92d9c61d3ad28d5b7d37f5049ff455dbc7e6 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 21:02:49 +0000 Subject: [PATCH 23/30] update doc and docstring --- README.md | 58 ++++------- docs-static/usage.md | 113 ++++++++++++++++++--- src/pygitversionhelper/gitversionhelper.py | 21 ++-- 3 files changed, 137 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 77fbcfa..39ca5c2 100644 --- a/README.md +++ b/README.md @@ -3,46 +3,30 @@ ![](docs-static/Library.jpg) -# Python project template +#pyGitVersionHelper -A nice template to start a blank python projet. - -This template automate a lot of handy things and allow CI/CD automatic releases generation. +a tiny library to help versioning management of git python project -It is also collectings data to feed Jenkins build. - -Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pychachadummyproject/{{branch}}/latest/). +Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/{{branch}}/latest/). ## Features - -### Generic pipeline skeleton: - - Prepare - - GetCode - - BuildPackage - - Install - - CheckCode - - PlotMetrics - - RunUnitTests - - GenDOC - - PostRelease + - list tags + - get last tag + - get last version + - get current version (bump) + - convert / switch from SemVer to PEP440 (both ways) + - automatic version format detection (SemVer by default) -### CI/CD Environment - - Jenkins - - Gitea (with patch for dynamic Readme variables: https://chacha.ddns.net/gitea/chacha/GiteaMarkupVariable) - - Docker - - MkDocsWeb - -### CI/CD Helper libs - - VirtualEnv - - Changelog generation based on commits - - copier - - pylint + pylint_json2html - - mypy - - unittest + xmlrunner + junitparser + junit2htmlreport - - mkdocs +# Options: + - restrict to same branch + - both SemVer and PEP440 support + - custom output format + - configurable default bump type major, minor, patch or dev + - configurable default bump type: post, pre-patch, pre-minor, pre-major + - ignore non-version tag + - force version format -### Python project - - Full .toml implementation - - .whl automatic generation - - dynamic versionning using git repository - - embedded unit-test \ No newline at end of file +# Process: + - CI/CD developpment: Gitea / Jenkins + few python libs + - Generated documentation through mkdocs + - CI/CD on Linux, manually tested in Windows environnement \ No newline at end of file diff --git a/docs-static/usage.md b/docs-static/usage.md index 7763bbd..ce1b628 100644 --- a/docs-static/usage.md +++ b/docs-static/usage.md @@ -1,16 +1,105 @@ # Usage -## Pulvinar dolor -Donec dapibus est fermentum justo volutpat condimentum. Integer quis nunc neque. Donec dictum vehicula justo, in facilisis ex tincidunt in. -Vivamus sollicitudin sem dui, id mollis orci facilisis ut. Proin sed pulvinar dolor. Donec volutpat commodo urna imperdiet pulvinar. Fusce eget aliquam risus. -Vivamus viverra luctus ex, in finibus mi. Nullam elementum dapibus mollis. Ut suscipit volutpat ex, quis feugiat lacus consectetur eu. +## Installation +From master repository: -## Condimentum faucibus -Quisque auctor egestas sem, luctus suscipit ex maximus vitae. Duis facilisis augue et condimentum faucibus. -Donec cursus, enim a sagittis egestas, lectus lorem eleifend libero, at tincidunt leo magna at libero. -Nunc eros velit, suscipit luctus tempor vel, finibus et est. Curabitur efficitur pretium pulvinar. -Donec urna lectus, vulputate quis turpis sed, placerat congue urna. Phasellus aliquet fermentum quam, non auctor elit porta nec. Morbi eu ligula at nisl ultricies condimentum vitae id ante. + python -m pip install git+https://chacha.ddns.net/gitea/chacha/pygitversionhelper.git@master -## Aliquam lacinia -In volutpat lorem ex, et fringilla nibh faucibus quis. Mauris et arcu elementum, auctor dui vitae, egestas arcu. Duis sit amet aliquam quam. -Phasellus a odio turpis. Etiam tristique mi eu enim varius, eget facilisis est vestibulum. Aliquam lacinia nec purus sed luctus. Cras at laoreet erat. \ No newline at end of file +From local .whl file: + + python -m pip install pygitversionhelper--py3-none-any.whl + +From public repository: + + TBD + +## Import in your project +Add this line on the top of your python script: + + #from pygitversionhelper import gitversionhelper + +(optionnal)If you need to catch exception from this module: + + #from pygitversionhelper import gitversionhelperException + +## Basic API +All the API commands are static and so it is not needed to create instantiate any object. + +They are all executed in the current active directory. + +One easy way to change directory: + + import os + os.chdir("") + +### sublib: repository +To check if a repository is dirty: + + if gitversionhelper.repository.isDirty(): + print("repository is dirty") + +### sublib: tag +List all tags (default to taggerdate order): + + for tag in gitversionhelper.tag.getTags(): + print(f"found tag: {tag}") + +List all tags (using git refname order): + + for tag in gitversionhelper.tag.getTags("v:refname"): + print(f"found tag: {tag}") + +Get the last tag: + + print(f"most recent repository tag: {gitversionhelper.tag.getLastTag()}") + +Get the last tag (only on same branch): + + print(f"most recent repository tag: {gitversionhelper.tag.getLastTag(same_branch=True)}") + + +Get the distance from HEAD to last tag: + + print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag()}") + +Get the distance from HEAD to last tag (only on same branch): + + print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag(same_branch=True)}") + +### sublib: version +Get the last found version in the repository (return MetaVersion object): + + print(f"most recent repository version: {gitversionhelper.tag.getLastVersion()}") + +Get the last found version in the repository (return formated string): + + print(f"most recent repository version: {gitversionhelper.tag.getLastVersion(formated_output=True)}") + +Others kwargs available to this function: + - version_std: string to force a version standard for rendering ("PEP440" or "SemVer") + - same_branch: boolean to force searching on same branch + - ignore_unknown_tags: boolean to allow unknown tag to be ignored + +Get the current version of the repository, including bumped one if the last one is not tagged (return MetaVersion object): + + print(f"most recent repository version: {gitversionhelper.tag.getCurrentVersion()}") + +kwargs available to this function: + - All same args as getLastVersion() + - bump_type: if version need to be pump, allow to configure next release update type: major, minor, patch, dev + - bump_dev_strategy: if bump_type is dev, allow to choose dev update strategy: post, pre-patch, pre-minor, pre-major + +A version object can also be manually formated: + + _version = gitversionhelper.tag.getCurrentVersion() + _version.doFormatVersion() + #or + gitversionhelper.version.doFormatVersion(_version) + +kwargs available to those function: + - output_format: string to choose a rendering format ("Auto","PEP440" or "SemVer") + +##Limitations +- MultiThreading and async behavior is not tested. +- Multiple tag on the same commit is not supported. +- Branch filter when searching for a version is only tested with -no-ff strategy \ No newline at end of file diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 75ced2d..30d8fd5 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -9,19 +9,22 @@ """ This project try to help doing handy operations with git when dealing with project versioning and tags on python project - -or at leat for project using PEP440 versionning or SemVer. +at leat for project using PEP440 or SemVer standards. -Goal is to keep it compact and not covering too much other things. -This is the reason it is one single file with nested classes. -=> Design is on purpose poorly expandable to keep the scope maintainable. +One requirement is to keep it compact and to not cover too much fancy features. +This is the reason why it is one single file with nested classes. +=> Design is on-purpose poorly expandable to keep the scope light. This library is maid for repository using tag as version. +Support for non-version tags is optional and not well tested. - -This module is the main gitversionhelper file, containing all the code. +This module is the main project file, containing all the code. Read the read me for more information. Check the unittest s for usage samples. + +Note: + Other Parameters are **kwargs """ from __future__ import annotations @@ -338,6 +341,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def doFormatVersion(self,**kwargs) -> str: """ output a formated version string + Keyword Arguments: + output_format: output format to render ("Auto" or "PEP440" or "SemVer") Returns: formated version string """ @@ -368,6 +373,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods version_std(str): the given version_std (can be None) same_branch(bool): force searching only in the same branch formated_output(bool) : output a formated version string + bump_type(str): the given bump_type (can be None) + bump_dev_strategy(str): the given bump_dev_strategy (can be None) Returns: the last version """ @@ -500,6 +507,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods def doFormatVersion(cls,inputversion:MetaVersion,**kwargs) -> str: """ output a formated version string + Keyword Arguments: + output_format: output format to render ("Auto" or "PEP440" or "SemVer") Args: inputversion: version to be rendered Returns: -- 2.47.3 From 3ce09a019407e0d4fff0292e45409e366d135e64 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 21:04:03 +0000 Subject: [PATCH 24/30] fix typo --- README.md | 8 ++++---- docs-static/usage.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 39ca5c2..83d9851 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ ![](docs-static/Library.jpg) -#pyGitVersionHelper +# pyGitVersionHelper -a tiny library to help versioning management of git python project +A tiny library to help versioning management of git python project Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/{{branch}}/latest/). @@ -17,7 +17,7 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv - convert / switch from SemVer to PEP440 (both ways) - automatic version format detection (SemVer by default) -# Options: +# Options - restrict to same branch - both SemVer and PEP440 support - custom output format @@ -26,7 +26,7 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv - ignore non-version tag - force version format -# Process: +# Process - CI/CD developpment: Gitea / Jenkins + few python libs - Generated documentation through mkdocs - CI/CD on Linux, manually tested in Windows environnement \ No newline at end of file diff --git a/docs-static/usage.md b/docs-static/usage.md index ce1b628..2147106 100644 --- a/docs-static/usage.md +++ b/docs-static/usage.md @@ -99,7 +99,7 @@ A version object can also be manually formated: kwargs available to those function: - output_format: string to choose a rendering format ("Auto","PEP440" or "SemVer") -##Limitations +## Limitations - MultiThreading and async behavior is not tested. - Multiple tag on the same commit is not supported. - Branch filter when searching for a version is only tested with -no-ff strategy \ No newline at end of file -- 2.47.3 From fff52596b1aef03621bacee73bc186f3d5e5abee Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 21:06:39 +0000 Subject: [PATCH 25/30] update doc --- README.md | 8 ++++---- docs-static/usage.md | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 83d9851..f5e3154 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv - convert / switch from SemVer to PEP440 (both ways) - automatic version format detection (SemVer by default) -# Options +## Options - restrict to same branch - both SemVer and PEP440 support - custom output format @@ -26,7 +26,7 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv - ignore non-version tag - force version format -# Process - - CI/CD developpment: Gitea / Jenkins + few python libs - - Generated documentation through mkdocs +## Process + - full CI/CD developpment: Gitea / Jenkins + few python libs (pytlint, coverage, unittest, mkdocs) + - documentation generated mkdocs and self-hosted - CI/CD on Linux, manually tested in Windows environnement \ No newline at end of file diff --git a/docs-static/usage.md b/docs-static/usage.md index 2147106..1b29332 100644 --- a/docs-static/usage.md +++ b/docs-static/usage.md @@ -1,6 +1,7 @@ # Usage ## Installation + From master repository: python -m pip install git+https://chacha.ddns.net/gitea/chacha/pygitversionhelper.git@master @@ -14,6 +15,7 @@ From public repository: TBD ## Import in your project + Add this line on the top of your python script: #from pygitversionhelper import gitversionhelper @@ -23,6 +25,7 @@ Add this line on the top of your python script: #from pygitversionhelper import gitversionhelperException ## Basic API + All the API commands are static and so it is not needed to create instantiate any object. They are all executed in the current active directory. @@ -33,12 +36,14 @@ One easy way to change directory: os.chdir("") ### sublib: repository + To check if a repository is dirty: if gitversionhelper.repository.isDirty(): print("repository is dirty") ### sublib: tag + List all tags (default to taggerdate order): for tag in gitversionhelper.tag.getTags(): @@ -67,6 +72,7 @@ Get the distance from HEAD to last tag (only on same branch): print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag(same_branch=True)}") ### sublib: version + Get the last found version in the repository (return MetaVersion object): print(f"most recent repository version: {gitversionhelper.tag.getLastVersion()}") @@ -100,6 +106,8 @@ kwargs available to those function: - output_format: string to choose a rendering format ("Auto","PEP440" or "SemVer") ## Limitations + +There is unfortunately some technical limitation : - MultiThreading and async behavior is not tested. - Multiple tag on the same commit is not supported. - Branch filter when searching for a version is only tested with -no-ff strategy \ No newline at end of file -- 2.47.3 From 38cde9d700660a4be0eaed228414a1e474decc7a Mon Sep 17 00:00:00 2001 From: cclecle Date: Sat, 18 Mar 2023 21:13:11 +0000 Subject: [PATCH 26/30] reword --- README.md | 7 +++++-- docs-static/usage.md | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f5e3154..65cb993 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,10 @@ # pyGitVersionHelper -A tiny library to help versioning management of git python project +_A tiny library to help versioning management of git python projects_ + +Because a good developer is a lazy developer and version management in CI/CD can be very time consuming. + Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/{{branch}}/latest/). @@ -13,7 +16,7 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv - list tags - get last tag - get last version - - get current version (bump) + - get current version (bumped) - convert / switch from SemVer to PEP440 (both ways) - automatic version format detection (SemVer by default) diff --git a/docs-static/usage.md b/docs-static/usage.md index 1b29332..18b1cdb 100644 --- a/docs-static/usage.md +++ b/docs-static/usage.md @@ -20,13 +20,13 @@ Add this line on the top of your python script: #from pygitversionhelper import gitversionhelper -(optionnal)If you need to catch exception from this module: +[optionnal] If you need to catch exception from this module: #from pygitversionhelper import gitversionhelperException ## Basic API -All the API commands are static and so it is not needed to create instantiate any object. +All the API commands are static so it is not needed to create instantiate any object. They are all executed in the current active directory. @@ -44,12 +44,12 @@ To check if a repository is dirty: ### sublib: tag -List all tags (default to taggerdate order): +List all tags [default to taggerdate order]: for tag in gitversionhelper.tag.getTags(): print(f"found tag: {tag}") -List all tags (using git refname order): +List all tags [using git refname order]: for tag in gitversionhelper.tag.getTags("v:refname"): print(f"found tag: {tag}") @@ -58,7 +58,7 @@ Get the last tag: print(f"most recent repository tag: {gitversionhelper.tag.getLastTag()}") -Get the last tag (only on same branch): +Get the last tag [only on same branch]: print(f"most recent repository tag: {gitversionhelper.tag.getLastTag(same_branch=True)}") @@ -67,26 +67,26 @@ Get the distance from HEAD to last tag: print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag()}") -Get the distance from HEAD to last tag (only on same branch): +Get the distance from HEAD to last tag [only on same branch]: print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag(same_branch=True)}") ### sublib: version -Get the last found version in the repository (return MetaVersion object): +Get the last found version in the repository [return MetaVersion object]: print(f"most recent repository version: {gitversionhelper.tag.getLastVersion()}") -Get the last found version in the repository (return formated string): +Get the last found version in the repository [return formated string]: print(f"most recent repository version: {gitversionhelper.tag.getLastVersion(formated_output=True)}") Others kwargs available to this function: - - version_std: string to force a version standard for rendering ("PEP440" or "SemVer") + - version_std: string to force a version standard for rendering ["PEP440" or "SemVer"] - same_branch: boolean to force searching on same branch - ignore_unknown_tags: boolean to allow unknown tag to be ignored -Get the current version of the repository, including bumped one if the last one is not tagged (return MetaVersion object): +Get the current version of the repository, automatically bump it if the last one is not tagged [returns MetaVersion object]: print(f"most recent repository version: {gitversionhelper.tag.getCurrentVersion()}") @@ -103,7 +103,7 @@ A version object can also be manually formated: gitversionhelper.version.doFormatVersion(_version) kwargs available to those function: - - output_format: string to choose a rendering format ("Auto","PEP440" or "SemVer") + - output_format: string to choose a rendering format ["Auto","PEP440" or "SemVer"] ## Limitations -- 2.47.3 From cefa964a3a8fcf5debe0c578964eeaa16408fd7d Mon Sep 17 00:00:00 2001 From: cclecle Date: Sun, 19 Mar 2023 09:52:42 +0000 Subject: [PATCH 27/30] add commit class --- Jenkinsfile | 1 - src/pygitversionhelper/gitversionhelper.py | 115 +++++++++++- test/test_gitversionhelper.py | 204 ++++++++++++++++++++- 3 files changed, 309 insertions(+), 11 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ceb6d3a..2b80254 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -181,7 +181,6 @@ pipeline { sh("rm -Rf ~/_gitrepo || true") - //sh(". ~/BUILD_ENV/bin/activate && python -m copier --vcs-ref HEAD --prereleases --defaults ./ ~/_gitrepo") sh(script: """#!/bin/sh - |. ~/BUILD_ENV/bin/activate |exec python - << '__EOWRAPPER__' diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 30d8fd5..9f70d58 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -5,7 +5,6 @@ # # You should have received a copy of the license along with this # work. If not, see . - """ This project try to help doing handy operations with git when dealing with project versioning and tags on python project - @@ -13,6 +12,7 @@ at leat for project using PEP440 or SemVer standards. One requirement is to keep it compact and to not cover too much fancy features. This is the reason why it is one single file with nested classes. + => Design is on-purpose poorly expandable to keep the scope light. This library is maid for repository using tag as version. @@ -23,8 +23,7 @@ This module is the main project file, containing all the code. Read the read me for more information. Check the unittest s for usage samples. -Note: - Other Parameters are **kwargs +Note: _Other Parameters_ are **kwargs """ from __future__ import annotations @@ -37,7 +36,7 @@ import logging from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN -def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: +def _exec(cmd: str, root: str | os.PathLike | None = None, raw:bool = False) -> list[str]: """ helper function to handle system cmd execution Args: @@ -47,13 +46,16 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]: a list of command's return lines """ - p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False, timeout=2) + p = subprocess.run(cmd, text=True, cwd=root, capture_output=True, check=False, timeout=2,shell=True) if re.search("not a git repository",p.stderr): raise gitversionhelper.repository.notAGitRepository() if re.search("fatal:",p.stderr): #pragma: nocover raise gitversionhelper.unknownGITFatalError(p.stderr) if int(p.returncode) < 0: #pragma: nocover raise gitversionhelper.unknownGITError(p.stderr) + + if raw: + return p.stdout lines = p.stdout.splitlines() return [line.rstrip() for line in lines if line.rstrip()] @@ -108,6 +110,103 @@ class gitversionhelper: # pylint: disable=too-few-public-methods True if it is dirty """ return bool(_exec("git status --short")) + class commit: + """ + class containing methods focusing on commits + """ + __OptDict = {"same_branch": "same_branch", + "merged_output":"merged_output"} + + class commitException(gitversionhelperException): + """ + generic commit exception + """ + + class commitNotFound(commitException): + """ + tag not found exception + """ + + @classmethod + def getMessagesSinceTag(cls,tag:str,**kwargs) -> str: + """ + retrieve a commits message history from repository + from LastCommit to the given tag + Keyword Arguments: + merged_output: output one single merged string + same_branch(bool): force searching only in the same branch + Returns: + the commit message + """ + current_commit_id=cls.getLast(**kwargs) + tag_commit_id=cls.getFromTag(tag,**kwargs) + + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + commits = _exec(f"git rev-list --first-parent --ancestry-path {tag_commit_id}..{current_commit_id}") + else: + commits = _exec(f"git rev-list --ancestry-path {tag_commit_id}..{current_commit_id}") + result=[] + for commit in commits: + result.append(cls.getMessage(commit,**kwargs)) + + if ((cls.__OptDict["merged_output"] in kwargs) and (kwargs[cls.__OptDict["merged_output"]] is True)): + print("JOIN") + return os.linesep.join(result) + return result + + @classmethod + def getMessage(cls, id:str, **kwargs) -> str: + """ + retrieve a commit message from repository + Args: + id: id of the commit + Returns: + the commit message + """ + try: + res=_exec(f"git log -z --pretty=tformat:%B%-C() -n 1 {id}",None,True).rstrip('\x00') + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + + return res.replace('\r\n','\n').replace('\n','\r\n') + + @classmethod + def getFromTag(cls,tag:str,**kwargs) -> str: + """ + retrieve a commit from repository associated to a tag + Args: + tag: tag of the commit + Returns: + the commit Id + """ + try: + res=_exec(f"git rev-list -n 1 {tag}") + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + if len(res)==0: + raise cls.commitNotFound("no commit found in commit history") + return res[0] + + @classmethod + def getLast(cls,**kwargs) -> str: + """ + retrieve last commit from repository + Keyword Arguments: + same_branch(bool): force searching only in the same branch + Returns: + the commit Id + """ + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + try: + res = _exec("git rev-parse HEAD") + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + else: + res = _exec("git for-each-ref --sort=-committerdate refs/heads/ --count 1 --format=%(objectname)") + + if len(res)==0: + raise cls.commitNotFound("no commit found in commit history") + return res[0] class tag: """ @@ -132,7 +231,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ @classmethod - def getTags(cls,sort:str = "taggerdate",**kwargs) -> list[str]: + def getTags(cls,sort:str = "taggerdate",**kwargs) -> list[str|None]: """ retrieve all tags from a repository Args: @@ -457,8 +556,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods VersionStd = "PEP440" if not bFound : - raise gitversionhelper.version.noValidVersion("no valid version found in tags") - + raise gitversionhelper.version.noValidVersion("no valid version found in tags") + if pre_count > 0 and post_count > 0: raise cls.PreAndPostVersionUnsupported("can not parse a version with both pre" \ " and post release number.") diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 869b00a..0d7db2b 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -13,6 +13,8 @@ import os import pathlib import re import copy +import time +import subprocess print(__name__) print(__package__) @@ -507,8 +509,7 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(_v.major,0) self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,0) - - + def test_nominal__version___AUTO_bump_commits(self): with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") @@ -1114,6 +1115,205 @@ class Test_gitversionhelper(unittest.TestCase): self.assertEqual(_v.minor,1) self.assertEqual(_v.patch,3) + def test_nominal__commit_getLast(self): + # sleeps are needed because commit date have a 1-sec accuracy :-/ + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + initial_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + second_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,second_commit) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + third_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,third_commit) + self.assertNotEqual(second_commit,third_commit) + + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + fourth_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,fourth_commit) + self.assertNotEqual(second_commit,fourth_commit) + self.assertNotEqual(third_commit,fourth_commit) + + os.system("git switch master") + + fourth2_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertEqual(fourth2_commit,fourth_commit) + + fourth3_commit = pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + + self.assertNotEqual(fourth3_commit,fourth_commit) + self.assertEqual(fourth3_commit,third_commit) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + fifth_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertNotEqual(fifth_commit,fourth3_commit) + + os.system("git switch dev") + + fifth2_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertEqual(fifth2_commit,fifth_commit) + + fifth2_commit = pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + self.assertEqual(fifth2_commit,fourth_commit) + + def test_defect__commit_notfound(self): + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getLast() + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + + def test_nominal__commit_getFromTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + + initial_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit2\"") + os.system(f"git tag TAG") + + second_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertNotEqual(second_commit,initial_commit) + second_commit2 = pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + self.assertEqual(second_commit,second_commit2) + self.assertNotEqual(second_commit2,initial_commit) + + def test_defect__commit_notfound2(self): + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + os.system(f"git tag OTHER_TAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + def test_nominal__commit_getMessage(self): + commit_message="AAAABBB CCCCDDDD" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system(f"git commit -m \"{commit_message}\"") + commit = pygitversionhelper.gitversionhelper.commit.getLast() + message = pygitversionhelper.gitversionhelper.commit.getMessage(commit) + self.assertEqual(message,commit_message) + + def test_nominal__commit_getMessage2(self): + commit_message="""AAAABBB + CCCCDDDD + -f dfsds dfsdfs $""" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message) + subprocess.run(cmd,text=True,check=True) + + commit = pygitversionhelper.gitversionhelper.commit.getLast() + message = pygitversionhelper.gitversionhelper.commit.getMessage(commit) + print(message) + self.assertEqual(message,commit_message) + + def test_nominal__commit_getMessagesSinceLastTag(self): + commit_message1="1.1 update this"+ os.linesep+\ + "1.1 fix that" + os.linesep+\ + "1.1 test" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message1) + subprocess.run(cmd,text=True,check=True) + os.system(f"git tag 0.1.1") + + commit_message2="2.1 update this"+ os.linesep+\ + "2.1 fix that" + os.linesep+\ + "2.1 test" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message2) + subprocess.run(cmd,text=True,check=True) + + commit_message3="3.1 update this"+ os.linesep+\ + "3.1 fix that" + os.linesep+\ + "3.1 test" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message3) + subprocess.run(cmd,text=True,check=True) + + commit_message4="4.1 update this" + os.linesep+\ + "4.1 fix that" + os.linesep+\ + "4.1 test" + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message4) + subprocess.run(cmd,text=True,check=True) + + res = pygitversionhelper.gitversionhelper.commit.getMessagesSinceTag("0.1.1") + self.assertEqual( [commit_message4,commit_message3,commit_message2],res) + + res = pygitversionhelper.gitversionhelper.commit.getMessagesSinceTag("0.1.1",merged_output=True) + self.assertEqual( os.linesep.join([commit_message4,commit_message3,commit_message2]),res) + + def tearDown(self): os.chdir("/") -- 2.47.3 From 63b3f25b330ea318cb2bb6c2ce7237a89ba2c028 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sun, 19 Mar 2023 10:03:50 +0000 Subject: [PATCH 28/30] fix quality warning + commit messages unittest --- src/pygitversionhelper/gitversionhelper.py | 28 +++++++++++----------- test/test_gitversionhelper.py | 11 ++++++--- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 9f70d58..9bbcef3 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -53,7 +53,7 @@ def _exec(cmd: str, root: str | os.PathLike | None = None, raw:bool = False) -> raise gitversionhelper.unknownGITFatalError(p.stderr) if int(p.returncode) < 0: #pragma: nocover raise gitversionhelper.unknownGITError(p.stderr) - + if raw: return p.stdout lines = p.stdout.splitlines() @@ -126,7 +126,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ tag not found exception """ - + @classmethod def getMessagesSinceTag(cls,tag:str,**kwargs) -> str: """ @@ -140,38 +140,38 @@ class gitversionhelper: # pylint: disable=too-few-public-methods """ current_commit_id=cls.getLast(**kwargs) tag_commit_id=cls.getFromTag(tag,**kwargs) - - if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): commits = _exec(f"git rev-list --first-parent --ancestry-path {tag_commit_id}..{current_commit_id}") else: commits = _exec(f"git rev-list --ancestry-path {tag_commit_id}..{current_commit_id}") result=[] for commit in commits: result.append(cls.getMessage(commit,**kwargs)) - - if ((cls.__OptDict["merged_output"] in kwargs) and (kwargs[cls.__OptDict["merged_output"]] is True)): + + if ((cls.__OptDict["merged_output"] in kwargs) and (kwargs[cls.__OptDict["merged_output"]] is True)): print("JOIN") return os.linesep.join(result) return result - + @classmethod - def getMessage(cls, id:str, **kwargs) -> str: + def getMessage(cls, hash:str) -> str: """ retrieve a commit message from repository Args: - id: id of the commit + hash: id of the commit Returns: the commit message """ try: - res=_exec(f"git log -z --pretty=tformat:%B%-C() -n 1 {id}",None,True).rstrip('\x00') + res=_exec(f"git log -z --pretty=tformat:%B%-C() -n 1 {hash}",None,True).rstrip('\x00') except gitversionhelper.unknownGITFatalError as _e: raise cls.commitNotFound("no commit found in commit history") from _e return res.replace('\r\n','\n').replace('\n','\r\n') - + @classmethod - def getFromTag(cls,tag:str,**kwargs) -> str: + def getFromTag(cls,tag:str) -> str: """ retrieve a commit from repository associated to a tag Args: @@ -196,14 +196,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods Returns: the commit Id """ - if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): try: res = _exec("git rev-parse HEAD") except gitversionhelper.unknownGITFatalError as _e: raise cls.commitNotFound("no commit found in commit history") from _e else: res = _exec("git for-each-ref --sort=-committerdate refs/heads/ --count 1 --format=%(objectname)") - + if len(res)==0: raise cls.commitNotFound("no commit found in commit history") return res[0] diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py index 0d7db2b..ed0af02 100644 --- a/test/test_gitversionhelper.py +++ b/test/test_gitversionhelper.py @@ -1235,7 +1235,7 @@ class Test_gitversionhelper(unittest.TestCase): pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") def test_nominal__commit_getMessage(self): - commit_message="AAAABBB CCCCDDDD" + commit_message="AAAABBB CCCCDDDD".replace('\r\n','\n').replace('\n','\r\n') with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -1247,7 +1247,8 @@ class Test_gitversionhelper(unittest.TestCase): def test_nominal__commit_getMessage2(self): commit_message="""AAAABBB CCCCDDDD - -f dfsds dfsdfs $""" + -f dfsds dfsdfs $""".replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -1258,13 +1259,14 @@ class Test_gitversionhelper(unittest.TestCase): commit = pygitversionhelper.gitversionhelper.commit.getLast() message = pygitversionhelper.gitversionhelper.commit.getMessage(commit) - print(message) + self.assertEqual(message,commit_message) def test_nominal__commit_getMessagesSinceLastTag(self): commit_message1="1.1 update this"+ os.linesep+\ "1.1 fix that" + os.linesep+\ "1.1 test" + commit_message1=commit_message1.replace('\r\n','\n').replace('\n','\r\n') with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue") os.system("git add .") @@ -1277,6 +1279,7 @@ class Test_gitversionhelper(unittest.TestCase): commit_message2="2.1 update this"+ os.linesep+\ "2.1 fix that" + os.linesep+\ "2.1 test" + commit_message2=commit_message2.replace('\r\n','\n').replace('\n','\r\n') with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue2") os.system("git add .") @@ -1288,6 +1291,7 @@ class Test_gitversionhelper(unittest.TestCase): commit_message3="3.1 update this"+ os.linesep+\ "3.1 fix that" + os.linesep+\ "3.1 test" + commit_message3=commit_message3.replace('\r\n','\n').replace('\n','\r\n') with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue3") os.system("git add .") @@ -1299,6 +1303,7 @@ class Test_gitversionhelper(unittest.TestCase): commit_message4="4.1 update this" + os.linesep+\ "4.1 fix that" + os.linesep+\ "4.1 test" + commit_message4=commit_message4.replace('\r\n','\n').replace('\n','\r\n') with open("demofile.txt", "w+t") as tmpFile: tmpFile.write("testvalue4") os.system("git add .") -- 2.47.3 From 2951e70c47f55ff437c98f58cdf8a524061ae110 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sun, 19 Mar 2023 10:15:23 +0000 Subject: [PATCH 29/30] fix: escapes git strings options --- src/pygitversionhelper/gitversionhelper.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 9bbcef3..68c1ebd 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -139,7 +139,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the commit message """ current_commit_id=cls.getLast(**kwargs) - tag_commit_id=cls.getFromTag(tag,**kwargs) + tag_commit_id=cls.getFromTag(tag) if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): commits = _exec(f"git rev-list --first-parent --ancestry-path {tag_commit_id}..{current_commit_id}") @@ -147,7 +147,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods commits = _exec(f"git rev-list --ancestry-path {tag_commit_id}..{current_commit_id}") result=[] for commit in commits: - result.append(cls.getMessage(commit,**kwargs)) + result.append(cls.getMessage(commit)) if ((cls.__OptDict["merged_output"] in kwargs) and (kwargs[cls.__OptDict["merged_output"]] is True)): print("JOIN") @@ -164,7 +164,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods the commit message """ try: - res=_exec(f"git log -z --pretty=tformat:%B%-C() -n 1 {hash}",None,True).rstrip('\x00') + res=_exec(f"git log -z --pretty=\"tformat:%B%-C()\" -n 1 {hash}",None,True).rstrip('\x00') except gitversionhelper.unknownGITFatalError as _e: raise cls.commitNotFound("no commit found in commit history") from _e @@ -202,7 +202,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods except gitversionhelper.unknownGITFatalError as _e: raise cls.commitNotFound("no commit found in commit history") from _e else: - res = _exec("git for-each-ref --sort=-committerdate refs/heads/ --count 1 --format=%(objectname)") + res = _exec("git for-each-ref --sort=-committerdate refs/heads/ --count 1 --format=\"%(objectname)\"") if len(res)==0: raise cls.commitNotFound("no commit found in commit history") -- 2.47.3 From 792666c6ecb623d8c3afd88f4d97dd86dfda7018 Mon Sep 17 00:00:00 2001 From: cclecle Date: Sun, 19 Mar 2023 10:17:58 +0000 Subject: [PATCH 30/30] fix: rename hash -> commit_hash to avoid using builtin symbol --- src/pygitversionhelper/gitversionhelper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py index 68c1ebd..9b0dfab 100644 --- a/src/pygitversionhelper/gitversionhelper.py +++ b/src/pygitversionhelper/gitversionhelper.py @@ -155,16 +155,16 @@ class gitversionhelper: # pylint: disable=too-few-public-methods return result @classmethod - def getMessage(cls, hash:str) -> str: + def getMessage(cls, commit_hash:str) -> str: """ retrieve a commit message from repository Args: - hash: id of the commit + commit_hash: id of the commit Returns: the commit message """ try: - res=_exec(f"git log -z --pretty=\"tformat:%B%-C()\" -n 1 {hash}",None,True).rstrip('\x00') + res=_exec(f"git log -z --pretty=\"tformat:%B%-C()\" -n 1 {commit_hash}",None,True).rstrip('\x00') except gitversionhelper.unknownGITFatalError as _e: raise cls.commitNotFound("no commit found in commit history") from _e -- 2.47.3