-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Shows possible resulting versions of the `bump` command
- Loading branch information
Showing
4 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
"""Visualize the bumpversion process.""" | ||
from dataclasses import dataclass | ||
from typing import Optional | ||
|
||
from bumpversion.bump import get_next_version | ||
from bumpversion.config import Config | ||
from bumpversion.exceptions import BumpVersionError | ||
from bumpversion.ui import print_info | ||
from bumpversion.utils import get_context | ||
|
||
BOX_CHARS = { | ||
"ascii": ["+", "+", "+", "+", "+", "+", "+", "+", "-", "|", "+"], | ||
"light": ["╯", "╮", "╭", "╰", "┤", "┴", "┬", "├", "─", "│", "┼"], | ||
} | ||
|
||
|
||
@dataclass | ||
class Border: | ||
"""A border definition.""" | ||
|
||
corner_bottom_right: str | ||
corner_top_right: str | ||
corner_top_left: str | ||
corner_bottom_left: str | ||
divider_left: str | ||
divider_up: str | ||
divider_down: str | ||
divider_right: str | ||
line: str | ||
pipe: str | ||
cross: str | ||
|
||
|
||
def lead_string(version_str: str, border: Border, blank: bool = False) -> str: | ||
""" | ||
Return the first part of a string with the bump character or spaces of the correct amount. | ||
Examples: | ||
>>> lead_string("1.0.0", Border(*BOX_CHARS["light"])) | ||
'1.0.0 ── bump ─' | ||
>>> lead_string("1.0.0", Border(*BOX_CHARS["light"]), blank=True) | ||
' ' | ||
Args: | ||
version_str: The string to render as the starting point | ||
border: The border definition to draw the lines | ||
blank: If `True`, return a blank string the same length as the version bump string | ||
Returns: | ||
The version bump string or a blank string | ||
""" | ||
version_bump = f"{version_str} {border.line * 2} bump {border.line}" | ||
return " " * len(version_bump) if blank else version_bump | ||
|
||
|
||
def connection_str(border: Border, has_next: bool = False, has_previous: bool = False) -> str: | ||
""" | ||
Return the correct connection string based on the next and previous. | ||
Args: | ||
border: The border definition to draw the lines | ||
has_next: If `True`, there is a next line | ||
has_previous: If `True`, there is a previous line | ||
Returns: | ||
A string that connects left-to-right and top-to-bottom based on the next and previous | ||
""" | ||
if has_next and has_previous: | ||
return border.divider_right + border.line | ||
elif has_next: | ||
return border.divider_down + border.line | ||
elif has_previous: | ||
return border.corner_bottom_left + border.line | ||
else: | ||
return border.line * 2 | ||
|
||
|
||
def labeled_line(label: str, border: Border, fit_length: Optional[int] = None) -> str: | ||
""" | ||
Return the version part string with the correct padding. | ||
Args: | ||
label: The label to render | ||
border: The border definition to draw the lines | ||
fit_length: The length to fit the label to | ||
Returns: | ||
A labeled line with leading and trailing spaces | ||
""" | ||
if fit_length is None: | ||
fit_length = len(label) | ||
return f" {label} {border.line * (fit_length - len(label))}{border.line} " | ||
|
||
|
||
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 | ||
num_parts = len(version_parts) | ||
|
||
box_style = box_style if box_style in BOX_CHARS else "light" | ||
border = Border(*BOX_CHARS[box_style]) | ||
|
||
version_lead = lead_string(version_str, border) | ||
blank_lead = lead_string(version_str, border, blank=True) | ||
version_part_length = max(len(part) for part in version_parts) | ||
|
||
for i, part in enumerate(version_parts): | ||
line = [version_lead] if i == 0 else [blank_lead] | ||
|
||
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" | ||
|
||
has_next = i < num_parts - 1 | ||
has_previous = i > 0 | ||
line.append(connection_str(border, has_next=has_next, has_previous=has_previous)) | ||
line.append(labeled_line(part, border, version_part_length)) | ||
line.append(next_version_str) | ||
print_info("".join(line)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
"""Tests the show_bump command.""" | ||
import shutil | ||
from pathlib import Path | ||
|
||
from click.testing import CliRunner, Result | ||
from bumpversion import cli | ||
from tests.conftest import inside_dir | ||
|
||
|
||
def test_show_bump_uses_current_version(tmp_path: Path, fixtures_path: Path): | ||
"""The show_bump subcommand should list the parts of the configuration.""" | ||
# Arrange | ||
config_path = tmp_path / "pyproject.toml" | ||
toml_path = fixtures_path / "basic_cfg.toml" | ||
shutil.copy(toml_path, config_path) | ||
runner: CliRunner = CliRunner() | ||
|
||
with inside_dir(tmp_path): | ||
result: Result = runner.invoke(cli.cli, ["show-bump"]) | ||
|
||
if result.exit_code != 0: | ||
print(result.output) | ||
print(result.exception) | ||
|
||
assert result.exit_code == 0 | ||
assert result.output == "\n".join( | ||
[ | ||
"1.0.0 ── bump ─┬─ major ─── 2.0.0-dev", | ||
" ├─ minor ─── 1.1.0-dev", | ||
" ├─ patch ─── 1.0.1-dev", | ||
" ╰─ release ─ invalid\n", | ||
] | ||
) | ||
|
||
|
||
def test_show_bump_uses_passed_version(tmp_path: Path, fixtures_path: Path): | ||
"""The show_bump subcommand should list the parts of the configuration.""" | ||
# Arrange | ||
config_path = tmp_path / "pyproject.toml" | ||
toml_path = fixtures_path / "basic_cfg.toml" | ||
shutil.copy(toml_path, config_path) | ||
runner: CliRunner = CliRunner() | ||
|
||
with inside_dir(tmp_path): | ||
result: Result = runner.invoke(cli.cli, ["show-bump", "1.2.3"]) | ||
|
||
if result.exit_code != 0: | ||
print(result.output) | ||
print(result.exception) | ||
|
||
assert result.exit_code == 0 | ||
assert result.output == "\n".join( | ||
[ | ||
"1.2.3 ── bump ─┬─ major ─── 2.0.0-dev", | ||
" ├─ minor ─── 1.3.0-dev", | ||
" ├─ patch ─── 1.2.4-dev", | ||
" ╰─ release ─ invalid\n", | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"""Tests of the visualize module.""" | ||
from pathlib import Path | ||
|
||
from bumpversion.visualize import Border, BOX_CHARS, connection_str, lead_string, labeled_line, visualize | ||
from bumpversion.config import get_configuration | ||
|
||
|
||
class TestLeadString: | ||
"""Tests of the lead_string function.""" | ||
|
||
def test_returns_string_with_bump(self): | ||
assert lead_string("1.0.0", Border(*BOX_CHARS["light"])) == "1.0.0 ── bump ─" | ||
|
||
def test_returns_blank_string(self): | ||
assert lead_string("1.0.0", Border(*BOX_CHARS["light"]), blank=True) == " " | ||
|
||
|
||
class TestConnectionStr: | ||
"""Tests of the connection_str function.""" | ||
|
||
def test_returns_correct_connection_string(self): | ||
border = Border(*BOX_CHARS["light"]) | ||
assert connection_str(border, has_next=True, has_previous=True) == border.divider_right + border.line | ||
assert connection_str(border, has_next=True, has_previous=False) == border.divider_down + border.line | ||
assert connection_str(border, has_next=False, has_previous=True) == border.corner_bottom_left + border.line | ||
assert connection_str(border, has_next=False, has_previous=False) == border.line * 2 | ||
|
||
|
||
class TestLabeledLine: | ||
"""Tests of the labeled_line function.""" | ||
|
||
def test_no_label_fill_when_no_fit_length(self): | ||
"""Without a fit_length, there will be no filler in the line.""" | ||
border = Border(*BOX_CHARS["light"]) | ||
assert labeled_line("major", border, fit_length=None) == " major ─ " | ||
|
||
def test_pads_label_if_fit_length(self): | ||
"""Without a fit_length, there will be no filler in the line.""" | ||
border = Border(*BOX_CHARS["light"]) | ||
assert labeled_line("major", border, fit_length=10) == " major ────── " | ||
|
||
|
||
class TestVisualize: | ||
"""Tests of the visualize function.""" | ||
|
||
def test_outputs_using_default_config(self, tmp_path: Path, capsys): | ||
"""Test that the correct string is returned.""" | ||
config = get_configuration(tmp_path.joinpath("missing.toml"), current_version="1.0.0") | ||
visualize(config, "1.0.0") | ||
captured = capsys.readouterr() | ||
assert captured.out == "\n".join( | ||
["1.0.0 ── bump ─┬─ major ─ 2.0.0", " ├─ minor ─ 1.1.0", " ╰─ patch ─ 1.0.1\n"] | ||
) | ||
|
||
def test_indicates_invalid_paths(self, tmp_path: Path, fixtures_path: Path, capsys): | ||
"""Test that the correct string is returned.""" | ||
config_content = fixtures_path.joinpath("basic_cfg.toml").read_text() | ||
config_path = tmp_path.joinpath(".bumpversion-1.toml") | ||
config_path.write_text(config_content) | ||
config = get_configuration(config_path) | ||
visualize(config, "1.0.0") | ||
captured = capsys.readouterr() | ||
assert captured.out == "\n".join( | ||
[ | ||
"1.0.0 ── bump ─┬─ major ─── 2.0.0-dev", | ||
" ├─ minor ─── 1.1.0-dev", | ||
" ├─ patch ─── 1.0.1-dev", | ||
" ╰─ release ─ invalid\n", | ||
] | ||
) |