Add more flexible parsing and formating

This commit is contained in:
Manuel Barkhau 2019-01-06 14:38:20 +01:00
parent 32447b03d4
commit 9eda61d95b
13 changed files with 932 additions and 359 deletions

View file

@ -10,7 +10,7 @@ import pytest
from click.testing import CliRunner
import pycalver.config as config
import pycalver.version as version
import pycalver.patterns as patterns
import pycalver.__main__ as pycalver
@ -80,18 +80,52 @@ def test_version(runner):
result = runner.invoke(pycalver.cli, ['--version', "--verbose"])
assert result.exit_code == 0
assert " version v20" in result.output
match = version.PYCALVER_RE.search(result.output)
match = patterns.PYCALVER_RE.search(result.output)
assert match
def test_incr(runner):
def test_incr_default(runner):
old_version = "v201701.0999-alpha"
initial_version = config._initial_version()
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose"])
result = runner.invoke(pycalver.cli, ['test', "--verbose", old_version])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000-alpha")
assert f"PyCalVer Version: {new_version}\n" in result.output
assert f"Version: {new_version}\n" in result.output
def test_incr_semver(runner):
semver_pattern = "{MAJOR}.{MINOR}.{PATCH}"
old_version = "0.1.0"
new_version = "0.1.1"
result = runner.invoke(pycalver.cli, ['test', "--verbose", "--patch", old_version, "{semver}"])
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
result = runner.invoke(
pycalver.cli, ['test', "--verbose", "--patch", old_version, semver_pattern]
)
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
old_version = "0.1.1"
new_version = "0.2.0"
result = runner.invoke(
pycalver.cli, ['test', "--verbose", "--minor", old_version, semver_pattern]
)
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
old_version = "0.1.1"
new_version = "1.0.0"
result = runner.invoke(
pycalver.cli, ['test', "--verbose", "--major", old_version, semver_pattern]
)
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
def test_incr_to_beta(runner):
@ -101,7 +135,7 @@ def test_incr_to_beta(runner):
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "beta"])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000-beta")
assert f"PyCalVer Version: {new_version}\n" in result.output
assert f"Version: {new_version}\n" in result.output
def test_incr_to_final(runner):
@ -111,7 +145,7 @@ def test_incr_to_final(runner):
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "final"])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000")
assert f"PyCalVer Version: {new_version}\n" in result.output
assert f"Version: {new_version}\n" in result.output
def test_incr_invalid(runner, caplog):
@ -164,7 +198,7 @@ def test_novcs_nocfg_init(runner):
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
assert result.exit_code == 0
assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 Version : {config._initial_version_pep440()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
def test_novcs_setupcfg_init(runner):
@ -184,7 +218,7 @@ def test_novcs_setupcfg_init(runner):
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
assert result.exit_code == 0
assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 Version : {config._initial_version_pep440()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
def test_novcs_pyproject_init(runner):
@ -202,7 +236,7 @@ def test_novcs_pyproject_init(runner):
result = runner.invoke(pycalver.cli, ['show'])
assert result.exit_code == 0
assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 Version : {config._initial_version_pep440()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
def _vcs_init(vcs):
@ -224,7 +258,7 @@ def test_git_init(runner):
result = runner.invoke(pycalver.cli, ['show'])
assert result.exit_code == 0
assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 Version : {config._initial_version_pep440()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
def test_hg_init(runner):
@ -237,7 +271,7 @@ def test_hg_init(runner):
result = runner.invoke(pycalver.cli, ['show'])
assert result.exit_code == 0
assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 Version : {config._initial_version_pep440()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
def test_git_tag_eval(runner):
@ -257,7 +291,7 @@ def test_git_tag_eval(runner):
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
assert result.exit_code == 0
assert f"Current Version: {tag_version}\n" in result.output
assert f"PEP440 Version : {tag_version_pep440}\n" in result.output
assert f"PEP440 : {tag_version_pep440}\n" in result.output
def test_hg_tag_eval(runner):
@ -277,7 +311,7 @@ def test_hg_tag_eval(runner):
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
assert result.exit_code == 0
assert f"Current Version: {tag_version}\n" in result.output
assert f"PEP440 Version : {tag_version_pep440}\n" in result.output
assert f"PEP440 : {tag_version_pep440}\n" in result.output
def test_novcs_bump(runner):

View file

@ -58,8 +58,8 @@ def test_parse_toml():
assert cfg.push is True
assert "pycalver.toml" in cfg.file_patterns
assert cfg.file_patterns["README.md" ] == ["{version}", "{pep440_version}"]
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{version}"']
assert cfg.file_patterns["README.md" ] == ["{pycalver}", "{pep440_pycalver}"]
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{pycalver}"']
def test_parse_cfg():
@ -74,8 +74,8 @@ def test_parse_cfg():
assert cfg.push is True
assert "setup.cfg" in cfg.file_patterns
assert cfg.file_patterns["setup.py" ] == ["{version}", "{pep440_version}"]
assert cfg.file_patterns["setup.cfg"] == ['current_version = "{version}"']
assert cfg.file_patterns["setup.py" ] == ["{pycalver}", "{pep440_pycalver}"]
assert cfg.file_patterns["setup.cfg"] == ['current_version = "{pycalver}"']
def test_parse_default_toml():
@ -168,8 +168,8 @@ def test_parse_toml_file(tmpdir):
assert cfg.push is True
assert cfg.file_patterns == {
"README.md" : ["{version}", "{pep440_version}"],
"pycalver.toml": ['current_version = "{version}"'],
"README.md" : ["{pycalver}", "{pep440_pycalver}"],
"pycalver.toml": ['current_version = "{pycalver}"'],
}
@ -190,8 +190,8 @@ def test_parse_cfg_file(tmpdir):
assert cfg.push is True
assert cfg.file_patterns == {
"setup.py" : ["{version}", "{pep440_version}"],
"setup.cfg": ['current_version = "{version}"'],
"setup.py" : ["{pycalver}", "{pep440_pycalver}"],
"setup.cfg": ['current_version = "{pycalver}"'],
}

View file

@ -1,50 +1,6 @@
import re
from pycalver import parse
def test_re_pattern_parts():
part_re_by_name = {
part_name: re.compile(part_re_str)
for part_name, part_re_str in parse.RE_PATTERN_PARTS.items()
}
cases = [
("pep440_version", "201712.31" , "201712.31"),
("pep440_version", "v201712.0032" , None),
("pep440_version", "201712.0033-alpha" , None),
("version" , "v201712.0034" , "v201712.0034"),
("version" , "v201712.0035-alpha" , "v201712.0035-alpha"),
("version" , "v201712.0036-alpha0", "v201712.0036-alpha"),
("version" , "v201712.0037-pre" , "v201712.0037"),
("version" , "201712.38a0" , None),
("version" , "201712.0039" , None),
("calver" , "v201712" , "v201712"),
("calver" , "v201799" , "v201799"), # maybe date validation should be a thing
("calver" , "201712" , None),
("calver" , "v20171" , None),
("build" , ".0012" , ".0012"),
("build" , ".11012" , ".11012"),
("build" , ".012" , None),
("build" , "11012" , None),
("release" , "-alpha" , "-alpha"),
("release" , "-beta" , "-beta"),
("release" , "-dev" , "-dev"),
("release" , "-rc" , "-rc"),
("release" , "-post" , "-post"),
("release" , "-pre" , ""),
("release" , "alpha" , ""),
]
for part_name, line, expected in cases:
part_re = part_re_by_name[part_name]
result = part_re.search(line)
if result is None:
assert expected is None, (part_name, line)
else:
result_val = result.group(0)
assert result_val == expected, (part_name, line)
SETUP_PY_FIXTURE = """
# setup.py
import setuptools
@ -57,7 +13,7 @@ setuptools.setup(
def test_default_parse_patterns():
lines = SETUP_PY_FIXTURE.splitlines()
patterns = ["{version}", "{pep440_version}"]
patterns = ["{pycalver}", "{pep440_pycalver}"]
matches = list(parse.iter_matches(lines, patterns))
assert len(matches) == 2
@ -75,7 +31,7 @@ def test_default_parse_patterns():
def test_explicit_parse_patterns():
lines = SETUP_PY_FIXTURE.splitlines()
patterns = ["__version__ = '{version}'", "version='{pep440_version}'"]
patterns = ["__version__ = '{pycalver}'", "version='{pep440_pycalver}'"]
matches = list(parse.iter_matches(lines, patterns))
assert len(matches) == 2
@ -102,7 +58,7 @@ README_RST_FIXTURE = """
def test_badge_parse_patterns():
lines = README_RST_FIXTURE.splitlines()
patterns = ["badge/CalVer-{calver}{build}-{release}-blue.svg", ":alt: CalVer {version}"]
patterns = ["badge/CalVer-{calver}{build}-{release}-blue.svg", ":alt: CalVer {pycalver}"]
matches = list(parse.iter_matches(lines, patterns))
assert len(matches) == 2
@ -115,30 +71,3 @@ def test_badge_parse_patterns():
assert matches[0].match == "badge/CalVer-v201809.0002--beta-blue.svg"
assert matches[1].match == ":alt: CalVer v201809.0002-beta"
CLI_MAIN_FIXTURE = """
@click.group()
@click.version_option(version="v201812.0123-beta")
@click.help_option()
"""
def test_pattern_escapes():
pattern_re = parse.compile_pattern(r'click.version_option(version="{version}")')
match = pattern_re.search(CLI_MAIN_FIXTURE)
assert match.group(0) == 'click.version_option(version="v201812.0123-beta")'
CURLY_BRACE_FIXTURE = """
package_metadata = {"name": "mypackage", "version": "v201812.0123-beta"}
"""
def test_curly_escapes():
pattern = r'package_metadata = {"name": "mypackage", "version": "{version}"}'
pattern_re = parse.compile_pattern(pattern)
match = pattern_re.search(CURLY_BRACE_FIXTURE)
assert (
match.group(0) == 'package_metadata = {"name": "mypackage", "version": "v201812.0123-beta"}'
)

81
test/test_patterns.py Normal file
View file

@ -0,0 +1,81 @@
import re
import pytest
from pycalver import patterns
def _part_re_by_name(name):
return re.compile(patterns.PART_PATTERNS[name])
@pytest.mark.parametrize("part_name", patterns.PART_PATTERNS.keys())
def test_part_compilation(part_name):
assert _part_re_by_name(part_name)
PATTERN_PART_CASES = [
("pep440_pycalver", "201712.31" , "201712.31"),
("pep440_pycalver", "v201712.0032" , None),
("pep440_pycalver", "201712.0033-alpha" , None),
("pycalver" , "v201712.0034" , "v201712.0034"),
("pycalver" , "v201712.0035-alpha" , "v201712.0035-alpha"),
("pycalver" , "v201712.0036-alpha0", "v201712.0036-alpha"),
("pycalver" , "v201712.0037-pre" , "v201712.0037"),
("pycalver" , "201712.38a0" , None),
("pycalver" , "201712.0039" , None),
("semver" , "1.23.456" , "1.23.456"),
("calver" , "v201712" , "v201712"),
("calver" , "v201799" , None), # invalid date
("calver" , "201712" , None),
("calver" , "v20171" , None),
("build" , ".0012" , ".0012"),
("build" , ".11012" , ".11012"),
("build" , ".012" , None),
("build" , "11012" , None),
("release" , "-alpha" , "-alpha"),
("release" , "-beta" , "-beta"),
("release" , "-dev" , "-dev"),
("release" , "-rc" , "-rc"),
("release" , "-post" , "-post"),
("release" , "-pre" , None),
("release" , "alpha" , None),
]
@pytest.mark.parametrize("part_name, line, expected", PATTERN_PART_CASES)
def test_re_pattern_parts(part_name, line, expected):
part_re = _part_re_by_name(part_name)
result = part_re.search(line)
if result is None:
assert expected is None, (part_name, line)
else:
result_val = result.group(0)
assert result_val == expected, (part_name, line)
CLI_MAIN_FIXTURE = """
@click.group()
@click.version_option(version="v201812.0123-beta")
@click.help_option()
"""
def test_pattern_escapes():
pattern = 'click.version_option(version="{pycalver}")'
pattern_re = patterns.compile_pattern(pattern)
match = pattern_re.search(CLI_MAIN_FIXTURE)
expected = 'click.version_option(version="v201812.0123-beta")'
assert match.group(0) == expected
CURLY_BRACE_FIXTURE = """
package_metadata = {"name": "mypackage", "version": "v201812.0123-beta"}
"""
def test_curly_escapes():
pattern = 'package_metadata = {"name": "mypackage", "version": "{pycalver}"}'
pattern_re = patterns.compile_pattern(pattern)
match = pattern_re.search(CURLY_BRACE_FIXTURE)
expected = 'package_metadata = {"name": "mypackage", "version": "v201812.0123-beta"}'
assert match.group(0) == expected

View file

@ -9,7 +9,7 @@ __version__ = "v201809.0002-beta"
def test_rewrite_lines():
old_lines = REWRITE_FIXTURE.splitlines()
patterns = ['__version__ = "{version}"']
patterns = ['__version__ = "{pycalver}"']
new_lines = rewrite.rewrite_lines(patterns, "v201911.0003", old_lines)
assert len(new_lines) == len(old_lines)

View file

@ -2,18 +2,11 @@ import random
import datetime as dt
from pycalver import version
def test_current_calver():
v = version.current_calver()
assert len(v) == 7
assert v.startswith("v")
assert v[1:].isdigit()
from pycalver import patterns
def test_bump_beta():
calver = version.current_calver()
cur_version = calver + ".0001-beta"
cur_version = "v201712.0001-beta"
assert cur_version < version.incr(cur_version)
assert version.incr(cur_version).endswith("-beta")
assert version.incr(cur_version, release="alpha").endswith("-alpha")
@ -21,8 +14,7 @@ def test_bump_beta():
def test_bump_final():
calver = version.current_calver()
cur_version = calver + ".0001"
cur_version = "v201712.0001"
assert cur_version < version.incr(cur_version)
assert version.incr(cur_version).endswith(".0002")
assert version.incr(cur_version, release="alpha").endswith("-alpha")
@ -34,20 +26,19 @@ def test_bump_final():
def test_bump_future():
"""Test that versions don't go back in time."""
future_date = dt.datetime.today() + dt.timedelta(days=300)
future_calver = future_date.strftime("v%Y%m")
cur_version = future_calver + ".0001"
assert cur_version < version.incr(cur_version)
new_version = version.incr(cur_version)
assert cur_version < new_version
def test_bump_random(monkeypatch):
cur_date = dt.date.today()
cur_date = dt.date(2016, 1, 1) + dt.timedelta(days=random.randint(1, 2000))
cur_version = cur_date.strftime("v%Y%m") + ".0001-dev"
def _mock_current_calver():
return cur_date.strftime("v%Y%m")
monkeypatch.setattr(version, 'current_calver', _mock_current_calver)
monkeypatch.setattr(version, 'TODAY', cur_date)
for i in range(1000):
cur_date += dt.timedelta(days=int((1 + random.random()) ** 10))
@ -62,37 +53,31 @@ def test_parse_version_info():
version_str = "v201712.0001-alpha"
version_nfo = version.parse_version_info(version_str)
assert version_nfo.pep440_version == "201712.1a0"
assert version_nfo.version == "v201712.0001-alpha"
assert version_nfo.calver == "v201712"
assert version_nfo.year == "2017"
assert version_nfo.month == "12"
assert version_nfo.build == ".0001"
assert version_nfo.release == "-alpha"
assert version_nfo.build_no == "0001"
assert version_nfo.release_tag == "alpha"
# assert version_nfo.pep440_version == "201712.1a0"
# assert version_nfo.version == "v201712.0001-alpha"
assert version_nfo.year == 2017
assert version_nfo.month == 12
assert version_nfo.bid == "0001"
assert version_nfo.tag == "alpha"
version_str = "v201712.0001"
version_nfo = version.parse_version_info(version_str)
assert version_nfo.pep440_version == "201712.1"
assert version_nfo.version == "v201712.0001"
assert version_nfo.calver == "v201712"
assert version_nfo.year == "2017"
assert version_nfo.month == "12"
assert version_nfo.build == ".0001"
assert version_nfo.release == "-final"
assert version_nfo.build_no == "0001"
assert version_nfo.release_tag == "final"
# assert version_nfo.pep440_version == "201712.1"
# assert version_nfo.version == "v201712.0001"
assert version_nfo.year == 2017
assert version_nfo.month == 12
assert version_nfo.bid == "0001"
assert version_nfo.tag == "final"
def test_readme_pycalver1():
version_str = "v201712.0001-alpha"
version_info = version.PYCALVER_RE.match(version_str).groupdict()
version_info = patterns.PYCALVER_RE.match(version_str).groupdict()
assert version_info == {
'version' : "v201712.0001-alpha",
'calver' : "v201712",
'pycalver' : "v201712.0001-alpha",
'vYYYYMM' : "v201712",
'year' : "2017",
'month' : "12",
'build' : ".0001",
@ -104,11 +89,11 @@ def test_readme_pycalver1():
def test_readme_pycalver2():
version_str = "v201712.0033"
version_info = version.PYCALVER_RE.match(version_str).groupdict()
version_info = patterns.PYCALVER_RE.match(version_str).groupdict()
assert version_info == {
'version' : "v201712.0033",
'calver' : "v201712",
'pycalver' : "v201712.0033",
'vYYYYMM' : "v201712",
'year' : "2017",
'month' : "12",
'build' : ".0033",
@ -140,3 +125,19 @@ def test_parse_error_nopadding():
assert False
except ValueError as err:
pass
def test_part_field_mapping():
a_names = set(version.PATTERN_PART_FIELDS.keys())
b_names = set(patterns.PART_PATTERNS.keys())
c_names = set(patterns.COMPOSITE_PART_PATTERNS.keys())
extra_names = a_names - b_names
assert not any(extra_names)
missing_names = b_names - a_names
assert missing_names == c_names
a_fields = set(version.PATTERN_PART_FIELDS.values())
b_fields = set(version.VersionInfo._fields)
assert a_fields == b_fields