cli -> __main__ refactor

This commit is contained in:
Manuel Barkhau 2020-09-06 21:15:27 +00:00
parent 669e8944e9
commit 4caece2817
3 changed files with 450 additions and 401 deletions

View file

@ -9,8 +9,384 @@ __main__ module for PyCalVer.
Enables use as module: $ python -m pycalver --version
"""
import sys
import typing as typ
import logging
import subprocess as sp
import click
import pycalver.cli as v1cli
import pycalver2.cli as v2cli
import pycalver.version as v1version
import pycalver2.version as v2version
from pycalver import vcs
from pycalver import config
_VERBOSE = 0
try:
import pretty_traceback
pretty_traceback.install()
except ImportError:
pass # no need to fail because of missing dev dependency
click.disable_unicode_literals_warning = True
logger = logging.getLogger("pycalver.__main__")
def _configure_logging(verbose: int = 0) -> None:
if verbose >= 2:
log_format = "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-17s - %(message)s"
log_level = logging.DEBUG
elif verbose == 1:
log_format = "%(levelname)-7s - %(message)s"
log_level = logging.INFO
else:
log_format = "%(levelname)-7s - %(message)s"
log_level = logging.INFO
logging.basicConfig(level=log_level, format=log_format, datefmt="%Y-%m-%dT%H:%M:%S")
logger.debug("Logging configured.")
VALID_RELEASE_VALUES = ("alpha", "beta", "dev", "rc", "post", "final")
def _validate_release_tag(release: str) -> None:
if release in VALID_RELEASE_VALUES:
return
logger.error(f"Invalid argument --release={release}")
logger.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}")
sys.exit(1)
@click.group()
@click.version_option(version="v202007.0036")
@click.help_option()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
def cli(verbose: int = 0) -> None:
"""Automatically update PyCalVer version strings on python projects."""
global _VERBOSE
_VERBOSE = verbose
@cli.command()
@click.argument("old_version")
@click.argument("pattern", default="{pycalver}")
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"--release", default=None, metavar="<name>", help="Override release name of current_version"
)
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
def test(
old_version: str,
pattern : str = "{pycalver}",
verbose : int = 0,
release : str = None,
major : bool = False,
minor : bool = False,
patch : bool = False,
) -> None:
"""Increment a version number for demo purposes."""
_configure_logging(verbose=max(_VERBOSE, verbose))
if release:
_validate_release_tag(release)
new_version = _incr(
old_version,
pattern=pattern,
release=release,
major=major,
minor=minor,
patch=patch,
)
if new_version is None:
logger.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.")
sys.exit(1)
# TODO (mb 2020-09-05): version switch
pep440_version = v1version.to_pep440(new_version)
# pep440_version = v2version.to_pep440(new_version)
click.echo(f"New Version: {new_version}")
click.echo(f"PEP440 : {pep440_version}")
@cli.command()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
)
def show(verbose: int = 0, fetch: bool = True) -> None:
"""Show current version of your project."""
_configure_logging(verbose=max(_VERBOSE, verbose))
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg is None:
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
sys.exit(1)
cfg = _update_cfg_from_vcs(cfg, fetch)
click.echo(f"Current Version: {cfg.current_version}")
click.echo(f"PEP440 : {cfg.pep440_version}")
def _try_print_diff(cfg: config.Config, new_version: str) -> None:
try:
# TODO (mb 2020-09-05): version switch
diff = v1cli.get_diff(cfg, new_version)
# diff = v2cli.get_diff(cfg, new_version)
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)
else:
click.echo(diff)
except Exception as ex:
logger.error(str(ex), exc_info=True)
sys.exit(1)
def _incr(
old_version: str,
pattern : str = "{pycalver}",
*,
release: str = None,
major : bool = False,
minor : bool = False,
patch : bool = False,
) -> typ.Optional[str]:
is_v1_pattern = "{" in pattern
if is_v1_pattern:
return v1version.incr(
old_version,
pattern=pattern,
release=release,
major=major,
minor=minor,
patch=patch,
)
else:
return v2version.incr(
old_version,
pattern=pattern,
release=release,
major=major,
minor=minor,
patch=patch,
)
def _bump(
cfg : config.Config,
new_version : str,
commit_message: str,
allow_dirty : bool = False,
) -> None:
vcs_api: typ.Optional[vcs.VCSAPI] = None
if cfg.commit:
try:
vcs_api = vcs.get_vcs_api()
except OSError:
logger.warning("Version Control System not found, aborting commit.")
filepaths = set(cfg.file_patterns.keys())
if vcs_api:
vcs.assert_not_dirty(vcs_api, filepaths, allow_dirty)
try:
# TODO (mb 2020-09-05): version switch
v1cli.rewrite(cfg, new_version)
# v2cli.rewrite(cfg, new_version)
except Exception as ex:
logger.error(str(ex))
sys.exit(1)
if vcs_api:
vcs.commit(cfg, vcs_api, filepaths, new_version, commit_message)
def _try_bump(
cfg : config.Config,
new_version : str,
commit_message: str,
allow_dirty : bool = False,
) -> None:
try:
_bump(cfg, new_version, commit_message, allow_dirty)
except sp.CalledProcessError as ex:
logger.error(f"Error running subcommand: {ex.cmd}")
if ex.stdout:
sys.stdout.write(ex.stdout.decode('utf-8'))
if ex.stderr:
sys.stderr.write(ex.stderr.decode('utf-8'))
sys.exit(1)
@cli.command()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
)
def init(verbose: int = 0, dry: bool = False) -> None:
"""Initialize [pycalver] configuration."""
_configure_logging(verbose=max(_VERBOSE, verbose))
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg:
logger.error(f"Configuration already initialized in {ctx.config_filepath}")
sys.exit(1)
if dry:
click.echo(f"Exiting because of '--dry'. Would have written to {ctx.config_filepath}:")
cfg_text: str = config.default_config(ctx)
click.echo("\n " + "\n ".join(cfg_text.splitlines()))
sys.exit(0)
config.write_content(ctx)
def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
all_tags = vcs.get_tags(fetch=fetch)
# TODO (mb 2020-09-05): version switch
cfg = v1cli.update_cfg_from_vcs(cfg, all_tags)
# cfg = v2cli.update_cfg_from_vcs(cfg, all_tags)
return cfg
@cli.command()
@click.option(
"-v",
"--verbose",
count=True,
help="Control log level. -vv for debug level.",
)
@click.option(
"-f/-n",
"--fetch/--no-fetch",
is_flag=True,
default=True,
help="Sync tags from remote origin.",
)
@click.option(
"--dry",
default=False,
is_flag=True,
help="Display diff of changes, don't rewrite files.",
)
@click.option(
"--release",
default=None,
metavar="<name>",
help=(
f"Override release name of current_version. Valid options are: "
f"{', '.join(VALID_RELEASE_VALUES)}."
),
)
@click.option(
"--allow-dirty",
default=False,
is_flag=True,
help=(
"Commit even when working directory is has uncomitted changes. "
"(WARNING: The commit will still be aborted if there are uncomitted "
"to files with version strings."
),
)
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
def bump(
release : typ.Optional[str] = None,
verbose : int = 0,
dry : bool = False,
allow_dirty: bool = False,
fetch : bool = True,
major : bool = False,
minor : bool = False,
patch : bool = False,
) -> None:
"""Increment the current version string and update project files."""
verbose = max(_VERBOSE, verbose)
_configure_logging(verbose)
if release:
_validate_release_tag(release)
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg is None:
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
sys.exit(1)
cfg = _update_cfg_from_vcs(cfg, fetch)
old_version = cfg.current_version
new_version = _incr(
old_version,
pattern=cfg.version_pattern,
release=release,
major=major,
minor=minor,
patch=patch,
)
if new_version is None:
is_semver = "{semver}" 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}'.")
sys.exit(1)
logger.info(f"Old Version: {old_version}")
logger.info(f"New Version: {new_version}")
if dry or verbose >= 2:
_try_print_diff(cfg, new_version)
if dry:
return
# # TODO (mb 2020-09-05): format from config
# commit_message_kwargs = {
# new_version
# old_version
# pep440_new_version
# pep440_old_version
# }
# cfg.commit_message =
commit_message = f"bump version to {new_version}"
_try_bump(cfg, new_version, commit_message, allow_dirty)
if __name__ == '__main__':
from . import cli
cli.cli()
cli()

View file

@ -9,372 +9,45 @@ CLI module for PyCalVer.
Provided subcommands: show, test, init, bump
"""
import sys
import typing as typ
import logging
import subprocess as sp
import click
from . import vcs
from . import config
from . import rewrite
from . import version
_VERBOSE = 0
try:
import pretty_traceback
pretty_traceback.install()
except ImportError:
pass # no need to fail because of missing dev dependency
click.disable_unicode_literals_warning = True
VALID_RELEASE_VALUES = ("alpha", "beta", "dev", "rc", "post", "final")
import pycalver.rewrite as v1rewrite
import pycalver.version as v1version
from pycalver import config
logger = logging.getLogger("pycalver.cli")
def _configure_logging(verbose: int = 0) -> None:
if verbose >= 2:
log_format = "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-17s - %(message)s"
log_level = logging.DEBUG
elif verbose == 1:
log_format = "%(levelname)-7s - %(message)s"
log_level = logging.INFO
else:
log_format = "%(levelname)-7s - %(message)s"
log_level = logging.INFO
def update_cfg_from_vcs(cfg: config.Config, all_tags: typ.List[str]) -> config.Config:
version_tags = [tag for tag in all_tags if v1version.is_valid(tag, cfg.version_pattern)]
if not version_tags:
logger.debug("no vcs tags found")
return cfg
logging.basicConfig(level=log_level, format=log_format, datefmt="%Y-%m-%dT%H:%M:%S")
logger.debug("Logging configured.")
version_tags.sort(reverse=True)
logger.debug(f"found {len(version_tags)} tags: {version_tags[:2]}")
latest_version_tag = version_tags[0]
latest_version_pep440 = v1version.to_pep440(latest_version_tag)
if latest_version_tag <= cfg.current_version:
return cfg
def _validate_release_tag(release: str) -> None:
if release in VALID_RELEASE_VALUES:
return
logger.error(f"Invalid argument --release={release}")
logger.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}")
sys.exit(1)
@click.group()
@click.version_option(version="v202007.0036")
@click.help_option()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
def cli(verbose: int = 0) -> None:
"""Automatically update PyCalVer version strings on python projects."""
global _VERBOSE
_VERBOSE = verbose
@cli.command()
@click.argument("old_version")
@click.argument("pattern", default="{pycalver}")
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"--release", default=None, metavar="<name>", help="Override release name of current_version"
)
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
def test(
old_version: str,
pattern : str = "{pycalver}",
verbose : int = 0,
release : str = None,
major : bool = False,
minor : bool = False,
patch : bool = False,
) -> None:
"""Increment a version number for demo purposes."""
_configure_logging(verbose=max(_VERBOSE, verbose))
if release:
_validate_release_tag(release)
new_version = version.incr(
old_version, pattern=pattern, release=release, major=major, minor=minor, patch=patch
logger.info(f"Working dir version : {cfg.current_version}")
logger.info(f"Latest version from VCS tag: {latest_version_tag}")
return cfg._replace(
current_version=latest_version_tag,
pep440_version=latest_version_pep440,
)
if new_version is None:
logger.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.")
sys.exit(1)
pep440_version = version.to_pep440(new_version)
click.echo(f"New Version: {new_version}")
click.echo(f"PEP440 : {pep440_version}")
def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
try:
vcs_api = vcs.get_vcs_api()
logger.debug(f"vcs found: {vcs_api.name}")
if fetch:
logger.info("fetching tags from remote (to turn off use: -n / --no-fetch)")
vcs_api.fetch()
version_tags = [
tag for tag in vcs_api.ls_tags() if version.is_valid(tag, cfg.version_pattern)
]
if version_tags:
version_tags.sort(reverse=True)
logger.debug(f"found {len(version_tags)} tags: {version_tags[:2]}")
latest_version_tag = version_tags[0]
latest_version_pep440 = version.to_pep440(latest_version_tag)
if latest_version_tag > cfg.current_version:
logger.info(f"Working dir version : {cfg.current_version}")
logger.info(f"Latest version from {vcs_api.name:>3} tag: {latest_version_tag}")
cfg = cfg._replace(
current_version=latest_version_tag, pep440_version=latest_version_pep440
)
else:
logger.debug("no vcs tags found")
except OSError:
logger.debug("No vcs found")
return cfg
@cli.command()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
)
def show(verbose: int = 0, fetch: bool = True) -> None:
"""Show current version."""
_configure_logging(verbose=max(_VERBOSE, verbose))
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg is None:
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
sys.exit(1)
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
click.echo(f"Current Version: {cfg.current_version}")
click.echo(f"PEP440 : {cfg.pep440_version}")
@cli.command()
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
@click.option(
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
)
def init(verbose: int = 0, dry: bool = False) -> None:
"""Initialize [pycalver] configuration."""
_configure_logging(verbose=max(_VERBOSE, verbose))
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg:
logger.error(f"Configuration already initialized in {ctx.config_filepath}")
sys.exit(1)
if dry:
click.echo(f"Exiting because of '--dry'. Would have written to {ctx.config_filepath}:")
cfg_text: str = config.default_config(ctx)
click.echo("\n " + "\n ".join(cfg_text.splitlines()))
sys.exit(0)
config.write_content(ctx)
def _assert_not_dirty(vcs_api: vcs.VCSAPI, filepaths: typ.Set[str], allow_dirty: bool) -> None:
dirty_files = vcs_api.status(required_files=filepaths)
if dirty_files:
logger.warning(f"{vcs_api.name} working directory is not clean. Uncomitted file(s):")
for dirty_file in dirty_files:
logger.warning(" " + dirty_file)
if not allow_dirty and dirty_files:
sys.exit(1)
dirty_pattern_files = set(dirty_files) & filepaths
if dirty_pattern_files:
logger.error("Not commiting when pattern files are dirty:")
for dirty_file in dirty_pattern_files:
logger.warning(" " + dirty_file)
sys.exit(1)
def _commit(
cfg: config.Config, new_version: str, vcs_api: vcs.VCSAPI, filepaths: typ.Set[str]
def rewrite(
cfg : config.Config,
new_version: str,
) -> None:
for filepath in filepaths:
vcs_api.add(filepath)
vcs_api.commit(f"bump version to {new_version}")
if cfg.commit and cfg.tag:
vcs_api.tag(new_version)
if cfg.commit and cfg.tag and cfg.push:
vcs_api.push(new_version)
new_vinfo = v1version.parse_version_info(new_version, cfg.version_pattern)
v1rewrite.rewrite(cfg.file_patterns, new_vinfo)
def _bump(cfg: config.Config, new_version: str, allow_dirty: bool = False) -> None:
vcs_api: typ.Optional[vcs.VCSAPI] = None
if cfg.commit:
try:
vcs_api = vcs.get_vcs_api()
except OSError:
logger.warning("Version Control System not found, aborting commit.")
filepaths = set(cfg.file_patterns.keys())
if vcs_api:
_assert_not_dirty(vcs_api, filepaths, allow_dirty)
try:
new_vinfo = version.parse_version_info(new_version, cfg.version_pattern)
rewrite.rewrite(cfg.file_patterns, new_vinfo)
except Exception as ex:
logger.error(str(ex))
sys.exit(1)
if vcs_api:
_commit(cfg, new_version, vcs_api, filepaths)
def _try_bump(cfg: config.Config, new_version: str, allow_dirty: bool = False) -> None:
try:
_bump(cfg, new_version, allow_dirty)
except sp.CalledProcessError as ex:
logger.error(f"Error running subcommand: {ex.cmd}")
if ex.stdout:
sys.stdout.write(ex.stdout.decode('utf-8'))
if ex.stderr:
sys.stderr.write(ex.stderr.decode('utf-8'))
sys.exit(1)
def _print_diff(cfg: config.Config, new_version: str) -> None:
new_vinfo = version.parse_version_info(new_version, cfg.version_pattern)
diff: str = rewrite.diff(new_vinfo, cfg.file_patterns)
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)
else:
click.echo(diff)
def _try_print_diff(cfg: config.Config, new_version: str) -> None:
try:
_print_diff(cfg, new_version)
except Exception as ex:
logger.error(str(ex))
sys.exit(1)
@cli.command()
@click.option("-v", "--verbose", count=True, help="Control log level. -vv for debug level.")
@click.option(
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
)
@click.option(
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
)
@click.option(
"--release",
default=None,
metavar="<name>",
help=(
f"Override release name of current_version. Valid options are: "
f"{', '.join(VALID_RELEASE_VALUES)}."
),
)
@click.option(
"--allow-dirty",
default=False,
is_flag=True,
help=(
"Commit even when working directory is has uncomitted changes. "
"(WARNING: The commit will still be aborted if there are uncomitted "
"to files with version strings."
),
)
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
def bump(
release : typ.Optional[str] = None,
verbose : int = 0,
dry : bool = False,
allow_dirty: bool = False,
fetch : bool = True,
major : bool = False,
minor : bool = False,
patch : bool = False,
) -> None:
"""Increment the current version string and update project files."""
verbose = max(_VERBOSE, verbose)
_configure_logging(verbose)
if release:
_validate_release_tag(release)
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
cfg: config.MaybeConfig = config.parse(ctx)
if cfg is None:
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
sys.exit(1)
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
old_version = cfg.current_version
new_version = version.incr(
old_version,
pattern=cfg.version_pattern,
release=release,
major=major,
minor=minor,
patch=patch,
)
if new_version is None:
is_semver = "{semver}" 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}'.")
sys.exit(1)
logger.info(f"Old Version: {old_version}")
logger.info(f"New Version: {new_version}")
if dry or verbose >= 2:
_try_print_diff(cfg, new_version)
if dry:
return
_try_bump(cfg, new_version, allow_dirty)
if __name__ == '__main__':
cli()
def get_diff(cfg: config.Config, new_version: str) -> str:
new_vinfo = v1version.parse_version_info(new_version, cfg.version_pattern)
return v1rewrite.diff(new_vinfo, cfg.file_patterns)

View file

@ -10,9 +10,9 @@ import pytest
import pathlib2 as pl
from click.testing import CliRunner
import pycalver.cli as cli
import pycalver.config as config
import pycalver.patterns as patterns
import pycalver2.patterns as patterns
from pycalver.__main__ import cli
SETUP_CFG_FIXTURE = """
[metadata]
@ -68,7 +68,7 @@ def runner(tmpdir):
def test_help(runner):
result = runner.invoke(cli.cli, ['--help', "-vv"])
result = runner.invoke(cli, ['--help', "-vv"])
assert result.exit_code == 0
assert "PyCalVer" in result.output
assert "bump " in result.output
@ -78,7 +78,7 @@ def test_help(runner):
def test_version(runner):
result = runner.invoke(cli.cli, ['--version', "-vv"])
result = runner.invoke(cli, ['--version', "-vv"])
assert result.exit_code == 0
assert " version v20" in result.output
match = patterns.PYCALVER_RE.search(result.output)
@ -89,7 +89,7 @@ def test_incr_default(runner):
old_version = "v201701.0999-alpha"
initial_version = config._initial_version()
result = runner.invoke(cli.cli, ['test', "-vv", old_version])
result = runner.invoke(cli, ['test', "-vv", old_version])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000-alpha")
assert f"Version: {new_version}\n" in result.output
@ -100,31 +100,31 @@ def test_incr_semver(runner):
old_version = "0.1.0"
new_version = "0.1.1"
result = runner.invoke(cli.cli, ['test', "-vv", "--patch", old_version, "{semver}"])
result = runner.invoke(cli, ['test', "-vv", "--patch", old_version, "{semver}"])
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
result = runner.invoke(cli.cli, ['test', "-vv", "--patch", old_version, semver_pattern])
result = runner.invoke(cli, ['test', "-vv", "--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(cli.cli, ['test', "-vv", "--minor", old_version, semver_pattern])
result = runner.invoke(cli, ['test', "-vv", "--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(cli.cli, ['test', "-vv", "--major", old_version, semver_pattern])
result = runner.invoke(cli, ['test', "-vv", "--major", old_version, semver_pattern])
assert result.exit_code == 0
assert f"Version: {new_version}\n" in result.output
def test_incr_semver_invalid(runner, caplog):
result = runner.invoke(cli.cli, ['test', "-vv", "--patch", "0.1.1"])
result = runner.invoke(cli, ['test', "-vv", "--patch", "0.1.1"])
assert result.exit_code == 1
assert len(caplog.records) > 0
log_record = caplog.records[0]
@ -136,7 +136,7 @@ def test_incr_to_beta(runner):
old_version = "v201701.0999-alpha"
initial_version = config._initial_version()
result = runner.invoke(cli.cli, ['test', old_version, "-vv", "--release", "beta"])
result = runner.invoke(cli, ['test', old_version, "-vv", "--release", "beta"])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000-beta")
assert f"Version: {new_version}\n" in result.output
@ -146,7 +146,7 @@ def test_incr_to_final(runner):
old_version = "v201701.0999-alpha"
initial_version = config._initial_version()
result = runner.invoke(cli.cli, ['test', old_version, "-vv", "--release", "final"])
result = runner.invoke(cli, ['test', old_version, "-vv", "--release", "final"])
assert result.exit_code == 0
new_version = initial_version.replace(".0001-alpha", ".11000")
assert f"Version: {new_version}\n" in result.output
@ -155,7 +155,7 @@ def test_incr_to_final(runner):
def test_incr_invalid(runner):
old_version = "v201701.0999-alpha"
result = runner.invoke(cli.cli, ['test', old_version, "-vv", "--release", "alfa"])
result = runner.invoke(cli, ['test', old_version, "-vv", "--release", "alfa"])
assert result.exit_code == 1
@ -184,7 +184,7 @@ def _add_project_files(*files):
def test_nocfg(runner, caplog):
_add_project_files("README.md")
result = runner.invoke(cli.cli, ['show', "-vv"])
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)
@ -195,7 +195,7 @@ def test_nocfg(runner, caplog):
def test_novcs_nocfg_init(runner, caplog):
_add_project_files("README.md")
# dry mode test
result = runner.invoke(cli.cli, ['init', "-vv", "--dry"])
result = runner.invoke(cli, ['init', "-vv", "--dry"])
assert result.exit_code == 0
assert not os.path.exists("pycalver.toml")
@ -206,7 +206,7 @@ def test_novcs_nocfg_init(runner, caplog):
assert "File not found" in log.message
# non dry mode
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
# check logging
@ -223,12 +223,12 @@ def test_novcs_nocfg_init(runner, caplog):
assert base_str in cfg_content
assert config.DEFAULT_TOML_README_MD_STR in cfg_content
result = runner.invoke(cli.cli, ['show', "-vv"])
result = runner.invoke(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
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 1
# check logging
@ -240,7 +240,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"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
with pl.Path("setup.cfg").open(mode="r", encoding="utf-8") as fobj:
@ -252,7 +252,7 @@ def test_novcs_setupcfg_init(runner):
assert base_str in cfg_content
assert config.DEFAULT_CONFIGPARSER_README_MD_STR in cfg_content
result = runner.invoke(cli.cli, ['show', "-vv"])
result = runner.invoke(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
@ -260,7 +260,7 @@ def test_novcs_setupcfg_init(runner):
def test_novcs_pyproject_init(runner):
_add_project_files("README.md", "pyproject.toml")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
with pl.Path("pyproject.toml").open(mode="r", encoding="utf-8") as fobj:
@ -270,7 +270,7 @@ def test_novcs_pyproject_init(runner):
assert base_str in cfg_content
assert config.DEFAULT_TOML_README_MD_STR in cfg_content
result = runner.invoke(cli.cli, ['show'])
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
@ -292,10 +292,10 @@ def test_git_init(runner):
_add_project_files("README.md")
_vcs_init("git")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
result = runner.invoke(cli.cli, ['show'])
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
@ -305,10 +305,10 @@ def test_hg_init(runner):
_add_project_files("README.md")
_vcs_init("hg")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
result = runner.invoke(cli.cli, ['show'])
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
@ -320,7 +320,7 @@ def test_git_tag_eval(runner):
# This will set a version that is older than the version tag
# we set in the vcs, which should take precedence.
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
initial_version = config._initial_version()
tag_version = initial_version.replace(".0001-alpha", ".0123-beta")
@ -328,7 +328,7 @@ def test_git_tag_eval(runner):
shell("git", "tag", "--annotate", tag_version, "--message", f"bump version to {tag_version}")
result = runner.invoke(cli.cli, ['show', "-vv"])
result = runner.invoke(cli, ['show', "-vv"])
assert result.exit_code == 0
assert f"Current Version: {tag_version}\n" in result.output
assert f"PEP440 : {tag_version_pep440}\n" in result.output
@ -340,7 +340,7 @@ def test_hg_tag_eval(runner):
# This will set a version that is older than the version tag
# we set in the vcs, which should take precedence.
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
initial_version = config._initial_version()
tag_version = initial_version.replace(".0001-alpha", ".0123-beta")
@ -348,7 +348,7 @@ def test_hg_tag_eval(runner):
shell("hg", "tag", tag_version, "--message", f"bump version to {tag_version}")
result = runner.invoke(cli.cli, ['show', "-vv"])
result = runner.invoke(cli, ['show', "-vv"])
assert result.exit_code == 0
assert f"Current Version: {tag_version}\n" in result.output
assert f"PEP440 : {tag_version_pep440}\n" in result.output
@ -357,10 +357,10 @@ def test_hg_tag_eval(runner):
def test_novcs_bump(runner):
_add_project_files("README.md")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
result = runner.invoke(cli.cli, ['bump', "-vv"])
result = runner.invoke(cli, ['bump', "-vv"])
assert result.exit_code == 0
calver = config._initial_version()[:7]
@ -370,7 +370,7 @@ def test_novcs_bump(runner):
assert calver + ".0002-alpha !\n" in content
assert calver[1:] + ".2a0 !\n" in content
result = runner.invoke(cli.cli, ['bump', "-vv", "--release", "beta"])
result = runner.invoke(cli, ['bump', "-vv", "--release", "beta"])
assert result.exit_code == 0
with pl.Path("README.md").open() as fobj:
@ -383,13 +383,13 @@ def test_git_bump(runner):
_add_project_files("README.md")
_vcs_init("git")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
shell("git", "add", "pycalver.toml")
shell("git", "commit", "-m", "initial commit")
result = runner.invoke(cli.cli, ['bump', "-vv"])
result = runner.invoke(cli, ['bump', "-vv"])
assert result.exit_code == 0
calver = config._initial_version()[:7]
@ -403,13 +403,13 @@ def test_hg_bump(runner):
_add_project_files("README.md")
_vcs_init("hg")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
shell("hg", "add", "pycalver.toml")
shell("hg", "commit", "-m", "initial commit")
result = runner.invoke(cli.cli, ['bump', "-vv"])
result = runner.invoke(cli, ['bump', "-vv"])
assert result.exit_code == 0
calver = config._initial_version()[:7]
@ -423,7 +423,7 @@ def test_empty_git_bump(runner, caplog):
shell("git", "init")
with pl.Path("setup.cfg").open(mode="w") as fobj:
fobj.write("")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
with pl.Path("setup.cfg").open(mode="r") as fobj:
@ -434,7 +434,7 @@ def test_empty_git_bump(runner, caplog):
assert "\n[pycalver:file_patterns]\n" in default_cfg_data
assert "\nsetup.cfg =\n" in default_cfg_data
result = runner.invoke(cli.cli, ['bump'])
result = runner.invoke(cli, ['bump'])
assert any(("working directory is not clean" in r.message) for r in caplog.records)
assert any(("setup.cfg" in r.message) for r in caplog.records)
@ -444,7 +444,7 @@ def test_empty_hg_bump(runner, caplog):
shell("hg", "init")
with pl.Path("setup.cfg").open(mode="w") as fobj:
fobj.write("")
result = runner.invoke(cli.cli, ['init', "-vv"])
result = runner.invoke(cli, ['init', "-vv"])
assert result.exit_code == 0
with pl.Path("setup.cfg").open(mode="r") as fobj:
@ -455,7 +455,7 @@ def test_empty_hg_bump(runner, caplog):
assert "\n[pycalver:file_patterns]\n" in default_cfg_text
assert "\nsetup.cfg =\n" in default_cfg_text
result = runner.invoke(cli.cli, ['bump'])
result = runner.invoke(cli, ['bump'])
assert any(("working directory is not clean" in r.message) for r in caplog.records)
assert any(("setup.cfg" in r.message) for r in caplog.records)
@ -486,13 +486,13 @@ def test_bump_semver_warning(runner, caplog):
_vcs_init("hg", files=["README.md", "setup.cfg"])
result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry"])
result = runner.invoke(cli, ['bump', "-vv", "-n", "--dry"])
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)
result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry", "--patch"])
result = runner.invoke(cli, ['bump', "-vv", "-n", "--dry", "--patch"])
assert result.exit_code == 0
@ -507,7 +507,7 @@ def test_bump_semver_diff(runner, caplog):
cases = [("--major", "1.0.0"), ("--minor", "0.2.0"), ("--patch", "0.1.1")]
for flag, expected in cases:
result = runner.invoke(cli.cli, ['bump', "-vv", "-n", "--dry", flag])
result = runner.invoke(cli, ['bump', "-vv", "-n", "--dry", flag])
assert result.exit_code == 0
assert len(caplog.records) == 0