more coverage

This commit is contained in:
Manuel Barkhau 2019-01-07 17:30:02 +01:00
parent 4598286f12
commit df492a20d6
10 changed files with 128 additions and 27 deletions

View file

@ -3,7 +3,12 @@ FROM registry.gitlab.com/mbarkhau/pycalver/base
ADD src/ src/ ADD src/ src/
ADD stubs/ stubs/ ADD stubs/ stubs/
ADD test/ test/ ADD test/ test/
ADD requirements/ requirements/
ADD setup.cfg setup.cfg ADD setup.cfg setup.cfg
ADD setup.py setup.py
ADD README.md README.md
ADD CHANGELOG.md CHANGELOG.md
ADD LICENSE LICENSE
ADD makefile makefile ADD makefile makefile
ADD makefile.config.make makefile.config.make ADD makefile.config.make makefile.config.make
ADD makefile.extra.make makefile.extra.make ADD makefile.extra.make makefile.extra.make

View file

@ -31,7 +31,7 @@ test_compat: $(COMPAT_TEST_FILES)
IFS=' ' read -r -a env_paths <<< "$(CONDA_ENV_PATHS)"; \ IFS=' ' read -r -a env_paths <<< "$(CONDA_ENV_PATHS)"; \
for i in $${!env_paths[@]}; do \ for i in $${!env_paths[@]}; do \
env_py=$${env_paths[i]}/bin/python; \ env_py=$${env_paths[i]}/bin/python; \
$${env_py} -m pip install --upgrade build/test_wheel/*.whl; \ $${env_py} -m pip install --upgrade pytest build/test_wheel/*.whl; \
PYTHONPATH="" ENV=$${ENV-dev} \ PYTHONPATH="" ENV=$${ENV-dev} \
$${env_py} -m pytest --verbose compat_test/; \ $${env_py} -m pytest --verbose compat_test/; \
done; done;

View file

@ -16,7 +16,6 @@ pylint
mypy mypy
pytest pytest
pytest-cov pytest-cov
pylint
readme_renderer[md] readme_renderer[md]
twine twine

View file

@ -24,14 +24,14 @@ from . import rewrite
_VERBOSE = 0 _VERBOSE = 0
# try: try:
# import backtrace import backtrace
# # To enable pretty tracebacks: # To enable pretty tracebacks:
# # echo "export ENABLE_BACKTRACE=1;" >> ~/.bashrc # echo "export ENABLE_BACKTRACE=1;" >> ~/.bashrc
# backtrace.hook(align=True, strip_path=True, enable_on_envvar_only=True) backtrace.hook(align=True, strip_path=True, enable_on_envvar_only=True)
# except ImportError: except ImportError:
# pass pass
click.disable_unicode_literals_warning = True click.disable_unicode_literals_warning = True
@ -183,10 +183,10 @@ def init(verbose: int = 0, dry: bool = False) -> None:
sys.exit(1) sys.exit(1)
if dry: if dry:
print("Exiting because of '--dry'. Would have written to setup.cfg:") print("Exiting because of '--dry'. Would have written to {ctx.config_filepath}:")
cfg_lines = config.default_config(ctx) cfg_lines = config.default_config(ctx)
print("\n " + "\n ".join(cfg_lines)) print("\n " + "\n ".join(cfg_lines))
return sys.exit(0)
config.write_content(ctx) config.write_content(ctx)

View file

@ -222,8 +222,8 @@ def _parse_config(raw_cfg: RawConfig) -> Config:
version_pattern = raw_cfg.get('version_pattern', "{pycalver}") version_pattern = raw_cfg.get('version_pattern', "{pycalver}")
version_pattern = raw_cfg['version_pattern'] = version_pattern.strip("'\" ") version_pattern = raw_cfg['version_pattern'] = version_pattern.strip("'\" ")
# NOTE (mb 2019-01-05): trigger ValueError if version_pattern # NOTE (mb 2019-01-05): Provoke ValueError if version_pattern
# and current_version don't work together. # and current_version are not compatible.
version.parse_version_info(version_str, version_pattern) version.parse_version_info(version_str, version_pattern)
pep440_version = version.to_pep440(version_str) pep440_version = version.to_pep440(version_str)
@ -245,7 +245,15 @@ def _parse_config(raw_cfg: RawConfig) -> Config:
file_patterns = _normalize_file_patterns(raw_cfg) file_patterns = _normalize_file_patterns(raw_cfg)
cfg = Config(version_str, version_pattern, pep440_version, tag, commit, push, file_patterns) cfg = Config(
current_version=version_str,
version_pattern=version_pattern,
pep440_version=pep440_version,
commit=commit,
tag=tag,
push=push,
file_patterns=file_patterns,
)
log.debug(_debug_str(cfg)) log.debug(_debug_str(cfg))
return cfg return cfg
@ -263,7 +271,8 @@ def parse(ctx: ProjectContext) -> MaybeConfig:
elif ctx.config_format == 'cfg': elif ctx.config_format == 'cfg':
raw_cfg = _parse_cfg(fh) raw_cfg = _parse_cfg(fh)
else: else:
return None err_msg = "Invalid config_format='{ctx.config_format}'"
raise RuntimeError(err_msg)
return _parse_config(raw_cfg) return _parse_config(raw_cfg)
except ValueError as ex: except ValueError as ex:

View file

@ -109,6 +109,8 @@ def iter_rewritten(
... ] ... ]
>>> >>>
''' '''
fh: typ.IO[str]
for filepath, patterns in file_patterns.items(): for filepath, patterns in file_patterns.items():
with io.open(filepath, mode="rt", encoding="utf-8") as fh: with io.open(filepath, mode="rt", encoding="utf-8") as fh:
content = fh.read() content = fh.read()
@ -151,6 +153,8 @@ def diff(new_version: str, file_patterns: config.PatternsByFilePath) -> str:
full_diff = "" full_diff = ""
file_path: str file_path: str
fh : typ.IO[str]
for file_path, patterns in sorted(file_patterns.items()): for file_path, patterns in sorted(file_patterns.items()):
with io.open(file_path, mode="rt", encoding="utf-8") as fh: with io.open(file_path, mode="rt", encoding="utf-8") as fh:
content = fh.read() content = fh.read()
@ -165,6 +169,7 @@ def diff(new_version: str, file_patterns: config.PatternsByFilePath) -> str:
def rewrite(new_version: str, file_patterns: config.PatternsByFilePath) -> None: def rewrite(new_version: str, file_patterns: config.PatternsByFilePath) -> None:
"""Rewrite project files, updating each with the new version.""" """Rewrite project files, updating each with the new version."""
fh: typ.IO[str]
for file_data in iter_rewritten(file_patterns, new_version): for file_data in iter_rewritten(file_patterns, new_version):
new_content = file_data.line_sep.join(file_data.new_lines) new_content = file_data.line_sep.join(file_data.new_lines)

View file

@ -50,6 +50,9 @@ VCS_SUBCOMMANDS_BY_NAME = {
} }
Env = typ.Dict[str, str]
class VCS: class VCS:
"""VCS absraction for git and mercurial.""" """VCS absraction for git and mercurial."""
@ -60,7 +63,7 @@ class VCS:
else: else:
self.subcommands = subcommands self.subcommands = subcommands
def __call__(self, cmd_name: str, env=None, **kwargs: str) -> str: def __call__(self, cmd_name: str, env: Env = None, **kwargs: str) -> str:
"""Invoke subcommand and return output.""" """Invoke subcommand and return output."""
cmd_tmpl = self.subcommands[cmd_name] cmd_tmpl = self.subcommands[cmd_name]
cmd_str = cmd_tmpl.format(**kwargs) cmd_str = cmd_tmpl.format(**kwargs)
@ -68,7 +71,7 @@ class VCS:
log.info(cmd_str) log.info(cmd_str)
else: else:
log.debug(cmd_str) log.debug(cmd_str)
output_data = sp.check_output(cmd_str.split(), env=env, stderr=sp.STDOUT) output_data: bytes = sp.check_output(cmd_str.split(), env=env, stderr=sp.STDOUT)
# TODO (mb 2018-11-15): Detect encoding of output? # TODO (mb 2018-11-15): Detect encoding of output?
_encoding = "utf-8" _encoding = "utf-8"
@ -141,12 +144,11 @@ class VCS:
tmp_file = tempfile.NamedTemporaryFile("wb", delete=False) tmp_file = tempfile.NamedTemporaryFile("wb", delete=False)
assert " " not in tmp_file.name assert " " not in tmp_file.name
fh : typ.IO[bytes]
with tmp_file as fh: with tmp_file as fh:
fh.write(message_data) fh.write(message_data)
env = os.environ.copy() env: Env = os.environ.copy()
# TODO (mb 2018-09-04): check that this works on py27,
# might need to be bytes there, idk.
env['HGENCODING'] = "utf-8" env['HGENCODING'] = "utf-8"
self('commit', env=env, path=tmp_file.name) self('commit', env=env, path=tmp_file.name)
os.unlink(tmp_file.name) os.unlink(tmp_file.name)

View file

@ -430,7 +430,12 @@ def incr(
'old_version' is assumed to be a string that matches 'pattern' 'old_version' is assumed to be a string that matches 'pattern'
""" """
try:
old_ver_nfo = parse_version_info(old_version, pattern) old_ver_nfo = parse_version_info(old_version, pattern)
except ValueError as ex:
log.error(str(ex))
return None
cur_ver_nfo = old_ver_nfo cur_ver_nfo = old_ver_nfo
cur_cal_nfo = cal_info() cur_cal_nfo = cal_info()

View file

@ -128,6 +128,15 @@ def test_incr_semver(runner):
assert f"Version: {new_version}\n" in result.output assert f"Version: {new_version}\n" in result.output
def test_incr_semver_invalid(runner, caplog):
result = runner.invoke(pycalver.cli, ['test', "--verbose", "--patch", "0.1.1"])
assert result.exit_code == 1
assert len(caplog.records) > 0
log_record = caplog.records[0]
assert "Invalid version string" in log_record.message
assert "for pattern '{pycalver}'" in log_record.message
def test_incr_to_beta(runner): def test_incr_to_beta(runner):
old_version = "v201701.0999-alpha" old_version = "v201701.0999-alpha"
initial_version = config._initial_version() initial_version = config._initial_version()
@ -148,7 +157,7 @@ def test_incr_to_final(runner):
assert f"Version: {new_version}\n" in result.output assert f"Version: {new_version}\n" in result.output
def test_incr_invalid(runner, caplog): def test_incr_invalid(runner):
old_version = "v201701.0999-alpha" old_version = "v201701.0999-alpha"
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "alfa"]) result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "alfa"])
@ -183,11 +192,35 @@ def test_nocfg(runner, caplog):
) )
def test_novcs_nocfg_init(runner): def test_novcs_nocfg_init(runner, caplog, capsys):
_add_project_files("README.md") _add_project_files("README.md")
# dry mode test
result = runner.invoke(pycalver.cli, ['init', "--verbose", "--dry"])
assert result.exit_code == 0
assert not os.path.exists("pycalver.toml")
# check logging
assert len(caplog.records) == 1
log = caplog.records[0]
assert log.levelname == 'WARNING'
assert "File not found" in log.message
# print("moep")
# captured = capsys.readouterr()
# assert not captured.err
# assert "Would have written to pycalver.toml:" in captured.out
# non dry mode
result = runner.invoke(pycalver.cli, ['init', "--verbose"]) result = runner.invoke(pycalver.cli, ['init', "--verbose"])
assert result.exit_code == 0 assert result.exit_code == 0
# check logging
assert len(caplog.records) == 2
log = caplog.records[1]
assert log.levelname == 'WARNING'
assert "File not found" in log.message
assert os.path.exists("pycalver.toml")
with io.open("pycalver.toml", mode="r", encoding="utf-8") as fh: with io.open("pycalver.toml", mode="r", encoding="utf-8") as fh:
cfg_content = fh.read() cfg_content = fh.read()
@ -200,6 +233,15 @@ def test_novcs_nocfg_init(runner):
assert f"Current Version: {config._initial_version()}\n" in result.output assert f"Current Version: {config._initial_version()}\n" in result.output
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
assert result.exit_code == 1
# check logging
assert len(caplog.records) == 3
log = caplog.records[2]
assert log.levelname == 'ERROR'
assert "Configuration already initialized" in log.message
def test_novcs_setupcfg_init(runner): def test_novcs_setupcfg_init(runner):
_add_project_files("README.md", "setup.cfg") _add_project_files("README.md", "setup.cfg")

View file

@ -5,7 +5,7 @@ from pycalver import config
from . import util from . import util
PYCALVER_TOML_FIXTURE = """ PYCALVER_TOML_FIXTURE_1 = """
[pycalver] [pycalver]
current_version = "v201808.0123-alpha" current_version = "v201808.0123-alpha"
commit = true commit = true
@ -23,6 +23,22 @@ push = true
""" """
PYCALVER_TOML_FIXTURE_2 = """
[pycalver]
current_version = "1.2.3"
version_pattern = "{semver}"
[pycalver.file_patterns]
"README.md" = [
"{version}",
"{pep440_version}",
]
"pycalver.toml" = [
'current_version = "{version}"',
]
"""
SETUP_CFG_FIXTURE = """ SETUP_CFG_FIXTURE = """
[pycalver] [pycalver]
current_version = "v201808.0456-beta" current_version = "v201808.0456-beta"
@ -46,13 +62,14 @@ def mk_buf(text):
return buf return buf
def test_parse_toml(): def test_parse_toml_1():
buf = mk_buf(PYCALVER_TOML_FIXTURE) buf = mk_buf(PYCALVER_TOML_FIXTURE_1)
raw_cfg = config._parse_toml(buf) raw_cfg = config._parse_toml(buf)
cfg = config._parse_config(raw_cfg) cfg = config._parse_config(raw_cfg)
assert cfg.current_version == "v201808.0123-alpha" assert cfg.current_version == "v201808.0123-alpha"
assert cfg.version_pattern == "{pycalver}"
assert cfg.commit is True assert cfg.commit is True
assert cfg.tag is True assert cfg.tag is True
assert cfg.push is True assert cfg.push is True
@ -62,6 +79,23 @@ def test_parse_toml():
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{pycalver}"'] assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{pycalver}"']
def test_parse_toml_2():
buf = mk_buf(PYCALVER_TOML_FIXTURE_2)
raw_cfg = config._parse_toml(buf)
cfg = config._parse_config(raw_cfg)
assert cfg.current_version == "1.2.3"
assert cfg.version_pattern == "{semver}"
assert cfg.commit is False
assert cfg.tag is False
assert cfg.push is False
assert "pycalver.toml" in cfg.file_patterns
assert cfg.file_patterns["README.md" ] == ["{semver}", "{semver}"]
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{semver}"']
def test_parse_cfg(): def test_parse_cfg():
buf = mk_buf(SETUP_CFG_FIXTURE) buf = mk_buf(SETUP_CFG_FIXTURE)
@ -154,7 +188,7 @@ def test_parse_project_cfg():
def test_parse_toml_file(tmpdir): def test_parse_toml_file(tmpdir):
project_path = tmpdir.mkdir("minimal") project_path = tmpdir.mkdir("minimal")
setup_cfg = project_path.join("pycalver.toml") setup_cfg = project_path.join("pycalver.toml")
setup_cfg.write(PYCALVER_TOML_FIXTURE) setup_cfg.write(PYCALVER_TOML_FIXTURE_1)
ctx = config.init_project_ctx(project_path) ctx = config.init_project_ctx(project_path)
assert ctx == config.ProjectContext(project_path, setup_cfg, 'toml', None) assert ctx == config.ProjectContext(project_path, setup_cfg, 'toml', None)