diff --git a/src/bumpver/config.py b/src/bumpver/config.py index 52591e0..af48613 100644 --- a/src/bumpver/config.py +++ b/src/bumpver/config.py @@ -47,23 +47,39 @@ class ProjectContext(typ.NamedTuple): vcs_type : typ.Optional[str] +def _pick_config_filepath(path: pl.Path) -> pl.Path: + config_candidates: typ.List[pl.Path] = [ + path / "pycalver.toml", + path / "bumpver.toml", + path / "pyproject.toml", + path / "setup.cfg", + ] + + # Prefer to use a config which contains a bumpver and current_version + # This means a project can have multiple different configs. + for config_filepath in config_candidates: + if config_filepath.exists(): + with config_filepath.open(mode="rb") as fobj: + data = fobj.read() + + has_bumpver_section = ( + b"bumpver]" in data or b"pycalver]" in data + ) and b"current_version" in data + if has_bumpver_section: + return config_filepath + + # Next pick whatever config happens to exist, even if it + # doesn't have a [bumpver] section (yet). + for config_filepath in config_candidates: + if config_filepath.exists(): + return config_filepath + + # fallback to creating a new bumpver.toml + return path / "bumpver.toml" + + def _parse_config_and_format(path: pl.Path) -> typ.Tuple[pl.Path, str, str]: - if (path / "pycalver.toml").exists(): - config_filepath = path / "pycalver.toml" - config_format = 'toml' - elif (path / "bumpver.toml").exists(): - config_filepath = path / "bumpver.toml" - config_format = 'toml' - elif (path / "pyproject.toml").exists(): - config_filepath = path / "pyproject.toml" - config_format = 'toml' - elif (path / "setup.cfg").exists(): - config_filepath = path / "setup.cfg" - config_format = 'cfg' - else: - # fallback to creating a new bumpver.toml - config_filepath = path / "bumpver.toml" - config_format = 'toml' + config_filepath = _pick_config_filepath(path) if config_filepath.is_absolute(): config_rel_path = str(config_filepath.relative_to(path.absolute())) @@ -71,6 +87,7 @@ def _parse_config_and_format(path: pl.Path) -> typ.Tuple[pl.Path, str, str]: config_rel_path = str(config_filepath) config_filepath = pl.Path.cwd() / config_filepath + config_format = config_filepath.suffix[1:] return (config_filepath, config_rel_path, config_format) @@ -446,9 +463,10 @@ def parse(ctx: ProjectContext, cfg_missing_ok: bool = False) -> MaybeConfig: except (TypeError, ValueError) as ex: logger.warning(f"Couldn't parse {ctx.config_rel_path}: {str(ex)}") return None + elif cfg_missing_ok: + return None else: - if not cfg_missing_ok: - logger.warning(f"File not found: {ctx.config_rel_path}") + logger.warning(f"File not found: {ctx.config_rel_path}") return None diff --git a/test/test_cli.py b/test/test_cli.py index 9d14602..48b2603 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -24,6 +24,7 @@ from bumpver import v2patterns # pylint:disable=redefined-outer-name ; pytest fixtures # pylint:disable=protected-access ; allowed for test code # pylint:disable=unused-argument ; allowed for test code +# pylint:disable=too-many-lines ; allowed for test code README_TEXT_FIXTURE = """ @@ -323,6 +324,7 @@ def test_novcs_nocfg_init(runner, caplog): def test_novcs_setupcfg_init(runner): _add_project_files("README.md", "setup.cfg") + result = runner.invoke(cli.cli, ['init', "-vv"]) assert result.exit_code == 0 @@ -341,6 +343,24 @@ def test_novcs_setupcfg_init(runner): assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output +def test_novcs_multi_cfg(runner): + _add_project_files("README.md", "setup.cfg") + + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + # NOTE (mb 2020-11-16): Even though a pyproject.toml exists, it shouldn't + # be used because the setup.cfg has the [bumpver] config section and + # should have higher priorty. + with pl.Path("pyproject.toml").open(mode="wt", encoding="utf-8") as fobj: + fobj.write("") + + result = runner.invoke(cli.cli, ['show', "-vv"]) + 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_novcs_pyproject_init(runner, caplog): _add_project_files("README.md", "pyproject.toml") result = runner.invoke(cli.cli, ['init', "-vv"])