mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 14:30:09 +01:00
wip: add v2 module placeholders
This commit is contained in:
parent
7962a7cb9f
commit
669e8944e9
27 changed files with 1361 additions and 393 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""PyCalVer: CalVer for Python Packages."""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
__main__ module for PyCalVer.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CLI module for PyCalVer.
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@ def _parse_config(raw_cfg: RawConfig) -> Config:
|
|||
version_str: str = raw_cfg['current_version']
|
||||
version_str = raw_cfg['current_version'] = version_str.strip("'\" ")
|
||||
|
||||
# TODO (mb 2020-09-06): new style pattern by default
|
||||
# version_pattern: str = raw_cfg.get('version_pattern', "vYYYY0M.BUILD[-TAG]")
|
||||
version_pattern: str = raw_cfg.get('version_pattern', "{pycalver}")
|
||||
version_pattern = raw_cfg['version_pattern'] = version_pattern.strip("'\" ")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,169 +0,0 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""A scheme for lexically ordered numerical ids.
|
||||
|
||||
Throughout the sequence this expression remains true, whether you
|
||||
are dealing with integers or strings:
|
||||
|
||||
older_id < newer_id
|
||||
|
||||
The left most character/digit is only used to maintain lexical
|
||||
order, so that the position in the sequence is maintained in the
|
||||
remaining digits.
|
||||
|
||||
sequence_pos = int(idval[1:], 10)
|
||||
|
||||
lexical sequence_pos
|
||||
0 0
|
||||
11 1
|
||||
12 2
|
||||
...
|
||||
19 9
|
||||
220 20
|
||||
221 21
|
||||
...
|
||||
298 98
|
||||
299 99
|
||||
3300 300
|
||||
3301 301
|
||||
...
|
||||
3998 998
|
||||
3999 999
|
||||
44000 4000
|
||||
44001 4001
|
||||
...
|
||||
899999998 99999998
|
||||
899999999 99999999
|
||||
9900000000 900000000
|
||||
9900000001 900000001
|
||||
...
|
||||
9999999998 999999998
|
||||
9999999999 999999999 # maximum value
|
||||
|
||||
You can add leading zeros to delay the expansion and/or increase
|
||||
the maximum possible value.
|
||||
|
||||
lexical sequence_pos
|
||||
0001 1
|
||||
0002 2
|
||||
0003 3
|
||||
...
|
||||
0999 999
|
||||
11000 1000
|
||||
11001 1001
|
||||
11002 1002
|
||||
...
|
||||
19998 9998
|
||||
19999 9999
|
||||
220000 20000
|
||||
220001 20001
|
||||
...
|
||||
899999999998 99999999998
|
||||
899999999999 99999999999
|
||||
9900000000000 900000000000
|
||||
9900000000001 900000000001
|
||||
...
|
||||
9999999999998 999999999998
|
||||
9999999999999 999999999999 # maximum value
|
||||
|
||||
This scheme is useful when you just want an ordered sequence of
|
||||
numbers, but the numbers don't have any particular meaning or
|
||||
arithmetical relation. The only relation they have to each other
|
||||
is that numbers generated later in the sequence are greater than
|
||||
ones generated earlier.
|
||||
"""
|
||||
|
||||
|
||||
MINIMUM_ID = "0"
|
||||
|
||||
|
||||
def next_id(prev_id: str) -> str:
|
||||
"""Generate next lexical id.
|
||||
|
||||
Increments by one and adds padding if required.
|
||||
|
||||
>>> next_id("0098")
|
||||
'0099'
|
||||
>>> next_id("0099")
|
||||
'0100'
|
||||
>>> next_id("0999")
|
||||
'11000'
|
||||
>>> next_id("11000")
|
||||
'11001'
|
||||
"""
|
||||
|
||||
num_digits = len(prev_id)
|
||||
|
||||
if prev_id.count("9") == num_digits:
|
||||
raise OverflowError("max lexical version reached: " + prev_id)
|
||||
|
||||
_prev_id_val = int(prev_id, 10)
|
||||
_maybe_next_id_val = int(_prev_id_val) + 1
|
||||
_maybe_next_id_str = f"{_maybe_next_id_val:0{num_digits}}"
|
||||
|
||||
_is_padding_ok = prev_id[0] == _maybe_next_id_str[0]
|
||||
_next_id_str: str
|
||||
|
||||
if _is_padding_ok:
|
||||
_next_id_str = _maybe_next_id_str
|
||||
else:
|
||||
_next_id_str = str(_maybe_next_id_val * 11)
|
||||
return _next_id_str
|
||||
|
||||
|
||||
def ord_val(lex_id: str) -> int:
|
||||
"""Parse the ordinal value of a lexical id.
|
||||
|
||||
The ordinal value is the position in the sequence,
|
||||
from repeated calls to next_id.
|
||||
|
||||
>>> ord_val("0098")
|
||||
98
|
||||
>>> ord_val("0099")
|
||||
99
|
||||
>>> ord_val("0100")
|
||||
100
|
||||
>>> ord_val("11000")
|
||||
1000
|
||||
>>> ord_val("11001")
|
||||
1001
|
||||
"""
|
||||
if len(lex_id) == 1:
|
||||
return int(lex_id, 10)
|
||||
else:
|
||||
return int(lex_id[1:], 10)
|
||||
|
||||
|
||||
def _main() -> None:
|
||||
_curr_id = "01"
|
||||
print(f"{'lexical':<13} {'numerical':>12}")
|
||||
|
||||
while True:
|
||||
print(f"{_curr_id:<13} {ord_val(_curr_id):>12}")
|
||||
_next_id = next_id(_curr_id)
|
||||
|
||||
if _next_id.count("9") == len(_next_id):
|
||||
# all nines, we're done
|
||||
print(f"{_next_id:<13} {ord_val(_next_id):>12}")
|
||||
break
|
||||
|
||||
if _next_id[0] != _curr_id[0] and len(_curr_id) > 1:
|
||||
print(f"{_next_id:<13} {ord_val(_next_id):>12}")
|
||||
_next_id = next_id(_next_id)
|
||||
print(f"{_next_id:<13} {ord_val(_next_id):>12}")
|
||||
_next_id = next_id(_next_id)
|
||||
|
||||
print("...")
|
||||
|
||||
# skip ahead
|
||||
_next_id = _next_id[:1] + "9" * (len(_next_id) - 2) + "8"
|
||||
|
||||
_curr_id = _next_id
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_main()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Parse PyCalVer strings from files."""
|
||||
|
||||
|
|
@ -22,6 +22,8 @@ class PatternMatch(typ.NamedTuple):
|
|||
|
||||
PatternMatches = typ.Iterable[PatternMatch]
|
||||
|
||||
RegexpPatterns = typ.List[typ.Pattern[str]]
|
||||
|
||||
|
||||
def _iter_for_pattern(lines: typ.List[str], pattern: str) -> PatternMatches:
|
||||
# The pattern is escaped, so that everything besides the format
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Compose Regular Expressions from Patterns.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Rewrite files, updating occurences of version strings."""
|
||||
|
||||
|
|
@ -13,8 +13,9 @@ import logging
|
|||
|
||||
import pathlib2 as pl
|
||||
|
||||
from . import parse
|
||||
from . import config
|
||||
from pycalver import parse
|
||||
from pycalver import config
|
||||
|
||||
from . import version
|
||||
from . import patterns
|
||||
|
||||
|
|
@ -53,6 +54,28 @@ class NoPatternMatch(Exception):
|
|||
"""
|
||||
|
||||
|
||||
class RewrittenFileData(typ.NamedTuple):
|
||||
"""Container for line-wise content of rewritten files."""
|
||||
|
||||
path : str
|
||||
line_sep : str
|
||||
old_lines: typ.List[str]
|
||||
new_lines: typ.List[str]
|
||||
|
||||
|
||||
def iter_file_paths(
|
||||
file_patterns: config.PatternsByGlob,
|
||||
) -> typ.Iterable[typ.Tuple[pl.Path, config.Patterns]]:
|
||||
for globstr, pattern_strs in file_patterns.items():
|
||||
file_paths = glob.glob(globstr)
|
||||
if not any(file_paths):
|
||||
errmsg = f"No files found for path/glob '{globstr}'"
|
||||
raise IOError(errmsg)
|
||||
for file_path_str in file_paths:
|
||||
file_path = pl.Path(file_path_str)
|
||||
yield (file_path, pattern_strs)
|
||||
|
||||
|
||||
def rewrite_lines(
|
||||
pattern_strs: typ.List[str], new_vinfo: version.VersionInfo, old_lines: typ.List[str]
|
||||
) -> typ.List[str]:
|
||||
|
|
@ -88,15 +111,6 @@ def rewrite_lines(
|
|||
return new_lines
|
||||
|
||||
|
||||
class RewrittenFileData(typ.NamedTuple):
|
||||
"""Container for line-wise content of rewritten files."""
|
||||
|
||||
path : str
|
||||
line_sep : str
|
||||
old_lines: typ.List[str]
|
||||
new_lines: typ.List[str]
|
||||
|
||||
|
||||
def rfd_from_content(
|
||||
pattern_strs: typ.List[str], new_vinfo: version.VersionInfo, content: str
|
||||
) -> RewrittenFileData:
|
||||
|
|
@ -122,19 +136,6 @@ def rfd_from_content(
|
|||
return RewrittenFileData("<path>", line_sep, old_lines, new_lines)
|
||||
|
||||
|
||||
def _iter_file_paths(
|
||||
file_patterns: config.PatternsByGlob,
|
||||
) -> typ.Iterable[typ.Tuple[pl.Path, config.Patterns]]:
|
||||
for globstr, pattern_strs in file_patterns.items():
|
||||
file_paths = glob.glob(globstr)
|
||||
if not any(file_paths):
|
||||
errmsg = f"No files found for path/glob '{globstr}'"
|
||||
raise IOError(errmsg)
|
||||
for file_path_str in file_paths:
|
||||
file_path = pl.Path(file_path_str)
|
||||
yield (file_path, pattern_strs)
|
||||
|
||||
|
||||
def iter_rewritten(
|
||||
file_patterns: config.PatternsByGlob, new_vinfo: version.VersionInfo
|
||||
) -> typ.Iterable[RewrittenFileData]:
|
||||
|
|
@ -144,23 +145,23 @@ def iter_rewritten(
|
|||
>>> new_vinfo = version.parse_version_info("v201809.0123")
|
||||
>>> rewritten_datas = iter_rewritten(file_patterns, new_vinfo)
|
||||
>>> rfd = list(rewritten_datas)[0]
|
||||
>>> assert rfd.new_lines == [
|
||||
>>> expected = [
|
||||
... '# This file is part of the pycalver project',
|
||||
... '# https://gitlab.com/mbarkhau/pycalver',
|
||||
... '# https://github.com/mbarkhau/pycalver',
|
||||
... '#',
|
||||
... '# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License',
|
||||
... '# 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[:len(expected)] == expected
|
||||
'''
|
||||
|
||||
fobj: typ.IO[str]
|
||||
|
||||
for file_path, pattern_strs in _iter_file_paths(file_patterns):
|
||||
for file_path, pattern_strs in iter_file_paths(file_patterns):
|
||||
with file_path.open(mode="rt", encoding="utf-8") as fobj:
|
||||
content = fobj.read()
|
||||
|
||||
|
|
@ -204,7 +205,7 @@ def diff(new_vinfo: version.VersionInfo, file_patterns: config.PatternsByGlob) -
|
|||
full_diff = ""
|
||||
fobj: typ.IO[str]
|
||||
|
||||
for file_path, pattern_strs in sorted(_iter_file_paths(file_patterns)):
|
||||
for file_path, pattern_strs in sorted(iter_file_paths(file_patterns)):
|
||||
with file_path.open(mode="rt", encoding="utf-8") as fobj:
|
||||
content = fobj.read()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# pycalver/vcs.py (this file) is based on code from the
|
||||
|
|
@ -15,11 +15,14 @@ mercurial, then the git terms are used. For example "fetch"
|
|||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import typing as typ
|
||||
import logging
|
||||
import tempfile
|
||||
import subprocess as sp
|
||||
|
||||
from pycalver import config
|
||||
|
||||
logger = logging.getLogger("pycalver.vcs")
|
||||
|
||||
|
||||
|
|
@ -179,3 +182,57 @@ def get_vcs_api() -> VCSAPI:
|
|||
return vcs_api
|
||||
|
||||
raise OSError("No such directory .git/ or .hg/ ")
|
||||
|
||||
|
||||
# cli helper methods
|
||||
|
||||
|
||||
def assert_not_dirty(vcs_api: VCSAPI, filepaths: typ.Set[str], allow_dirty: bool) -> None:
|
||||
dirty_files = vcs_api.status(required_files=filepaths)
|
||||
|
||||
if dirty_files:
|
||||
logger.warning(f"{vcs_api.name} working directory is not clean. Uncomitted file(s):")
|
||||
for dirty_file in dirty_files:
|
||||
logger.warning(" " + dirty_file)
|
||||
|
||||
if not allow_dirty and dirty_files:
|
||||
sys.exit(1)
|
||||
|
||||
dirty_pattern_files = set(dirty_files) & filepaths
|
||||
if dirty_pattern_files:
|
||||
logger.error("Not commiting when pattern files are dirty:")
|
||||
for dirty_file in dirty_pattern_files:
|
||||
logger.warning(" " + dirty_file)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def commit(
|
||||
cfg : config.Config,
|
||||
vcs_api : VCSAPI,
|
||||
filepaths : typ.Set[str],
|
||||
new_version : str,
|
||||
commit_message: str,
|
||||
) -> None:
|
||||
for filepath in filepaths:
|
||||
vcs_api.add(filepath)
|
||||
|
||||
vcs_api.commit(commit_message)
|
||||
|
||||
if cfg.commit and cfg.tag:
|
||||
vcs_api.tag(new_version)
|
||||
|
||||
if cfg.commit and cfg.tag and cfg.push:
|
||||
vcs_api.push(new_version)
|
||||
|
||||
|
||||
def get_tags(fetch: bool) -> typ.List[str]:
|
||||
try:
|
||||
vcs_api = get_vcs_api()
|
||||
logger.debug(f"vcs found: {vcs_api.name}")
|
||||
if fetch:
|
||||
logger.info("fetching tags from remote (to turn off use: -n / --no-fetch)")
|
||||
vcs_api.fetch()
|
||||
return vcs_api.ls_tags()
|
||||
except OSError:
|
||||
logger.debug("No vcs found")
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
# https://github.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# Copyright (c) 2018-2020 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Functions related to version string manipulation."""
|
||||
|
||||
|
|
@ -9,9 +9,9 @@ import typing as typ
|
|||
import logging
|
||||
import datetime as dt
|
||||
|
||||
import lexid
|
||||
import pkg_resources
|
||||
|
||||
from . import lex_id
|
||||
from . import patterns
|
||||
|
||||
logger = logging.getLogger("pycalver.version")
|
||||
|
|
@ -482,7 +482,7 @@ def incr(
|
|||
else:
|
||||
logger.warning(f"Version appears to be from the future '{old_version}'")
|
||||
|
||||
cur_vinfo = cur_vinfo._replace(bid=lex_id.next_id(cur_vinfo.bid))
|
||||
cur_vinfo = cur_vinfo._replace(bid=lexid.next_id(cur_vinfo.bid))
|
||||
|
||||
if major:
|
||||
cur_vinfo = cur_vinfo._replace(major=cur_vinfo.major + 1, minor=0, patch=0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue