mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 14:30:09 +01:00
much bugfixing
This commit is contained in:
parent
56c9f9b36c
commit
49e19fbf89
18 changed files with 687 additions and 451 deletions
104
pylint-ignore.md
104
pylint-ignore.md
|
|
@ -23,7 +23,7 @@ The recommended approach to using `pylint-ignore` is:
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
- [W0511: fixme (9x)](#w0511-fixme)
|
- [W0511: fixme (8x)](#w0511-fixme)
|
||||||
- [W0703: broad-except (1x)](#w0703-broad-except)
|
- [W0703: broad-except (1x)](#w0703-broad-except)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -44,37 +44,20 @@ The recommended approach to using `pylint-ignore` is:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## File src/pycalver/vcs.py - Line 78 - W0511 (fixme)
|
## File src/pycalver/vcs.py - Line 80 - W0511 (fixme)
|
||||||
|
|
||||||
- `message: TODO (mb 2018-11-15): Detect encoding of output? Use chardet?`
|
- `message: TODO (mb 2018-11-15): Detect encoding of output? Use chardet?`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-18T17:24:49`
|
- `date : 2020-09-18T17:24:49`
|
||||||
|
|
||||||
```
|
```
|
||||||
68: def __call__(self, cmd_name: str, env: Env = None, **kwargs: str) -> str:
|
69: def __call__(self, cmd_name: str, env: Env = None, **kwargs: str) -> str:
|
||||||
...
|
...
|
||||||
76: output_data: bytes = sp.check_output(cmd_str.split(), env=env, stderr=sp.STDOUT)
|
78: output_data: bytes = sp.check_output(cmd_parts, env=env, stderr=sp.STDOUT)
|
||||||
77:
|
79:
|
||||||
> 78: # TODO (mb 2018-11-15): Detect encoding of output? Use chardet?
|
> 80: # TODO (mb 2018-11-15): Detect encoding of output? Use chardet?
|
||||||
79: _encoding = "utf-8"
|
81: _encoding = "utf-8"
|
||||||
80: return output_data.decode(_encoding)
|
82: return output_data.decode(_encoding)
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## File test/test_config.py - Line 156 - W0511 (fixme)
|
|
||||||
|
|
||||||
- `message: TODO (mb 2020-09-18):`
|
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
|
||||||
- `date : 2020-09-18T19:04:06`
|
|
||||||
|
|
||||||
```
|
|
||||||
143: def test_parse_v2_cfg():
|
|
||||||
...
|
|
||||||
154: assert "setup.py" in cfg.file_patterns
|
|
||||||
155: assert "setup.cfg" in cfg.file_patterns
|
|
||||||
> 156: # TODO (mb 2020-09-18):
|
|
||||||
157: # assert cfg.file_patterns["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"]
|
|
||||||
158: # assert cfg.file_patterns["setup.cfg" ] == ['current_version = "vYYYY0M.BUILD[-RELEASE]"']
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -95,37 +78,37 @@ The recommended approach to using `pylint-ignore` is:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## File src/pycalver/v1patterns.py - Line 214 - W0511 (fixme)
|
## File test/test_config.py - Line 170 - W0511 (fixme)
|
||||||
|
|
||||||
- `message: TODO (mb 2020-09-19): replace {version} etc with version_pattern`
|
- `message: TODO (mb 2020-09-18):`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-19T16:24:10`
|
- `date : 2020-09-18T19:04:06`
|
||||||
|
|
||||||
```
|
```
|
||||||
201: def _compile_pattern_re(version_pattern: str, raw_pattern: str) -> typ.Pattern[str]:
|
156: def test_parse_v2_cfg():
|
||||||
...
|
...
|
||||||
212: escaped_pattern = escaped_pattern.replace(char, escaped)
|
168: assert "setup.cfg" in cfg.file_patterns
|
||||||
213:
|
169:
|
||||||
> 214: # TODO (mb 2020-09-19): replace {version} etc with version_pattern
|
> 170: # TODO (mb 2020-09-18):
|
||||||
215: pattern_str = _replace_pattern_parts(escaped_pattern)
|
171: # raw_patterns_by_file = _parse_raw_patterns_by_file(cfg)
|
||||||
216: return re.compile(pattern_str)
|
172: # assert raw_patterns_by_file["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## File src/pycalver/__main__.py - Line 250 - W0511 (fixme)
|
## File src/pycalver/__main__.py - Line 259 - W0511 (fixme)
|
||||||
|
|
||||||
- `message: TODO (mb 2020-09-18): Investigate error messages`
|
- `message: TODO (mb 2020-09-18): Investigate error messages`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-19T16:24:10`
|
- `date : 2020-09-19T16:24:10`
|
||||||
|
|
||||||
```
|
```
|
||||||
222: def _bump(
|
231: def _bump(
|
||||||
...
|
...
|
||||||
248: sys.exit(1)
|
257: sys.exit(1)
|
||||||
249: except Exception as ex:
|
258: except Exception as ex:
|
||||||
> 250: # TODO (mb 2020-09-18): Investigate error messages
|
> 259: # TODO (mb 2020-09-18): Investigate error messages
|
||||||
251: logger.error(str(ex))
|
260: logger.error(str(ex))
|
||||||
252: sys.exit(1)
|
261: sys.exit(1)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -146,53 +129,52 @@ The recommended approach to using `pylint-ignore` is:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## File test/test_cli.py - Line 536 - W0511 (fixme)
|
## File test/test_cli.py - Line 599 - W0511 (fixme)
|
||||||
|
|
||||||
- `message: # TODO (mb 2020-09-18):`
|
- `message: # TODO (mb 2020-09-18):`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-18T19:35:32`
|
- `date : 2020-09-18T19:35:32`
|
||||||
|
|
||||||
```
|
```
|
||||||
534:
|
597:
|
||||||
535: # def test_custom_commit_message(runner):
|
598: # def test_custom_commit_message(runner):
|
||||||
> 536: # # TODO (mb 2020-09-18):
|
> 599: # # TODO (mb 2020-09-18):
|
||||||
537: # assert False
|
600: # assert False
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## File src/pycalver/v2version.py - Line 551 - W0511 (fixme)
|
## File src/pycalver/v2version.py - Line 616 - W0511 (fixme)
|
||||||
|
|
||||||
- `message: TODO (mb 2020-09-20): New Rollover Behaviour:`
|
- `message: TODO (mb 2020-09-20): New Rollover Behaviour:`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-20T17:36:38`
|
- `date : 2020-09-20T17:36:38`
|
||||||
|
|
||||||
```
|
```
|
||||||
508: def incr(
|
578: def incr(
|
||||||
...
|
...
|
||||||
549: cur_vinfo = cur_vinfo._replace(patch=cur_vinfo.patch + 1)
|
614: )
|
||||||
550:
|
615:
|
||||||
> 551: # TODO (mb 2020-09-20): New Rollover Behaviour:
|
> 616: # TODO (mb 2020-09-20): New Rollover Behaviour:
|
||||||
552: # Reset major, minor, patch to zero if any part to the left of it is incremented
|
617: # Reset major, minor, patch to zero if any part to the left of it is incremented
|
||||||
553:
|
618:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# W0703: broad-except
|
# W0703: broad-except
|
||||||
|
|
||||||
## File src/pycalver/__main__.py - Line 249 - W0703 (broad-except)
|
## File src/pycalver/__main__.py - Line 258 - W0703 (broad-except)
|
||||||
|
|
||||||
- `message: Catching too general exception Exception`
|
- `message: Catching too general exception Exception`
|
||||||
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
- `author : Manuel Barkhau <mbarkhau@gmail.com>`
|
||||||
- `date : 2020-09-05T14:30:17`
|
- `date : 2020-09-05T14:30:17`
|
||||||
|
|
||||||
```
|
```
|
||||||
222: def _bump(
|
231: def _bump(
|
||||||
...
|
...
|
||||||
247: logger.error(str(ex))
|
256: logger.error(str(ex))
|
||||||
248: sys.exit(1)
|
257: sys.exit(1)
|
||||||
> 249: except Exception as ex:
|
> 258: except Exception as ex:
|
||||||
250: # TODO (mb 2020-09-18): Investigate error messages
|
259: # TODO (mb 2020-09-18): Investigate error messages
|
||||||
251: logger.error(str(ex))
|
260: logger.error(str(ex))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ output-format = colorized
|
||||||
max-locals = 21
|
max-locals = 21
|
||||||
|
|
||||||
# Maximum number of arguments for function / method
|
# Maximum number of arguments for function / method
|
||||||
max-args = 9
|
max-args = 12
|
||||||
|
|
||||||
good-names = logger,i,ex
|
good-names = logger,i,ex
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ from . import v2cli
|
||||||
from . import config
|
from . import config
|
||||||
from . import rewrite
|
from . import rewrite
|
||||||
from . import version
|
from . import version
|
||||||
|
from . import v1rewrite
|
||||||
from . import v1version
|
from . import v1version
|
||||||
|
from . import v2rewrite
|
||||||
from . import v2version
|
from . import v2version
|
||||||
from . import v1patterns
|
from . import v1patterns
|
||||||
|
|
||||||
|
|
@ -93,10 +95,10 @@ def cli(verbose: int = 0) -> None:
|
||||||
f"{', '.join(VALID_RELEASE_VALUES)}."
|
f"{', '.join(VALID_RELEASE_VALUES)}."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
@click.option("--major" , is_flag=True, default=False, help="Increment major component.")
|
||||||
@click.option("-m", "--minor", is_flag=True, default=False, help="Increment minor component.")
|
@click.option("-m" , "--minor" , is_flag=True, default=False, help="Increment minor component.")
|
||||||
@click.option("-p", "--patch", is_flag=True, default=False, help="Increment patch component.")
|
@click.option("-p" , "--patch" , is_flag=True, default=False, help="Increment patch component.")
|
||||||
@click.option("-r", "--release-num", is_flag=True, default=False, help="Increment release number.")
|
@click.option("-r" , "--release-num", is_flag=True, default=False, help="Increment release number.")
|
||||||
@click.option("--pin-date", is_flag=True, default=False, help="Leave date components unchanged.")
|
@click.option("--pin-date", is_flag=True, default=False, help="Leave date components unchanged.")
|
||||||
def test(
|
def test(
|
||||||
old_version: str,
|
old_version: str,
|
||||||
|
|
@ -145,8 +147,7 @@ def show(verbose: int = 0, fetch: bool = True) -> None:
|
||||||
"""Show current version of your project."""
|
"""Show current version of your project."""
|
||||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||||
|
|
||||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
_, cfg = config.init(project_path=".")
|
||||||
cfg: config.MaybeConfig = config.parse(ctx)
|
|
||||||
|
|
||||||
if cfg is None:
|
if cfg is None:
|
||||||
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||||
|
|
@ -188,7 +189,7 @@ def _print_diff(cfg: config.Config, new_version: str) -> None:
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
# pylint:disable=broad-except; Mostly we expect IOError here, but
|
# pylint:disable=broad-except; Mostly we expect IOError here, but
|
||||||
# could be other things and there's no option to recover anyway.
|
# could be other things and there's no option to recover anyway.
|
||||||
logger.error(str(ex))
|
logger.error(str(ex), exc_info=True)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -201,7 +202,7 @@ def _incr(
|
||||||
minor : bool = False,
|
minor : bool = False,
|
||||||
patch : bool = False,
|
patch : bool = False,
|
||||||
release_num: bool = False,
|
release_num: bool = False,
|
||||||
pin_date: bool = False,
|
pin_date : bool = False,
|
||||||
) -> typ.Optional[str]:
|
) -> typ.Optional[str]:
|
||||||
v1_parts = list(v1patterns.PART_PATTERNS) + list(v1patterns.FULL_PART_FORMATS)
|
v1_parts = list(v1patterns.PART_PATTERNS) + list(v1patterns.FULL_PART_FORMATS)
|
||||||
has_v1_part = any("{" + part + "}" in raw_pattern for part in v1_parts)
|
has_v1_part = any("{" + part + "}" in raw_pattern for part in v1_parts)
|
||||||
|
|
@ -250,9 +251,11 @@ def _bump(
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if cfg.is_new_pattern:
|
if cfg.is_new_pattern:
|
||||||
v2cli.rewrite_files(cfg, new_version)
|
new_v2_vinfo = v2version.parse_version_info(new_version, cfg.version_pattern)
|
||||||
|
v2rewrite.rewrite_files(cfg.file_patterns, new_v2_vinfo)
|
||||||
else:
|
else:
|
||||||
v1cli.rewrite_files(cfg, new_version)
|
new_v1_vinfo = v1version.parse_version_info(new_version, cfg.version_pattern)
|
||||||
|
v1rewrite.rewrite_files(cfg.file_patterns, new_v1_vinfo)
|
||||||
except rewrite.NoPatternMatch as ex:
|
except rewrite.NoPatternMatch as ex:
|
||||||
logger.error(str(ex))
|
logger.error(str(ex))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
@ -291,8 +294,7 @@ def init(verbose: int = 0, dry: bool = False) -> None:
|
||||||
"""Initialize [pycalver] configuration."""
|
"""Initialize [pycalver] configuration."""
|
||||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||||
|
|
||||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
ctx, cfg = config.init(project_path=".")
|
||||||
cfg: config.MaybeConfig = config.parse(ctx)
|
|
||||||
|
|
||||||
if cfg:
|
if cfg:
|
||||||
logger.error(f"Configuration already initialized in {ctx.config_rel_path}")
|
logger.error(f"Configuration already initialized in {ctx.config_rel_path}")
|
||||||
|
|
@ -355,10 +357,10 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
|
||||||
"to files with version strings."
|
"to files with version strings."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
@click.option("--major" , is_flag=True, default=False, help="Increment major component.")
|
||||||
@click.option("-m", "--minor", is_flag=True, default=False, help="Increment minor component.")
|
@click.option("-m" , "--minor" , is_flag=True, default=False, help="Increment minor component.")
|
||||||
@click.option("-p", "--patch", is_flag=True, default=False, help="Increment patch component.")
|
@click.option("-p" , "--patch" , is_flag=True, default=False, help="Increment patch component.")
|
||||||
@click.option("-r", "--release-num", is_flag=True, default=False, help="Increment release number.")
|
@click.option("-r" , "--release-num", is_flag=True, default=False, help="Increment release number.")
|
||||||
@click.option("--pin-date", is_flag=True, default=False, help="Leave date components unchanged.")
|
@click.option("--pin-date", is_flag=True, default=False, help="Leave date components unchanged.")
|
||||||
def bump(
|
def bump(
|
||||||
release : typ.Optional[str] = None,
|
release : typ.Optional[str] = None,
|
||||||
|
|
@ -379,8 +381,7 @@ def bump(
|
||||||
if release:
|
if release:
|
||||||
_validate_release_tag(release)
|
_validate_release_tag(release)
|
||||||
|
|
||||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
_, cfg = config.init(project_path=".")
|
||||||
cfg: config.MaybeConfig = config.parse(ctx)
|
|
||||||
|
|
||||||
if cfg is None:
|
if cfg is None:
|
||||||
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
logger.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,8 @@ def _parse_cfg(cfg_buffer: typ.IO[str]) -> RawConfig:
|
||||||
|
|
||||||
raw_cfg['file_patterns'] = dict(_parse_cfg_file_patterns(cfg_parser))
|
raw_cfg['file_patterns'] = dict(_parse_cfg_file_patterns(cfg_parser))
|
||||||
|
|
||||||
|
_set_raw_config_defaults(raw_cfg)
|
||||||
|
|
||||||
return raw_cfg
|
return raw_cfg
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -198,6 +200,8 @@ def _parse_toml(cfg_buffer: typ.IO[str]) -> RawConfig:
|
||||||
for option, default_val in BOOL_OPTIONS.items():
|
for option, default_val in BOOL_OPTIONS.items():
|
||||||
raw_cfg[option] = raw_cfg.get(option, default_val)
|
raw_cfg[option] = raw_cfg.get(option, default_val)
|
||||||
|
|
||||||
|
_set_raw_config_defaults(raw_cfg)
|
||||||
|
|
||||||
return raw_cfg
|
return raw_cfg
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -227,9 +231,7 @@ def _compile_v1_file_patterns(raw_cfg: RawConfig) -> typ.Iterable[FilePatternsIt
|
||||||
raw_patterns_by_file: RawPatternsByFile = raw_cfg['file_patterns']
|
raw_patterns_by_file: RawPatternsByFile = raw_cfg['file_patterns']
|
||||||
|
|
||||||
for filepath, raw_patterns in _iter_glob_expanded_file_patterns(raw_patterns_by_file):
|
for filepath, raw_patterns in _iter_glob_expanded_file_patterns(raw_patterns_by_file):
|
||||||
compiled_patterns = [
|
compiled_patterns = v1patterns.compile_patterns(version_pattern, raw_patterns)
|
||||||
v1patterns.compile_pattern(version_pattern, raw_pattern) for raw_pattern in raw_patterns
|
|
||||||
]
|
|
||||||
yield filepath, compiled_patterns
|
yield filepath, compiled_patterns
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -242,9 +244,7 @@ def _compile_v2_file_patterns(raw_cfg: RawConfig) -> typ.Iterable[FilePatternsIt
|
||||||
raw_patterns_by_file: RawPatternsByFile = raw_cfg['file_patterns']
|
raw_patterns_by_file: RawPatternsByFile = raw_cfg['file_patterns']
|
||||||
|
|
||||||
for filepath, raw_patterns in _iter_glob_expanded_file_patterns(raw_patterns_by_file):
|
for filepath, raw_patterns in _iter_glob_expanded_file_patterns(raw_patterns_by_file):
|
||||||
compiled_patterns = [
|
compiled_patterns = v2patterns.compile_patterns(version_pattern, raw_patterns)
|
||||||
v2patterns.compile_pattern(version_pattern, raw_pattern) for raw_pattern in raw_patterns
|
|
||||||
]
|
|
||||||
yield filepath, compiled_patterns
|
yield filepath, compiled_patterns
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -319,12 +319,7 @@ def _parse_config(raw_cfg: RawConfig) -> Config:
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
def _parse_current_version_default_pattern(ctx: ProjectContext, raw_cfg: RawConfig) -> str:
|
def _parse_current_version_default_pattern(raw_cfg: RawConfig, raw_cfg_text: str) -> str:
|
||||||
fobj: typ.IO[str]
|
|
||||||
|
|
||||||
with ctx.config_filepath.open(mode="rt", encoding="utf-8") as fobj:
|
|
||||||
raw_cfg_text = fobj.read()
|
|
||||||
|
|
||||||
is_pycalver_section = False
|
is_pycalver_section = False
|
||||||
for line in raw_cfg_text.splitlines():
|
for line in raw_cfg_text.splitlines():
|
||||||
if is_pycalver_section and line.startswith("current_version"):
|
if is_pycalver_section and line.startswith("current_version"):
|
||||||
|
|
@ -340,19 +335,7 @@ def _parse_current_version_default_pattern(ctx: ProjectContext, raw_cfg: RawConf
|
||||||
raise ValueError("Could not parse pycalver.current_version")
|
raise ValueError("Could not parse pycalver.current_version")
|
||||||
|
|
||||||
|
|
||||||
def _parse_raw_config(ctx: ProjectContext) -> RawConfig:
|
def _set_raw_config_defaults(raw_cfg: RawConfig) -> None:
|
||||||
with ctx.config_filepath.open(mode="rt", encoding="utf-8") as fobj:
|
|
||||||
if ctx.config_format == 'toml':
|
|
||||||
raw_cfg = _parse_toml(fobj)
|
|
||||||
elif ctx.config_format == 'cfg':
|
|
||||||
raw_cfg = _parse_cfg(fobj)
|
|
||||||
else:
|
|
||||||
err_msg = (
|
|
||||||
f"Invalid config_format='{ctx.config_format}'."
|
|
||||||
"Supported formats are 'setup.cfg' and 'pyproject.toml'"
|
|
||||||
)
|
|
||||||
raise RuntimeError(err_msg)
|
|
||||||
|
|
||||||
if 'current_version' in raw_cfg:
|
if 'current_version' in raw_cfg:
|
||||||
if not isinstance(raw_cfg['current_version'], str):
|
if not isinstance(raw_cfg['current_version'], str):
|
||||||
err = f"Invalid type for pycalver.current_version = {raw_cfg['current_version']}"
|
err = f"Invalid type for pycalver.current_version = {raw_cfg['current_version']}"
|
||||||
|
|
@ -370,10 +353,27 @@ def _parse_raw_config(ctx: ProjectContext) -> RawConfig:
|
||||||
if 'file_patterns' not in raw_cfg:
|
if 'file_patterns' not in raw_cfg:
|
||||||
raw_cfg['file_patterns'] = {}
|
raw_cfg['file_patterns'] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_raw_config(ctx: ProjectContext) -> RawConfig:
|
||||||
|
with ctx.config_filepath.open(mode="rt", encoding="utf-8") as fobj:
|
||||||
|
if ctx.config_format == 'toml':
|
||||||
|
raw_cfg = _parse_toml(fobj)
|
||||||
|
elif ctx.config_format == 'cfg':
|
||||||
|
raw_cfg = _parse_cfg(fobj)
|
||||||
|
else:
|
||||||
|
err_msg = (
|
||||||
|
f"Invalid config_format='{ctx.config_format}'."
|
||||||
|
"Supported formats are 'setup.cfg' and 'pyproject.toml'"
|
||||||
|
)
|
||||||
|
raise RuntimeError(err_msg)
|
||||||
|
|
||||||
if ctx.config_rel_path not in raw_cfg['file_patterns']:
|
if ctx.config_rel_path not in raw_cfg['file_patterns']:
|
||||||
# NOTE (mb 2020-09-19): By default we always add
|
# NOTE (mb 2020-09-19): By default we always add
|
||||||
# a pattern for the config section itself.
|
# a pattern for the config section itself.
|
||||||
raw_version_pattern = _parse_current_version_default_pattern(ctx, raw_cfg)
|
with ctx.config_filepath.open(mode="rt", encoding="utf-8") as fobj:
|
||||||
|
raw_cfg_text = fobj.read()
|
||||||
|
|
||||||
|
raw_version_pattern = _parse_current_version_default_pattern(raw_cfg, raw_cfg_text)
|
||||||
raw_cfg['file_patterns'][ctx.config_rel_path] = [raw_version_pattern]
|
raw_cfg['file_patterns'][ctx.config_rel_path] = [raw_version_pattern]
|
||||||
|
|
||||||
return raw_cfg
|
return raw_cfg
|
||||||
|
|
@ -393,6 +393,14 @@ def parse(ctx: ProjectContext) -> MaybeConfig:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def init(
|
||||||
|
project_path: typ.Union[str, pl.Path, None] = "."
|
||||||
|
) -> typ.Tuple[ProjectContext, MaybeConfig]:
|
||||||
|
ctx = init_project_ctx(project_path)
|
||||||
|
cfg = parse(ctx)
|
||||||
|
return (ctx, cfg)
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_CONFIGPARSER_BASE_TMPL = """
|
DEFAULT_CONFIGPARSER_BASE_TMPL = """
|
||||||
[pycalver]
|
[pycalver]
|
||||||
current_version = "{initial_version}"
|
current_version = "{initial_version}"
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,43 @@ import typing as typ
|
||||||
|
|
||||||
from .patterns import Pattern
|
from .patterns import Pattern
|
||||||
|
|
||||||
|
LineNo = int
|
||||||
|
Start = int
|
||||||
|
End = int
|
||||||
|
|
||||||
|
|
||||||
|
class LineSpan(typ.NamedTuple):
|
||||||
|
lineno: LineNo
|
||||||
|
start : Start
|
||||||
|
end : End
|
||||||
|
|
||||||
|
|
||||||
|
LineSpans = typ.List[LineSpan]
|
||||||
|
|
||||||
|
|
||||||
|
def _has_overlap(needle: LineSpan, haystack: LineSpans) -> bool:
|
||||||
|
for span in haystack:
|
||||||
|
# assume needle is in the center
|
||||||
|
has_overlap = (
|
||||||
|
span.lineno == needle.lineno
|
||||||
|
# needle starts before (or at) span end
|
||||||
|
and needle.start <= span.end
|
||||||
|
# needle ends after (or at) span start
|
||||||
|
and needle.end >= span.start
|
||||||
|
)
|
||||||
|
if has_overlap:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PatternMatch(typ.NamedTuple):
|
class PatternMatch(typ.NamedTuple):
|
||||||
"""Container to mark a version string in a file."""
|
"""Container to mark a version string in a file."""
|
||||||
|
|
||||||
lineno : int # zero based
|
lineno : LineNo # zero based
|
||||||
line : str
|
line : str
|
||||||
pattern: Pattern
|
pattern: Pattern
|
||||||
span : typ.Tuple[int, int]
|
span : typ.Tuple[Start, End]
|
||||||
match : str
|
match : str
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,6 +76,10 @@ def iter_matches(lines: typ.List[str], patterns: typ.List[Pattern]) -> PatternMa
|
||||||
... match = "v201712.0002-alpha",
|
... match = "v201712.0002-alpha",
|
||||||
... )
|
... )
|
||||||
"""
|
"""
|
||||||
|
matched_spans: LineSpans = []
|
||||||
for pattern in patterns:
|
for pattern in patterns:
|
||||||
for match in _iter_for_pattern(lines, pattern):
|
for match in _iter_for_pattern(lines, pattern):
|
||||||
|
needle_span = LineSpan(match.lineno, *match.span)
|
||||||
|
if not _has_overlap(needle_span, matched_spans):
|
||||||
yield match
|
yield match
|
||||||
|
matched_spans.append(needle_span)
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,6 @@ def update_cfg_from_vcs(cfg: config.Config, all_tags: typ.List[str]) -> config.C
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def rewrite_files(
|
|
||||||
cfg : config.Config,
|
|
||||||
new_version: str,
|
|
||||||
) -> None:
|
|
||||||
new_vinfo = v1version.parse_version_info(new_version, cfg.version_pattern)
|
|
||||||
v1rewrite.rewrite_files(cfg.file_patterns, new_vinfo)
|
|
||||||
|
|
||||||
|
|
||||||
def get_diff(cfg: config.Config, new_version: str) -> str:
|
def get_diff(cfg: config.Config, new_version: str) -> str:
|
||||||
old_vinfo = v1version.parse_version_info(cfg.current_version, cfg.version_pattern)
|
old_vinfo = v1version.parse_version_info(cfg.current_version, cfg.version_pattern)
|
||||||
new_vinfo = v1version.parse_version_info(new_version , cfg.version_pattern)
|
new_vinfo = v1version.parse_version_info(new_version , cfg.version_pattern)
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ PART_PATTERNS = {
|
||||||
'month' : r"(?:0[0-9]|1[0-2])",
|
'month' : r"(?:0[0-9]|1[0-2])",
|
||||||
'month_short': r"(?:1[0-2]|[1-9])",
|
'month_short': r"(?:1[0-2]|[1-9])",
|
||||||
'build_no' : r"\d{4,}",
|
'build_no' : r"\d{4,}",
|
||||||
'pep440_tag' : r"(?:post|dev|rc|a|b)?\d*",
|
'pep440_tag' : r"(?:a|b|dev|rc|post)?\d*",
|
||||||
'tag' : r"(?:preview|final|alpha|beta|post|pre|dev|rc|a|b|c|r)",
|
'tag' : r"(?:alpha|beta|dev|rc|post|final)",
|
||||||
'yy' : r"\d{2}",
|
'yy' : r"\d{2}",
|
||||||
'yyyy' : r"\d{4}",
|
'yyyy' : r"\d{4}",
|
||||||
'quarter' : r"[1-4]",
|
'quarter' : r"[1-4]",
|
||||||
|
|
@ -198,20 +198,11 @@ def _init_composite_patterns() -> None:
|
||||||
_init_composite_patterns()
|
_init_composite_patterns()
|
||||||
|
|
||||||
|
|
||||||
def _compile_pattern_re(version_pattern: str, raw_pattern: str) -> typ.Pattern[str]:
|
def _compile_pattern_re(normalized_pattern: str) -> typ.Pattern[str]:
|
||||||
normalized_pattern = raw_pattern.replace(r"{version}", version_pattern)
|
|
||||||
if version_pattern == r"{pycalver}":
|
|
||||||
normalized_pattern = normalized_pattern.replace(r"{pep440_version}", r"{pep440_pycalver}")
|
|
||||||
elif version_pattern == r"{semver}":
|
|
||||||
normalized_pattern = normalized_pattern.replace(r"{pep440_version}", r"{semver}")
|
|
||||||
elif r"{pep440_version}" in raw_pattern:
|
|
||||||
logger.warning(f"No mapping of '{version_pattern}' to '{{pep440_version}}'")
|
|
||||||
|
|
||||||
escaped_pattern = normalized_pattern
|
escaped_pattern = normalized_pattern
|
||||||
for char, escaped in RE_PATTERN_ESCAPES:
|
for char, escaped in RE_PATTERN_ESCAPES:
|
||||||
escaped_pattern = escaped_pattern.replace(char, escaped)
|
escaped_pattern = escaped_pattern.replace(char, escaped)
|
||||||
|
|
||||||
# TODO (mb 2020-09-19): replace {version} etc with version_pattern
|
|
||||||
pattern_str = _replace_pattern_parts(escaped_pattern)
|
pattern_str = _replace_pattern_parts(escaped_pattern)
|
||||||
return re.compile(pattern_str)
|
return re.compile(pattern_str)
|
||||||
|
|
||||||
|
|
@ -219,5 +210,17 @@ def _compile_pattern_re(version_pattern: str, raw_pattern: str) -> typ.Pattern[s
|
||||||
@utils.memo
|
@utils.memo
|
||||||
def compile_pattern(version_pattern: str, raw_pattern: typ.Optional[str] = None) -> Pattern:
|
def compile_pattern(version_pattern: str, raw_pattern: typ.Optional[str] = None) -> Pattern:
|
||||||
_raw_pattern = version_pattern if raw_pattern is None else raw_pattern
|
_raw_pattern = version_pattern if raw_pattern is None else raw_pattern
|
||||||
regexp = _compile_pattern_re(version_pattern, _raw_pattern)
|
normalized_pattern = _raw_pattern.replace(r"{version}", version_pattern)
|
||||||
return Pattern(version_pattern, _raw_pattern, regexp)
|
if version_pattern == r"{pycalver}":
|
||||||
|
normalized_pattern = normalized_pattern.replace(r"{pep440_version}", r"{pep440_pycalver}")
|
||||||
|
elif version_pattern == r"{semver}":
|
||||||
|
normalized_pattern = normalized_pattern.replace(r"{pep440_version}", r"{semver}")
|
||||||
|
elif r"{pep440_version}" in _raw_pattern:
|
||||||
|
logger.warning(f"No mapping of '{version_pattern}' to '{{pep440_version}}'")
|
||||||
|
|
||||||
|
regexp = _compile_pattern_re(normalized_pattern)
|
||||||
|
return Pattern(version_pattern, normalized_pattern, regexp)
|
||||||
|
|
||||||
|
|
||||||
|
def compile_patterns(version_pattern: str, raw_patterns: typ.List[str]) -> typ.List[Pattern]:
|
||||||
|
return [compile_pattern(version_pattern, raw_pattern) for raw_pattern in raw_patterns]
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,7 @@ def rewrite_lines(
|
||||||
new_vinfo: version.V1VersionInfo,
|
new_vinfo: version.V1VersionInfo,
|
||||||
old_lines: typ.List[str],
|
old_lines: typ.List[str],
|
||||||
) -> typ.List[str]:
|
) -> typ.List[str]:
|
||||||
"""Replace occurances of patterns in old_lines with new_vinfo.
|
"""Replace occurances of patterns in old_lines with new_vinfo."""
|
||||||
|
|
||||||
>>> from .v1patterns import compile_pattern
|
|
||||||
>>> version_pattern = "{pycalver}"
|
|
||||||
>>> new_vinfo = v1version.parse_version_info("v201811.0123-beta", version_pattern)
|
|
||||||
>>> patterns = [compile_pattern(version_pattern, '__version__ = "{pycalver}"')]
|
|
||||||
>>> rewrite_lines(patterns, new_vinfo, ['__version__ = "v201809.0002-beta"'])
|
|
||||||
['__version__ = "v201811.0123-beta"']
|
|
||||||
|
|
||||||
>>> patterns = [compile_pattern(version_pattern, '__version__ = "{pep440_version}"')]
|
|
||||||
>>> rewrite_lines(patterns, new_vinfo, ['__version__ = "201809.2b0"'])
|
|
||||||
['__version__ = "201811.123b0"']
|
|
||||||
"""
|
|
||||||
found_patterns: typ.Set[Pattern] = set()
|
found_patterns: typ.Set[Pattern] = set()
|
||||||
|
|
||||||
new_lines = old_lines[:]
|
new_lines = old_lines[:]
|
||||||
|
|
@ -65,10 +53,12 @@ def rfd_from_content(
|
||||||
) -> rewrite.RewrittenFileData:
|
) -> rewrite.RewrittenFileData:
|
||||||
r"""Rewrite pattern occurrences with version string.
|
r"""Rewrite pattern occurrences with version string.
|
||||||
|
|
||||||
>>> from .v1patterns import compile_pattern
|
>>> version_pattern = "{pycalver}"
|
||||||
>>> patterns = [compile_pattern("{pycalver}", '__version__ = "{pycalver}"']
|
|
||||||
>>> new_vinfo = v1version.parse_version_info("v201809.0123")
|
>>> new_vinfo = v1version.parse_version_info("v201809.0123")
|
||||||
|
|
||||||
|
>>> from .v1patterns import compile_pattern
|
||||||
|
>>> patterns = [compile_pattern(version_pattern, '__version__ = "{pycalver}"')]
|
||||||
|
|
||||||
>>> content = '__version__ = "v201809.0001-alpha"'
|
>>> content = '__version__ = "v201809.0001-alpha"'
|
||||||
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
||||||
>>> rfd.new_lines
|
>>> rfd.new_lines
|
||||||
|
|
@ -92,26 +82,7 @@ def iter_rewritten(
|
||||||
file_patterns: config.PatternsByFile,
|
file_patterns: config.PatternsByFile,
|
||||||
new_vinfo : version.V1VersionInfo,
|
new_vinfo : version.V1VersionInfo,
|
||||||
) -> typ.Iterable[rewrite.RewrittenFileData]:
|
) -> typ.Iterable[rewrite.RewrittenFileData]:
|
||||||
r'''Iterate over files with version string replaced.
|
"""Iterate over files with version string replaced."""
|
||||||
|
|
||||||
>>> version_pattern = "{pycalver}"
|
|
||||||
>>> file_patterns = {"src/pycalver/__init__.py": ['__version__ = "{pycalver}"']}
|
|
||||||
>>> new_vinfo = v1version.parse_version_info("v201809.0123")
|
|
||||||
>>> rewritten_datas = iter_rewritten(version_pattern, file_patterns, new_vinfo)
|
|
||||||
>>> rfd = list(rewritten_datas)[0]
|
|
||||||
>>> expected = [
|
|
||||||
... '# This file is part of the pycalver project',
|
|
||||||
... '# https://github.com/mbarkhau/pycalver',
|
|
||||||
... '#',
|
|
||||||
... '# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License',
|
|
||||||
... '# SPDX-License-Identifier: MIT',
|
|
||||||
... '"""PyCalVer: CalVer for Python Packages."""',
|
|
||||||
... '',
|
|
||||||
... '__version__ = "v201809.0123"',
|
|
||||||
... '',
|
|
||||||
... ]
|
|
||||||
>>> assert rfd.new_lines == expected
|
|
||||||
'''
|
|
||||||
|
|
||||||
fobj: typ.IO[str]
|
fobj: typ.IO[str]
|
||||||
|
|
||||||
|
|
@ -128,24 +99,7 @@ def diff(
|
||||||
new_vinfo : version.V1VersionInfo,
|
new_vinfo : version.V1VersionInfo,
|
||||||
file_patterns: config.PatternsByFile,
|
file_patterns: config.PatternsByFile,
|
||||||
) -> str:
|
) -> str:
|
||||||
r"""Generate diffs of rewritten files.
|
"""Generate diffs of rewritten files."""
|
||||||
|
|
||||||
>>> old_vinfo = v1version.parse_version_info("v201809.0123")
|
|
||||||
>>> new_vinfo = v1version.parse_version_info("v201810.1124")
|
|
||||||
>>> file_patterns = {"src/pycalver/__init__.py": ['__version__ = "{pycalver}"']}
|
|
||||||
>>> diff_str = diff(old_vinfo, new_vinfo, file_patterns)
|
|
||||||
>>> lines = diff_str.split("\n")
|
|
||||||
>>> lines[:2]
|
|
||||||
['--- src/pycalver/__init__.py', '+++ src/pycalver/__init__.py']
|
|
||||||
>>> assert lines[6].startswith('-__version__ = "v2')
|
|
||||||
>>> assert not lines[6].startswith('-__version__ = "v201809.0123"')
|
|
||||||
>>> lines[7]
|
|
||||||
'+__version__ = "v201809.0123"'
|
|
||||||
|
|
||||||
>>> file_patterns = {"LICENSE": ['Copyright (c) 2018-{year}']}
|
|
||||||
>>> diff_str = diff(old_vinfo, new_vinfo, file_patterns)
|
|
||||||
>>> assert not diff_str
|
|
||||||
"""
|
|
||||||
|
|
||||||
full_diff = ""
|
full_diff = ""
|
||||||
fobj: typ.IO[str]
|
fobj: typ.IO[str]
|
||||||
|
|
@ -165,13 +119,13 @@ def diff(
|
||||||
rfd = rfd_from_content(patterns, new_vinfo, content)
|
rfd = rfd_from_content(patterns, new_vinfo, content)
|
||||||
except rewrite.NoPatternMatch:
|
except rewrite.NoPatternMatch:
|
||||||
# pylint:disable=raise-missing-from ; we support py2, so not an option
|
# pylint:disable=raise-missing-from ; we support py2, so not an option
|
||||||
errmsg = f"No patterns matched for '{file_path}'"
|
errmsg = f"No patterns matched for file '{file_path}'"
|
||||||
raise rewrite.NoPatternMatch(errmsg)
|
raise rewrite.NoPatternMatch(errmsg)
|
||||||
|
|
||||||
rfd = rfd._replace(path=str(file_path))
|
rfd = rfd._replace(path=str(file_path))
|
||||||
lines = rewrite.diff_lines(rfd)
|
lines = rewrite.diff_lines(rfd)
|
||||||
if len(lines) == 0 and has_updated_version:
|
if len(lines) == 0 and has_updated_version:
|
||||||
errmsg = f"No patterns matched for '{file_path}'"
|
errmsg = f"No patterns matched for file '{file_path}'"
|
||||||
raise rewrite.NoPatternMatch(errmsg)
|
raise rewrite.NoPatternMatch(errmsg)
|
||||||
|
|
||||||
full_diff += "\n".join(lines) + "\n"
|
full_diff += "\n".join(lines) + "\n"
|
||||||
|
|
|
||||||
|
|
@ -379,7 +379,7 @@ def incr(
|
||||||
minor : bool = False,
|
minor : bool = False,
|
||||||
patch : bool = False,
|
patch : bool = False,
|
||||||
release_num: bool = False,
|
release_num: bool = False,
|
||||||
pin_date: bool = False,
|
pin_date : bool = False,
|
||||||
) -> typ.Optional[str]:
|
) -> typ.Optional[str]:
|
||||||
"""Increment version string.
|
"""Increment version string.
|
||||||
|
|
||||||
|
|
@ -408,7 +408,7 @@ def incr(
|
||||||
if patch:
|
if patch:
|
||||||
cur_vinfo = cur_vinfo._replace(patch=cur_vinfo.patch + 1)
|
cur_vinfo = cur_vinfo._replace(patch=cur_vinfo.patch + 1)
|
||||||
if release_num:
|
if release_num:
|
||||||
cur_vinfo = cur_vinfo._replace(num=cur_vinfo.num + 1)
|
raise NotImplementedError("--release-num not supported for old style patterns")
|
||||||
if release:
|
if release:
|
||||||
cur_vinfo = cur_vinfo._replace(tag=release)
|
cur_vinfo = cur_vinfo._replace(tag=release)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,6 @@ def update_cfg_from_vcs(cfg: config.Config, all_tags: typ.List[str]) -> config.C
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def rewrite_files(
|
|
||||||
cfg : config.Config,
|
|
||||||
new_version: str,
|
|
||||||
) -> None:
|
|
||||||
new_vinfo = v2version.parse_version_info(new_version, cfg.version_pattern)
|
|
||||||
v2rewrite.rewrite_files(cfg.file_patterns, new_vinfo)
|
|
||||||
|
|
||||||
|
|
||||||
def get_diff(cfg: config.Config, new_version: str) -> str:
|
def get_diff(cfg: config.Config, new_version: str) -> str:
|
||||||
old_vinfo = v2version.parse_version_info(cfg.current_version, cfg.version_pattern)
|
old_vinfo = v2version.parse_version_info(cfg.current_version, cfg.version_pattern)
|
||||||
new_vinfo = v2version.parse_version_info(new_version , cfg.version_pattern)
|
new_vinfo = v2version.parse_version_info(new_version , cfg.version_pattern)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
>>> pattern = compile_pattern("vYYYY0M.BUILD[-RELEASE]")
|
>>> pattern = compile_pattern("vYYYY0M.BUILD[-RELEASE]")
|
||||||
>>> version_info = pattern.regexp.match("v201712.0123-alpha")
|
>>> version_info = pattern.regexp.match("v201712.0123-alpha")
|
||||||
>>> assert version_info.groupdict() == {
|
>>> assert version_info.groupdict() == {
|
||||||
... "version": "v201712.0123-alpha",
|
|
||||||
... "year_y" : "2017",
|
... "year_y" : "2017",
|
||||||
... "month" : "12",
|
... "month" : "12",
|
||||||
... "bid" : "0123",
|
... "bid" : "0123",
|
||||||
|
|
@ -23,7 +22,6 @@
|
||||||
|
|
||||||
>>> version_info = pattern.regexp.match("v201712.1234")
|
>>> version_info = pattern.regexp.match("v201712.1234")
|
||||||
>>> assert version_info.groupdict() == {
|
>>> assert version_info.groupdict() == {
|
||||||
... "version": "v201712.1234",
|
|
||||||
... "year_y" : "2017",
|
... "year_y" : "2017",
|
||||||
... "month" : "12",
|
... "month" : "12",
|
||||||
... "bid" : "1234",
|
... "bid" : "1234",
|
||||||
|
|
@ -251,6 +249,13 @@ def _convert_to_pep440(version_pattern: str) -> str:
|
||||||
else:
|
else:
|
||||||
pep440_pattern = pep440_pattern.replace(part_name, substitution)
|
pep440_pattern = pep440_pattern.replace(part_name, substitution)
|
||||||
|
|
||||||
|
# PYTAG and NUM must be adjacent and also be the last (optional) part
|
||||||
|
if 'PYTAGNUM' not in pep440_pattern:
|
||||||
|
pep440_pattern = pep440_pattern.replace("PYTAG", "")
|
||||||
|
pep440_pattern = pep440_pattern.replace("NUM" , "")
|
||||||
|
pep440_pattern = pep440_pattern.replace("[]" , "")
|
||||||
|
pep440_pattern += "[PYTAGNUM]"
|
||||||
|
|
||||||
return pep440_pattern
|
return pep440_pattern
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -304,8 +309,7 @@ def _replace_pattern_parts(pattern: str) -> str:
|
||||||
return result_pattern
|
return result_pattern
|
||||||
|
|
||||||
|
|
||||||
def _compile_pattern_re(version_pattern: str, raw_pattern: str) -> typ.Pattern[str]:
|
def _compile_pattern_re(normalized_pattern: str) -> typ.Pattern[str]:
|
||||||
normalized_pattern = normalize_pattern(version_pattern, raw_pattern)
|
|
||||||
escaped_pattern = normalized_pattern
|
escaped_pattern = normalized_pattern
|
||||||
for char, escaped in RE_PATTERN_ESCAPES:
|
for char, escaped in RE_PATTERN_ESCAPES:
|
||||||
# [] braces are used for optional parts, such as [-RELEASE]/[-beta]
|
# [] braces are used for optional parts, such as [-RELEASE]/[-beta]
|
||||||
|
|
@ -322,5 +326,10 @@ def _compile_pattern_re(version_pattern: str, raw_pattern: str) -> typ.Pattern[s
|
||||||
@utils.memo
|
@utils.memo
|
||||||
def compile_pattern(version_pattern: str, raw_pattern: typ.Optional[str] = None) -> Pattern:
|
def compile_pattern(version_pattern: str, raw_pattern: typ.Optional[str] = None) -> Pattern:
|
||||||
_raw_pattern = version_pattern if raw_pattern is None else raw_pattern
|
_raw_pattern = version_pattern if raw_pattern is None else raw_pattern
|
||||||
regexp = _compile_pattern_re(version_pattern, _raw_pattern)
|
normalized_pattern = normalize_pattern(version_pattern, _raw_pattern)
|
||||||
return Pattern(version_pattern, _raw_pattern, regexp)
|
regexp = _compile_pattern_re(normalized_pattern)
|
||||||
|
return Pattern(version_pattern, normalized_pattern, regexp)
|
||||||
|
|
||||||
|
|
||||||
|
def compile_patterns(version_pattern: str, raw_patterns: typ.List[str]) -> typ.List[Pattern]:
|
||||||
|
return [compile_pattern(version_pattern, raw_pattern) for raw_pattern in raw_patterns]
|
||||||
|
|
|
||||||
|
|
@ -25,23 +25,7 @@ def rewrite_lines(
|
||||||
new_vinfo: version.V2VersionInfo,
|
new_vinfo: version.V2VersionInfo,
|
||||||
old_lines: typ.List[str],
|
old_lines: typ.List[str],
|
||||||
) -> typ.List[str]:
|
) -> typ.List[str]:
|
||||||
"""Replace occurances of patterns in old_lines with new_vinfo.
|
"""Replace occurances of patterns in old_lines with new_vinfo."""
|
||||||
|
|
||||||
>>> from .v2patterns import compile_pattern
|
|
||||||
>>> version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
|
||||||
>>> new_vinfo = v2version.parse_version_info("v201811.0123-beta", version_pattern)
|
|
||||||
>>> patterns = [compile_pattern(version_pattern, '__version__ = "{version}"')]
|
|
||||||
>>> rewrite_lines(patterns, new_vinfo, ['__version__ = "v201809.0002-alpha" '])
|
|
||||||
['__version__ = "v201811.0123-beta" ']
|
|
||||||
|
|
||||||
>>> rewrite_lines(patterns, new_vinfo, ['__version__ = "v201809.0002-alpha" # comment'])
|
|
||||||
['__version__ = "v201811.0123-beta" # comment']
|
|
||||||
|
|
||||||
>>> patterns = [compile_pattern(version_pattern, '__version__ = "{pep440_version}"')]
|
|
||||||
>>> old_lines = ['__version__ = "201809.2a0"']
|
|
||||||
>>> rewrite_lines(patterns, new_vinfo, old_lines)
|
|
||||||
['__version__ = "201811.123b0"']
|
|
||||||
"""
|
|
||||||
found_patterns: typ.Set[Pattern] = set()
|
found_patterns: typ.Set[Pattern] = set()
|
||||||
|
|
||||||
new_lines = old_lines[:]
|
new_lines = old_lines[:]
|
||||||
|
|
@ -73,10 +57,10 @@ def rfd_from_content(
|
||||||
) -> rewrite.RewrittenFileData:
|
) -> rewrite.RewrittenFileData:
|
||||||
r"""Rewrite pattern occurrences with version string.
|
r"""Rewrite pattern occurrences with version string.
|
||||||
|
|
||||||
|
>>> from .v2patterns import compile_pattern
|
||||||
>>> version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
>>> version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
||||||
>>> new_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
>>> new_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
||||||
>>> raw_patterns = ['__version__ = "vYYYY0M.BUILD[-RELEASE]"']
|
>>> patterns = [compile_pattern(version_pattern, '__version__ = "vYYYY0M.BUILD[-RELEASE]"')]
|
||||||
>>> patterns =
|
|
||||||
>>> content = '__version__ = "v201809.0001-alpha"'
|
>>> content = '__version__ = "v201809.0001-alpha"'
|
||||||
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
||||||
>>> rfd.new_lines
|
>>> rfd.new_lines
|
||||||
|
|
@ -84,8 +68,7 @@ def rfd_from_content(
|
||||||
|
|
||||||
>>> version_pattern = "vMAJOR.MINOR.PATCH"
|
>>> version_pattern = "vMAJOR.MINOR.PATCH"
|
||||||
>>> new_vinfo = v2version.parse_version_info("v1.2.3", version_pattern)
|
>>> new_vinfo = v2version.parse_version_info("v1.2.3", version_pattern)
|
||||||
>>> raw_patterns = ['__version__ = "vMAJOR.MINOR.PATCH"']
|
>>> patterns = [compile_pattern(version_pattern, '__version__ = "vMAJOR.MINOR.PATCH"')]
|
||||||
>>> patterns =
|
|
||||||
>>> content = '__version__ = "v1.2.2"'
|
>>> content = '__version__ = "v1.2.2"'
|
||||||
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
>>> rfd = rfd_from_content(patterns, new_vinfo, content)
|
||||||
>>> rfd.new_lines
|
>>> rfd.new_lines
|
||||||
|
|
@ -113,26 +96,7 @@ def iter_rewritten(
|
||||||
file_patterns: config.PatternsByFile,
|
file_patterns: config.PatternsByFile,
|
||||||
new_vinfo : version.V2VersionInfo,
|
new_vinfo : version.V2VersionInfo,
|
||||||
) -> typ.Iterable[rewrite.RewrittenFileData]:
|
) -> typ.Iterable[rewrite.RewrittenFileData]:
|
||||||
r'''Iterate over files with version string replaced.
|
"""Iterate over files with version string replaced."""
|
||||||
|
|
||||||
>>> version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
|
||||||
>>> file_patterns = {"src/pycalver/__init__.py": ['__version__ = "vYYYY0M.BUILD[-RELEASE]"']}
|
|
||||||
>>> new_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
|
||||||
>>> rewritten_datas = iter_rewritten(file_patterns, new_vinfo)
|
|
||||||
>>> rfd = list(rewritten_datas)[0]
|
|
||||||
>>> expected = [
|
|
||||||
... '# This file is part of the pycalver project',
|
|
||||||
... '# https://github.com/mbarkhau/pycalver',
|
|
||||||
... '#',
|
|
||||||
... '# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License',
|
|
||||||
... '# SPDX-License-Identifier: MIT',
|
|
||||||
... '"""PyCalVer: CalVer for Python Packages."""',
|
|
||||||
... '',
|
|
||||||
... '__version__ = "v201809.0123"',
|
|
||||||
... '',
|
|
||||||
... ]
|
|
||||||
>>> assert rfd.new_lines == expected
|
|
||||||
'''
|
|
||||||
|
|
||||||
fobj: typ.IO[str]
|
fobj: typ.IO[str]
|
||||||
|
|
||||||
|
|
@ -149,24 +113,7 @@ def diff(
|
||||||
new_vinfo : version.V2VersionInfo,
|
new_vinfo : version.V2VersionInfo,
|
||||||
file_patterns: config.PatternsByFile,
|
file_patterns: config.PatternsByFile,
|
||||||
) -> str:
|
) -> str:
|
||||||
r"""Generate diffs of rewritten files.
|
r"""Generate diffs of rewritten files."""
|
||||||
|
|
||||||
>>> old_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
|
||||||
>>> new_vinfo = v2version.parse_version_info("v201810.1124", version_pattern)
|
|
||||||
>>> file_patterns = {"src/pycalver/__init__.py": ['__version__ = "vYYYY0M.BUILD[-RELEASE]"']}
|
|
||||||
>>> diff_str = diff(old_vinfo, new_vinfo, file_patterns)
|
|
||||||
>>> lines = diff_str.split("\n")
|
|
||||||
>>> lines[:2]
|
|
||||||
['--- src/pycalver/__init__.py', '+++ src/pycalver/__init__.py']
|
|
||||||
>>> assert lines[6].startswith('-__version__ = "v2')
|
|
||||||
>>> assert not lines[6].startswith('-__version__ = "v201810.1124"')
|
|
||||||
>>> lines[7]
|
|
||||||
'+__version__ = "v201810.1124"'
|
|
||||||
|
|
||||||
>>> file_patterns = {"LICENSE": ['Copyright (c) 2018-YYYY']}
|
|
||||||
>>> diff_str = diff(old_vinfo, new_vinfo, file_patterns)
|
|
||||||
>>> assert not diff_str
|
|
||||||
"""
|
|
||||||
|
|
||||||
full_diff = ""
|
full_diff = ""
|
||||||
fobj: typ.IO[str]
|
fobj: typ.IO[str]
|
||||||
|
|
@ -179,7 +126,7 @@ def diff(
|
||||||
rfd = rfd_from_content(patterns, new_vinfo, content)
|
rfd = rfd_from_content(patterns, new_vinfo, content)
|
||||||
except rewrite.NoPatternMatch:
|
except rewrite.NoPatternMatch:
|
||||||
# pylint:disable=raise-missing-from ; we support py2, so not an option
|
# pylint:disable=raise-missing-from ; we support py2, so not an option
|
||||||
errmsg = f"No patterns matched for '{file_path}'"
|
errmsg = f"No patterns matched for file '{file_path}'"
|
||||||
raise rewrite.NoPatternMatch(errmsg)
|
raise rewrite.NoPatternMatch(errmsg)
|
||||||
|
|
||||||
rfd = rfd._replace(path=str(file_path))
|
rfd = rfd._replace(path=str(file_path))
|
||||||
|
|
@ -187,7 +134,7 @@ def diff(
|
||||||
|
|
||||||
patterns_with_change = _patterns_with_change(old_vinfo, new_vinfo, patterns)
|
patterns_with_change = _patterns_with_change(old_vinfo, new_vinfo, patterns)
|
||||||
if len(lines) == 0 and patterns_with_change > 0:
|
if len(lines) == 0 and patterns_with_change > 0:
|
||||||
errmsg = f"No patterns matched for '{file_path}'"
|
errmsg = f"No patterns matched for file '{file_path}'"
|
||||||
raise rewrite.NoPatternMatch(errmsg)
|
raise rewrite.NoPatternMatch(errmsg)
|
||||||
|
|
||||||
full_diff += "\n".join(lines) + "\n"
|
full_diff += "\n".join(lines) + "\n"
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
||||||
assert key in VALID_FIELD_KEYS, key
|
assert key in VALID_FIELD_KEYS, key
|
||||||
|
|
||||||
fvals = field_values
|
fvals = field_values
|
||||||
tag = fvals.get('tag' ) or "final"
|
tag = fvals.get('tag' ) or ""
|
||||||
pytag = fvals.get('pytag') or ""
|
pytag = fvals.get('pytag') or ""
|
||||||
|
|
||||||
if tag and not pytag:
|
if tag and not pytag:
|
||||||
|
|
@ -153,6 +153,9 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
||||||
elif pytag and not tag:
|
elif pytag and not tag:
|
||||||
tag = version.RELEASE_BY_PEP440_TAG[pytag]
|
tag = version.RELEASE_BY_PEP440_TAG[pytag]
|
||||||
|
|
||||||
|
if not tag:
|
||||||
|
tag = "final"
|
||||||
|
|
||||||
date: typ.Optional[dt.date] = None
|
date: typ.Optional[dt.date] = None
|
||||||
|
|
||||||
year_y: MaybeInt = int(fvals['year_y']) if 'year_y' in fvals else None
|
year_y: MaybeInt = int(fvals['year_y']) if 'year_y' in fvals else None
|
||||||
|
|
@ -221,22 +224,22 @@ def _parse_version_info(field_values: FieldValues) -> version.V2VersionInfo:
|
||||||
|
|
||||||
|
|
||||||
def parse_version_info(
|
def parse_version_info(
|
||||||
version_str: str, raw_pattern: str = "vYYYY0M.BUILD[-RELEASE[NUM]]"
|
version_str: str, raw_pattern: str = "vYYYY0M.BUILD[-RELEASE]"
|
||||||
) -> version.V2VersionInfo:
|
) -> version.V2VersionInfo:
|
||||||
"""Parse normalized V2VersionInfo.
|
"""Parse normalized V2VersionInfo.
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("v201712.0033-beta0", raw_pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> vinfo = parse_version_info("v201712.0033-beta", raw_pattern="vYYYY0M.BUILD[-RELEASE]")
|
||||||
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "0033", 'tag': "beta", 'num': 0}
|
|
||||||
>>> assert vinfo == _parse_version_info(fvals)
|
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("v201712.0033-beta", raw_pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
|
||||||
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "0033", 'tag': "beta"}
|
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "0033", 'tag': "beta"}
|
||||||
>>> assert vinfo == _parse_version_info(fvals)
|
>>> assert vinfo == _parse_version_info(fvals)
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("v201712.0033", raw_pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> vinfo = parse_version_info("v201712.0033", raw_pattern="vYYYY0M.BUILD[-RELEASE]")
|
||||||
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "0033"}
|
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "0033"}
|
||||||
>>> assert vinfo == _parse_version_info(fvals)
|
>>> assert vinfo == _parse_version_info(fvals)
|
||||||
|
|
||||||
|
>>> vinfo = parse_version_info("201712.33b0", raw_pattern="YYYY0M.BLD[PYTAGNUM]")
|
||||||
|
>>> fvals = {'year_y': 2017, 'month': 12, 'bid': "33", 'tag': "beta", 'num': 0}
|
||||||
|
>>> assert vinfo == _parse_version_info(fvals)
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("1.23.456", raw_pattern="MAJOR.MINOR.PATCH")
|
>>> vinfo = parse_version_info("1.23.456", raw_pattern="MAJOR.MINOR.PATCH")
|
||||||
>>> fvals = {'major': "1", 'minor': "23", 'patch': "456"}
|
>>> fvals = {'major': "1", 'minor': "23", 'patch': "456"}
|
||||||
>>> assert vinfo == _parse_version_info(fvals)
|
>>> assert vinfo == _parse_version_info(fvals)
|
||||||
|
|
@ -291,14 +294,14 @@ def _format_part_values(vinfo: version.V2VersionInfo) -> PartValues:
|
||||||
It may for example have month=9, but not the formatted
|
It may for example have month=9, but not the formatted
|
||||||
representation '09' for '0M'.
|
representation '09' for '0M'.
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("v200709.1033-beta", pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> vinfo = parse_version_info("v200709.1033-beta", raw_pattern="vYYYY0M.BUILD[-RELEASE]")
|
||||||
>>> kwargs = dict(_format_part_values(vinfo))
|
>>> kwargs = dict(_format_part_values(vinfo))
|
||||||
>>> (kwargs['YYYY'], kwargs['0M'], kwargs['BUILD'], kwargs['RELEASE[NUM]'])
|
>>> (kwargs['YYYY'], kwargs['0M'], kwargs['BUILD'], kwargs['RELEASE'])
|
||||||
('2007', '09', '1033', 'beta')
|
('2007', '09', '1033', 'beta')
|
||||||
>>> (kwargs['YY'], kwargs['0Y'], kwargs['MM'], kwargs['PYTAG'])
|
>>> (kwargs['YY'], kwargs['0Y'], kwargs['MM'], kwargs['PYTAG'])
|
||||||
('7', '07', '9', 'b')
|
('7', '07', '9', 'b')
|
||||||
|
|
||||||
>>> vinfo = parse_version_info("200709.1033b1", pattern="YYYY0M.BLD[PYTAGNUM]")
|
>>> vinfo = parse_version_info("200709.1033b1", raw_pattern="YYYY0M.BLD[PYTAGNUM]")
|
||||||
>>> kwargs = dict(_format_part_values(vinfo))
|
>>> kwargs = dict(_format_part_values(vinfo))
|
||||||
>>> (kwargs['YYYY'], kwargs['0M'], kwargs['BUILD'], kwargs['PYTAG'], kwargs['NUM'])
|
>>> (kwargs['YYYY'], kwargs['0M'], kwargs['BUILD'], kwargs['PYTAG'], kwargs['NUM'])
|
||||||
('2007', '09', '1033', 'b', '1')
|
('2007', '09', '1033', 'b', '1')
|
||||||
|
|
@ -386,129 +389,190 @@ def _parse_segment_tree(raw_pattern: str) -> SegmentTree:
|
||||||
FormattedSegmentParts = typ.List[str]
|
FormattedSegmentParts = typ.List[str]
|
||||||
|
|
||||||
|
|
||||||
|
class FormatedSeg(typ.NamedTuple):
|
||||||
|
is_literal: bool
|
||||||
|
is_zero : bool
|
||||||
|
result : str
|
||||||
|
|
||||||
|
|
||||||
|
def _format_segment(seg: Segment, part_values: PartValues) -> FormatedSeg:
|
||||||
|
zero_part_count = 0
|
||||||
|
|
||||||
|
# find all parts, regardless of zero value
|
||||||
|
used_parts: typ.List[typ.Tuple[str, str]] = []
|
||||||
|
|
||||||
|
for part, part_value in part_values:
|
||||||
|
if part in seg:
|
||||||
|
used_parts.append((part, part_value))
|
||||||
|
if version.is_zero_val(part, part_value):
|
||||||
|
zero_part_count += 1
|
||||||
|
|
||||||
|
result = seg
|
||||||
|
# unescape braces
|
||||||
|
result = result.replace(r"\[", r"[")
|
||||||
|
result = result.replace(r"\]", r"]")
|
||||||
|
|
||||||
|
for part, part_value in used_parts:
|
||||||
|
result = result.replace(part, part_value)
|
||||||
|
|
||||||
|
# If a segment has no parts at all, it is a literal string
|
||||||
|
# (typically a prefix or sufix) and should be output as is.
|
||||||
|
is_literal_seg = len(used_parts) == 0
|
||||||
|
if is_literal_seg:
|
||||||
|
return FormatedSeg(True, False, result)
|
||||||
|
elif zero_part_count > 0 and zero_part_count == len(used_parts):
|
||||||
|
# all zero, omit segment completely
|
||||||
|
return FormatedSeg(False, True, result)
|
||||||
|
else:
|
||||||
|
return FormatedSeg(False, False, result)
|
||||||
|
|
||||||
|
|
||||||
def _format_segment_tree(
|
def _format_segment_tree(
|
||||||
seg_tree : SegmentTree,
|
seg_tree : SegmentTree,
|
||||||
part_values: PartValues,
|
part_values: PartValues,
|
||||||
) -> FormattedSegmentParts:
|
) -> FormatedSeg:
|
||||||
result_parts = []
|
# print("??>>>", seg_tree)
|
||||||
|
# NOTE (mb 2020-10-02): starting from the right, if there is any non-zero
|
||||||
|
# part, all further parts going left will be used. In other words, a part
|
||||||
|
# is only omitted, if all parts to the right of it were also omitted.
|
||||||
|
result_parts: typ.List[str] = []
|
||||||
|
is_zero = True
|
||||||
for seg in seg_tree:
|
for seg in seg_tree:
|
||||||
if isinstance(seg, list):
|
if isinstance(seg, list):
|
||||||
result_parts.extend(_format_segment_tree(seg, part_values))
|
formatted_seg = _format_segment_tree(seg, part_values)
|
||||||
else:
|
else:
|
||||||
# If a segment has any non-zero parts, the whole segment is used.
|
formatted_seg = _format_segment(seg, part_values)
|
||||||
non_zero_parts = 0
|
|
||||||
formatted_seg = seg
|
if formatted_seg.is_literal:
|
||||||
# unescape braces
|
result_parts.append(formatted_seg.result)
|
||||||
formatted_seg = formatted_seg.replace(r"\[", r"[")
|
|
||||||
formatted_seg = formatted_seg.replace(r"\]", r"]")
|
|
||||||
# replace non zero parts
|
|
||||||
for part, part_value in part_values:
|
|
||||||
if part in formatted_seg:
|
|
||||||
is_zero_part = (
|
|
||||||
part in version.ZERO_VALUES and str(part_value) == version.ZERO_VALUES[part]
|
|
||||||
)
|
|
||||||
if is_zero_part:
|
|
||||||
formatted_seg = formatted_seg.replace(part, "")
|
|
||||||
else:
|
else:
|
||||||
non_zero_parts += 1
|
is_zero = is_zero and formatted_seg.is_zero
|
||||||
formatted_seg = formatted_seg.replace(part, part_value)
|
result_parts.append(formatted_seg.result)
|
||||||
|
|
||||||
if non_zero_parts:
|
# print("<<<<", is_zero, result_parts)
|
||||||
result_parts.append(formatted_seg)
|
result = "" if is_zero else "".join(result_parts)
|
||||||
|
return FormatedSeg(False, is_zero, result)
|
||||||
return result_parts
|
|
||||||
|
|
||||||
|
|
||||||
def format_version(vinfo: version.V2VersionInfo, raw_pattern: str) -> str:
|
def format_version(vinfo: version.V2VersionInfo, raw_pattern: str) -> str:
|
||||||
"""Generate version string.
|
"""Generate version string.
|
||||||
|
|
||||||
>>> import datetime as dt
|
>>> import datetime as dt
|
||||||
>>> vinfo = parse_version_info("v200712.0033-beta", pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> vinfo = parse_version_info("v200712.0033-beta", raw_pattern="vYYYY0M.BUILD[-RELEASE]")
|
||||||
>>> vinfo_a = vinfo._replace(**cal_info(date=dt.date(2007, 1, 1))._asdict())
|
>>> vinfo_a = vinfo._replace(**cal_info(date=dt.date(2007, 1, 1))._asdict())
|
||||||
>>> vinfo_b = vinfo._replace(**cal_info(date=dt.date(2007, 12, 31))._asdict())
|
>>> vinfo_b = vinfo._replace(**cal_info(date=dt.date(2007, 12, 31))._asdict())
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="vYY.BLD[-PYTAGNUM]")
|
>>> format_version(vinfo_a, raw_pattern="vYY.BLD[-PYTAGNUM]")
|
||||||
'v7.33-b0'
|
'v7.33-b0'
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="YYYY0M.BUILD[PYTAG[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="YYYY0M.BUILD[PYTAG[NUM]]")
|
||||||
'200701.0033b'
|
'200701.0033b'
|
||||||
>>> format_version(vinfo_a, pattern="vYY.BLD[-PYTAGNUM]")
|
>>> format_version(vinfo_a, raw_pattern="vYY.BLD[-PYTAGNUM]")
|
||||||
'v7.33-b0'
|
'v7.33-b0'
|
||||||
>>> format_version(vinfo_a, pattern="v0Y.BLD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="v0Y.BLD[-RELEASE[NUM]]")
|
||||||
'v07.33-beta'
|
'v07.33-beta'
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
||||||
'v200701.0033-beta'
|
'v200701.0033-beta'
|
||||||
>>> format_version(vinfo_b, pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_b, raw_pattern="vYYYY0M.BUILD[-RELEASE[NUM]]")
|
||||||
'v200712.0033-beta'
|
'v200712.0033-beta'
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="vYYYYw0W.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vYYYYw0W.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007w01.0033-beta'
|
'v2007w01.0033-beta'
|
||||||
>>> format_version(vinfo_a, pattern="vYYYYwWW.BLD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vYYYYwWW.BLD[-RELEASE[NUM]]")
|
||||||
'v2007w1.33-beta'
|
'v2007w1.33-beta'
|
||||||
>>> format_version(vinfo_b, pattern="vYYYYw0W.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_b, raw_pattern="vYYYYw0W.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007w53.0033-beta'
|
'v2007w53.0033-beta'
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="vYYYYd00J.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vYYYYd00J.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007d001.0033-beta'
|
'v2007d001.0033-beta'
|
||||||
>>> format_version(vinfo_a, pattern="vYYYYdJJJ.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vYYYYdJJJ.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007d1.0033-beta'
|
'v2007d1.0033-beta'
|
||||||
>>> format_version(vinfo_b, pattern="vYYYYd00J.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_b, raw_pattern="vYYYYd00J.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007d365.0033-beta'
|
'v2007d365.0033-beta'
|
||||||
|
|
||||||
>>> format_version(vinfo_a, pattern="vGGGGwVV.BLD[PYTAGNUM]")
|
>>> format_version(vinfo_a, raw_pattern="vGGGGwVV.BLD[PYTAGNUM]")
|
||||||
'v2007w1.33b0'
|
'v2007w1.33b0'
|
||||||
>>> format_version(vinfo_a, pattern="vGGGGw0V.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_a, raw_pattern="vGGGGw0V.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007w01.0033-beta'
|
'v2007w01.0033-beta'
|
||||||
>>> format_version(vinfo_b, pattern="vGGGGw0V.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_b, raw_pattern="vGGGGw0V.BUILD[-RELEASE[NUM]]")
|
||||||
'v2008w01.0033-beta'
|
'v2008w01.0033-beta'
|
||||||
|
|
||||||
>>> vinfo_c = vinfo_b._replace(major=1, minor=2, patch=34, tag='final')
|
>>> vinfo_c = vinfo_b._replace(major=1, minor=2, patch=34, tag='final')
|
||||||
|
|
||||||
>>> format_version(vinfo_c, pattern="vYYYYwWW.BUILD-RELEASE")
|
>>> format_version(vinfo_c, raw_pattern="vYYYYwWW.BUILD-RELEASE")
|
||||||
'v2007w53.0033-final'
|
'v2007w53.0033-final'
|
||||||
>>> format_version(vinfo_c, pattern="vYYYYwWW.BUILD[-RELEASE[NUM]]")
|
>>> format_version(vinfo_c, raw_pattern="vYYYYwWW.BUILD[-RELEASE[NUM]]")
|
||||||
'v2007w53.0033'
|
'v2007w53.0033'
|
||||||
|
|
||||||
>>> format_version(vinfo_c, pattern="vMAJOR.MINOR.PATCH")
|
>>> format_version(vinfo_c, raw_pattern="vMAJOR.MINOR.PATCH")
|
||||||
'v1.2.34'
|
'v1.2.34'
|
||||||
|
|
||||||
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='final')
|
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='final')
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR.MINOR.PATCH-RELEASENUM")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR.MINOR.PATCH-RELEASENUM")
|
||||||
'v1.0.0-final0'
|
'v1.0.0-final0'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR.MINOR.PATCH-RELEASE[NUM]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR.MINOR.PATCH-RELEASE[NUM]")
|
||||||
'v1.0.0-final'
|
'v1.0.0-final'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR.MINOR.PATCH-RELEASE")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR.MINOR.PATCH-RELEASE")
|
||||||
'v1.0.0-final'
|
'v1.0.0-final'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR.MINOR.PATCH[-RELEASE[NUM]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR.MINOR.PATCH[-RELEASE[NUM]]")
|
||||||
'v1.0.0'
|
'v1.0.0'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR.MINOR[.PATCH[-RELEASE[NUM]]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR.MINOR[.PATCH[-RELEASE[NUM]]]")
|
||||||
'v1.0'
|
'v1.0'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
||||||
'v1'
|
'v1'
|
||||||
|
|
||||||
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=1, tag='rc', num=0)
|
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=2, tag='rc', pytag='rc', num=0)
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH]]")
|
||||||
'v1.0.1'
|
'v1.0.2'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
||||||
'v1.0.1-rc'
|
'v1.0.2-rc'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH[-RELEASENUM]]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH[PYTAGNUM]]]")
|
||||||
'v1.0.1-rc0'
|
'v1.0.2rc0'
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH]]")
|
||||||
'v1.0.1'
|
'v1.0.2'
|
||||||
|
|
||||||
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='rc', num=2)
|
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='rc', num=2)
|
||||||
>>> format_version(vinfo_d, pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
>>> format_version(vinfo_d, raw_pattern="vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]")
|
||||||
'v1.0.0-rc2'
|
'v1.0.0-rc2'
|
||||||
|
|
||||||
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='rc', num=2)
|
>>> vinfo_d = vinfo_b._replace(major=1, minor=0, patch=0, tag='rc', num=2)
|
||||||
>>> format_version(vinfo_d, pattern='__version__ = "vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]"')
|
>>> format_version(vinfo_d, raw_pattern='__version__ = "vMAJOR[.MINOR[.PATCH[-RELEASE[NUM]]]]"')
|
||||||
'__version__ = "v1.0.0-rc2"'
|
'__version__ = "v1.0.0-rc2"'
|
||||||
"""
|
"""
|
||||||
part_values = _format_part_values(vinfo)
|
part_values = _format_part_values(vinfo)
|
||||||
seg_tree = _parse_segment_tree(raw_pattern)
|
seg_tree = _parse_segment_tree(raw_pattern)
|
||||||
version_str_parts = _format_segment_tree(seg_tree, part_values)
|
formatted_seg = _format_segment_tree(seg_tree, part_values)
|
||||||
return "".join(version_str_parts)
|
return formatted_seg.result
|
||||||
|
|
||||||
|
|
||||||
|
def _incr_numeric(
|
||||||
|
vinfo : version.V2VersionInfo,
|
||||||
|
major : bool,
|
||||||
|
minor : bool,
|
||||||
|
patch : bool,
|
||||||
|
release : typ.Optional[str],
|
||||||
|
release_num: bool,
|
||||||
|
) -> version.V2VersionInfo:
|
||||||
|
# prevent truncation of leading zeros
|
||||||
|
if int(vinfo.bid) < 1000:
|
||||||
|
vinfo = vinfo._replace(bid=str(int(vinfo.bid) + 1000))
|
||||||
|
|
||||||
|
vinfo = vinfo._replace(bid=lexid.next_id(vinfo.bid))
|
||||||
|
|
||||||
|
if major:
|
||||||
|
vinfo = vinfo._replace(major=vinfo.major + 1, minor=0, patch=0)
|
||||||
|
if minor:
|
||||||
|
vinfo = vinfo._replace(minor=vinfo.minor + 1, patch=0)
|
||||||
|
if patch:
|
||||||
|
vinfo = vinfo._replace(patch=vinfo.patch + 1)
|
||||||
|
if release_num:
|
||||||
|
vinfo = vinfo._replace(num=vinfo.num + 1)
|
||||||
|
if release:
|
||||||
|
if release != vinfo.tag:
|
||||||
|
vinfo = vinfo._replace(num=0)
|
||||||
|
vinfo = vinfo._replace(tag=release)
|
||||||
|
return vinfo
|
||||||
|
|
||||||
|
|
||||||
def incr(
|
def incr(
|
||||||
|
|
@ -520,7 +584,7 @@ def incr(
|
||||||
minor : bool = False,
|
minor : bool = False,
|
||||||
patch : bool = False,
|
patch : bool = False,
|
||||||
release_num: bool = False,
|
release_num: bool = False,
|
||||||
pin_date: bool = False,
|
pin_date : bool = False,
|
||||||
) -> typ.Optional[str]:
|
) -> typ.Optional[str]:
|
||||||
"""Increment version string.
|
"""Increment version string.
|
||||||
|
|
||||||
|
|
@ -540,24 +604,14 @@ def incr(
|
||||||
else:
|
else:
|
||||||
cur_vinfo = old_vinfo._replace(**cur_cinfo._asdict())
|
cur_vinfo = old_vinfo._replace(**cur_cinfo._asdict())
|
||||||
|
|
||||||
# prevent truncation of leading zeros
|
cur_vinfo = _incr_numeric(
|
||||||
if int(cur_vinfo.bid) < 1000:
|
cur_vinfo,
|
||||||
cur_vinfo = cur_vinfo._replace(bid=str(int(cur_vinfo.bid) + 1000))
|
major=major,
|
||||||
|
minor=minor,
|
||||||
cur_vinfo = cur_vinfo._replace(bid=lexid.next_id(cur_vinfo.bid))
|
patch=patch,
|
||||||
|
release=release,
|
||||||
if major:
|
release_num=release_num,
|
||||||
cur_vinfo = cur_vinfo._replace(major=cur_vinfo.major + 1, minor=0, patch=0)
|
)
|
||||||
if minor:
|
|
||||||
cur_vinfo = cur_vinfo._replace(minor=cur_vinfo.minor + 1, patch=0)
|
|
||||||
if patch:
|
|
||||||
cur_vinfo = cur_vinfo._replace(patch=cur_vinfo.patch + 1)
|
|
||||||
if release_num:
|
|
||||||
cur_vinfo = cur_vinfo._replace(num=cur_vinfo.num + 1)
|
|
||||||
if release:
|
|
||||||
if release != cur_vinfo.tag:
|
|
||||||
cur_vinfo = cur_vinfo._replace(num=0)
|
|
||||||
cur_vinfo = cur_vinfo._replace(tag=release)
|
|
||||||
|
|
||||||
# TODO (mb 2020-09-20): New Rollover Behaviour:
|
# TODO (mb 2020-09-20): New Rollover Behaviour:
|
||||||
# Reset major, minor, patch to zero if any part to the left of it is incremented
|
# Reset major, minor, patch to zero if any part to the left of it is incremented
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ mercurial, then the git terms are used. For example "fetch"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import shlex
|
||||||
import typing as typ
|
import typing as typ
|
||||||
import logging
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
@ -73,7 +74,8 @@ class VCSAPI:
|
||||||
logger.info(cmd_str)
|
logger.info(cmd_str)
|
||||||
else:
|
else:
|
||||||
logger.debug(cmd_str)
|
logger.debug(cmd_str)
|
||||||
output_data: bytes = sp.check_output(cmd_str.split(), env=env, stderr=sp.STDOUT)
|
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?
|
# TODO (mb 2018-11-15): Detect encoding of output? Use chardet?
|
||||||
_encoding = "utf-8"
|
_encoding = "utf-8"
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,10 @@ ZERO_VALUES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def is_zero_val(part: str, part_value: str) -> bool:
|
||||||
|
return part in ZERO_VALUES and part_value == ZERO_VALUES[part]
|
||||||
|
|
||||||
|
|
||||||
class PatternError(Exception):
|
class PatternError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
|
|
@ -13,6 +15,8 @@ import pytest
|
||||||
import pathlib2 as pl
|
import pathlib2 as pl
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
|
from pycalver import v1cli
|
||||||
|
from pycalver import v2cli
|
||||||
from pycalver import config
|
from pycalver import config
|
||||||
from pycalver import v1patterns
|
from pycalver import v1patterns
|
||||||
from pycalver.__main__ import cli
|
from pycalver.__main__ import cli
|
||||||
|
|
@ -21,6 +25,12 @@ from pycalver.__main__ import cli
|
||||||
# pylint:disable=protected-access ; allowed for test code
|
# pylint:disable=protected-access ; allowed for test code
|
||||||
|
|
||||||
|
|
||||||
|
README_TEXT_FIXTURE = """
|
||||||
|
Hello World v201701.1002-alpha !
|
||||||
|
aka. 201701.1002a0 !
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
SETUP_CFG_FIXTURE = """
|
SETUP_CFG_FIXTURE = """
|
||||||
[metadata]
|
[metadata]
|
||||||
license_file = LICENSE
|
license_file = LICENSE
|
||||||
|
|
@ -110,14 +120,16 @@ def test_incr_pin_date(runner):
|
||||||
|
|
||||||
|
|
||||||
def test_incr_semver(runner):
|
def test_incr_semver(runner):
|
||||||
semver_pattern = "{MAJOR}.{MINOR}.{PATCH}"
|
semver_patterns = [
|
||||||
|
"{semver}",
|
||||||
|
"{MAJOR}.{MINOR}.{PATCH}",
|
||||||
|
"MAJOR.MINOR.PATCH",
|
||||||
|
]
|
||||||
|
|
||||||
|
for semver_pattern in semver_patterns:
|
||||||
old_version = "0.1.0"
|
old_version = "0.1.0"
|
||||||
new_version = "0.1.1"
|
new_version = "0.1.1"
|
||||||
|
|
||||||
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, ['test', "-vv", "--patch", old_version, semver_pattern])
|
result = runner.invoke(cli, ['test', "-vv", "--patch", old_version, semver_pattern])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert f"Version: {new_version}\n" in result.output
|
assert f"Version: {new_version}\n" in result.output
|
||||||
|
|
@ -175,12 +187,8 @@ def test_incr_invalid(runner):
|
||||||
|
|
||||||
def _add_project_files(*files):
|
def _add_project_files(*files):
|
||||||
if "README.md" in files:
|
if "README.md" in files:
|
||||||
README_TEXT = """
|
|
||||||
Hello World v201701.1002-alpha !
|
|
||||||
aka. 201701.1002a0 !
|
|
||||||
"""
|
|
||||||
with pl.Path("README.md").open(mode="wt", encoding="utf-8") as fobj:
|
with pl.Path("README.md").open(mode="wt", encoding="utf-8") as fobj:
|
||||||
fobj.write(README_TEXT)
|
fobj.write(README_TEXT_FIXTURE)
|
||||||
|
|
||||||
if "setup.cfg" in files:
|
if "setup.cfg" in files:
|
||||||
with pl.Path("setup.cfg").open(mode="wt", encoding="utf-8") as fobj:
|
with pl.Path("setup.cfg").open(mode="wt", encoding="utf-8") as fobj:
|
||||||
|
|
@ -195,6 +203,22 @@ def _add_project_files(*files):
|
||||||
fobj.write(PYPROJECT_TOML_FIXTURE)
|
fobj.write(PYPROJECT_TOML_FIXTURE)
|
||||||
|
|
||||||
|
|
||||||
|
def _update_config_val(filename, **kwargs):
|
||||||
|
with io.open(filename, mode="r", encoding="utf-8") as fobj:
|
||||||
|
old_cfg_text = fobj.read()
|
||||||
|
|
||||||
|
new_cfg_text = old_cfg_text
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
replacement = "{} = {}\n".format(key, val)
|
||||||
|
if replacement not in new_cfg_text:
|
||||||
|
pattern = r"^{} = .*$".format(key)
|
||||||
|
new_cfg_text = re.sub(pattern, replacement, new_cfg_text, flags=re.MULTILINE)
|
||||||
|
assert old_cfg_text != new_cfg_text
|
||||||
|
|
||||||
|
with io.open(filename, mode="w", encoding="utf-8") as fobj:
|
||||||
|
fobj.write(new_cfg_text)
|
||||||
|
|
||||||
|
|
||||||
def test_nocfg(runner, caplog):
|
def test_nocfg(runner, caplog):
|
||||||
_add_project_files("README.md")
|
_add_project_files("README.md")
|
||||||
result = runner.invoke(cli, ['show', "-vv"])
|
result = runner.invoke(cli, ['show', "-vv"])
|
||||||
|
|
@ -491,7 +515,7 @@ setup.cfg =
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def test_bump_semver_warning(runner, caplog):
|
def test_v1_bump_semver_warning(runner, caplog):
|
||||||
_add_project_files("README.md")
|
_add_project_files("README.md")
|
||||||
|
|
||||||
with pl.Path("setup.cfg").open(mode="w") as fobj:
|
with pl.Path("setup.cfg").open(mode="w") as fobj:
|
||||||
|
|
@ -509,7 +533,7 @@ def test_bump_semver_warning(runner, caplog):
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
|
||||||
def test_bump_semver_diff(runner, caplog):
|
def test_v1_bump_semver_diff(runner, caplog):
|
||||||
_add_project_files("README.md")
|
_add_project_files("README.md")
|
||||||
|
|
||||||
with pl.Path("setup.cfg").open(mode="w") as fobj:
|
with pl.Path("setup.cfg").open(mode="w") as fobj:
|
||||||
|
|
@ -531,6 +555,48 @@ def test_bump_semver_diff(runner, caplog):
|
||||||
assert f"+current_version = \"{expected}\"" in out_lines
|
assert f"+current_version = \"{expected}\"" in out_lines
|
||||||
|
|
||||||
|
|
||||||
|
def test_v1_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='"{pycalver}"')
|
||||||
|
|
||||||
|
_, 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
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
assert '-current_version = "v202010.1001-alpha"' in diff_lines
|
||||||
|
assert '+current_version = "v202010.1003-beta"' in diff_lines
|
||||||
|
|
||||||
|
|
||||||
# def test_custom_commit_message(runner):
|
# def test_custom_commit_message(runner):
|
||||||
# # TODO (mb 2020-09-18):
|
# # TODO (mb 2020-09-18):
|
||||||
# assert False
|
# assert False
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,13 @@ def mk_buf(text):
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_raw_patterns_by_filepath(cfg):
|
||||||
|
return {
|
||||||
|
filepath: [pattern.raw_pattern for pattern in patterns]
|
||||||
|
for filepath, patterns in cfg.file_patterns.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_parse_toml_1():
|
def test_parse_toml_1():
|
||||||
buf = mk_buf(PYCALVER_TOML_FIXTURE_1)
|
buf = mk_buf(PYCALVER_TOML_FIXTURE_1)
|
||||||
|
|
||||||
|
|
@ -103,8 +110,10 @@ def test_parse_toml_1():
|
||||||
assert cfg.push is True
|
assert cfg.push is True
|
||||||
|
|
||||||
assert "pycalver.toml" in cfg.file_patterns
|
assert "pycalver.toml" in cfg.file_patterns
|
||||||
assert cfg.file_patterns["README.md" ] == ["{pycalver}", "{pep440_pycalver}"]
|
|
||||||
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{pycalver}"']
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath["README.md" ] == ["{pycalver}", "{pep440_pycalver}"]
|
||||||
|
assert raw_patterns_by_filepath["pycalver.toml"] == ['current_version = "{pycalver}"']
|
||||||
|
|
||||||
|
|
||||||
def test_parse_toml_2():
|
def test_parse_toml_2():
|
||||||
|
|
@ -120,8 +129,10 @@ def test_parse_toml_2():
|
||||||
assert cfg.push is False
|
assert cfg.push is False
|
||||||
|
|
||||||
assert "pycalver.toml" in cfg.file_patterns
|
assert "pycalver.toml" in cfg.file_patterns
|
||||||
assert cfg.file_patterns["README.md" ] == ["{semver}", "{semver}"]
|
|
||||||
assert cfg.file_patterns["pycalver.toml"] == ['current_version = "{semver}"']
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath["README.md" ] == ["{semver}", "{semver}"]
|
||||||
|
assert raw_patterns_by_filepath["pycalver.toml"] == ['current_version = "{semver}"']
|
||||||
|
|
||||||
|
|
||||||
def test_parse_v1_cfg():
|
def test_parse_v1_cfg():
|
||||||
|
|
@ -136,8 +147,10 @@ def test_parse_v1_cfg():
|
||||||
assert cfg.push is True
|
assert cfg.push is True
|
||||||
|
|
||||||
assert "setup.cfg" in cfg.file_patterns
|
assert "setup.cfg" in cfg.file_patterns
|
||||||
assert cfg.file_patterns["setup.py" ] == ["{pycalver}", "{pep440_pycalver}"]
|
|
||||||
assert cfg.file_patterns["setup.cfg"] == ['current_version = "{pycalver}"']
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath["setup.py" ] == ["{pycalver}", "{pep440_pycalver}"]
|
||||||
|
assert raw_patterns_by_filepath["setup.cfg"] == ['current_version = "{pycalver}"']
|
||||||
|
|
||||||
|
|
||||||
def test_parse_v2_cfg():
|
def test_parse_v2_cfg():
|
||||||
|
|
@ -153,10 +166,12 @@ def test_parse_v2_cfg():
|
||||||
|
|
||||||
assert "setup.py" in cfg.file_patterns
|
assert "setup.py" in cfg.file_patterns
|
||||||
assert "setup.cfg" in cfg.file_patterns
|
assert "setup.cfg" in cfg.file_patterns
|
||||||
|
|
||||||
# TODO (mb 2020-09-18):
|
# TODO (mb 2020-09-18):
|
||||||
# assert cfg.file_patterns["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"]
|
# raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
# assert cfg.file_patterns["setup.cfg" ] == ['current_version = "vYYYY0M.BUILD[-RELEASE]"']
|
# assert raw_patterns_by_filepath["setup.py" ] == ["vYYYY0M.BUILD[-RELEASE]", "YYYY0M.BLD[PYTAGNUM]"]
|
||||||
# assert cfg.file_patterns["src/project/*.py"] == ['Copyright (c) 2018-YYYY"']
|
# 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():
|
def test_parse_default_toml():
|
||||||
|
|
@ -188,6 +203,7 @@ def test_parse_default_cfg():
|
||||||
def test_parse_project_toml():
|
def test_parse_project_toml():
|
||||||
project_path = util.FIXTURES_DIR / "project_a"
|
project_path = util.FIXTURES_DIR / "project_a"
|
||||||
config_path = util.FIXTURES_DIR / "project_a" / "pycalver.toml"
|
config_path = util.FIXTURES_DIR / "project_a" / "pycalver.toml"
|
||||||
|
config_rel_path = "pycalver.toml"
|
||||||
|
|
||||||
with config_path.open() as fobj:
|
with config_path.open() as fobj:
|
||||||
config_data = fobj.read()
|
config_data = fobj.read()
|
||||||
|
|
@ -195,7 +211,7 @@ def test_parse_project_toml():
|
||||||
assert "v201710.0123-alpha" in config_data
|
assert "v201710.0123-alpha" in config_data
|
||||||
|
|
||||||
ctx = config.init_project_ctx(project_path)
|
ctx = config.init_project_ctx(project_path)
|
||||||
assert ctx == config.ProjectContext(project_path, config_path, "toml", None)
|
assert ctx == config.ProjectContext(project_path, config_path, config_rel_path, "toml", None)
|
||||||
|
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
|
|
||||||
|
|
@ -212,6 +228,7 @@ def test_parse_project_toml():
|
||||||
def test_parse_project_cfg():
|
def test_parse_project_cfg():
|
||||||
project_path = util.FIXTURES_DIR / "project_b"
|
project_path = util.FIXTURES_DIR / "project_b"
|
||||||
config_path = util.FIXTURES_DIR / "project_b" / "setup.cfg"
|
config_path = util.FIXTURES_DIR / "project_b" / "setup.cfg"
|
||||||
|
config_rel_path = "setup.cfg"
|
||||||
|
|
||||||
with config_path.open() as fobj:
|
with config_path.open() as fobj:
|
||||||
config_data = fobj.read()
|
config_data = fobj.read()
|
||||||
|
|
@ -219,7 +236,7 @@ def test_parse_project_cfg():
|
||||||
assert "v201307.0456-beta" in config_data
|
assert "v201307.0456-beta" in config_data
|
||||||
|
|
||||||
ctx = config.init_project_ctx(project_path)
|
ctx = config.init_project_ctx(project_path)
|
||||||
assert ctx == config.ProjectContext(project_path, config_path, 'cfg', None)
|
assert ctx == config.ProjectContext(project_path, config_path, config_rel_path, 'cfg', None)
|
||||||
|
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
|
|
||||||
|
|
@ -241,9 +258,10 @@ def test_parse_toml_file(tmpdir):
|
||||||
project_path = tmpdir.mkdir("minimal")
|
project_path = tmpdir.mkdir("minimal")
|
||||||
setup_cfg = project_path.join("pycalver.toml")
|
setup_cfg = project_path.join("pycalver.toml")
|
||||||
setup_cfg.write(PYCALVER_TOML_FIXTURE_1)
|
setup_cfg.write(PYCALVER_TOML_FIXTURE_1)
|
||||||
|
setup_cfg_rel_path = "pycalver.toml"
|
||||||
|
|
||||||
ctx = config.init_project_ctx(project_path)
|
ctx = config.init_project_ctx(project_path)
|
||||||
assert ctx == config.ProjectContext(project_path, setup_cfg, 'toml', None)
|
assert ctx == config.ProjectContext(project_path, setup_cfg, setup_cfg_rel_path, 'toml', None)
|
||||||
|
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
|
|
||||||
|
|
@ -253,7 +271,8 @@ def test_parse_toml_file(tmpdir):
|
||||||
assert cfg.commit is True
|
assert cfg.commit is True
|
||||||
assert cfg.push is True
|
assert cfg.push is True
|
||||||
|
|
||||||
assert cfg.file_patterns == {
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath == {
|
||||||
"README.md" : ["{pycalver}", "{pep440_pycalver}"],
|
"README.md" : ["{pycalver}", "{pep440_pycalver}"],
|
||||||
"pycalver.toml": ['current_version = "{pycalver}"'],
|
"pycalver.toml": ['current_version = "{pycalver}"'],
|
||||||
}
|
}
|
||||||
|
|
@ -262,10 +281,11 @@ def test_parse_toml_file(tmpdir):
|
||||||
def test_parse_default_pattern():
|
def test_parse_default_pattern():
|
||||||
project_path = util.FIXTURES_DIR / "project_c"
|
project_path = util.FIXTURES_DIR / "project_c"
|
||||||
config_path = util.FIXTURES_DIR / "project_c" / "pyproject.toml"
|
config_path = util.FIXTURES_DIR / "project_c" / "pyproject.toml"
|
||||||
|
config_rel_path = "pyproject.toml"
|
||||||
|
|
||||||
ctx = config.init_project_ctx(project_path)
|
ctx = config.init_project_ctx(project_path)
|
||||||
|
|
||||||
assert ctx == config.ProjectContext(project_path, config_path, "toml", None)
|
assert ctx == config.ProjectContext(project_path, config_path, config_rel_path, "toml", None)
|
||||||
|
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
|
|
||||||
|
|
@ -276,7 +296,8 @@ def test_parse_default_pattern():
|
||||||
assert cfg.tag is True
|
assert cfg.tag is True
|
||||||
assert cfg.push is True
|
assert cfg.push is True
|
||||||
|
|
||||||
assert cfg.file_patterns == {
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath == {
|
||||||
"pyproject.toml": [r'current_version = "v{year}q{quarter}.{build_no}"']
|
"pyproject.toml": [r'current_version = "v{year}q{quarter}.{build_no}"']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,9 +306,10 @@ def test_parse_cfg_file(tmpdir):
|
||||||
project_path = tmpdir.mkdir("minimal")
|
project_path = tmpdir.mkdir("minimal")
|
||||||
setup_cfg = project_path.join("setup.cfg")
|
setup_cfg = project_path.join("setup.cfg")
|
||||||
setup_cfg.write(SETUP_CFG_FIXTURE)
|
setup_cfg.write(SETUP_CFG_FIXTURE)
|
||||||
|
setup_cfg_rel_path = "setup.cfg"
|
||||||
|
|
||||||
ctx = config.init_project_ctx(project_path)
|
ctx = config.init_project_ctx(project_path)
|
||||||
assert ctx == config.ProjectContext(project_path, setup_cfg, 'cfg', None)
|
assert ctx == config.ProjectContext(project_path, setup_cfg, setup_cfg_rel_path, 'cfg', None)
|
||||||
|
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
|
|
||||||
|
|
@ -297,7 +319,8 @@ def test_parse_cfg_file(tmpdir):
|
||||||
assert cfg.commit is True
|
assert cfg.commit is True
|
||||||
assert cfg.push is True
|
assert cfg.push is True
|
||||||
|
|
||||||
assert cfg.file_patterns == {
|
raw_patterns_by_filepath = _parse_raw_patterns_by_filepath(cfg)
|
||||||
|
assert raw_patterns_by_filepath == {
|
||||||
"setup.py" : ["{pycalver}", "{pep440_pycalver}"],
|
"setup.py" : ["{pycalver}", "{pep440_pycalver}"],
|
||||||
"setup.cfg": ['current_version = "{pycalver}"'],
|
"setup.cfg": ['current_version = "{pycalver}"'],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from __future__ import print_function
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import re
|
||||||
import copy
|
import copy
|
||||||
from test import util
|
from test import util
|
||||||
|
|
||||||
|
|
@ -13,35 +14,77 @@ from pycalver import v1rewrite
|
||||||
from pycalver import v1version
|
from pycalver import v1version
|
||||||
from pycalver import v2rewrite
|
from pycalver import v2rewrite
|
||||||
from pycalver import v2version
|
from pycalver import v2version
|
||||||
|
from pycalver import v1patterns
|
||||||
|
from pycalver import v2patterns
|
||||||
|
|
||||||
# pylint:disable=protected-access ; allowed for test code
|
# pylint:disable=protected-access ; allowed for test code
|
||||||
|
|
||||||
|
|
||||||
|
# Fix for Python<3.7
|
||||||
|
# https://stackoverflow.com/a/56935186/62997
|
||||||
|
copy._deepcopy_dispatch[type(re.compile(''))] = lambda r, _: r
|
||||||
|
|
||||||
|
|
||||||
REWRITE_FIXTURE = """
|
REWRITE_FIXTURE = """
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
__version__ = "v201809.0002-beta"
|
__version__ = "v201809.0002-beta"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def test_rewrite_lines():
|
def test_v1_rewrite_lines_basic():
|
||||||
old_lines = REWRITE_FIXTURE.splitlines()
|
pattern = v1patterns.compile_pattern("{pycalver}", '__version__ = "{pycalver}"')
|
||||||
patterns = ['__version__ = "{pycalver}"']
|
|
||||||
new_vinfo = v1version.parse_version_info("v201911.0003")
|
new_vinfo = v1version.parse_version_info("v201911.0003")
|
||||||
new_lines = v1rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
|
||||||
|
old_lines = REWRITE_FIXTURE.splitlines()
|
||||||
|
new_lines = v1rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "v201911.0003" not in "\n".join(old_lines)
|
assert "v201911.0003" not in "\n".join(old_lines)
|
||||||
assert "v201911.0003" in "\n".join(new_lines)
|
assert "v201911.0003" in "\n".join(new_lines)
|
||||||
|
|
||||||
|
|
||||||
def test_rewrite_final():
|
def test_v1_rewrite_lines():
|
||||||
|
version_pattern = "{pycalver}"
|
||||||
|
new_vinfo = v1version.parse_version_info("v201811.0123-beta", version_pattern)
|
||||||
|
patterns = [v1patterns.compile_pattern(version_pattern, '__version__ = "{pycalver}"')]
|
||||||
|
lines = v1rewrite.rewrite_lines(patterns, new_vinfo, ['__version__ = "v201809.0002-beta"'])
|
||||||
|
assert lines == ['__version__ = "v201811.0123-beta"']
|
||||||
|
|
||||||
|
patterns = [v1patterns.compile_pattern(version_pattern, '__version__ = "{pep440_version}"')]
|
||||||
|
lines = v1rewrite.rewrite_lines(patterns, new_vinfo, ['__version__ = "201809.2b0"'])
|
||||||
|
assert lines == ['__version__ = "201811.123b0"']
|
||||||
|
|
||||||
|
|
||||||
|
def test_v2_rewrite_lines():
|
||||||
|
version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
||||||
|
new_vinfo = v2version.parse_version_info("v201811.0123-beta", version_pattern)
|
||||||
|
patterns = [v2patterns.compile_pattern(version_pattern, '__version__ = "{version}"')]
|
||||||
|
lines = v2rewrite.rewrite_lines(patterns, new_vinfo, ['__version__ = "v201809.0002-alpha" '])
|
||||||
|
assert lines == ['__version__ = "v201811.0123-beta" ']
|
||||||
|
|
||||||
|
lines = v2rewrite.rewrite_lines(
|
||||||
|
patterns, new_vinfo, ['__version__ = "v201809.0002-alpha" # comment']
|
||||||
|
)
|
||||||
|
assert lines == ['__version__ = "v201811.0123-beta" # comment']
|
||||||
|
|
||||||
|
patterns = [v2patterns.compile_pattern(version_pattern, '__version__ = "YYYY0M.BLD[PYTAGNUM]"')]
|
||||||
|
old_lines = ['__version__ = "201809.2a0"']
|
||||||
|
lines = v2rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
||||||
|
assert lines == ['__version__ = "201811.123b0"']
|
||||||
|
|
||||||
|
|
||||||
|
def test_v1_rewrite_final():
|
||||||
# Patterns written with {release_tag} placeholder preserve
|
# Patterns written with {release_tag} placeholder preserve
|
||||||
# the release tag even if the new version is -final
|
# the release tag even if the new version is -final
|
||||||
|
|
||||||
old_lines = REWRITE_FIXTURE.splitlines()
|
pattern = v1patterns.compile_pattern(
|
||||||
patterns = ['__version__ = "v{year}{month}.{build_no}-{release_tag}"']
|
"v{year}{month}.{build_no}-{release_tag}",
|
||||||
|
'__version__ = "v{year}{month}.{build_no}-{release_tag}"',
|
||||||
|
)
|
||||||
new_vinfo = v1version.parse_version_info("v201911.0003")
|
new_vinfo = v1version.parse_version_info("v201911.0003")
|
||||||
new_lines = v1rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
|
||||||
|
old_lines = REWRITE_FIXTURE.splitlines()
|
||||||
|
new_lines = v1rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "v201911.0003" not in "\n".join(old_lines)
|
assert "v201911.0003" not in "\n".join(old_lines)
|
||||||
|
|
@ -93,14 +136,19 @@ def test_error_bad_path():
|
||||||
assert "setup.py" in str(ex)
|
assert "setup.py" in str(ex)
|
||||||
|
|
||||||
|
|
||||||
def test_error_bad_pattern():
|
def test_v1_error_bad_pattern():
|
||||||
with util.Project(project="b") as project:
|
with util.Project(project="b") as project:
|
||||||
ctx = config.init_project_ctx(project.dir)
|
ctx = config.init_project_ctx(project.dir)
|
||||||
cfg = config.parse(ctx)
|
cfg = config.parse(ctx)
|
||||||
assert cfg
|
assert cfg
|
||||||
|
|
||||||
patterns = copy.deepcopy(cfg.file_patterns)
|
patterns = copy.deepcopy(cfg.file_patterns)
|
||||||
patterns["setup.py"] = patterns["setup.py"][0] + "invalid"
|
original_pattern = patterns["setup.py"][0]
|
||||||
|
invalid_pattern = v1patterns.compile_pattern(
|
||||||
|
original_pattern.version_pattern,
|
||||||
|
original_pattern.raw_pattern + ".invalid",
|
||||||
|
)
|
||||||
|
patterns["setup.py"] = [invalid_pattern]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_vinfo = v1version.parse_version_info("v201808.0233")
|
old_vinfo = v1version.parse_version_info("v201808.0233")
|
||||||
|
|
@ -118,45 +166,163 @@ __version__ = "2018.0002-beta"
|
||||||
|
|
||||||
|
|
||||||
def test_v1_optional_release():
|
def test_v1_optional_release():
|
||||||
old_lines = OPTIONAL_RELEASE_FIXTURE.splitlines()
|
version_pattern = "{year}.{build_no}{release}"
|
||||||
pattern = "{year}.{build_no}{release}"
|
new_vinfo = v1version.parse_version_info("2019.0003", version_pattern)
|
||||||
patterns = ['__version__ = "{year}.{build_no}{release}"']
|
|
||||||
|
|
||||||
new_vinfo = v1version.parse_version_info("2019.0003", pattern)
|
raw_pattern = '__version__ = "{year}.{build_no}{release}"'
|
||||||
new_lines = v1rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
pattern = v1patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
|
||||||
|
old_lines = OPTIONAL_RELEASE_FIXTURE.splitlines()
|
||||||
|
new_lines = v1rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "2019.0003" not in "\n".join(old_lines)
|
assert "2019.0003" not in "\n".join(old_lines)
|
||||||
new_text = "\n".join(new_lines)
|
assert "2019.0003" in "\n".join(new_lines)
|
||||||
assert "2019.0003" in new_text
|
assert '__version__ = "2019.0003"' in "\n".join(new_lines)
|
||||||
|
|
||||||
new_vinfo = v1version.parse_version_info("2019.0004-beta", pattern)
|
new_vinfo = v1version.parse_version_info("2019.0004-beta", version_pattern)
|
||||||
new_lines = v1rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
new_lines = v1rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
# make sure optional release tag is added back on
|
# make sure optional release tag is added back on
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "2019.0004-beta" not in "\n".join(old_lines)
|
assert "2019.0004-beta" not in "\n".join(old_lines)
|
||||||
assert "2019.0004-beta" in "\n".join(new_lines)
|
assert "2019.0004-beta" in "\n".join(new_lines)
|
||||||
|
assert '__version__ = "2019.0004-beta"' in "\n".join(new_lines)
|
||||||
|
|
||||||
|
|
||||||
def test_v2_optional_release():
|
def test_v2_optional_release():
|
||||||
old_lines = OPTIONAL_RELEASE_FIXTURE.splitlines()
|
version_pattern = "YYYY.BUILD[-RELEASE]"
|
||||||
pattern = "YYYY.BUILD[-RELEASE]"
|
new_vinfo = v2version.parse_version_info("2019.0003", version_pattern)
|
||||||
patterns = ['__version__ = "YYYY.BUILD[-RELEASE]"']
|
|
||||||
|
|
||||||
new_vinfo = v2version.parse_version_info("2019.0003", pattern)
|
raw_pattern = '__version__ = "YYYY.BUILD[-RELEASE]"'
|
||||||
new_lines = v2rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
pattern = v2patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
|
||||||
|
old_lines = OPTIONAL_RELEASE_FIXTURE.splitlines()
|
||||||
|
new_lines = v2rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "2019.0003" not in "\n".join(old_lines)
|
assert "2019.0003" not in "\n".join(old_lines)
|
||||||
new_text = "\n".join(new_lines)
|
assert "2019.0003" in "\n".join(new_lines)
|
||||||
assert "2019.0003" in new_text
|
assert '__version__ = "2019.0003"' in "\n".join(new_lines)
|
||||||
assert '__version__ = "2019.0003"' in new_text
|
|
||||||
|
|
||||||
new_vinfo = v2version.parse_version_info("2019.0004-beta", pattern)
|
new_vinfo = v2version.parse_version_info("2019.0004-beta", version_pattern)
|
||||||
new_lines = v2rewrite.rewrite_lines(patterns, new_vinfo, old_lines)
|
new_lines = v2rewrite.rewrite_lines([pattern], new_vinfo, old_lines)
|
||||||
|
|
||||||
# make sure optional release tag is added back on
|
# make sure optional release tag is added back on
|
||||||
assert len(new_lines) == len(old_lines)
|
assert len(new_lines) == len(old_lines)
|
||||||
assert "2019.0004-beta" not in "\n".join(old_lines)
|
assert "2019.0004-beta" not in "\n".join(old_lines)
|
||||||
assert "2019.0004-beta" in "\n".join(new_lines)
|
assert "2019.0004-beta" in "\n".join(new_lines)
|
||||||
|
assert '__version__ = "2019.0004-beta"' in "\n".join(new_lines)
|
||||||
|
|
||||||
|
|
||||||
|
def test_v1_iter_rewritten():
|
||||||
|
version_pattern = "{pycalver}"
|
||||||
|
new_vinfo = v1version.parse_version_info("v201809.0123")
|
||||||
|
|
||||||
|
file_patterns = {
|
||||||
|
"src/pycalver/__init__.py": [
|
||||||
|
v1patterns.compile_pattern(version_pattern, '__version__ = "{pycalver}"'),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
rewritten_datas = v1rewrite.iter_rewritten(file_patterns, new_vinfo)
|
||||||
|
rfd = list(rewritten_datas)[0]
|
||||||
|
expected = [
|
||||||
|
"# This file is part of the pycalver project",
|
||||||
|
"# https://github.com/mbarkhau/pycalver",
|
||||||
|
"#",
|
||||||
|
"# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License",
|
||||||
|
"# SPDX-License-Identifier: MIT",
|
||||||
|
'"""PyCalVer: CalVer for Python Packages."""',
|
||||||
|
'',
|
||||||
|
'__version__ = "v201809.0123"',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
assert rfd.new_lines == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_v2_iter_rewritten():
|
||||||
|
version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
||||||
|
new_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
||||||
|
|
||||||
|
file_patterns = {
|
||||||
|
"src/pycalver/__init__.py": [
|
||||||
|
v2patterns.compile_pattern(version_pattern, '__version__ = "vYYYY0M.BUILD[-RELEASE]"'),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rewritten_datas = v2rewrite.iter_rewritten(file_patterns, new_vinfo)
|
||||||
|
rfd = list(rewritten_datas)[0]
|
||||||
|
expected = [
|
||||||
|
"# This file is part of the pycalver project",
|
||||||
|
"# https://github.com/mbarkhau/pycalver",
|
||||||
|
"#",
|
||||||
|
"# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License",
|
||||||
|
"# SPDX-License-Identifier: MIT",
|
||||||
|
'"""PyCalVer: CalVer for Python Packages."""',
|
||||||
|
'',
|
||||||
|
'__version__ = "v201809.0123"',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
assert rfd.new_lines == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_v1_diff():
|
||||||
|
version_pattern = "{pycalver}"
|
||||||
|
raw_pattern = '__version__ = "{pycalver}"'
|
||||||
|
pattern = v1patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
file_patterns = {"src/pycalver/__init__.py": [pattern]}
|
||||||
|
|
||||||
|
old_vinfo = v1version.parse_version_info("v201809.0123")
|
||||||
|
new_vinfo = v1version.parse_version_info("v201910.1124")
|
||||||
|
|
||||||
|
diff_str = v1rewrite.diff(old_vinfo, new_vinfo, file_patterns)
|
||||||
|
lines = diff_str.split("\n")
|
||||||
|
|
||||||
|
assert lines[:2] == ["--- src/pycalver/__init__.py", "+++ src/pycalver/__init__.py"]
|
||||||
|
|
||||||
|
assert lines[6].startswith('-__version__ = "v20')
|
||||||
|
assert lines[7].startswith('+__version__ = "v20')
|
||||||
|
|
||||||
|
assert not lines[6].startswith('-__version__ = "v201809.0123"')
|
||||||
|
|
||||||
|
assert lines[7] == '+__version__ = "v201910.1124"'
|
||||||
|
|
||||||
|
raw_pattern = "Copyright (c) 2018-{year}"
|
||||||
|
pattern = v1patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
file_patterns = {'LICENSE': [pattern]}
|
||||||
|
diff_str = v1rewrite.diff(old_vinfo, new_vinfo, file_patterns)
|
||||||
|
|
||||||
|
lines = diff_str.split("\n")
|
||||||
|
assert lines[3].startswith("-MIT License Copyright (c) 2018-20")
|
||||||
|
assert lines[4].startswith("+MIT License Copyright (c) 2018-2019")
|
||||||
|
|
||||||
|
|
||||||
|
def test_v2_diff():
|
||||||
|
version_pattern = "vYYYY0M.BUILD[-RELEASE]"
|
||||||
|
raw_pattern = '__version__ = "vYYYY0M.BUILD[-RELEASE]"'
|
||||||
|
pattern = v2patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
file_patterns = {"src/pycalver/__init__.py": [pattern]}
|
||||||
|
|
||||||
|
old_vinfo = v2version.parse_version_info("v201809.0123", version_pattern)
|
||||||
|
new_vinfo = v2version.parse_version_info("v201910.1124", version_pattern)
|
||||||
|
|
||||||
|
diff_str = v2rewrite.diff(old_vinfo, new_vinfo, file_patterns)
|
||||||
|
lines = diff_str.split("\n")
|
||||||
|
|
||||||
|
assert lines[:2] == ["--- src/pycalver/__init__.py", "+++ src/pycalver/__init__.py"]
|
||||||
|
|
||||||
|
assert lines[6].startswith('-__version__ = "v20')
|
||||||
|
assert lines[7].startswith('+__version__ = "v20')
|
||||||
|
|
||||||
|
assert not lines[6].startswith('-__version__ = "v201809.0123"')
|
||||||
|
|
||||||
|
assert lines[7] == '+__version__ = "v201910.1124"'
|
||||||
|
|
||||||
|
raw_pattern = "Copyright (c) 2018-YYYY"
|
||||||
|
pattern = v2patterns.compile_pattern(version_pattern, raw_pattern)
|
||||||
|
file_patterns = {'LICENSE': [pattern]}
|
||||||
|
diff_str = v2rewrite.diff(old_vinfo, new_vinfo, file_patterns)
|
||||||
|
|
||||||
|
lines = diff_str.split("\n")
|
||||||
|
assert lines[3].startswith("-MIT License Copyright (c) 2018-20")
|
||||||
|
assert lines[4].startswith("+MIT License Copyright (c) 2018-2019")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue