mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 06:20:08 +01:00
cli usability improvements
This commit is contained in:
parent
86a321b287
commit
3efb72dd3c
5 changed files with 143 additions and 79 deletions
|
|
@ -131,7 +131,7 @@ jobs = 4
|
|||
output-format = colorized
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals = 25
|
||||
max-locals = 20
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args = 12
|
||||
|
|
|
|||
|
|
@ -100,6 +100,52 @@ def _validate_release_tag(tag: typ.Optional[str]) -> None:
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def _validate_flags(
|
||||
raw_pattern: str,
|
||||
major : bool,
|
||||
minor : bool,
|
||||
patch : bool,
|
||||
) -> None:
|
||||
if "{" in raw_pattern and "}" in raw_pattern:
|
||||
# only validate for new style patterns
|
||||
return
|
||||
|
||||
valid = True
|
||||
if major and "MAJOR" not in raw_pattern:
|
||||
logger.error(f"Flag --major is not applicable to pattern '{raw_pattern}'")
|
||||
valid = False
|
||||
if minor and "MINOR" not in raw_pattern:
|
||||
logger.error(f"Flag --minor is not applicable to pattern '{raw_pattern}'")
|
||||
valid = False
|
||||
if patch and "PATCH" not in raw_pattern:
|
||||
logger.error(f"Flag --patch is not applicable to pattern '{raw_pattern}'")
|
||||
valid = False
|
||||
|
||||
if not valid:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _log_no_change(subcmd: str, version_pattern: str, old_version: str) -> None:
|
||||
msg = (
|
||||
f"Version did not change: '{old_version}'. "
|
||||
f"Invalid version and/or pattern '{version_pattern}'."
|
||||
)
|
||||
logger.error(msg)
|
||||
|
||||
is_semver = "{semver}" in version_pattern or (
|
||||
"MAJOR" in version_pattern and "MAJOR" in version_pattern and "PATCH" in version_pattern
|
||||
)
|
||||
if is_semver:
|
||||
logger.warning(f"pycalver {subcmd} [--major/--minor/--patch] required for use with SemVer.")
|
||||
else:
|
||||
available_flags = [
|
||||
"--" + part.lower() for part in ['MAJOR', 'MINOR', 'PATCH'] if part in version_pattern
|
||||
]
|
||||
if available_flags:
|
||||
available_flags_str = "/".join(available_flags)
|
||||
logger.info(f"Perhaps try: pycalver {subcmd} {available_flags_str} ")
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(version="v202010.1041-beta")
|
||||
@click.help_option()
|
||||
|
|
@ -151,6 +197,7 @@ def test(
|
|||
|
||||
tag = release # use internal naming convention
|
||||
_validate_release_tag(tag)
|
||||
_validate_flags(raw_pattern, major, minor, patch)
|
||||
_date = _validate_date(date, pin_date)
|
||||
|
||||
new_version = incr_dispatch(
|
||||
|
|
@ -165,7 +212,7 @@ def test(
|
|||
date=_date,
|
||||
)
|
||||
if new_version is None:
|
||||
logger.error(f"Invalid version '{old_version}' and/or pattern '{raw_pattern}'.")
|
||||
_log_no_change('test', raw_pattern, old_version)
|
||||
sys.exit(1)
|
||||
|
||||
pep440_version = version.to_pep440(new_version)
|
||||
|
|
@ -395,7 +442,7 @@ def incr_dispatch(
|
|||
logger.info("regex = " + regexfmt.pyexpr_regex(pattern.regexp.pattern))
|
||||
|
||||
if has_v1_part:
|
||||
return v1version.incr(
|
||||
new_version = v1version.incr(
|
||||
old_version,
|
||||
raw_pattern=raw_pattern,
|
||||
tag=tag,
|
||||
|
|
@ -407,7 +454,7 @@ def incr_dispatch(
|
|||
date=date,
|
||||
)
|
||||
else:
|
||||
return v2version.incr(
|
||||
new_version = v2version.incr(
|
||||
old_version,
|
||||
raw_pattern=raw_pattern,
|
||||
tag=tag,
|
||||
|
|
@ -419,6 +466,15 @@ def incr_dispatch(
|
|||
date=date,
|
||||
)
|
||||
|
||||
if new_version is None:
|
||||
return None
|
||||
elif pkg_resources.parse_version(new_version) <= pkg_resources.parse_version(old_version):
|
||||
logger.error("Invariant violated: New version must be greater than old version ")
|
||||
logger.error(f" Result: '{new_version}' > '{old_version}' -> False")
|
||||
return None
|
||||
else:
|
||||
return new_version
|
||||
|
||||
|
||||
def _bump(
|
||||
cfg : config.Config,
|
||||
|
|
@ -625,16 +681,7 @@ def bump(
|
|||
)
|
||||
|
||||
if new_version is None:
|
||||
is_semver = "{semver}" in cfg.version_pattern or (
|
||||
"MAJOR" in cfg.version_pattern
|
||||
and "MAJOR" in cfg.version_pattern
|
||||
and "PATCH" in cfg.version_pattern
|
||||
)
|
||||
has_semver_inc = major or minor or patch
|
||||
if is_semver and not has_semver_inc:
|
||||
logger.warning("bump --major/--minor/--patch required when using semver.")
|
||||
else:
|
||||
logger.error(f"Invalid version '{old_version}' and/or pattern '{cfg.version_pattern}'.")
|
||||
_log_no_change('bump', cfg.version_pattern, old_version)
|
||||
sys.exit(1)
|
||||
|
||||
logger.info(f"Old Version: {old_version}")
|
||||
|
|
|
|||
|
|
@ -102,65 +102,26 @@ FieldValues = typ.Dict[FieldKey, MatchGroupStr]
|
|||
VersionInfoKW = typ.Dict[str, typ.Union[str, int, None]]
|
||||
|
||||
|
||||
def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
||||
"""Parse normalized V2VersionInfo from groups of a matched pattern.
|
||||
def _parse_calendar_info(field_values: FieldValues) -> version.V2CalendarInfo:
|
||||
"""Parse normalized V2CalendarInfo from groups of a matched pattern.
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'month': "11", 'bid': "0099"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.quarter, vinfo.bid, vinfo.tag)
|
||||
(2018, 11, 4, '0099', 'final')
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "18", 'month': "11"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.quarter)
|
||||
(2018, 11, 4)
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'doy': "11", 'bid': "099", 'tag': "beta"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.dom, vinfo.doy, vinfo.bid, vinfo.tag)
|
||||
(2018, 1, 11, 11, '099', 'beta')
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'month': "6", 'dom': "15"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.dom, vinfo.doy)
|
||||
(2018, 6, 15, 166)
|
||||
|
||||
>>> vinfo = _parse_version_info({'major': "1", 'minor': "23", 'patch': "45"})
|
||||
>>> (vinfo.major, vinfo.minor, vinfo.patch)
|
||||
(1, 23, 45)
|
||||
|
||||
>>> vinfo = _parse_version_info({'major': "1", 'minor': "023", 'patch': "0045"})
|
||||
>>> (vinfo.major, vinfo.minor, vinfo.patch)
|
||||
(1, 23, 45)
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2021", 'week_w': "02"})
|
||||
>>> (vinfo.year_y, vinfo.week_w)
|
||||
>>> cinfo = _parse_version_info({'year_y': "2021", 'week_w': "02"})
|
||||
>>> (cinfo.year_y, cinfo.week_w)
|
||||
(2021, 2)
|
||||
>>> vinfo = _parse_version_info({'year_y': "2021", 'week_u': "02"})
|
||||
>>> (vinfo.year_y, vinfo.week_u)
|
||||
>>> cinfo = _parse_version_info({'year_y': "2021", 'week_u': "02"})
|
||||
>>> (cinfo.year_y, cinfo.week_u)
|
||||
(2021, 2)
|
||||
>>> vinfo = _parse_version_info({'year_g': "2021", 'week_v': "02"})
|
||||
>>> (vinfo.year_g, vinfo.week_v)
|
||||
>>> cinfo = _parse_version_info({'year_g': "2021", 'week_v': "02"})
|
||||
>>> (cinfo.year_g, cinfo.week_v)
|
||||
(2021, 2)
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2021", 'month': "01", 'dom': "03"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.dom, vinfo.tag)
|
||||
(2021, 1, 3, 'final')
|
||||
>>> (vinfo.year_y, vinfo.week_w, vinfo.year_y, vinfo.week_u,vinfo.year_g, vinfo.week_v)
|
||||
>>> cinfo = _parse_version_info({'year_y': "2021", 'month': "01", 'dom': "03"})
|
||||
>>> (cinfo.year_y, cinfo.month, cinfo.dom)
|
||||
(2021, 1, 3)
|
||||
>>> (cinfo.year_y, cinfo.week_w, cinfo.year_y, cinfo.week_u,cinfo.year_g, cinfo.week_v)
|
||||
(2021, 0, 2021, 1, 2020, 53)
|
||||
"""
|
||||
# pylint:disable=dangerous-default-value; We don't mutate args, mypy would fail if we did.
|
||||
for key in field_values:
|
||||
assert key in VALID_FIELD_KEYS, key
|
||||
|
||||
fvals = field_values
|
||||
tag = fvals.get('tag' ) or ""
|
||||
pytag = fvals.get('pytag') or ""
|
||||
|
||||
if tag and not pytag:
|
||||
pytag = version.PEP440_TAG_BY_RELEASE[tag]
|
||||
elif pytag and not tag:
|
||||
tag = version.RELEASE_BY_PEP440_TAG[pytag]
|
||||
|
||||
if not tag:
|
||||
tag = "final"
|
||||
|
||||
date: typ.Optional[dt.date] = None
|
||||
|
||||
year_y: MaybeInt = int(fvals['year_y']) if 'year_y' in fvals else None
|
||||
|
|
@ -205,16 +166,7 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
|||
if quarter is None and month:
|
||||
quarter = version.quarter_from_month(month)
|
||||
|
||||
# NOTE (mb 2020-09-18): If a part is optional, fvals[<field>] may be None
|
||||
major = int(fvals.get('major') or 0)
|
||||
minor = int(fvals.get('minor') or 0)
|
||||
patch = int(fvals.get('patch') or 0)
|
||||
num = int(fvals.get('num' ) or 0)
|
||||
bid = fvals['bid'] if 'bid' in fvals else "1000"
|
||||
inc0 = int(fvals.get('inc0') or 0)
|
||||
inc1 = int(fvals.get('inc1') or 1)
|
||||
|
||||
vinfo = version.V2VersionInfo(
|
||||
return version.V2CalendarInfo(
|
||||
year_y=year_y,
|
||||
year_g=year_g,
|
||||
quarter=quarter,
|
||||
|
|
@ -224,6 +176,74 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
|||
week_w=week_w,
|
||||
week_u=week_u,
|
||||
week_v=week_v,
|
||||
)
|
||||
|
||||
|
||||
def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
||||
"""Parse normalized V2VersionInfo from groups of a matched pattern.
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'month': "11", 'bid': "0099"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.quarter, vinfo.bid, vinfo.tag)
|
||||
(2018, 11, 4, '0099', 'final')
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "18", 'month': "11"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.quarter)
|
||||
(2018, 11, 4)
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'doy': "11", 'bid': "099", 'tag': "beta"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.dom, vinfo.doy, vinfo.bid, vinfo.tag)
|
||||
(2018, 1, 11, 11, '099', 'beta')
|
||||
|
||||
>>> vinfo = _parse_version_info({'year_y': "2018", 'month': "6", 'dom': "15"})
|
||||
>>> (vinfo.year_y, vinfo.month, vinfo.dom, vinfo.doy)
|
||||
(2018, 6, 15, 166)
|
||||
|
||||
>>> vinfo = _parse_version_info({'major': "1", 'minor': "23", 'patch': "45"})
|
||||
>>> (vinfo.major, vinfo.minor, vinfo.patch)
|
||||
(1, 23, 45)
|
||||
|
||||
>>> vinfo = _parse_version_info({'major': "1", 'minor': "023", 'patch': "0045"})
|
||||
>>> (vinfo.major, vinfo.minor, vinfo.patch, vinfo.tag)
|
||||
(1, 23, 45, 'final')
|
||||
"""
|
||||
# pylint:disable=dangerous-default-value; We don't mutate args, mypy would fail if we did.
|
||||
for key in field_values:
|
||||
assert key in VALID_FIELD_KEYS, key
|
||||
|
||||
cinfo = _parse_calendar_info(field_values)
|
||||
|
||||
fvals = field_values
|
||||
|
||||
tag = fvals.get('tag' ) or ""
|
||||
pytag = fvals.get('pytag') or ""
|
||||
|
||||
if tag and not pytag:
|
||||
pytag = version.PEP440_TAG_BY_RELEASE[tag]
|
||||
elif pytag and not tag:
|
||||
tag = version.RELEASE_BY_PEP440_TAG[pytag]
|
||||
|
||||
if not tag:
|
||||
tag = "final"
|
||||
|
||||
# NOTE (mb 2020-09-18): If a part is optional, fvals[<field>] may be None
|
||||
major = int(fvals.get('major') or 0)
|
||||
minor = int(fvals.get('minor') or 0)
|
||||
patch = int(fvals.get('patch') or 0)
|
||||
num = int(fvals.get('num' ) or 0)
|
||||
bid = fvals['bid'] if 'bid' in fvals else "1000"
|
||||
inc0 = int(fvals.get('inc0') or 0)
|
||||
inc1 = int(fvals.get('inc1') or 1)
|
||||
|
||||
return version.V2VersionInfo(
|
||||
year_y=cinfo.year_y,
|
||||
year_g=cinfo.year_g,
|
||||
quarter=cinfo.quarter,
|
||||
month=cinfo.month,
|
||||
dom=cinfo.dom,
|
||||
doy=cinfo.doy,
|
||||
week_w=cinfo.week_w,
|
||||
week_u=cinfo.week_u,
|
||||
week_v=cinfo.week_v,
|
||||
major=major,
|
||||
minor=minor,
|
||||
patch=patch,
|
||||
|
|
@ -234,7 +254,6 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
|||
inc0=inc0,
|
||||
inc1=inc1,
|
||||
)
|
||||
return vinfo
|
||||
|
||||
|
||||
def parse_version_info(
|
||||
|
|
|
|||
|
|
@ -126,8 +126,6 @@ V2_FIELD_INITIAL_VALUES = {
|
|||
'major': "0",
|
||||
'minor': "0",
|
||||
'patch': "0",
|
||||
'tag' : "final",
|
||||
'pytag': "",
|
||||
'num' : "0",
|
||||
'inc0' : "0",
|
||||
'inc1' : "1",
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ def test_v1_bump_semver_warning(runner, caplog, version_pattern):
|
|||
assert result.exit_code == 1
|
||||
|
||||
assert any("version did not change" in r.message for r in caplog.records)
|
||||
assert any("--major/--minor/--patch required" in r.message for r in caplog.records)
|
||||
assert any("[--major/--minor/--patch] required" in r.message for r in caplog.records)
|
||||
|
||||
result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry", "--patch"])
|
||||
assert result.exit_code == 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue