diff --git a/pylint-ignore.md b/pylint-ignore.md index 0857d3c..ac42083 100644 --- a/pylint-ignore.md +++ b/pylint-ignore.md @@ -20,99 +20,3 @@ The recommended approach to using `pylint-ignore` is: 3. If a message is a false positive, add a comment of this form to your code: `# pylint:disable= ; explain why this is a false positive` - -# Overview - - - [W0511: fixme (4x)](#w0511-fixme) - - [W0703: broad-except (1x)](#w0703-broad-except) - - -# W0511: fixme - -## File src/pycalver/v1cli.py - Line 29 - W0511 (fixme) - -- `message: TODO (mb 2020-10-03): This codepath is not tested since switch to` -- `author : Manuel Barkhau ` -- `date : 2020-10-03T23:40:01` - -``` - 23: def update_cfg_from_vcs(cfg: config.Config, all_tags: typ.List[str]) -> config.Config: - ... - 27: return cfg - 28: -> 29: # TODO (mb 2020-10-03): This codepath is not tested since switch to - 30: # v2 as default version_pattern. - 31: version_tags.sort(reverse=True) -``` - - -## File src/pycalver/vcs.py - Line 80 - W0511 (fixme) - -- `message: TODO (mb 2018-11-15): Detect encoding of output? Use chardet?` -- `author : Manuel Barkhau ` -- `date : 2020-09-18T17:24:49` - -``` - 69: def __call__(self, cmd_name: str, env: Env = None, **kwargs: str) -> str: - ... - 78: output_data: bytes = sp.check_output(cmd_parts, env=env, stderr=sp.STDOUT) - 79: -> 80: # TODO (mb 2018-11-15): Detect encoding of output? Use chardet? - 81: _encoding = "utf-8" - 82: return output_data.decode(_encoding) -``` - - -## File test/test_config.py - Line 170 - W0511 (fixme) - -- `message: TODO (mb 2020-09-18):` -- `author : Manuel Barkhau ` -- `date : 2020-09-18T19:04:06` - -``` - 156: def test_parse_v2_cfg(): - ... - 168: assert "setup.cfg" in cfg.file_patterns - 169: -> 170: # TODO (mb 2020-09-18): - 171: # raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg) - 172: # assert raw_patterns_by_filepath["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"] -``` - - -## File src/pycalver/__main__.py - Line 421 - W0511 (fixme) - -- `message: TODO (mb 2020-09-18): Investigate error messages` -- `author : Manuel Barkhau ` -- `date : 2020-09-19T16:24:10` - -``` - 391: def _bump( - ... - 419: sys.exit(1) - 420: except Exception as ex: -> 421: # TODO (mb 2020-09-18): Investigate error messages - 422: logger.error(str(ex)) - 423: sys.exit(1) -``` - - -# W0703: broad-except - -## File src/pycalver/__main__.py - Line 420 - W0703 (broad-except) - -- `message: Catching too general exception Exception` -- `author : Manuel Barkhau ` -- `date : 2020-09-05T14:30:17` - -``` - 391: def _bump( - ... - 418: logger.error(str(ex)) - 419: sys.exit(1) -> 420: except Exception as ex: - 421: # TODO (mb 2020-09-18): Investigate error messages - 422: logger.error(str(ex)) -``` - - diff --git a/src/pycalver/__main__.py b/src/pycalver/__main__.py index 1c45e6b..c2afc15 100755 --- a/src/pycalver/__main__.py +++ b/src/pycalver/__main__.py @@ -303,19 +303,24 @@ def show(verbose: int = 0, fetch: bool = True) -> None: click.echo(f"PEP440 : {cfg.pep440_version}") +def _colored_diff_lines(diff: str) -> typ.Iterable[str]: + for line in diff.splitlines(): + if line.startswith("+++") or line.startswith("---"): + yield line + elif line.startswith("+"): + yield "\u001b[32m" + line + "\u001b[0m" + elif line.startswith("-"): + yield "\u001b[31m" + line + "\u001b[0m" + elif line.startswith("@"): + yield "\u001b[36m" + line + "\u001b[0m" + else: + yield line + + def _print_diff_str(diff: str) -> None: + colored_diff = "\n".join(_colored_diff_lines(diff)) if sys.stdout.isatty(): - for line in diff.splitlines(): - if line.startswith("+++") or line.startswith("---"): - click.echo(line) - elif line.startswith("+"): - click.echo("\u001b[32m" + line + "\u001b[0m") - elif line.startswith("-"): - click.echo("\u001b[31m" + line + "\u001b[0m") - elif line.startswith("@"): - click.echo("\u001b[36m" + line + "\u001b[0m") - else: - click.echo(line) + click.echo(colored_diff) else: click.echo(diff) @@ -331,11 +336,6 @@ def _print_diff(cfg: config.Config, new_version: str) -> None: except rewrite.NoPatternMatch as ex: logger.error(str(ex)) sys.exit(1) - except Exception as ex: - # pylint:disable=broad-except; Mostly we expect IOError here, but - # could be other things and there's no option to recover anyway. - logger.error(str(ex), exc_info=True) - sys.exit(1) def incr_dispatch( @@ -417,10 +417,6 @@ def _bump( except rewrite.NoPatternMatch as ex: logger.error(str(ex)) sys.exit(1) - except Exception as ex: - # TODO (mb 2020-09-18): Investigate error messages - logger.error(str(ex)) - sys.exit(1) if vcs_api: vcs.commit(cfg, vcs_api, filepaths, new_version, commit_message) diff --git a/src/pycalver/v1cli.py b/src/pycalver/v1cli.py index a0c1c21..47c3c2d 100755 --- a/src/pycalver/v1cli.py +++ b/src/pycalver/v1cli.py @@ -26,8 +26,6 @@ def update_cfg_from_vcs(cfg: config.Config, all_tags: typ.List[str]) -> config.C logger.debug("no vcs tags found") return cfg - # TODO (mb 2020-10-03): This codepath is not tested since switch to - # v2 as default version_pattern. version_tags.sort(reverse=True) _debug_tags = ", ".join(version_tags[:3]) logger.debug(f"found tags: {_debug_tags} ... ({len(version_tags)} in total)") diff --git a/src/pycalver/v2version.py b/src/pycalver/v2version.py index 57f966a..dabcd53 100644 --- a/src/pycalver/v2version.py +++ b/src/pycalver/v2version.py @@ -141,6 +141,7 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo: >>> (vinfo.year_y, vinfo.week_w, vinfo.year_y, vinfo.week_u,vinfo.year_g, vinfo.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 diff --git a/src/pycalver/vcs.py b/src/pycalver/vcs.py index 93de8da..918778e 100644 --- a/src/pycalver/vcs.py +++ b/src/pycalver/vcs.py @@ -77,9 +77,7 @@ class VCSAPI: cmd_parts = shlex.split(cmd_str) output_data: bytes = sp.check_output(cmd_parts, env=env, stderr=sp.STDOUT) - # TODO (mb 2018-11-15): Detect encoding of output? Use chardet? - _encoding = "utf-8" - return output_data.decode(_encoding) + return output_data.decode("utf-8") @property def is_usable(self) -> bool: diff --git a/test/test_cli.py b/test/test_cli.py index 5f361db..99d79f5 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -241,10 +241,8 @@ def test_nocfg(runner, caplog): _add_project_files("README.md") result = runner.invoke(cli, ['show', "-vv"]) assert result.exit_code == 1 - assert any( - bool("Could not parse configuration. Perhaps try 'pycalver init'." in r.message) - for r in caplog.records - ) + expected_msg = "Could not parse configuration. Perhaps try 'pycalver init'." + assert any(expected_msg in r.message for r in caplog.records) def test_novcs_nocfg_init(runner, caplog): @@ -343,33 +341,46 @@ def _vcs_init(vcs, files=("README.md",)): shell(f"{vcs}", "commit", "-m", "initial commit") -def test_git_init(runner): +DEFAULT_VERSION_PATTERNS = [ + '"{pycalver}"', + '"vYYYY0M.BUILD[-RELEASE]"', +] + + +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_git_init(runner, version_pattern): _add_project_files("README.md") _vcs_init("git") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + _update_config_val("pycalver.toml", version_pattern=version_pattern) + result = runner.invoke(cli, ['show']) assert result.exit_code == 0 assert f"Current Version: {config._initial_version()}\n" in result.output assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output -def test_hg_init(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_hg_init(runner, version_pattern): _add_project_files("README.md") _vcs_init("hg") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + _update_config_val("pycalver.toml", version_pattern=version_pattern) + result = runner.invoke(cli, ['show']) assert result.exit_code == 0 assert f"Current Version: {config._initial_version()}\n" in result.output assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output -def test_git_tag_eval(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_v1_git_tag_eval(runner, version_pattern): _add_project_files("README.md") _vcs_init("git") @@ -377,6 +388,9 @@ def test_git_tag_eval(runner): # we set in the vcs, which should take precedence. result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + + _update_config_val("pycalver.toml", version_pattern=version_pattern) + initial_version = config._initial_version() tag_version = initial_version.replace(".1001-alpha", ".1123-beta") tag_version_pep440 = tag_version[1:7] + ".1123b0" @@ -389,7 +403,8 @@ def test_git_tag_eval(runner): assert f"PEP440 : {tag_version_pep440}\n" in result.output -def test_hg_tag_eval(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_hg_tag_eval(runner, version_pattern): _add_project_files("README.md") _vcs_init("hg") @@ -397,6 +412,9 @@ def test_hg_tag_eval(runner): # we set in the vcs, which should take precedence. result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + + _update_config_val("pycalver.toml", version_pattern=version_pattern) + initial_version = config._initial_version() tag_version = initial_version.replace(".1001-alpha", ".1123-beta") tag_version_pep440 = tag_version[1:7] + ".1123b0" @@ -409,12 +427,15 @@ def test_hg_tag_eval(runner): assert f"PEP440 : {tag_version_pep440}\n" in result.output -def test_novcs_bump(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_novcs_bump(runner, version_pattern): _add_project_files("README.md") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + _update_config_val("pycalver.toml", version_pattern=version_pattern) + result = runner.invoke(cli, ['bump', "-vv"]) assert result.exit_code == 0 @@ -434,13 +455,16 @@ def test_novcs_bump(runner): assert calver[1:] + ".1003b0 !]\n" in content -def test_git_bump(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_git_bump(runner, version_pattern): _add_project_files("README.md") _vcs_init("git") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + _update_config_val("pycalver.toml", version_pattern=version_pattern) + shell("git", "add", "pycalver.toml") shell("git", "commit", "-m", "initial commit") @@ -454,13 +478,16 @@ def test_git_bump(runner): assert calver + ".1002-alpha !\n" in content -def test_hg_bump(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_hg_bump(runner, version_pattern): _add_project_files("README.md") _vcs_init("hg") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 + _update_config_val("pycalver.toml", version_pattern=version_pattern) + shell("hg", "add", "pycalver.toml") shell("hg", "commit", "-m", "initial commit") @@ -533,12 +560,21 @@ setup.cfg = """ -def test_v1_bump_semver_warning(runner, caplog): +DEFAULT_SEMVER_PATTERNS = [ + '"{semver}"', + '"MAJOR.MINOR.PATCH"', +] + + +@pytest.mark.parametrize("version_pattern", DEFAULT_SEMVER_PATTERNS) +def test_v1_bump_semver_warning(runner, caplog, version_pattern): _add_project_files("README.md") with pl.Path("setup.cfg").open(mode="w") as fobj: fobj.write(SETUP_CFG_SEMVER_FIXTURE) + _update_config_val("setup.cfg", version_pattern=version_pattern) + _vcs_init("hg", files=["README.md", "setup.cfg"]) result = runner.invoke(cli, ['bump', "-vv", "-n", "--dry"]) @@ -551,12 +587,15 @@ def test_v1_bump_semver_warning(runner, caplog): assert result.exit_code == 0 -def test_v1_bump_semver_diff(runner, caplog): +@pytest.mark.parametrize("version_pattern", DEFAULT_SEMVER_PATTERNS) +def test_v1_bump_semver_diff(runner, caplog, version_pattern): _add_project_files("README.md") with pl.Path("setup.cfg").open(mode="w") as fobj: fobj.write(SETUP_CFG_SEMVER_FIXTURE) + _update_config_val("setup.cfg", version_pattern=version_pattern) + _vcs_init("hg", files=["README.md", "setup.cfg"]) cases = [("--major", "1.0.0"), ("--minor", "0.2.0"), ("--patch", "0.1.1")] @@ -573,38 +612,23 @@ def test_v1_bump_semver_diff(runner, caplog): assert f"+current_version = \"{expected}\"" in out_lines -def test_v1_get_diff(runner): +@pytest.mark.parametrize("version_pattern", DEFAULT_VERSION_PATTERNS) +def test_get_diff(runner, version_pattern): _add_project_files("README.md", "setup.cfg") result = runner.invoke(cli, ['init', "-vv"]) assert result.exit_code == 0 - _update_config_val("setup.cfg", version_pattern='"{pycalver}"') + _update_config_val("setup.cfg", version_pattern=version_pattern) _, cfg = config.init() new_version = "v202010.1003-beta" - diff_str = v1cli.get_diff(cfg, new_version) - diff_lines = set(diff_str.splitlines()) - assert "- Hello World v201701.1002-alpha !" in diff_lines - assert "- [aka. 201701.1002a0 !]" in diff_lines - assert "+ Hello World v202010.1003-beta !" in diff_lines - assert "+ [aka. 202010.1003b0 !]" in diff_lines + if cfg.is_new_pattern: + diff_str = v2cli.get_diff(cfg, new_version) + else: + diff_str = v1cli.get_diff(cfg, new_version) - assert '-current_version = "v202010.1001-alpha"' in diff_lines - assert '+current_version = "v202010.1003-beta"' in diff_lines - - -def test_v2_get_diff(runner): - _add_project_files("README.md", "setup.cfg") - result = runner.invoke(cli, ['init', "-vv"]) - assert result.exit_code == 0 - - _update_config_val("setup.cfg", version_pattern='"vYYYY0M.BUILD[-RELEASE]"') - - _, cfg = config.init() - new_version = "v202010.1003-beta" - diff_str = v2cli.get_diff(cfg, new_version) - diff_lines = set(diff_str.splitlines()) + diff_lines = set(diff_str.splitlines()) assert "- Hello World v201701.1002-alpha !" in diff_lines assert "- [aka. 201701.1002a0 !]" in diff_lines diff --git a/test/test_config.py b/test/test_config.py index 09807aa..7d66cbb 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -167,11 +167,13 @@ def test_parse_v2_cfg(): assert "setup.py" in cfg.file_patterns assert "setup.cfg" in cfg.file_patterns - # TODO (mb 2020-09-18): - # raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg) - # assert raw_patterns_by_filepath["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"] - # assert raw_patterns_by_filepath["setup.cfg" ] == ['current_version = "vYYYY0M.BUILD[-RELEASE]"'] - # assert raw_patterns_by_filepath["src/project/*.py"] == ['Copyright (c) 2018-YYYY"'] + raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg) + assert raw_patterns_by_filepath["setup.py"] == [ + "vYYYY0M.BUILD[-RELEASE]", + "YYYY0M.BLD[PYTAGNUM]", + ] + assert raw_patterns_by_filepath["setup.cfg"] == ['current_version = "vYYYY0M.BUILD[-RELEASE]"'] + assert raw_patterns_by_filepath["src/project/*.py"] == ["Copyright (c) 2018-YYYY"] def test_parse_default_toml(): diff --git a/test/test_version.py b/test/test_version.py index 7dadb50..18672c3 100644 --- a/test/test_version.py +++ b/test/test_version.py @@ -239,3 +239,36 @@ def test_v2_format_version(): result = v2version.format_version(vinfo, raw_pattern='__version__ = "YYYY.BLD"') assert result == '__version__ = "2007.33"' + + +WEEK_PATTERN_TEXT_CASES = [ + ("YYYYWW.PATCH", True), + ("YYYYUU.PATCH", True), + ("GGGGVV.PATCH", True), + ("YYWW.PATCH" , True), + ("YYUU.PATCH" , True), + ("GGVV.PATCH" , True), + ("0YWW.PATCH" , True), + ("0YUU.PATCH" , True), + ("0GVV.PATCH" , True), + ("0Y0W.PATCH" , True), + ("0Y0U.PATCH" , True), + ("0G0V.PATCH" , True), + ("GGGGWW.PATCH", False), + ("GGGGUU.PATCH", False), + ("YYYYVV.PATCH", False), + ("GGWW.PATCH" , False), + ("GGUU.PATCH" , False), + ("YYVV.PATCH" , False), + ("0GWW.PATCH" , False), + ("0GUU.PATCH" , False), + ("0YVV.PATCH" , False), + ("0G0W.PATCH" , False), + ("0G0U.PATCH" , False), + ("0Y0V.PATCH" , False), +] + + +@pytest.mark.parametrize("pattern, expected", WEEK_PATTERN_TEXT_CASES) +def test_is_valid_week_pattern(pattern, expected): + assert v2version.is_valid_week_pattern(pattern) == expected