From 89695decf680d187f47dccd38db2bcbff46dcf04 Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 17 Mar 2023 08:54:24 +0000 Subject: [PATCH] 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