diff --git a/src/pycalver/cli.py b/src/pycalver/cli.py index 71a0125..57eb65e 100755 --- a/src/pycalver/cli.py +++ b/src/pycalver/cli.py @@ -42,7 +42,7 @@ click.disable_unicode_literals_warning = True VALID_RELEASE_VALUES = ("alpha", "beta", "dev", "rc", "post", "final") -log = logging.getLogger("pycalver.cli") +logger = logging.getLogger("pycalver.cli") def _configure_logging(verbose: int = 0) -> None: @@ -57,15 +57,15 @@ def _configure_logging(verbose: int = 0) -> None: log_level = logging.INFO logging.basicConfig(level=log_level, format=log_format, datefmt="%Y-%m-%dT%H:%M:%S") - log.debug("Logging configured.") + logger.debug("Logging configured.") def _validate_release_tag(release: str) -> None: if release in VALID_RELEASE_VALUES: return - log.error(f"Invalid argument --release={release}") - log.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}") + logger.error(f"Invalid argument --release={release}") + logger.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}") sys.exit(1) @@ -108,7 +108,7 @@ def test( old_version, pattern=pattern, release=release, major=major, minor=minor, patch=patch ) if new_version is None: - log.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.") + logger.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.") sys.exit(1) pep440_version = version.to_pep440(new_version) @@ -119,29 +119,31 @@ def test( def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config: try: - _vcs = vcs.get_vcs() - log.debug(f"vcs found: {_vcs.name}") + vcs_api = vcs.get_vcs_api() + logger.debug(f"vcs found: {vcs_api.name}") if fetch: - log.info("fetching tags from remote (to turn off use: -n / --no-fetch)") - _vcs.fetch() + logger.info("fetching tags from remote (to turn off use: -n / --no-fetch)") + vcs_api.fetch() - version_tags = [tag for tag in _vcs.ls_tags() if version.is_valid(tag, cfg.version_pattern)] + 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) - log.debug(f"found {len(version_tags)} tags: {version_tags[:2]}") + 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: - log.info(f"Working dir version : {cfg.current_version}") - log.info(f"Latest version from {_vcs.name:>3} tag: {latest_version_tag}") + 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: - log.debug("no vcs tags found") + logger.debug("no vcs tags found") except OSError: - log.debug("No vcs found") + logger.debug("No vcs found") return cfg @@ -159,7 +161,7 @@ def show(verbose: int = 0, fetch: bool = True) -> None: cfg: config.MaybeConfig = config.parse(ctx) if cfg is None: - log.error("Could not parse configuration. Perhaps try 'pycalver init'.") + logger.error("Could not parse configuration. Perhaps try 'pycalver init'.") sys.exit(1) cfg = _update_cfg_from_vcs(cfg, fetch=fetch) @@ -181,7 +183,7 @@ def init(verbose: int = 0, dry: bool = False) -> None: cfg: config.MaybeConfig = config.parse(ctx) if cfg: - log.error(f"Configuration already initialized in {ctx.config_filepath}") + logger.error(f"Configuration already initialized in {ctx.config_filepath}") sys.exit(1) if dry: @@ -193,67 +195,70 @@ def init(verbose: int = 0, dry: bool = False) -> None: config.write_content(ctx) -def _assert_not_dirty(_vcs: vcs.VCS, filepaths: typ.Set[str], allow_dirty: bool) -> None: - dirty_files = _vcs.status(required_files=filepaths) +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: - log.warning(f"{_vcs.name} working directory is not clean. Uncomitted file(s):") + logger.warning(f"{vcs_api.name} working directory is not clean. Uncomitted file(s):") for dirty_file in dirty_files: - log.warning(" " + dirty_file) + 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: - log.error("Not commiting when pattern files are dirty:") + logger.error("Not commiting when pattern files are dirty:") for dirty_file in dirty_pattern_files: - log.warning(" " + dirty_file) + logger.warning(" " + dirty_file) sys.exit(1) +def _commit( + cfg: config.Config, new_version: str, vcs_api: vcs.VCSAPI, filepaths: typ.Set[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) + + def _bump(cfg: config.Config, new_version: str, allow_dirty: bool = False) -> None: - _vcs: typ.Optional[vcs.VCS] + vcs_api: typ.Optional[vcs.VCSAPI] = None if cfg.commit: try: - _vcs = vcs.get_vcs() + vcs_api = vcs.get_vcs_api() except OSError: - log.warning("Version Control System not found, aborting commit.") - _vcs = None + logger.warning("Version Control System not found, aborting commit.") filepaths = set(cfg.file_patterns.keys()) - if _vcs: - _assert_not_dirty(_vcs, filepaths, allow_dirty) + 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: - log.error(str(ex)) + logger.error(str(ex)) sys.exit(1) - if _vcs is None or not cfg.commit: - return - - for filepath in filepaths: - _vcs.add(filepath) - - _vcs.commit(f"bump version to {new_version}") - - if cfg.commit and cfg.tag: - _vcs.tag(new_version) - - if cfg.commit and cfg.tag and cfg.push: - _vcs.push(new_version) + 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: - log.error(f"Error running subcommand: {ex.cmd}") + logger.error(f"Error running subcommand: {ex.cmd}") if ex.stdout: sys.stdout.write(ex.stdout.decode('utf-8')) if ex.stderr: @@ -285,7 +290,7 @@ def _try_print_diff(cfg: config.Config, new_version: str) -> None: try: _print_diff(cfg, new_version) except Exception as ex: - log.error(str(ex)) + logger.error(str(ex)) sys.exit(1) @@ -340,7 +345,7 @@ def bump( cfg: config.MaybeConfig = config.parse(ctx) if cfg is None: - log.error("Could not parse configuration. Perhaps try 'pycalver init'.") + logger.error("Could not parse configuration. Perhaps try 'pycalver init'.") sys.exit(1) cfg = _update_cfg_from_vcs(cfg, fetch=fetch) @@ -358,13 +363,13 @@ def bump( is_semver = "{semver}" in cfg.version_pattern has_semver_inc = major or minor or patch if is_semver and not has_semver_inc: - log.warning("bump --major/--minor/--patch required when using semver.") + logger.warning("bump --major/--minor/--patch required when using semver.") else: - log.error(f"Invalid version '{old_version}' and/or pattern '{cfg.version_pattern}'.") + logger.error(f"Invalid version '{old_version}' and/or pattern '{cfg.version_pattern}'.") sys.exit(1) - log.info(f"Old Version: {old_version}") - log.info(f"New Version: {new_version}") + 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) diff --git a/src/pycalver/config.py b/src/pycalver/config.py index d4e74fa..cfa8396 100644 --- a/src/pycalver/config.py +++ b/src/pycalver/config.py @@ -17,7 +17,7 @@ import pathlib2 as pl from . import version -log = logging.getLogger("pycalver.config") +logger = logging.getLogger("pycalver.config") Patterns = typ.List[str] PatternsByGlob = typ.Dict[str, Patterns] @@ -203,7 +203,7 @@ def _normalize_file_patterns(raw_cfg: RawConfig) -> FilePatterns: for filepath, patterns in list(file_patterns.items()): if not os.path.exists(filepath): - log.warning(f"Invalid config, no such file: {filepath}") + logger.warning(f"Invalid config, no such file: {filepath}") normalized_patterns: typ.List[str] = [] for pattern in patterns: @@ -215,8 +215,8 @@ def _normalize_file_patterns(raw_cfg: RawConfig) -> FilePatterns: elif version_pattern == "{semver}": normalized_pattern = normalized_pattern.replace("{pep440_version}", "{semver}") elif "{pep440_version}" in pattern: - log.warning(f"Invalid config, cannot match '{pattern}' for '{filepath}'.") - log.warning(f"No mapping of '{version_pattern}' to '{pep440_version}'") + logger.warning(f"Invalid config, cannot match '{pattern}' for '{filepath}'.") + logger.warning(f"No mapping of '{version_pattern}' to '{pep440_version}'") normalized_patterns.append(normalized_pattern) file_patterns[filepath] = normalized_patterns @@ -268,7 +268,7 @@ def _parse_config(raw_cfg: RawConfig) -> Config: push=push, file_patterns=file_patterns, ) - log.debug(_debug_str(cfg)) + logger.debug(_debug_str(cfg)) return cfg @@ -288,7 +288,7 @@ def _parse_current_version_default_pattern(cfg: Config, raw_cfg_text: str) -> st def parse(ctx: ProjectContext) -> MaybeConfig: """Parse config file if available.""" if not ctx.config_filepath.exists(): - log.warning(f"File not found: {ctx.config_filepath}") + logger.warning(f"File not found: {ctx.config_filepath}") return None fh: typ.IO[str] @@ -322,7 +322,7 @@ def parse(ctx: ProjectContext) -> MaybeConfig: return cfg except ValueError as ex: - log.warning(f"Couldn't parse {cfg_path}: {str(ex)}") + logger.warning(f"Couldn't parse {cfg_path}: {str(ex)}") return None diff --git a/src/pycalver/parse.py b/src/pycalver/parse.py index cb47b2a..9122440 100644 --- a/src/pycalver/parse.py +++ b/src/pycalver/parse.py @@ -6,12 +6,9 @@ """Parse PyCalVer strings from files.""" import typing as typ -import logging from . import patterns -log = logging.getLogger("pycalver.parse") - class PatternMatch(typ.NamedTuple): """Container to mark a version string in a file.""" diff --git a/src/pycalver/rewrite.py b/src/pycalver/rewrite.py index 437e4d6..a0d94c3 100644 --- a/src/pycalver/rewrite.py +++ b/src/pycalver/rewrite.py @@ -18,7 +18,7 @@ from . import config from . import version from . import patterns -log = logging.getLogger("pycalver.rewrite") +logger = logging.getLogger("pycalver.rewrite") def detect_line_sep(content: str) -> str: @@ -44,7 +44,7 @@ def detect_line_sep(content: str) -> str: class NoPatternMatch(Exception): """Pattern not found in content. - log.error is used to show error info about the patterns so + logger.error is used to show error info about the patterns so that users can debug what is wrong with them. The class itself doesn't capture that info. This approach is used so that all patter issues can be shown, rather than bubbling @@ -80,9 +80,9 @@ def rewrite_lines( non_matched_patterns = set(pattern_strs) - found_patterns if non_matched_patterns: for non_matched_pattern in non_matched_patterns: - log.error(f"No match for pattern '{non_matched_pattern}'") + logger.error(f"No match for pattern '{non_matched_pattern}'") compiled_pattern = patterns._compile_pattern(non_matched_pattern) - log.error(f"Pattern compiles to regex '{compiled_pattern}'") + logger.error(f"Pattern compiles to regex '{compiled_pattern}'") raise NoPatternMatch("Invalid pattern(s)") else: return new_lines diff --git a/src/pycalver/vcs.py b/src/pycalver/vcs.py index 1459fdc..b465954 100644 --- a/src/pycalver/vcs.py +++ b/src/pycalver/vcs.py @@ -20,7 +20,7 @@ import logging import tempfile import subprocess as sp -log = logging.getLogger("pycalver.vcs") +logger = logging.getLogger("pycalver.vcs") VCS_SUBCOMMANDS_BY_NAME = { @@ -52,8 +52,8 @@ VCS_SUBCOMMANDS_BY_NAME = { Env = typ.Dict[str, str] -class VCS: - """VCS absraction for git and mercurial.""" +class VCSAPI: + """Absraction for git and mercurial.""" def __init__(self, name: str, subcommands: typ.Dict[str, str] = None): self.name = name @@ -67,9 +67,9 @@ class VCS: cmd_tmpl = self.subcommands[cmd_name] cmd_str = cmd_tmpl.format(**kwargs) if cmd_name in ("commit", "tag", "push_tag"): - log.info(cmd_str) + logger.info(cmd_str) else: - log.debug(cmd_str) + logger.debug(cmd_str) output_data: bytes = sp.check_output(cmd_str.split(), env=env, stderr=sp.STDOUT) # TODO (mb 2018-11-15): Detect encoding of output? @@ -122,7 +122,7 @@ class VCS: def ls_tags(self) -> typ.List[str]: """List vcs tags on all branches.""" ls_tag_lines = self('ls_tags').splitlines() - log.debug(f"ls_tags output {ls_tag_lines}") + logger.debug(f"ls_tags output {ls_tag_lines}") return [line.strip().split(" ", 1)[0] for line in ls_tag_lines] def add(self, path: str) -> None: @@ -164,17 +164,17 @@ class VCS: def __repr__(self) -> str: """Generate string representation.""" - return f"VCS(name='{self.name}')" + return f"VCSAPI(name='{self.name}')" -def get_vcs() -> VCS: +def get_vcs_api() -> VCSAPI: """Detect the appropriate VCS for a repository. raises OSError if the directory doesn't use a supported VCS. """ for vcs_name in VCS_SUBCOMMANDS_BY_NAME.keys(): - vcs = VCS(name=vcs_name) - if vcs.is_usable: - return vcs + vcs_api = VCSAPI(name=vcs_name) + if vcs_api.is_usable: + return vcs_api raise OSError("No such directory .git/ or .hg/ ") diff --git a/src/pycalver/version.py b/src/pycalver/version.py index 3212132..46851aa 100644 --- a/src/pycalver/version.py +++ b/src/pycalver/version.py @@ -14,7 +14,7 @@ import pkg_resources from . import lex_id from . import patterns -log = logging.getLogger("pycalver.version") +logger = logging.getLogger("pycalver.version") # The test suite may replace this. @@ -467,7 +467,7 @@ def incr( try: old_vinfo = parse_version_info(old_version, pattern) except PatternError as ex: - log.error(str(ex)) + logger.error(str(ex)) return None cur_vinfo = old_vinfo @@ -480,7 +480,7 @@ def incr( if old_date <= cur_date: cur_vinfo = cur_vinfo._replace(**cur_cal_nfo._asdict()) else: - log.warning(f"Version appears to be from the future '{old_version}'") + logger.warning(f"Version appears to be from the future '{old_version}'") cur_vinfo = cur_vinfo._replace(bid=lex_id.next_id(cur_vinfo.bid)) @@ -496,7 +496,7 @@ def incr( new_version = format_version(cur_vinfo, pattern) if new_version == old_version: - log.error("Invalid arguments or pattern, version did not change.") + logger.error("Invalid arguments or pattern, version did not change.") return None else: return new_version