Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The next release of bump-my-version #94

Merged
merged 18 commits into from
Dec 6, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added key_path to FileConfig
- Also made all attributes required except `filename`, `glob`, and `key_path`
  • Loading branch information
coordt committed Nov 26, 2023
commit e160b401b0d14cef77255bbd87748721db4e2e3d
14 changes: 8 additions & 6 deletions bumpversion/config.py
Original file line number Diff line number Diff line change
@@ -37,14 +37,15 @@ class VersionPartConfig(BaseModel):
class FileConfig(BaseModel):
"""Search and replace file config."""

parse: str
serialize: List[str]
search: str
replace: str
regex: bool
ignore_missing_version: bool
filename: Optional[str] = None
glob: Optional[str] = None # Conflicts with filename. If both are specified, glob wins
parse: Optional[str] = None # If different from outer scope
serialize: Optional[List[str]] = None # If different from outer scope
search: Optional[str] = None # If different from outer scope
replace: Optional[str] = None # If different from outer scope
regex: Optional[bool] = None # If different from outer scope
ignore_missing_version: Optional[bool] = None
key_path: Optional[str] = None # If specified, and has an appropriate extension, will be treated as a data file


class Config(BaseSettings):
@@ -82,6 +83,7 @@ def add_files(self, filename: Union[str, List[str]]) -> None:
FileConfig(
filename=name,
glob=None,
key_path=None,
parse=self.parse,
serialize=self.serialize,
search=self.search,
11 changes: 6 additions & 5 deletions bumpversion/show.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
from bumpversion.config import Config
from bumpversion.exceptions import BadInputError
from bumpversion.ui import print_error, print_info
from bumpversion.utils import get_context
from bumpversion.utils import get_context, recursive_sort_dict


def output_default(value: dict) -> None:
@@ -17,15 +17,15 @@ def output_default(value: dict) -> None:
print_info(next(iter(value.values())))
else:
buffer = StringIO()
pprint(value, stream=buffer) # noqa: T203
pprint(value, stream=buffer, sort_dicts=True) # noqa: T203
print_info(buffer.getvalue())


def output_yaml(value: dict) -> None:
"""Output the value as yaml."""
from bumpversion.yaml_dump import dump

print_info(dump(value))
print_info(dump(recursive_sort_dict(value)))


def output_json(value: dict) -> None:
@@ -117,13 +117,14 @@ def log_list(config: Config, version_part: Optional[str], new_version: Optional[

print_info(f"new_version={next_version_str}")

for key, value in config.dict(exclude={"scm_info", "parts"}).items():
config_dict = recursive_sort_dict(config.model_dump(exclude={"scm_info", "parts"}))
for key, value in config_dict.items():
print_info(f"{key}={value}")


def do_show(*args, config: Config, format_: str = "default", increment: Optional[str] = None) -> None:
"""Show current version or configuration information."""
config_dict = config.dict()
config_dict = config.model_dump()
ctx = get_context(config)

if increment:
10 changes: 9 additions & 1 deletion bumpversion/utils.py
Original file line number Diff line number Diff line change
@@ -2,13 +2,21 @@
import string
from collections import ChainMap
from dataclasses import asdict
from typing import TYPE_CHECKING, List, Optional
from typing import TYPE_CHECKING, Any, List, Optional

if TYPE_CHECKING: # pragma: no-coverage
from bumpversion.config import Config
from bumpversion.version_part import Version


def recursive_sort_dict(input_value: Any) -> Any:
"""Sort a dictionary recursively."""
if not isinstance(input_value, dict):
return input_value

return {key: recursive_sort_dict(input_value[key]) for key in sorted(input_value.keys())}


def key_val_string(d: dict) -> str:
"""Render the dictionary as a comma-delimited key=value string."""
return ", ".join(f"{k}={v}" for k, v in sorted(d.items()))
1 change: 1 addition & 0 deletions bumpversion/version_part.py
Original file line number Diff line number Diff line change
@@ -146,6 +146,7 @@ def __init__(

self.serialize_formats = serialize
self.part_configs = part_configs or {}
# TODO: I think these two should be removed from the config object
self.search = search
self.replace = replace

3 changes: 3 additions & 0 deletions tests/fixtures/basic_cfg_expected.txt
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
'files': [{'filename': 'setup.py',
'glob': None,
'ignore_missing_version': False,
'key_path': None,
'parse': '(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?',
'regex': False,
'replace': '{new_version}',
@@ -15,6 +16,7 @@
{'filename': 'bumpversion/__init__.py',
'glob': None,
'ignore_missing_version': False,
'key_path': None,
'parse': '(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?',
'regex': False,
'replace': '{new_version}',
@@ -24,6 +26,7 @@
{'filename': 'CHANGELOG.md',
'glob': None,
'ignore_missing_version': False,
'key_path': None,
'parse': '(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?',
'regex': False,
'replace': '**unreleased**\n**v{new_version}**',
3 changes: 3 additions & 0 deletions tests/fixtures/basic_cfg_expected.yaml
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ files:
- filename: "setup.py"
glob: null
ignore_missing_version: false
key_path: null
parse: "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?"
regex: false
replace: "{new_version}"
@@ -18,6 +19,7 @@ files:
- filename: "bumpversion/__init__.py"
glob: null
ignore_missing_version: false
key_path: null
parse: "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?"
regex: false
replace: "{new_version}"
@@ -28,6 +30,7 @@ files:
- filename: "CHANGELOG.md"
glob: null
ignore_missing_version: false
key_path: null
parse: "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?"
regex: false
replace: "**unreleased**\n**v{new_version}**"
3 changes: 3 additions & 0 deletions tests/fixtures/basic_cfg_expected_full.json
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
"filename": "setup.py",
"glob": null,
"ignore_missing_version": false,
"key_path": null,
"parse": "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?",
"regex": false,
"replace": "{new_version}",
@@ -22,6 +23,7 @@
"filename": "bumpversion/__init__.py",
"glob": null,
"ignore_missing_version": false,
"key_path": null,
"parse": "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?",
"regex": false,
"replace": "{new_version}",
@@ -35,6 +37,7 @@
"filename": "CHANGELOG.md",
"glob": null,
"ignore_missing_version": false,
"key_path": null,
"parse": "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?",
"regex": false,
"replace": "**unreleased**\n**v{new_version}**",
62 changes: 36 additions & 26 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -218,19 +218,24 @@ def test_listing_with_version_part(tmp_path: Path, fixtures_path: Path):
"message=Bump version: {current_version} → {new_version}",
"commit_args=None",
(
"files=["
"{'filename': 'setup.py', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '{current_version}', "
"'replace': '{new_version}', 'regex': False, 'ignore_missing_version': False}, "
"{'filename': 'bumpversion/__init__.py', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '{current_version}', "
"'replace': '{new_version}', 'regex': False, 'ignore_missing_version': False}, "
"{'filename': 'CHANGELOG.md', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '**unreleased**', "
"'replace': '**unreleased**\\n**v{new_version}**', 'regex': False, 'ignore_missing_version': False}]"
"files=[{'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '{current_version}', 'replace': "
"'{new_version}', 'regex': False, 'ignore_missing_version': False, "
"'filename': 'setup.py', 'glob': None, 'key_path': None}, {'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '{current_version}', 'replace': "
"'{new_version}', 'regex': False, 'ignore_missing_version': False, "
"'filename': 'bumpversion/__init__.py', 'glob': None, 'key_path': None}, "
"{'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '**unreleased**', 'replace': "
"'**unreleased**\\n**v{new_version}**', 'regex': False, "
"'ignore_missing_version': False, 'filename': 'CHANGELOG.md', 'glob': None, "
"'key_path': None}]"
),
}

@@ -273,19 +278,24 @@ def test_listing_without_version_part(tmp_path: Path, fixtures_path: Path):
"message=Bump version: {current_version} → {new_version}",
"commit_args=None",
(
"files=["
"{'filename': 'setup.py', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '{current_version}', "
"'replace': '{new_version}', 'regex': False, 'ignore_missing_version': False}, "
"{'filename': 'bumpversion/__init__.py', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '{current_version}', "
"'replace': '{new_version}', 'regex': False, 'ignore_missing_version': False}, "
"{'filename': 'CHANGELOG.md', 'glob': None, 'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', 'serialize': "
"['{major}.{minor}.{patch}-{release}', '{major}.{minor}.{patch}'], 'search': '**unreleased**', "
"'replace': '**unreleased**\\n**v{new_version}**', 'regex': False, 'ignore_missing_version': False}]"
"files=[{'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '{current_version}', 'replace': "
"'{new_version}', 'regex': False, 'ignore_missing_version': False, "
"'filename': 'setup.py', 'glob': None, 'key_path': None}, {'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '{current_version}', 'replace': "
"'{new_version}', 'regex': False, 'ignore_missing_version': False, "
"'filename': 'bumpversion/__init__.py', 'glob': None, 'key_path': None}, "
"{'parse': "
"'(?P<major>\\\\d+)\\\\.(?P<minor>\\\\d+)\\\\.(?P<patch>\\\\d+)(\\\\-(?P<release>[a-z]+))?', "
"'serialize': ['{major}.{minor}.{patch}-{release}', "
"'{major}.{minor}.{patch}'], 'search': '**unreleased**', 'replace': "
"'**unreleased**\\n**v{new_version}**', 'regex': False, "
"'ignore_missing_version': False, 'filename': 'CHANGELOG.md', 'glob': None, "
"'key_path': None}]"
),
}