Compare commits

...

18 Commits

Author SHA1 Message Date
cclecle
a1cf4983ff improve code quality 2023-03-18 20:21:59 +00:00
cclecle
c9e6f4f436 improve detection of wrong case: both pre and post index + test 2023-03-18 20:20:11 +00:00
cclecle
7d9f2a7792 improve coverage and unittest and quality 2023-03-18 20:11:14 +00:00
cclecle
a223500509 cleanup code 2023-03-18 19:38:29 +00:00
cclecle
04578b3066 fix typing + add formated_output option to bump
add more unittest
2023-03-18 19:34:26 +00:00
cclecle
2598a41227 fix kwargs 2023-03-18 09:25:43 +00:00
cclecle
4e43629dfd test docstrings 2023-03-18 02:26:12 +00:00
cclecle
05093566d6 fix doc + try **kwargs 2023-03-18 01:59:21 +00:00
cclecle
f3f3459ccf improve quality 2023-03-18 01:42:53 +00:00
cclecle
df74016945 improve quality 2023-03-18 01:39:25 +00:00
cclecle
bce35f0a60 fix quality 2023-03-18 01:32:44 +00:00
cclecle
39e7d8236c update: update: quality column length check 120 -> 140 2023-03-18 01:23:33 +00:00
cclecle
6a1331d1bf improve quality 2023-03-18 01:22:32 +00:00
cclecle
96250682ec fix missing user/mail for git 2023-03-18 00:59:35 +00:00
cclecle
014e8ac0d2 fix + more unittests 2023-03-18 00:49:33 +00:00
cclecle
b74269b39b more tests and features 2023-03-18 00:10:00 +00:00
cclecle
46ee6dec57 fix: quality score 2023-03-17 18:54:36 +00:00
cclecle
c0d5e4480c fix: code quality 2023-03-17 18:48:18 +00:00
4 changed files with 1529 additions and 192 deletions

View File

@@ -61,7 +61,7 @@ class quality_check(helper_withresults_base):
'--ignore=_version.py', '--ignore=_version.py',
'--reports=y', '--reports=y',
'--score=yes', '--score=yes',
'--max-line-length=120', '--max-line-length=140',
'src.' + cls.pyproject['project']['name']], exit=False) 'src.' + cls.pyproject['project']['name']], exit=False)
with open(cls.get_result_dir()/"report.json","w+", encoding='utf-8') as Outfile: with open(cls.get_result_dir()/"report.json","w+", encoding='utf-8') as Outfile:

View File

@@ -19,4 +19,4 @@ except PackageNotFoundError: # pragma: no cover
warnings.warn("can not read __version__, assuming local test context, setting it to ?.?.?") warnings.warn("can not read __version__, assuming local test context, setting it to ?.?.?")
__version__ = "?.?.?" __version__ = "?.?.?"
from .gitversionhelper import gitversionhelper from .gitversionhelper import gitversionhelper, gitversionhelperException

View File

@@ -1,317 +1,547 @@
# 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 <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
"""
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.
Read the read me for more information.
Check the unittest s for usage samples.
"""
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING
import os import os
import subprocess import subprocess
import re import re
from copy import copy from copy import copy
import logging
from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN 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]: 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: Args:
cmd: command line to be executed cmd: command line to be executed
root: root directory where the command need to be executed root: root directory where the command need to be executed
Return: Returns:
a list of command's return lines a list of command's return lines
""" """
try: p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False, timeout=2)
stdout = subprocess.check_output(cmd, shell=True, text=True, cwd=root) if re.search("not a git repository",p.stderr):
except subprocess.CalledProcessError as e: raise gitversionhelper.repository.notAGitRepository()
stdout = e.output if re.search("fatal:",p.stderr): #pragma: nocover
lines = stdout.splitlines() raise gitversionhelper.unknownGITFatalError(p.stderr)
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()] return [line.rstrip() for line in lines if line.rstrip()]
class gitversionhelper: # pylint: disable=too-few-public-methods class gitversionhelperException(Exception):
""" """
Main gitversionhelper class general Module Exception
""" """
class gitversionhelper: # pylint: disable=too-few-public-methods
"""
main gitversionhelper class
"""
class wrongArguments(gitversionhelperException):
"""
wrong argument generic exception
"""
class unknownGITError(gitversionhelperException):
"""
unknown git error generic exception
"""
class unknownGITFatalError(unknownGITError):
"""
unknown fatal git error generic exception
"""
class repository: class repository:
""" """
class containing methods focusing on repository class containing methods focusing on repository
""" """
class repositoryException(gitversionhelperException):
"""
generic repository exeption
"""
class notAGitRepository(repositoryException):
"""
not a git repository exception
"""
class repositoryDirty(repositoryException):
"""
dirty repository exception
"""
@classmethod @classmethod
def isDirty(cls) -> bool: def isDirty(cls) -> bool:
""" """
Check if the repository is in dirty state check if the repository is in dirty state
Return: Returns:
True if it is dirty True if it is dirty
""" """
return True if _exec(f"git status --short") else False return bool(_exec("git status --short"))
class tag: class tag:
""" """
class containing methods focusing on tags class containing methods focusing on tags
""" """
__OptDict = {"same_branch": "same_branch"} __OptDict = {"same_branch": "same_branch"}
__validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"]
class tagException(gitversionhelperException):
"""
generic tag exception
"""
class tagNotFound(tagException):
"""
tag not found exception
"""
class moreThanOneTag(tagException):
"""
more than one tag exception
"""
@classmethod @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 retrieve all tags from a repository
Args: Args:
sort: sorting constraints (git format) sort: sorting constraints (git format)
Return: Returns:
the tags list the tags list
""" """
if sort not in cls.__validGitTagSort: 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}")
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 @classmethod
def getLastTag(cls,**kwargs) -> Union[str,None]: def getLastTag(cls,**kwargs) -> str | None:
f""" """
retrieve the last tag from a repository retrieve the last tag from a repository
Arguments: Keyword Arguments:
sort: sorting constraints (git format) same_branch(bool): force searching only in the same branch
Kwargs: Returns:
{cls.__OptDict["same_branch"]}: force searching only in the same branch
Return:
the tag the tag
""" """
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)):
return _exec("git describe --tags --abbrev=0")[0] res = _exec("git describe --tags --first-parent --abbrev=0")
tag = _exec("git rev-list --tags --max-count=1") else:
return _exec(f"git describe --tags {tag[0]}")[0] res = _exec("git rev-list --tags --date-order --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: #pragma: nocover
raise cls.moreThanOneTag("multiple tags on same commit is unsupported")
return res[0]
@classmethod @classmethod
def getDistanceFromTag(cls,tag=None,**kwargs) -> int: def getDistanceFromTag(cls,tag:str=None,**kwargs) -> int:
f""" """
retrieve the distance from tag in the repository retrieve the distance between HEAD and tag in the repository
Arguments: Arguments:
tag: reference tag, if None the most recent one will be used tag: reference tag, if None the most recent one will be used
Kwargs: Keyword Arguments:
{cls.__OptDict["same_branch"]}: force searching only in the same branch same_branch(bool): force searching only in the same branch
Return: Returns:
the tag the tag
""" """
if (tag is None): if tag is None:
tag = cls.getLastTag(**kwargs) tag = cls.getLastTag(**kwargs)
return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) return int(_exec(f"git rev-list {tag}..HEAD --count")[0])
class version: class version:
""" """
class containing methods focusing on versions class containing methods focusing on versions
""" """
__OptDict = { "version_std": "version_std", __OptDict = { "version_std": "version_std",
"formated_output": "formated_output", "formated_output": "formated_output",
"output_format": "output_format"} "output_format": "output_format",
DefaultInputFormat = "PEP440" "ignore_unknown_tags": "ignore_unknown_tags"}
VersionStds = { "SemVer" : { "regex" : r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"}, DefaultInputFormat = "Auto"
"PEP440" : { "regex" : packaging_VERSION_PATTERN } VersionStds = { "SemVer" : { "regex" : r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)"\
r"(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$",
"regex_preversion_num": r"(?:\.)(?P<num>(?:\d+(?!\w))+)",
"regex_build_num" : r"(?:\.)(?P<num>(?:\d+(?!\w))+)"
},
"PEP440" : { "regex" : packaging_VERSION_PATTERN,
"Auto" : None
}
} }
__versionReseted = False
class versionException(gitversionhelperException):
"""
generic version exception
"""
class noValidVersion(versionException):
"""
no valid version found exception
"""
class PreAndPostVersionUnsupported(versionException):
"""
pre and post release can not be present at the same time
"""
class MetaVersion: class MetaVersion:
""" """
generic version object 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" DefaultBumpType = "patch"
BumpTypes = ["major","minor","patch","dev"] BumpTypes = ["major","minor","patch","dev"]
DefaultBumpDevStrategy = "post" DefaultBumpDevStrategy = "post"
BumpDevStrategys = ["post","pre","force_post","force_pre"] BumpDevStrategys = ["post","pre-patch","pre-minor","pre-major"]
major: int = 0
minor: int = 1 version_std: str = "None"
patch: int = 0 major: int = 0
pre_count:int = 0 minor: int = 1
post_count:int = 0 patch: int = 0
raw:str = "0.1.0" pre_count:int = 0
post_count:int = 0
def __init__(self,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): raw:str = "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
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
self.patch = patch
self.pre_count = pre_count
self.post_count = post_count
self.raw = raw
@classmethod @classmethod
def _getBumpDevStrategy(cls,**kwargs) -> str: def _getBumpDevStrategy(cls,**kwargs) -> str:
f""" """
get selected bump_dev_strategy get selected bump_dev_strategy
Kwargs: Keyword Arguments:
{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: Returns:
Kwargs given {cls.__OptDict["bump_dev_strategy"]} or the default one. Kwargs given bump_dev_strategy or the default one.
""" """
BumpDevStrategy = cls.DefaultBumpDevStrategy 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: if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys:
BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]]
else: else:
raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested")
return BumpDevStrategy return BumpDevStrategy
@classmethod @classmethod
def _getBumpType(cls,**kwargs) -> str: def _getBumpType(cls,**kwargs) -> str:
f""" """
get selected bump_type get selected bump_type
Kwargs: Keyword Arguments:
{cls.__OptDict["bump_type"]}: the given bump_type (can be None) bump_type(str): the given bump_type (can be None)
Return: Returns:
Kwargs given {cls.__OptDict["bump_type"]} or the default one. Kwargs given bump_type or the default one.
""" """
BumpType = cls.DefaultBumpType 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: if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes:
BumpType = kwargs[cls.__OptDict["bump_type"]] BumpType = kwargs[cls.__OptDict["bump_type"]]
else: else:
raise RuntimeError(f"invalid {cls.__OptDict['bump_type']} requested") raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested")
return BumpType return BumpType
def bump(self,**kwargs): def bump(self,amount:int=1,**kwargs) -> gitversionhelper.version.MetaVersion | str : # pylint: disable=R0912
f""" """
bump the version to the next one bump the version to the next one
Kwargs: Keyword Arguments:
{self.__OptDict["bump_type"]}: the given bump_type (can be None) bump_type(str): the given bump_type (can be None)
{self.__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: Returns:
the bumped version the bumped version
""" """
BumpType = self._getBumpType(**kwargs) BumpType = self._getBumpType(**kwargs)
BumpDevStrategy=self._getBumpDevStrategy(**kwargs) BumpDevStrategy=self._getBumpDevStrategy(**kwargs)
_v=copy(self) _v=copy(self)
if BumpType is "dev":
if BumpDevStrategy is "post": if BumpType == "dev":
if BumpDevStrategy == "post":
if _v.pre_count > 0: if _v.pre_count > 0:
_v.pre_count = _v.pre_count + 1 _v.pre_count = _v.pre_count + amount
else: else:
_v.post_count = _v.post_count + 1 _v.post_count = _v.post_count + amount
elif BumpDevStrategy is "pre": #elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]:
else:
if _v.post_count > 0: if _v.post_count > 0:
_v.post_count = _v.post_count + 1 _v.post_count = _v.post_count + amount
else: else:
_v.pre_count = _v.pre_count + 1 if _v.pre_count == 0:
elif BumpDevStrategy is "force_post": if BumpDevStrategy == "pre-patch":
pass _v.patch = _v.patch + 1
elif BumpDevStrategy is "force_pre": elif BumpDevStrategy == "pre-minor":
pass _v.minor = _v.minor + 1
_v.patch = 0
#elif BumpDevStrategy == "pre-major":
else:
_v.major = _v.major + 1
_v.minor = 0
_v.patch = 0
_v.pre_count = _v.pre_count + amount
else: else:
if BumpType is "major": if BumpType == "major":
_v.major = _v.major + 1 _v.major = _v.major + amount
elif BumpType is "minor": elif BumpType == "minor":
_v.minor = _v.minor + 1 _v.minor = _v.minor + amount
elif BumpType is "patch": #elif BumpType == "patch":
_v.patch = _v.patch + 1 else:
_v.patch = _v.patch + amount
_v.pre_count=0 _v.pre_count=0
_v.post_count=0 _v.post_count=0
_v.raw=_v.doFormatVersion(**kwargs)
_v.raw="{major}.{minor}.{patch}{revpattern}{revcount}".format(major=_v.major,minor=_v.minor,patch=_v.patch,revpattern="",revcount="")
if ((self.__OptDict["formated_output"] in kwargs) and (kwargs[self.__OptDict["formated_output"]] is True)):
return _v.doFormatVersion(**kwargs)
return _v return _v
def doFormatVersion(self,**kwargs): def doFormatVersion(self,**kwargs) -> str:
"""
output a formated version string
Returns:
formated version string
"""
return gitversionhelper.version.doFormatVersion(self,**kwargs) return gitversionhelper.version.doFormatVersion(self,**kwargs)
@classmethod @classmethod
def _getVersionStd(cls,**kwargs): def _getVersionStd(cls,**kwargs) -> str:
""" """
get selected version_std get selected version_std
Keyword Arguments:
version_std(str): the given version_std (can be None)
Returns:
Kwargs given version_std or the default one.
""" """
VersionStd = cls.DefaultInputFormat 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: if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds:
VersionStd = kwargs[cls.__OptDict["version_std"]] VersionStd = kwargs[cls.__OptDict["version_std"]]
else: else:
raise RuntimeError(f"invalid {cls.__OptDict['version_std']} requested") raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['version_std']} requested")
return VersionStd return VersionStd
@classmethod @classmethod
def getLastVersion(cls,**kwargs): def getCurrentVersion(cls,**kwargs) -> MetaVersion | str :
""" """
get last version from git tags get the current version or bump depending of repository state
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
""" """
VersionStd = cls._getVersionStd(**kwargs) if gitversionhelper.repository.isDirty() is not False:
_r=re.compile(r"^\s*" + cls.VersionStds[VersionStd]["regex"] + r"\s*$", re.VERBOSE | re.IGNORECASE) raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \
" can not be generated.")
lastTag = gitversionhelper.tag.getLastTag(**kwargs) saved_kwargs = copy(kwargs)
if "formated_output" in kwargs:
_m = re.match(_r,lastTag) del saved_kwargs["formated_output"]
if not _m:
raise RuntimeError("no valid version found in tags") _v = cls.getLastVersion(**saved_kwargs)
if VersionStd is "PEP440":
ver=_m.group("release").split(".") if not cls.__versionReseted:
ver += ["0"] * (3 - len(ver)) amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs)
ver[0]=int(ver[0]) _v = _v.bump(amount,**saved_kwargs)
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 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"]] is True)): if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)):
return cls.doFormatVersion(_v,**kwargs) return _v.doFormatVersion(**kwargs)
else: return _v
return _v
@classmethod @classmethod
def doFormatVersion(cls,inputversion:MetaVersion,**kwargs): def _parseTag(cls,tag,**kwargs): # pylint: disable=R0914, R0912, R0915
""" """get the last version from tags
output a formated version Arguments:
tag: the tag to be parsed
Keyword Arguments:
version_std(str): the given version_std (can be None)
ignore_unknown_tags(bool): skip tags with not decoded versions (default to False)
Returns:
the last version
""" """
VersionStd = cls._getVersionStd(**kwargs) VersionStd = cls._getVersionStd(**kwargs)
bAutoVersionStd = False
if VersionStd == "Auto":
bAutoVersionStd = 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,tag)
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,tag)
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 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
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 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
for _tag in tags:
try:
_v=cls._parseTag(_tag,**kwargs)
break
except gitversionhelper.version.noValidVersion:
continue
if _v is None:
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)
return _v
@classmethod
def doFormatVersion(cls,inputversion:MetaVersion,**kwargs) -> str:
"""
output a formated version string
Args:
inputversion: version to be rendered
Returns:
formated version string
"""
VersionStd = cls._getVersionStd(**kwargs)
if VersionStd=="Auto" :
VersionStd = inputversion.version_std
OutputFormat = None OutputFormat = None
revpattern="" revpattern=""
revcount="" revcount=""
post_count = inputversion.post_count post_count = inputversion.post_count
pre_count = inputversion.pre_count pre_count = inputversion.pre_count
patch = inputversion.patch patch = inputversion.patch
if (cls.__OptDict["output_format"] in kwargs):
if cls.__OptDict["output_format"] in kwargs:
OutputFormat=kwargs[cls.__OptDict["output_format"]] OutputFormat=kwargs[cls.__OptDict["output_format"]]
if OutputFormat is None: if OutputFormat is None:
if VersionStd is "PEP440": OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}"
OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" if post_count > 0 and pre_count > 0:
raise gitversionhelper.version.PreAndPostVersionUnsupported("cannot output a version with both pre " \
"and post release number.")
if VersionStd == "PEP440":
if post_count > 0: if post_count > 0:
revpattern=".post" revpattern=".post"
revcount=f"{post_count}" revcount=f"{post_count}"
elif VersionStd is "SemVer": elif pre_count > 0:
OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" revpattern=".pre"
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}" revcount=f"{pre_count}"
#elif VersionStd == "SemVer":
return OutputFormat.format(major=inputversion.major,minor=inputversion.minor,patch=patch,revpattern=revpattern,revcount=revcount) else:
if post_count > 0:
revpattern="+post"
revcount=f".{post_count}"
elif pre_count > 0:
revpattern="-pre"
#print(gitversionhelper.head.isDirty()) revcount=f".{pre_count}"
#print(gitversionhelper.tag.getTags()) return OutputFormat.format( major=inputversion.major, \
#print(gitversionhelper.tag.getLastTag()) minor=inputversion.minor, \
#print(gitversionhelper.tag.getLastTag(same_branch=True)) patch=patch, \
#print(gitversionhelper.tag.getDistanceFromLastTag()) revpattern=revpattern, \
#print(gitversionhelper.tag.getDistanceFromLastTag(same_branch=True)) revcount=revcount)
#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 ="")

File diff suppressed because it is too large Load Diff