diff --git a/bumpversion/scm.py b/bumpversion/scm.py index f5a2272b..fa4496df 100644 --- a/bumpversion/scm.py +++ b/bumpversion/scm.py @@ -25,7 +25,7 @@ class SCMInfo: tool: Optional[Type["SourceCodeManager"]] = None commit_sha: Optional[str] = None - distance_to_latest_tag: Optional[int] = None + distance_to_latest_tag: int = 0 current_version: Optional[str] = None branch_name: Optional[str] = None short_branch_name: Optional[str] = None diff --git a/bumpversion/utils.py b/bumpversion/utils.py index ea9b68d4..c6d30cc5 100644 --- a/bumpversion/utils.py +++ b/bumpversion/utils.py @@ -1,4 +1,5 @@ """General utilities.""" +import datetime import string from collections import ChainMap from dataclasses import asdict @@ -6,6 +7,7 @@ if TYPE_CHECKING: # pragma: no-coverage from bumpversion.config import Config + from bumpversion.scm import SCMInfo from bumpversion.version_part import Version @@ -51,19 +53,29 @@ def labels_for_format(serialize_format: str) -> List[str]: return [item[1] for item in string.Formatter().parse(serialize_format) if item[1]] -def get_context( - config: "Config", current_version: Optional["Version"] = None, new_version: Optional["Version"] = None -) -> ChainMap: - """Return the context for rendering messages and tags.""" - import datetime +def base_context(scm_info: Optional["SCMInfo"] = None) -> ChainMap: + """The default context for rendering messages and tags.""" + from bumpversion.scm import SCMInfo # Including this here to avoid circular imports + + scm = asdict(scm_info) if scm_info else asdict(SCMInfo()) - ctx = ChainMap( - {"current_version": config.current_version}, - {"now": datetime.datetime.now(), "utcnow": datetime.datetime.utcnow()}, + return ChainMap( + { + "now": datetime.datetime.now(), + "utcnow": datetime.datetime.now(datetime.timezone.utc), + }, prefixed_environ(), - asdict(config.scm_info), + scm, {c: c for c in ("#", ";")}, ) + + +def get_context( + config: "Config", current_version: Optional["Version"] = None, new_version: Optional["Version"] = None +) -> ChainMap: + """Return the context for rendering messages and tags.""" + ctx = base_context(config.scm_info) + ctx.new_child({"current_version": config.current_version}) if current_version: ctx = ctx.new_child({f"current_{part}": current_version[part].value for part in current_version}) if new_version: diff --git a/bumpversion/visualize.py b/bumpversion/visualize.py index f14d8c37..92c104d4 100644 --- a/bumpversion/visualize.py +++ b/bumpversion/visualize.py @@ -6,7 +6,7 @@ from bumpversion.config import Config from bumpversion.exceptions import BumpVersionError from bumpversion.ui import print_info -from bumpversion.utils import get_context +from bumpversion.utils import base_context, get_context BOX_CHARS = { "ascii": ["+", "+", "+", "+", "+", "+", "+", "+", "-", "|", "+"], @@ -92,10 +92,25 @@ def labeled_line(label: str, border: Border, fit_length: Optional[int] = None) - return f" {label} {border.line * (fit_length - len(label))}{border.line} " +def filter_version_parts(config: Config) -> list[str]: + """ + Return the version parts that are in the configuration. + + Args: + config: The configuration to check against + + Returns: + The version parts that are in the configuration + """ + version_parts = [part for part in config.version_config.order if not part.startswith("$")] + default_context = base_context(config.scm_info) + return [part for part in version_parts if part not in default_context] + + def visualize(config: Config, version_str: str, box_style: str = "light") -> None: """Output a visualization of the bump-my-version bump process.""" version = config.version_config.parse(version_str) - version_parts = config.version_config.order + version_parts = filter_version_parts(config) num_parts = len(version_parts) box_style = box_style if box_style in BOX_CHARS else "light" @@ -111,8 +126,8 @@ def visualize(config: Config, version_str: str, box_style: str = "light") -> Non try: next_version = get_next_version(version, config, part, None) next_version_str = config.version_config.serialize(next_version, get_context(config)) - except (BumpVersionError, ValueError): - next_version_str = "invalid" + except (BumpVersionError, ValueError) as e: + next_version_str = f"invalid: {e}" has_next = i < num_parts - 1 has_previous = i > 0