mirror of
https://github.com/drewcassidy/yaclog.git
synced 2024-09-01 14:58:58 +00:00
Improve version number incrementing by rewriting version module
This commit is contained in:
parent
17a17fea41
commit
8394fbfd94
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- improved version header parsing
|
- improved version header parsing
|
||||||
|
- improved version number incrementing. It can now handle other text surrounding a pep440-compliant version number, which will not be modified
|
||||||
|
|
||||||
## 0.3.3 - 2021-04-27
|
## 0.3.3 - 2021-04-27
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import unittest
|
import unittest
|
||||||
|
import traceback
|
||||||
|
|
||||||
import git
|
import git
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
@ -9,7 +10,9 @@ from yaclog.cli.__main__ import cli
|
|||||||
|
|
||||||
|
|
||||||
def check_result(runner, result, success: bool = True):
|
def check_result(runner, result, success: bool = True):
|
||||||
runner.assertEqual((result.exit_code == 0), success, f'output: {result.output}\ntraceback: {result.exc_info}')
|
runner.assertEqual((result.exit_code == 0), success,
|
||||||
|
f'\noutput: {result.output}\ntraceback: ' + ''.join(
|
||||||
|
traceback.format_exception(*result.exc_info)))
|
||||||
|
|
||||||
|
|
||||||
class TestCreation(unittest.TestCase):
|
class TestCreation(unittest.TestCase):
|
||||||
|
@ -269,7 +269,7 @@ class Changelog:
|
|||||||
# strip whitespace from header
|
# strip whitespace from header
|
||||||
self.header = markdown.join(header_segments)
|
self.header = markdown.join(header_segments)
|
||||||
|
|
||||||
def write(self, path: os.PathLike = None) -> None:
|
def write(self, path=None) -> None:
|
||||||
"""
|
"""
|
||||||
Write a markdown changelog to a file.
|
Write a markdown changelog to a file.
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ class Changelog:
|
|||||||
def current_version(self, released: Optional[bool] = None, new_version: bool = False,
|
def current_version(self, released: Optional[bool] = None, new_version: bool = False,
|
||||||
new_version_name: str = 'Unreleased') -> VersionEntry:
|
new_version_name: str = 'Unreleased') -> VersionEntry:
|
||||||
"""
|
"""
|
||||||
Get the current version entry from the changelog
|
Get the current version from the changelog
|
||||||
|
|
||||||
:param released: if the returned version should be a released version,
|
:param released: if the returned version should be a released version,
|
||||||
an unreleased version, or ``None`` to return the most recent
|
an unreleased version, or ``None`` to return the most recent
|
||||||
|
@ -179,33 +179,34 @@ def entry(obj: Changelog, bullets, paragraphs, section_name, version_name):
|
|||||||
|
|
||||||
|
|
||||||
@cli.command(short_help='Release versions.')
|
@cli.command(short_help='Release versions.')
|
||||||
@click.option('-v', '--version', 'v_flag', type=str, default=None, help='The new version number to use.')
|
@click.option('-v', '--version', 'version_name', type=str, default=None, help='The new version number to use.')
|
||||||
@click.option('-M', '--major', 'v_flag', flag_value='+M', help='Increment major version number.')
|
@click.option('-M', '--major', 'rel_seg', flag_value=0, default=None, help='Increment major version number.')
|
||||||
@click.option('-m', '--minor', 'v_flag', flag_value='+m', help='Increment minor version number.')
|
@click.option('-m', '--minor', 'rel_seg', flag_value=1, help='Increment minor version number.')
|
||||||
@click.option('-p', '--patch', 'v_flag', flag_value='+p', help='Increment patch number.')
|
@click.option('-p', '--patch', 'rel_seg', flag_value=2, help='Increment patch number.')
|
||||||
@click.option('-a', '--alpha', 'v_flag', flag_value='+a', help='Increment alpha version number.')
|
@click.option('-a', '--alpha', 'pre_seg', flag_value='a', default=None, help='Increment alpha version number.')
|
||||||
@click.option('-b', '--beta', 'v_flag', flag_value='+b', help='Increment beta version number.')
|
@click.option('-b', '--beta', 'pre_seg', flag_value='b', help='Increment beta version number.')
|
||||||
@click.option('-r', '--rc', 'v_flag', flag_value='+rc', help='Increment release candidate version number.')
|
@click.option('-r', '--rc', 'pre_seg', flag_value='rc', help='Increment release candidate version number.')
|
||||||
@click.option('-c', '--commit', is_flag=True, help='Create a git commit tagged with the new version number.')
|
@click.option('-c', '--commit', is_flag=True, help='Create a git commit tagged with the new version number.')
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def release(obj: Changelog, v_flag, commit):
|
def release(obj: Changelog, version_name, rel_seg, pre_seg, commit):
|
||||||
"""Release versions in the changelog and increment their version numbers"""
|
"""Release versions in the changelog and increment their version numbers"""
|
||||||
matches = [v for v in obj.versions if v.name.lower() != 'unreleased']
|
try:
|
||||||
if len(matches) == 0:
|
version = obj.current_version(released=True).name
|
||||||
|
except ValueError:
|
||||||
version = '0.0.0'
|
version = '0.0.0'
|
||||||
else:
|
|
||||||
version = matches[0].name
|
|
||||||
|
|
||||||
cur_version = obj.versions[0]
|
cur_version = obj.current_version()
|
||||||
|
new_name = version
|
||||||
old_name = cur_version.name
|
old_name = cur_version.name
|
||||||
|
|
||||||
if v_flag:
|
if version_name:
|
||||||
if v_flag[0] == '+':
|
new_name = version_name
|
||||||
new_name = yaclog.version.increment_version(version, v_flag)
|
|
||||||
else:
|
|
||||||
new_name = v_flag
|
|
||||||
|
|
||||||
if yaclog.version.is_release(cur_version.name):
|
if rel_seg is not None or pre_seg is not None:
|
||||||
|
new_name = yaclog.version.increment_version(new_name, rel_seg, pre_seg)
|
||||||
|
|
||||||
|
if new_name != old_name:
|
||||||
|
if yaclog.version.is_release(old_name):
|
||||||
click.confirm(f'Rename release version "{cur_version.name}" to "{new_name}"?', abort=True)
|
click.confirm(f'Rename release version "{cur_version.name}" to "{new_name}"?', abort=True)
|
||||||
|
|
||||||
cur_version.name = new_name
|
cur_version.name = new_name
|
||||||
|
@ -14,19 +14,37 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from packaging.version import Version, InvalidVersion
|
import re
|
||||||
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
|
from packaging.version import Version, VERSION_PATTERN
|
||||||
|
|
||||||
|
version_regex = re.compile(VERSION_PATTERN, re.VERBOSE | re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
def is_release(version: str) -> bool:
|
def extract_version(version_str: str) -> Tuple[Optional[Version], int, int]:
|
||||||
try:
|
"""
|
||||||
v = Version(version)
|
Extracts a PEP440 version object from a string which may have other text
|
||||||
return not (v.is_devrelease or v.is_prerelease)
|
|
||||||
except InvalidVersion:
|
:param version_str: The input string to extract from
|
||||||
return False
|
:return: A tuple of (version, start, end), where start and end are the span of the version in the original string
|
||||||
|
"""
|
||||||
|
match = version_regex.search(version_str)
|
||||||
|
if not match:
|
||||||
|
return None, -1, -1
|
||||||
|
return (Version(match[0]),) + match.span()
|
||||||
|
|
||||||
|
|
||||||
def increment_version(version: str, mode: str) -> str:
|
def increment_version(version_str: str, rel_seg: int = None, pre_seg: str = None) -> str:
|
||||||
v = Version(version)
|
"""
|
||||||
|
Increment the PEP440 version number in a string
|
||||||
|
|
||||||
|
:param version_str: The input string to manipulate
|
||||||
|
:param rel_seg: Which segment of the "release" value to increment, if any
|
||||||
|
:param pre_seg: Which kind of prerelease to use, if any
|
||||||
|
:return: The original string with the version number incremented
|
||||||
|
"""
|
||||||
|
v, *span = extract_version(version_str)
|
||||||
epoch = v.epoch
|
epoch = v.epoch
|
||||||
release = v.release
|
release = v.release
|
||||||
pre = v.pre
|
pre = v.pre
|
||||||
@ -34,27 +52,23 @@ def increment_version(version: str, mode: str) -> str:
|
|||||||
dev = v.dev
|
dev = v.dev
|
||||||
local = v.local
|
local = v.local
|
||||||
|
|
||||||
if mode == '+M':
|
if rel_seg is not None:
|
||||||
release = (release[0] + 1,) + ((0,) * len(release[1:]))
|
if len(release) <= rel_seg:
|
||||||
pre = post = dev = None
|
release += (0,) * (1 + rel_seg - len(release))
|
||||||
elif mode == '+m':
|
release = release[0:rel_seg] + (release[rel_seg] + 1,) + (0,) * (len(release) - rel_seg - 1)
|
||||||
release = (release[0], release[1] + 1) + ((0,) * len(release[2:]))
|
|
||||||
pre = post = dev = None
|
|
||||||
elif mode == '+p':
|
|
||||||
release = (release[0], release[1], release[2] + 1) + ((0,) * len(release[3:]))
|
|
||||||
pre = post = dev = None
|
|
||||||
elif mode in ['+a', '+b', '+rc']:
|
|
||||||
if pre[0] == mode[1:]:
|
|
||||||
pre = (mode[1:], pre[1] + 1)
|
|
||||||
else:
|
|
||||||
pre = (mode[1:], 0)
|
|
||||||
else:
|
|
||||||
raise IndexError(f'Unknown mode {mode}')
|
|
||||||
|
|
||||||
return join_version(epoch, release, pre, post, dev, local)
|
if pre_seg is not None:
|
||||||
|
if pre and pre[0] == pre_seg:
|
||||||
|
pre = (pre_seg, pre[1] + 1)
|
||||||
|
else:
|
||||||
|
pre = (pre_seg, 1)
|
||||||
|
|
||||||
|
new_v = join_version(epoch, release, pre, post, dev, local)
|
||||||
|
return version_str[0:span[0]] + new_v + version_str[span[1]:]
|
||||||
|
|
||||||
|
|
||||||
def join_version(epoch, release, pre, post, dev, local) -> str:
|
def join_version(epoch, release, pre, post, dev, local) -> str:
|
||||||
|
"""Join multiple segments of a PEP440 version"""
|
||||||
parts = []
|
parts = []
|
||||||
|
|
||||||
# Epoch
|
# Epoch
|
||||||
@ -83,3 +97,10 @@ def join_version(epoch, release, pre, post, dev, local) -> str:
|
|||||||
return "".join(parts)
|
return "".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def is_release(version_str: str) -> bool:
|
||||||
|
"""Check if a version string is a release version or not. Returns false if a PEP440 version could not be found"""
|
||||||
|
v, *span = extract_version(version_str)
|
||||||
|
if v:
|
||||||
|
return not (v.is_devrelease or v.is_prerelease)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
Loading…
Reference in New Issue
Block a user