-
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
192 additions
and
36 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
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,56 @@ | ||
"""Functions for serializing and deserializing version objects.""" | ||
import re | ||
from typing import Dict | ||
|
||
from bumpversion.exceptions import BumpVersionError | ||
from bumpversion.ui import get_indented_logger | ||
from bumpversion.utils import key_val_string | ||
|
||
logger = get_indented_logger(__name__) | ||
|
||
|
||
def parse_version(version_string: str, parse_pattern: str) -> Dict[str, str]: | ||
""" | ||
Parse a version string into a dictionary of the parts and values using a regular expression. | ||
Args: | ||
version_string: Version string to parse | ||
parse_pattern: The regular expression pattern to use for parsing | ||
Returns: | ||
A dictionary of version part labels and their values, or an empty dictionary | ||
if the version string doesn't match. | ||
Raises: | ||
BumpVersionError: If the parse_pattern is not a valid regular expression | ||
""" | ||
if not version_string: | ||
logger.debug("Version string is empty, returning empty dict") | ||
return {} | ||
elif not parse_pattern: | ||
logger.debug("Parse pattern is empty, returning empty dict") | ||
return {} | ||
|
||
logger.debug("Parsing version '%s' using regexp '%s'", version_string, parse_pattern) | ||
logger.indent() | ||
|
||
try: | ||
pattern = re.compile(parse_pattern, re.VERBOSE) | ||
except re.error as e: | ||
raise BumpVersionError(f"'{parse_pattern}' is not a valid regular expression.") from e | ||
|
||
match = re.search(pattern, version_string) | ||
|
||
if not match: | ||
logger.debug( | ||
"'%s' does not parse current version '%s'", | ||
parse_pattern, | ||
version_string, | ||
) | ||
return {} | ||
|
||
parsed = match.groupdict(default="") | ||
logger.debug("Parsed the following values: %s", key_val_string(parsed)) | ||
logger.dedent() | ||
|
||
return parsed |
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,62 @@ | ||
"""Tests for the serialization of versioned objects.""" | ||
from bumpversion.versioning.serialization import parse_version | ||
from bumpversion.versioning.models import SEMVER_PATTERN | ||
from bumpversion.exceptions import BumpVersionError | ||
|
||
import pytest | ||
from pytest import param | ||
|
||
|
||
class TestParseVersion: | ||
"""Test the parse_version function.""" | ||
|
||
def test_empty_version_returns_empty_dict(self): | ||
assert parse_version("", "") == {} | ||
assert parse_version(None, "") == {} | ||
|
||
def test_empty_parse_pattern_returns_empty_dict(self): | ||
assert parse_version("1.2.3", "") == {} | ||
assert parse_version("1.2.3", None) == {} | ||
|
||
@pytest.mark.parametrize( | ||
["version_string", "parse_pattern", "expected"], | ||
[ | ||
param( | ||
"1.2.3", | ||
SEMVER_PATTERN, | ||
{"buildmetadata": "", "major": "1", "minor": "2", "patch": "3", "pre_l": "", "pre_n": ""}, | ||
id="parse-version", | ||
), | ||
param( | ||
"1.2.3-alpha1", | ||
SEMVER_PATTERN, | ||
{"buildmetadata": "", "major": "1", "minor": "2", "patch": "3", "pre_l": "alpha", "pre_n": "1"}, | ||
id="parse-prerelease", | ||
), | ||
param( | ||
"1.2.3+build.1", | ||
SEMVER_PATTERN, | ||
{"buildmetadata": "build.1", "major": "1", "minor": "2", "patch": "3", "pre_l": "", "pre_n": ""}, | ||
id="parse-buildmetadata", | ||
), | ||
param( | ||
"1.2.3-alpha1+build.1", | ||
SEMVER_PATTERN, | ||
{"buildmetadata": "build.1", "major": "1", "minor": "2", "patch": "3", "pre_l": "alpha", "pre_n": "1"}, | ||
id="parse-prerelease-buildmetadata", | ||
), | ||
], | ||
) | ||
def test_parses_version_and_returns_full_dict(self, version_string: str, parse_pattern: str, expected: dict): | ||
"""The version string should be parsed into a dictionary of the parts and values, including missing parts.""" | ||
results = parse_version(version_string, parse_pattern) | ||
assert results == expected | ||
|
||
def test_unmatched_pattern_returns_empty_dict(self): | ||
"""If the version string doesn't match the parse pattern, an empty dictionary should be returned.""" | ||
assert parse_version("1.2.3", r"v(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)") == {} | ||
|
||
def test_invalid_parse_pattern_raises_error(self): | ||
"""If the parse pattern is not a valid regular expression, a ValueError should be raised.""" | ||
with pytest.raises(BumpVersionError): | ||
parse_version("1.2.3", r"v(?P<major>\d+\.(?P<minor>\d+)\.(?P<patch>\d+)") |