Repository: relekang/python-semantic-release
Pull request #466 (2022-07-11 21:25:57)

fix: prerelease tag in version patterns
Delay construction of version and release patterns until runtime.
This will allow to use non-default prerelease tag.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c561480..f9d9ee5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 
 <!--next-version-placeholder-->
 
+## v7.29.5 (2022-07-14)
+### Fix
+* **publish:** Get version bump for current release ([#467](https://github.com/relekang/python-semantic-release/issues/467)) ([`dd26888`](https://github.com/relekang/python-semantic-release/commit/dd26888a923b2f480303c19f1916647de48b02bf))
+* Add packaging module requirement ([#469](https://github.com/relekang/python-semantic-release/issues/469)) ([`b99c9fa`](https://github.com/relekang/python-semantic-release/commit/b99c9fa88dc25e5ceacb131cd93d9079c4fb2c86))
+
 ## v7.29.4 (2022-06-29)
 ### Fix
 * Add text for empty ValueError ([#461](https://github.com/relekang/python-semantic-release/issues/461)) ([`733254a`](https://github.com/relekang/python-semantic-release/commit/733254a99320d8c2f964d799ac4ec29737867faa))
diff --git a/semantic_release/__init__.py b/semantic_release/__init__.py
index a028d18..a444c13 100644
--- a/semantic_release/__init__.py
+++ b/semantic_release/__init__.py
@@ -1,6 +1,6 @@
 """Semantic Release
 """
-__version__ = "7.29.4"
+__version__ = "7.29.5"
 
 
 from .errors import UnknownCommitMessageStyleError  # noqa; noqa
diff --git a/semantic_release/cli.py b/semantic_release/cli.py
index fcdf614..b4b7bb5 100644
--- a/semantic_release/cli.py
+++ b/semantic_release/cli.py
@@ -294,7 +294,9 @@ def publish(
         current_version = get_previous_release_version(current_version)
     else:
         # Calculate the new version
-        level_bump = evaluate_version_bump(current_version, kwargs.get("force_level"))
+        level_bump = evaluate_version_bump(
+            current_release_version, kwargs.get("force_level")
+        )
         new_version = get_new_version(
             current_version, current_release_version, level_bump, prerelease
         )
diff --git a/semantic_release/history/__init__.py b/semantic_release/history/__init__.py
index 4a47c8b..ef6878c 100644
--- a/semantic_release/history/__init__.py
+++ b/semantic_release/history/__init__.py
@@ -25,12 +25,18 @@ from .parser_tag import parse_commit_message as tag_parser  # noqa isort:skip
 logger = logging.getLogger(__name__)
 
 
-prerelease_pattern = f"-{config.get('prerelease_tag')}\.\d+"
-version_pattern = f"(\d+\.\d+\.\d+({prerelease_pattern})?)"
-release_version_pattern = f"(\d+\.\d+\.\d+(?!.*{prerelease_pattern}))"
+def get_prerelease_pattern():
+    return f"-{config.get('prerelease_tag')}\.\d+"
 
-release_version_regex = rf"{release_version_pattern}"
-version_regex = rf"{version_pattern}"
+
+def get_version_pattern():
+    prerelease_pattern = get_prerelease_pattern()
+    return f"(\d+\.\d+\.\d+({prerelease_pattern})?)"
+
+
+def get_release_version_pattern():
+    prerelease_pattern = get_prerelease_pattern()
+    return f"(\d+\.\d+\.\d+(?!.*{prerelease_pattern}))"
 
 
 class VersionDeclaration(ABC):
@@ -53,7 +59,8 @@ class VersionDeclaration(ABC):
         variable name.
         """
         path, variable = config_str.split(":", 1)
-        pattern = rf'{variable} *[:=] *["\']{version_regex}["\']'
+        version_pattern = get_version_pattern()
+        pattern = rf'{variable} *[:=] *["\']{version_pattern}["\']'
         return PatternVersionDeclaration(path, pattern)
 
     @staticmethod
@@ -63,7 +70,7 @@ class VersionDeclaration(ABC):
         regular expression matching the version number.
         """
         path, pattern = config_str.split(":", 1)
-        pattern = pattern.format(version=version_regex)
+        pattern = pattern.format(version=get_version_pattern())
         return PatternVersionDeclaration(path, pattern)
 
     @abstractmethod
@@ -187,7 +194,7 @@ def get_current_version_by_tag() -> str:
 
     :return: A string with the version number or 0.0.0 on failure.
     """
-    version = get_last_version(pattern=version_pattern)
+    version = get_last_version(pattern=get_version_pattern())
     if version:
         return version
 
@@ -202,7 +209,7 @@ def get_current_release_version_by_tag() -> str:
 
     :return: A string with the version number or 0.0.0 on failure.
     """
-    version = get_last_version(pattern=release_version_pattern)
+    version = get_last_version(pattern=get_release_version_pattern())
     if version:
         return version
 
@@ -333,6 +340,8 @@ def get_previous_version(version: str) -> Optional[str]:
     :param version: A string with the version number.
     :return: A string with the previous version number.
     """
+    version_pattern = get_version_pattern()
+
     found_version = False
     for commit_hash, commit_message in get_commit_log():
         logger.debug(f"Checking commit {commit_hash}")
@@ -342,7 +351,7 @@ def get_previous_version(version: str) -> Optional[str]:
             continue
 
         if found_version:
-            match = re.search(rf"{version_pattern}", commit_message)
+            match = re.search(version_pattern, commit_message)
             if match:
                 logger.debug(f"Version matches regex {commit_message}")
                 return match.group(1).strip()
@@ -360,6 +369,8 @@ def get_previous_release_version(version: str) -> Optional[str]:
     :param version: A string with the version number.
     :return: A string with the previous version number.
     """
+    release_version_pattern = get_release_version_pattern()
+
     found_version = False
     for commit_hash, commit_message in get_commit_log():
         logger.debug(f"Checking commit {commit_hash}")
@@ -369,7 +380,7 @@ def get_previous_release_version(version: str) -> Optional[str]:
             continue
 
         if found_version:
-            match = re.search(rf"{release_version_pattern}", commit_message)
+            match = re.search(release_version_pattern, commit_message)
             if match:
                 logger.debug(f"Version matches regex {commit_message}")
                 return match.group(1).strip()
@@ -386,9 +397,11 @@ def get_current_release_version_by_commits() -> str:
 
     :return: A string with the current version number.
     """
+    release_version_re = re.compile(get_release_version_pattern())
+
     for commit_hash, commit_message in get_commit_log():
         logger.debug(f"Checking commit {commit_hash}")
-        match = re.search(rf"{release_version_pattern}", commit_message)
+        match = release_version_re.search(commit_message)
         if match:
             logger.debug(f"Version matches regex {commit_message}")
             return match.group(1).strip()
diff --git a/semantic_release/vcs_helpers.py b/semantic_release/vcs_helpers.py
index cdfb1ae..5cb8ebe 100644
--- a/semantic_release/vcs_helpers.py
+++ b/semantic_release/vcs_helpers.py
@@ -80,7 +80,7 @@ def get_last_version(pattern, skip_tags=None) -> Optional[str]:
         if i.name in skip_tags:
             continue
 
-        match = re.search(rf"{pattern}", i.name)
+        match = re.search(pattern, i.name)
         if match:
             return match.group(0).strip()
 
diff --git a/setup.py b/setup.py
index c0f8c11..49abaa7 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ setup(
         "tomlkit>=0.10.0,<0.11.0",
         "dotty-dict>=1.3.0,<2",
         "dataclasses==0.8; python_version < '3.7.0'",
+        "packaging",
     ],
     extras_require={
         "test": [


Test patch:
diff --git a/tests/history/test_version.py b/tests/history/test_version.py
index f62b2d5..f251a7f 100644
--- a/tests/history/test_version.py
+++ b/tests/history/test_version.py
@@ -461,6 +461,19 @@ class TestVersionPattern:
                 (Path("path2"), r'var2 *[:=] *["\'](\d+\.\d+\.\d+(-beta\.\d+)?)["\']'),
             ],
         ),
+        dict(
+            pyproject="""\
+                        [tool.semantic_release]
+                        version_variable = "path:__version__"
+                        prerelease_tag = "alpha"
+                        """,
+            patterns=[
+                (
+                    Path("path"),
+                    r'__version__ *[:=] *["\'](\d+\.\d+\.\d+(-alpha\.\d+)?)["\']',
+                ),
+            ],
+        ),
         dict(
             pyproject="""\
                         [tool.semantic_release]
diff --git a/tests/test_vcs_helpers.py b/tests/test_vcs_helpers.py
index 5a583a8..392556e 100644
--- a/tests/test_vcs_helpers.py
+++ b/tests/test_vcs_helpers.py
@@ -6,7 +6,7 @@ import pytest
 from git import GitCommandError, Repo, TagObject
 
 from semantic_release.errors import GitError, HvcsRepoParseError
-from semantic_release.history import release_version_pattern, version_pattern
+from semantic_release.history import get_release_version_pattern, get_version_pattern
 from semantic_release.vcs_helpers import (
     check_repo,
     checkout,
@@ -396,22 +396,22 @@ def test_get_last_version(pattern, skip_tags, expected_result):
 
 
 @pytest.mark.parametrize(
-    "pattern, skip_tags,expected_result",
+    "get_pattern, skip_tags,expected_result",
     [
-        (version_pattern, None, "2.1.0-beta.0"),
-        (version_pattern, ["v2.1.0-beta.0"], "2.0.0"),
-        (version_pattern, ["v2.1.0-beta.0", "v2.0.0-beta.0", "v2.0.0"], "1.1.0"),
+        (get_version_pattern, None, "2.1.0-beta.0"),
+        (get_version_pattern, ["v2.1.0-beta.0"], "2.0.0"),
+        (get_version_pattern, ["v2.1.0-beta.0", "v2.0.0-beta.0", "v2.0.0"], "1.1.0"),
         (
-            version_pattern,
+            get_version_pattern,
             ["v2.1.0-beta.0", "v2.0.0-beta.0", "v0.1.0", "v1.0.0", "v1.1.0", "v2.0.0"],
             None,
         ),
-        (release_version_pattern, None, "2.0.0"),
-        (release_version_pattern, ["v2.0.0"], "1.1.0"),
-        (release_version_pattern, ["v2.0.0", "v1.1.0", "v1.0.0", "v0.1.0"], None),
+        (get_release_version_pattern, None, "2.0.0"),
+        (get_release_version_pattern, ["v2.0.0"], "1.1.0"),
+        (get_release_version_pattern, ["v2.0.0", "v1.1.0", "v1.0.0", "v0.1.0"], None),
     ],
 )
-def test_get_last_version_with_real_pattern(pattern, skip_tags, expected_result):
+def test_get_last_version_with_real_pattern(get_pattern, skip_tags, expected_result):
     # TODO: add some prerelease tags
     class FakeCommit:
         def __init__(self, com_date):
@@ -442,7 +442,7 @@ def test_get_last_version_with_real_pattern(pattern, skip_tags, expected_result)
             FakeTag("v1.0.0", "bbbbbbbbbbbbbbbbbbbb", 2, False),
         ]
     )
-    assert expected_result == get_last_version(pattern, skip_tags)
+    assert expected_result == get_last_version(get_pattern(), skip_tags)
 
 
 def test_update_changelog_file_ok(mock_git, mocker):