From 1129de0beb9d89a7c53b1d508bc16cad93c01882 Mon Sep 17 00:00:00 2001 From: Manuel Barkhau Date: Tue, 6 Nov 2018 21:45:33 +0100 Subject: [PATCH] formatting updates --- src/pycalver/__init__.py | 5 +-- src/pycalver/__main__.py | 38 +++++++++++++-------- src/pycalver/config.py | 2 +- src/pycalver/lex_id.py | 2 +- src/pycalver/parse.py | 74 ++++++++++++++++++++++------------------ src/pycalver/vcs.py | 19 ++++++----- src/pycalver/version.py | 18 +++++++--- test/test_config.py | 44 +++++++++++++----------- test/test_lex_id.py | 16 ++++----- test/test_rewrite.py | 12 +++---- test/test_version.py | 51 +++++++++++++-------------- 11 files changed, 153 insertions(+), 128 deletions(-) diff --git a/src/pycalver/__init__.py b/src/pycalver/__init__.py index 07521a5..d396ee2 100644 --- a/src/pycalver/__init__.py +++ b/src/pycalver/__init__.py @@ -3,9 +3,6 @@ # # Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT - -import os +"""PyCalVer: Automatic CalVer Versioning for Python Packages.""" __version__ = "v201809.0002-beta" - -DEBUG = os.environ.get("PYDEBUG", "0") == "1" diff --git a/src/pycalver/__main__.py b/src/pycalver/__main__.py index 2f6712d..a1e5c81 100644 --- a/src/pycalver/__main__.py +++ b/src/pycalver/__main__.py @@ -4,6 +4,11 @@ # # Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT +""" +CLI module for pycalver. + +Provided subcommands: show, init, incr, bump +""" import io import os @@ -24,13 +29,13 @@ log = logging.getLogger("pycalver.__main__") def _init_loggers(verbose: bool) -> None: if DEBUG: - log_formatter = logging.Formatter('%(levelname)s - %(name)s - %(message)s') + log_formatter = logging.Formatter("%(levelname)s - %(name)s - %(message)s") log_level = logging.DEBUG elif verbose: - log_formatter = logging.Formatter('%(levelname)s - %(message)s') + log_formatter = logging.Formatter("%(levelname)s - %(message)s") log_level = logging.INFO else: - log_formatter = logging.Formatter('%(message)s') + log_formatter = logging.Formatter("%(message)s") log_level = logging.WARNING loggers = [log, vcs.log, parse.log, config.log, rewrite.log, version.log] @@ -47,11 +52,12 @@ def _init_loggers(verbose: bool) -> None: @click.group() def cli(): - """parse and update project versions automatically.""" + """Parse and update project versions.""" @cli.command() def show() -> None: + """Show current version.""" _init_loggers(verbose=False) cfg: config.MaybeConfig = config.parse() @@ -69,6 +75,7 @@ def show() -> None: "--release", default=None, metavar="", help="Override release name of current_version" ) def incr(old_version: str, release: str = None) -> None: + """Increment a version number for demo purposes.""" _init_loggers(verbose=False) if release and release not in parse.VALID_RELESE_VALUES: @@ -76,7 +83,7 @@ def incr(old_version: str, release: str = None) -> None: log.error(f"Valid arguments are: {', '.join(parse.VALID_RELESE_VALUES)}") sys.exit(1) - new_version = version.bump(old_version, release=release) + new_version = version.incr(old_version, release=release) new_version_nfo = parse.parse_version_info(new_version) print("PyCalVer Version:", new_version) @@ -88,7 +95,7 @@ def incr(old_version: str, release: str = None) -> None: "--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files." ) def init(dry: bool) -> None: - """Initialize [pycalver] configuration in setup.cfg""" + """Initialize [pycalver] configuration.""" _init_loggers(verbose=False) cfg : config.MaybeConfig = config.parse() @@ -138,6 +145,7 @@ def init(dry: bool) -> None: def bump( release: str, verbose: bool, dry: bool, commit: bool, tag: bool, allow_dirty: bool ) -> None: + """Increment the current version string and update project files.""" _init_loggers(verbose) if release and release not in parse.VALID_RELESE_VALUES: @@ -152,7 +160,7 @@ def bump( sys.exit(1) old_version = cfg.current_version - new_version = version.bump(old_version, release=release) + new_version = version.incr(old_version, release=release) log.info(f"Old Version: {old_version}") log.info(f"New Version: {new_version}") @@ -163,15 +171,17 @@ def bump( file_patterns = cfg.file_patterns filepaths = set(file_patterns.keys()) - _vcs = vcs.get_vcs() - if _vcs is None: - log.warn("Version Control System not found, aborting commit.") - else: - _vcs.assert_not_dirty(filepaths, allow_dirty) - rewrite.rewrite(new_version, file_patterns, dry, verbose) - if dry or not commit or _vcs is None: + try: + _vcs = vcs.get_vcs() + except OSError: + log.warn("Version Control System not found, aborting commit.") + return + + _vcs.assert_not_dirty(filepaths, allow_dirty) + + if dry or not commit: return # TODO (mb 2018-09-04): add files and commit diff --git a/src/pycalver/config.py b/src/pycalver/config.py index 51b3044..d6ea838 100644 --- a/src/pycalver/config.py +++ b/src/pycalver/config.py @@ -1,7 +1,7 @@ # This file is part of the pycalver project # https://github.com/mbarkhau/pycalver # -# (C) 2018 Manuel Barkhau (@mbarkhau) +# Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT import io diff --git a/src/pycalver/lex_id.py b/src/pycalver/lex_id.py index ea1fc4d..cf44704 100644 --- a/src/pycalver/lex_id.py +++ b/src/pycalver/lex_id.py @@ -1,7 +1,7 @@ # This file is part of the pycalver project # https://github.com/mbarkhau/pycalver # -# (C) 2018 Manuel Barkhau (@mbarkhau) +# Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT """ diff --git a/src/pycalver/parse.py b/src/pycalver/parse.py index 2441c1c..6daa1a7 100644 --- a/src/pycalver/parse.py +++ b/src/pycalver/parse.py @@ -1,7 +1,7 @@ # This file is part of the pycalver project # https://github.com/mbarkhau/pycalver # -# (C) 2018 Manuel Barkhau (@mbarkhau) +# Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT import re @@ -17,7 +17,7 @@ VALID_RELESE_VALUES = ("alpha", "beta", "dev", "rc", "post") # https://regex101.com/r/fnj60p/10 -PYCALVER_RE: typ.Pattern[str] = re.compile(r""" +PYCALVER_PATTERN = r""" \b (?P (?P @@ -34,8 +34,19 @@ PYCALVER_RE: typ.Pattern[str] = re.compile(r""" (?:alpha|beta|dev|rc|post) )? )(?:\s|$) -""", flags=re.VERBOSE) +""" +PYCALVER_RE: typ.Pattern[str] = re.compile(PYCALVER_PATTERN, flags=re.VERBOSE) + +PATTERN_ESCAPES = [ + ("\u005c", "\u005c\u005c"), + ("-" , "\u005c-"), + ("." , "\u005c."), + ("+" , "\u005c+"), + ("*" , "\u005c*"), + ("[" , "\u005c["), + ("(" , "\u005c("), +] # NOTE (mb 2018-09-03): These are matchers for parts, which are # used in the patterns, they're not for validation. This means @@ -45,32 +56,32 @@ PYCALVER_RE: typ.Pattern[str] = re.compile(r""" RE_PATTERN_PARTS = { - "pep440_version" : r"\d{6}\.[1-9]\d*(a|b|dev|rc|post)?\d*", - "version" : r"v\d{6}\.\d{4,}(\-(alpha|beta|dev|rc|post))?", - "calver" : r"v\d{6}", - "build" : r"\.\d{4,}", - "release" : r"(\-(alpha|beta|dev|rc|post))?", + 'pep440_version': r"\d{6}\.[1-9]\d*(a|b|dev|rc|post)?\d*", + 'version' : r"v\d{6}\.\d{4,}(\-(alpha|beta|dev|rc|post))?", + 'calver' : r"v\d{6}", + 'build' : r"\.\d{4,}", + 'release' : r"(\-(alpha|beta|dev|rc|post))?", } class PatternMatch(typ.NamedTuple): - lineno : int # zero based - line : str - pattern : str - span : typ.Tuple[int, int] - match : str + lineno : int # zero based + line : str + pattern: str + span : typ.Tuple[int, int] + match : str class VersionInfo(typ.NamedTuple): - pep440_version : str - version : str - calver : str - year : str - month : str - build : str - release : typ.Optional[str] + pep440_version: str + version : str + calver : str + year : str + month : str + build : str + release : typ.Optional[str] def parse_version_info(version: str) -> VersionInfo: @@ -81,20 +92,17 @@ def parse_version_info(version: str) -> VersionInfo: return VersionInfo(pep440_version=pep440_version, **match.groupdict()) -def iter_pattern_matches(lines: typ.List[str], pattern: str) -> typ.Iterable[PatternMatch]: +def _iter_pattern_matches(lines: typ.List[str], pattern: str) -> typ.Iterable[PatternMatch]: # The pattern is escaped, so that everything besides the format # string variables is treated literally. - pattern_re = re.compile( - pattern - .replace("\\", "\\\\") - .replace("-", "\\-") - .replace(".", "\\.") - .replace("+", "\\+") - .replace("*", "\\*") - .replace("[", "\\[") - .replace("(", "\\(") - .format(**RE_PATTERN_PARTS) - ) + + pattern_tmpl = pattern + + for char, escaped in PATTERN_ESCAPES: + pattern_tmpl = pattern_tmpl.replace(char, escaped) + + pattern_str = pattern_tmpl.format(**RE_PATTERN_PARTS) + pattern_re = re.compile(pattern_str) for lineno, line in enumerate(lines): match = pattern_re.search(line) if match: @@ -104,5 +112,5 @@ def iter_pattern_matches(lines: typ.List[str], pattern: str) -> typ.Iterable[Pat def parse_patterns(lines: typ.List[str], patterns: typ.List[str]) -> typ.List[PatternMatch]: all_matches: typ.List[PatternMatch] = [] for pattern in patterns: - all_matches.extend(iter_pattern_matches(lines, pattern)) + all_matches.extend(_iter_pattern_matches(lines, pattern)) return all_matches diff --git a/src/pycalver/vcs.py b/src/pycalver/vcs.py index 79633b7..23e208a 100644 --- a/src/pycalver/vcs.py +++ b/src/pycalver/vcs.py @@ -1,12 +1,12 @@ # This file is part of the pycalver project # https://github.com/mbarkhau/pycalver # -# (C) 2018 Manuel Barkhau (@mbarkhau) +# Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT # # pycalver/vcs.py (this file) is based on code from the # bumpversion project: https://github.com/peritus/bumpversion -# MIT License - (C) 2013-2014 Filip Noetzel +# Copyright (c) 2013-2014 Filip Noetzel - MIT License import os import sys @@ -83,9 +83,9 @@ class BaseVCS: class Git(BaseVCS): - _TEST_USABLE_COMMAND = ["git", "rev-parse", "--git-dir"] - _COMMIT_COMMAND = ["git", "commit" , "-F"] - _STATUS_COMMAND = ["git", "status" , "--porcelain"] + _TEST_USABLE_COMMAND = ["git", "rev-parse", '--git-dir'] + _COMMIT_COMMAND = ["git", "commit" , '-F'] + _STATUS_COMMAND = ["git", "status" , '--porcelain'] @classmethod def tag(cls, name): @@ -99,8 +99,8 @@ class Git(BaseVCS): class Mercurial(BaseVCS): _TEST_USABLE_COMMAND = ["hg", 'root'] - _COMMIT_COMMAND = ["hg", "commit", "--logfile"] - _STATUS_COMMAND = ["hg", "status", "-mard"] + _COMMIT_COMMAND = ["hg", "commit", '--logfile'] + _STATUS_COMMAND = ["hg", "status", '-mard'] @classmethod def tag(cls, name): @@ -114,9 +114,10 @@ class Mercurial(BaseVCS): VCS = [Git, Mercurial] -def get_vcs() -> typ.Optional[typ.Type[BaseVCS]]: +def get_vcs() -> typ.Type[BaseVCS]: + """Get appropriate sub""" for vcs in VCS: if vcs.is_usable(): return vcs - return None + raise OSError("No such directory .hg/ or .git/ ") diff --git a/src/pycalver/version.py b/src/pycalver/version.py index 7a680dc..566e420 100644 --- a/src/pycalver/version.py +++ b/src/pycalver/version.py @@ -1,8 +1,9 @@ # This file is part of the pycalver project # https://github.com/mbarkhau/pycalver # -# (C) 2018 Manuel Barkhau (@mbarkhau) +# Copyright (c) 2018 Manuel Barkhau (@mbarkhau) - MIT License # SPDX-License-Identifier: MIT +"""Functions related to version string manipulation.""" import logging import typing as typ @@ -15,19 +16,26 @@ log = logging.getLogger("pycalver.version") def current_calver() -> str: + """Generate calver version string based on current date. + + example result: "v201812" + """ return dt.date.today().strftime("v%Y%m") -def bump(old_version: str, *, release: str = None) -> str: - # old_version is assumed to be a valid calver string, - # validated in pycalver.config.parse. +def incr(old_version: str, *, release: str = None) -> str: + """Increment a full PyCalVer version string. + + Old_version is assumed to be a valid calver string, + already validated in pycalver.config.parse. + """ old_ver = parse.parse_version_info(old_version) new_calver = current_calver() if old_ver.calver > new_calver: log.warning( - f"'version.bump' called with '{old_version}', " + f"'version.incr' called with '{old_version}', " + f"which is from the future, " + f"maybe your system clock is out of sync." ) diff --git a/test/test_config.py b/test/test_config.py index 3c77f26..68f000e 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -23,16 +23,20 @@ def test_parse_default_config(): def test_parse(tmpdir): setup_path = tmpdir.mkdir("minimal").join("setup.cfg") - setup_path.write("\n".join(( - "[pycalver]", - "current_version = v201808.0001-dev", - "commit = False", - "tag = False", - "", - "[pycalver:file:setup.cfg]", - "patterns = ", - " current_version = {version}", - ))) + setup_path.write( + "\n".join( + ( + "[pycalver]", + "current_version = v201808.0001-dev", + "commit = False", + "tag = False", + "", + "[pycalver:file:setup.cfg]", + "patterns = ", + " current_version = {version}", + ) + ) + ) cfg = config.parse(str(setup_path)) @@ -64,11 +68,15 @@ def test_parse_empty_config(tmpdir): def test_parse_missing_version(tmpdir): setup_path = tmpdir.mkdir("fail").join("setup.cfg") - setup_path.write("\n".join(( - "[pycalver]", - # f"current_version = v201808.0001-dev", - "commit = False", - ))) + setup_path.write( + "\n".join( + ( + "[pycalver]", + # f"current_version = v201808.0001-dev", + "commit = False", + ) + ) + ) cfg = config.parse(str(setup_path)) assert cfg is None @@ -76,11 +84,7 @@ def test_parse_missing_version(tmpdir): def test_parse_invalid_version(tmpdir): setup_path = tmpdir.mkdir("fail").join("setup.cfg") - setup_path.write("\n".join(( - "[pycalver]", - "current_version = 0.1.0", - "commit = False", - ))) + setup_path.write("\n".join(("[pycalver]", "current_version = 0.1.0", "commit = False"))) cfg = config.parse(str(setup_path)) assert cfg is None diff --git a/test/test_lex_id.py b/test/test_lex_id.py index d454fb8..be01804 100644 --- a/test/test_lex_id.py +++ b/test/test_lex_id.py @@ -18,7 +18,7 @@ def test_next_id_overflow(): def test_next_id_random(): for i in range(1000): - prev_id = str(random.randint(1, 100000)) + prev_id = str(random.randint(1, 100_000)) try: next_id = lex_id.next_id(prev_id) assert prev_id < next_id @@ -27,10 +27,10 @@ def test_next_id_random(): def test_ord_val(): - assert lex_id.ord_val("1") == 1 - assert lex_id.ord_val("01") == 1 - assert lex_id.ord_val("02") == 2 - assert lex_id.ord_val("09") == 9 + assert lex_id.ord_val("1" ) == 1 + assert lex_id.ord_val("01" ) == 1 + assert lex_id.ord_val("02" ) == 2 + assert lex_id.ord_val("09" ) == 9 assert lex_id.ord_val("110") == 10 @@ -39,13 +39,13 @@ def test_main(capsys): captured = capsys.readouterr() assert len(captured.err) == 0 - lines = iter(captured.out.splitlines()) + lines = iter(captured.out.splitlines()) header = next(lines) assert "lexical" in header assert "numerical" in header - ids = [] + ids = [] ord_vals = [] for line in lines: @@ -60,5 +60,5 @@ def test_main(capsys): ord_vals.append(int(_ord_val.strip())) assert len(ids) > 0 - assert sorted(ids) == ids + assert sorted(ids ) == ids assert sorted(ord_vals) == ord_vals diff --git a/test/test_rewrite.py b/test/test_rewrite.py index 1bae9ac..6fc14fc 100644 --- a/test/test_rewrite.py +++ b/test/test_rewrite.py @@ -3,13 +3,13 @@ from pycalver import rewrite def test_rewrite_lines(): old_lines = [ - '# This file is part of the pycalver project', - '# https://github.com/mbarkhau/pycalver', - '#', - '# (C) 2018 Manuel Barkhau (@mbarkhau)', - '# SPDX-License-Identifier: MIT', + "# This file is part of the pycalver project", + "# https://github.com/mbarkhau/pycalver", + "#", + "# (C) 2018 Manuel Barkhau (@mbarkhau)", + "# SPDX-License-Identifier: MIT", '', - 'import os', + "import os", '', '__version__ = "v201809.0002-beta"', 'DEBUG = os.environ.get("PYDEBUG", "0") == "1"', diff --git a/test/test_version.py b/test/test_version.py index e2408c8..fda6f1a 100644 --- a/test/test_version.py +++ b/test/test_version.py @@ -12,46 +12,43 @@ def test_current_calver(): def test_bump_beta(): - calver = version.current_calver() + calver = version.current_calver() cur_version = calver + ".0001-beta" - assert cur_version < version.bump(cur_version) - assert version.bump(cur_version).endswith("-beta") - assert version.bump(cur_version, release="alpha").endswith("-alpha") - assert version.bump(cur_version, release="final").endswith("0002") + assert cur_version < version.incr(cur_version) + assert version.incr(cur_version).endswith("-beta") + assert version.incr(cur_version, release="alpha").endswith("-alpha") + assert version.incr(cur_version, release="final").endswith("0002") def test_bump_final(): - calver = version.current_calver() + calver = version.current_calver() cur_version = calver + ".0001" - assert cur_version < version.bump(cur_version) - assert version.bump(cur_version, release="alpha").endswith("-alpha") - assert version.bump(cur_version, release="final").endswith("0002") - assert version.bump(cur_version).endswith("0002") + assert cur_version < version.incr(cur_version) + assert version.incr(cur_version, release="alpha").endswith("-alpha") + assert version.incr(cur_version, release="final").endswith("0002") + assert version.incr(cur_version).endswith("0002") def test_bump_future(): - future_date = dt.datetime.today() + dt.timedelta(days=300) + future_date = dt.datetime.today() + dt.timedelta(days=300) future_calver = future_date.strftime("v%Y%m") - cur_version = future_calver + ".0001" - assert cur_version < version.bump(cur_version) + cur_version = future_calver + ".0001" + assert cur_version < version.incr(cur_version) -def test_bump_random(): - cur_date = dt.date.today() +def test_bump_random(monkeypatch): + cur_date = dt.date.today() cur_version = cur_date.strftime("v%Y%m") + ".0001-dev" def _mock_current_calver(): return cur_date.strftime("v%Y%m") - _orig_current_calver = version.current_calver - version.current_calver = _mock_current_calver - try: - for i in range(1000): - cur_date += dt.timedelta(days=int((1 + random.random()) ** 10)) - new_version = version.bump(cur_version, release=random.choice([ - None, "alpha", "beta", "rc", "final" - ])) - assert cur_version < new_version - cur_version = new_version - finally: - version.current_calver = _orig_current_calver + monkeypatch.setattr(version, 'current_calver', _mock_current_calver) + + for i in range(1000): + cur_date += dt.timedelta(days=int((1 + random.random()) ** 10)) + new_version = version.incr( + cur_version, release=random.choice([None, "alpha", "beta", "rc", 'final']) + ) + assert cur_version < new_version + cur_version = new_version