diff --git a/action.sh b/action.sh index 48ab72c35..28a287792 100644 --- a/action.sh +++ b/action.sh @@ -35,6 +35,7 @@ ARGS+=("$(eval_boolean_action_input "push" "$INPUT_PUSH" "--push" "--no-push")") ARGS+=("$(eval_boolean_action_input "changelog" "$INPUT_CHANGELOG" "--changelog" "--no-changelog")") || exit 1 ARGS+=("$(eval_boolean_action_input "vcs_release" "$INPUT_VCS_RELEASE" "--vcs-release" "--no-vcs-release")") || exit 1 ARGS+=("$(eval_boolean_action_input "build" "$INPUT_BUILD" "" "--skip-build")") || exit 1 +ARGS+=("$(eval_boolean_action_input "pep440" "$INPUT_PEP440" "--version-compat=pep440" "--version-compat=semver")") || exit 1 # Handle --patch, --minor, --major # https://stackoverflow.com/a/47541882 diff --git a/action.yml b/action.yml index 992b5d05d..445c2456c 100644 --- a/action.yml +++ b/action.yml @@ -108,6 +108,12 @@ inputs: description: | Build metadata to append to the new version + pep440: + type: string + required: false + description: | + Whether or not to use PEP440 versioning. + outputs: is_prerelease: description: | diff --git a/pyproject.toml b/pyproject.toml index 1ea076196..b940c32fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,7 +165,7 @@ commands = [testenv:ruff] deps = .[dev] commands = - ruff check . --statistics --output-format=text + ruff check . --statistics --output-format=full """ [tool.mypy] diff --git a/src/semantic_release/cli/commands/version.py b/src/semantic_release/cli/commands/version.py index 104faa9fe..4f8e8c691 100644 --- a/src/semantic_release/cli/commands/version.py +++ b/src/semantic_release/cli/commands/version.py @@ -74,17 +74,17 @@ def is_forced_prerelease( ) -def last_released(repo_dir: Path, tag_format: str) -> tuple[Tag, Version] | None: +def last_released(repo_dir: Path, tag_format: str, version_compat: str) -> tuple[Tag, Version] | None: with Repo(str(repo_dir)) as git_repo: ts_and_vs = tags_and_versions( - git_repo.tags, VersionTranslator(tag_format=tag_format) + git_repo.tags, VersionTranslator(tag_format=tag_format, version_compat=version_compat) ) return ts_and_vs[0] if ts_and_vs else None def version_from_forced_level( - repo_dir: Path, forced_level_bump: LevelBump, translator: VersionTranslator + repo_dir: Path, forced_level_bump: LevelBump, translator: VersionTranslator, ) -> Version: with Repo(str(repo_dir)) as git_repo: ts_and_vs = tags_and_versions(git_repo.tags, translator) @@ -323,6 +323,12 @@ def build_distributions( default=None, help="Force the next version to use this prerelease token, if it is a prerelease", ) +@click.option( + "--version-compat", + "version_compat", + default=None, + help="Choose a versioning scheme to use", +) @click.option( "--major", "force_level", @@ -399,6 +405,7 @@ def version( # noqa: C901 print_last_released_tag: bool, as_prerelease: bool, prerelease_token: str | None, + version_compat: str, commit_changes: bool, create_tag: bool, update_changelog: bool, @@ -436,7 +443,7 @@ def version( # noqa: C901 if print_last_released or print_last_released_tag: # TODO: get tag format a better way if not ( - last_release := last_released(config.repo_dir, tag_format=config.tag_format) + last_release := last_released(config.repo_dir, tag_format=config.tag_format, version_compat=version_compat) ): log.warning("No release tags found.") return @@ -470,6 +477,10 @@ def version( # noqa: C901 log.info("Forcing use of %s as the prerelease token", prerelease_token) translator.prerelease_token = prerelease_token + if version_compat: + translator.version_compat = version_compat + log.info("Using %s as the version compatibility scheme", translator.version_compat) + # Only push if we're committing changes if push_changes and not commit_changes and not create_tag: log.info("changes will not be pushed because --no-commit disables pushing") diff --git a/src/semantic_release/cli/config.py b/src/semantic_release/cli/config.py index 7e5c31131..bf88771d1 100644 --- a/src/semantic_release/cli/config.py +++ b/src/semantic_release/cli/config.py @@ -45,7 +45,12 @@ ScipyCommitParser, TagCommitParser, ) -from semantic_release.const import COMMIT_MESSAGE, DEFAULT_COMMIT_AUTHOR, SEMVER_REGEX +from semantic_release.const import ( + COMMIT_MESSAGE, + DEFAULT_COMMIT_AUTHOR, + PEP440_REGEX, + SEMVER_REGEX, +) from semantic_release.errors import ( DetachedHeadGitError, InvalidConfiguration, @@ -239,6 +244,7 @@ class BranchConfig(BaseModel): match: str = "(main|master)" prerelease_token: str = "rc" # noqa: S105 prerelease: bool = False + version_compat: str = "semver" @field_validator("match", mode="after") @classmethod @@ -712,7 +718,9 @@ def from_raw_config( # noqa: C901 try: path, search_text = decl.split(":", maxsplit=1) # VersionDeclarationABC handles path existence check - vd = TomlVersionDeclaration(path, search_text) + vd = TomlVersionDeclaration( + path, search_text, version_compat=branch_config.version_compat + ) except ValueError as exc: log.exception("Invalid TOML declaration %r", decl) raise InvalidConfiguration( @@ -724,6 +732,10 @@ def from_raw_config( # noqa: C901 for decl in () if raw.version_variables is None else raw.version_variables: try: path, variable = decl.split(":", maxsplit=1) + if branch_config.version_compat == "pep440": + version_pattern = PEP440_REGEX + else: + version_pattern = SEMVER_REGEX # VersionDeclarationABC handles path existence check search_text = str.join( "", @@ -734,10 +746,10 @@ def from_raw_config( # noqa: C901 # Supports walrus, equals sign, or colon as assignment operator ignoring whitespace separation r"\s*(:=|[:=])\s*", # Supports optional matching quotations around version number of a SEMVER pattern - f"""(?P['"])?(?P{SEMVER_REGEX.pattern})(?P=quote2)?""", + f"""(?P['"])?(?P{version_pattern.pattern})(?P=quote2)?""", ], ) - pd = PatternVersionDeclaration(path, search_text) + pd = PatternVersionDeclaration(path, search_text, version_compat=branch_config.version_compat) except ValueError as exc: log.exception("Invalid variable declaration %r", decl) raise InvalidConfiguration( @@ -800,7 +812,9 @@ def from_raw_config( # noqa: C901 # version_translator version_translator = VersionTranslator( - tag_format=raw.tag_format, prerelease_token=branch_config.prerelease_token + tag_format=raw.tag_format, + prerelease_token=branch_config.prerelease_token, + version_compat=branch_config.version_compat, ) build_cmd_env = {} diff --git a/src/semantic_release/const.py b/src/semantic_release/const.py index 231e30466..9b51248c6 100644 --- a/src/semantic_release/const.py +++ b/src/semantic_release/const.py @@ -19,6 +19,56 @@ flags=re.VERBOSE, ) +PEP440_REGEX = re.compile( + r""" + v? + (?:(?P[0-9]+)!)? + (?P0|[1-9]\d*) + \. + (?P0|[1-9]\d*) + \. + (?P0|[1-9]\d*) + (?:[-_\.]?(?P(?:(a|b|c|rc|alpha|beta|pre|preview|dev|post|rev|r))(?:[-_\.]?(?:[0-9]+))*))? + (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? + """, + flags=re.VERBOSE | re.IGNORECASE, +) + +# PEP440_PATTERN = re.compile( +# r""" +# ^\s* +# v? +# (?: +# (?:(?P[0-9]+)!)? # epoch +# (?P[0-9]+(?:\.[0-9]+)*) # release segment +# (?P
                                          # pre-release
+#             [-_\.]?
+#             (?P(a|b|c|rc|alpha|beta|pre|preview))
+#             [-_\.]?
+#             (?P[0-9]+)?
+#         )?
+#         (?P                                         # post release
+#             (?:-(?P[0-9]+))
+#             |
+#             (?:
+#                 [-_\.]?
+#                 (?Ppost|rev|r)
+#                 [-_\.]?
+#                 (?P[0-9]+)?
+#             )
+#         )?
+#         (?P                                          # dev release
+#             [-_\.]?
+#             (?Pdev)
+#             [-_\.]?
+#             (?P[0-9]+)?
+#         )?
+#     )
+#     (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+#     \s*$
+#     """,
+# )
+
 COMMIT_MESSAGE = "{version}\n\nAutomatically generated by python-semantic-release"
 DEFAULT_COMMIT_AUTHOR = "semantic-release "
 DEFAULT_VERSION = "0.0.0"
diff --git a/src/semantic_release/version/declaration.py b/src/semantic_release/version/declaration.py
index 89f310d8e..a5db05a76 100644
--- a/src/semantic_release/version/declaration.py
+++ b/src/semantic_release/version/declaration.py
@@ -20,11 +20,12 @@ class VersionDeclarationABC(ABC):
     within the source tree of the repository
     """
 
-    def __init__(self, path: Path | str, search_text: str) -> None:
+    def __init__(self, path: Path | str, search_text: str, version_compat: str) -> None:
         self.path = Path(path)
         if not self.path.exists():
             raise FileNotFoundError(f"path {self.path.resolve()!r} does not exist")
         self.search_text = search_text
+        self.version_compat = version_compat
         self._content: str | None = None
 
     @property
@@ -106,7 +107,7 @@ def parse(self) -> set[Version]:
                 self.search_text,
                 maybe_version,
             )
-            valid_version = Version.parse(maybe_version)
+            valid_version = Version.parse(maybe_version, version_compat=self.version_compat)
             return {valid_version} if valid_version else set()
         # Maybe in future raise error if not found?
         return set()
@@ -137,8 +138,8 @@ class PatternVersionDeclaration(VersionDeclarationABC):
 
     _VERSION_GROUP_NAME = "version"
 
-    def __init__(self, path: Path | str, search_text: str) -> None:
-        super().__init__(path, search_text)
+    def __init__(self, path: Path | str, search_text: str, version_compat: str) -> None:
+        super().__init__(path, search_text, version_compat)
         self.search_re = re.compile(self.search_text, flags=re.MULTILINE)
         if self._VERSION_GROUP_NAME not in self.search_re.groupindex:
             raise ValueError(
@@ -159,7 +160,7 @@ def parse(self) -> set[Version]:
         to check for this condition.
         """
         versions = {
-            Version.parse(m.group(self._VERSION_GROUP_NAME))
+            Version.parse(m.group(self._VERSION_GROUP_NAME), version_compat=self.version_compat)
             for m in self.search_re.finditer(self.content, re.MULTILINE)
         }
 
diff --git a/src/semantic_release/version/translator.py b/src/semantic_release/version/translator.py
index 7a4ce275f..61dbfbec8 100644
--- a/src/semantic_release/version/translator.py
+++ b/src/semantic_release/version/translator.py
@@ -3,7 +3,6 @@
 import logging
 import re
 
-from semantic_release.const import SEMVER_REGEX
 from semantic_release.helpers import check_tag_format
 from semantic_release.version.version import Version
 
@@ -16,8 +15,6 @@ class VersionTranslator:
     instances.
     """
 
-    _VERSION_REGEX = SEMVER_REGEX
-
     @classmethod
     def _invert_tag_format_to_re(cls, tag_format: str) -> re.Pattern[str]:
         r"""
@@ -44,10 +41,12 @@ def __init__(
         self,
         tag_format: str = "v{version}",
         prerelease_token: str = "rc",  # noqa: S107
+        version_compat: str = "semver"
     ) -> None:
         check_tag_format(tag_format)
         self.tag_format = tag_format
         self.prerelease_token = prerelease_token
+        self.version_compat = version_compat
         self.from_tag_re = self._invert_tag_format_to_re(self.tag_format)
 
     def from_string(self, version_str: str) -> Version:
@@ -59,6 +58,7 @@ def from_string(self, version_str: str) -> Version:
             version_str,
             tag_format=self.tag_format,
             prerelease_token=self.prerelease_token,
+            version_compat=self.version_compat,
         )
 
     def from_tag(self, tag: str) -> Version | None:
diff --git a/src/semantic_release/version/version.py b/src/semantic_release/version/version.py
index 41ec5e107..79ee27ab8 100644
--- a/src/semantic_release/version/version.py
+++ b/src/semantic_release/version/version.py
@@ -6,7 +6,7 @@
 from itertools import zip_longest
 from typing import Callable, Union, overload
 
-from semantic_release.const import SEMVER_REGEX
+from semantic_release.const import PEP440_REGEX, SEMVER_REGEX
 from semantic_release.enums import LevelBump
 from semantic_release.errors import InvalidVersion
 from semantic_release.helpers import check_tag_format
@@ -55,6 +55,7 @@ def _wrapper(self: Version, other: VersionComparable) -> bool:
                     other,
                     tag_format=self.tag_format,
                     prerelease_token=self.prerelease_token,
+                    version_compat=self.version_compat,
                 )
             except InvalidVersion as ex:
                 raise TypeError(str(ex)) from ex
@@ -77,6 +78,7 @@ def __init__(
         *,
         prerelease_token: str = "rc",  # noqa: S107
         prerelease_revision: int | None = None,
+        version_compat: str = "semver",
         build_metadata: str = "",
         tag_format: str = "v{version}",
     ) -> None:
@@ -86,6 +88,7 @@ def __init__(
         self.prerelease_token = prerelease_token
         self.prerelease_revision = prerelease_revision
         self.build_metadata = build_metadata
+        self.version_compat = version_compat
         self._tag_format = tag_format
 
     @property
@@ -104,6 +107,7 @@ def parse(
         version_str: str,
         tag_format: str = "v{version}",
         prerelease_token: str = "rc",  # noqa: S107
+        version_compat: str = "semver",
     ) -> Version:
         """
         Parse version string to a Version instance.
@@ -113,6 +117,16 @@ def parse(
         :param prerelease_token: will be ignored if the version string is a prerelease,
             the parsed token from `version_str` will be used instead.
         """
+        if version_compat == "pep440":
+            cls._VERSION_REGEX = PEP440_REGEX
+        elif version_compat == "semver":
+            cls._VERSION_REGEX = SEMVER_REGEX
+        else:
+            raise ValueError(
+                f"Invalid version compatibility mode {version_compat!r}. "
+                "Valid options are 'pep440' and 'semver'."
+            )
+
         if not isinstance(version_str, str):
             raise InvalidVersion(f"{version_str!r} cannot be parsed as a Version")
 
@@ -123,14 +137,34 @@ def parse(
 
         prerelease = match.group("prerelease")
         if prerelease:
-            pm = re.match(r"(?P[a-zA-Z0-9-\.]+)\.(?P\d+)", prerelease)
-            if not pm:
+            if version_compat == "semver":
+                pm = re.match(
+                    r"(?P[a-zA-Z0-9-\.]+)\.(?P\d+)", prerelease
+                )
+                if not pm:
+                    raise NotImplementedError(
+                        f"{cls.__qualname__} currently supports only prereleases "
+                        r"of the format (-([a-zA-Z0-9-])\.\(\d+)), for example "
+                        r"'1.2.3-my-custom-3rc.4'."
+                    )
+                prerelease_token, prerelease_revision = pm.groups()
+            elif version_compat == "pep440":
+                pm = re.match(
+                    r"(?P(a|b|c|rc|alpha|beta|pre|preview|dev|post|rev|r))[-_\.]?(?P\d+)",
+                    prerelease,
+                )
+                if not pm:
+                    raise NotImplementedError(
+                        f"{cls.__qualname__} currently supports only prereleases "
+                        r"of the format ([-_\.](a|b|c|rc|alpha|beta|pre|preview|dev|post|rev|r)[-_\.]\(\d+)), for example "
+                        r"'1.2.3.dev4'."
+                    )
+                prerelease_token, _, prerelease_revision = pm.groups()
+            else:
                 raise NotImplementedError(
-                    f"{cls.__qualname__} currently supports only prereleases "
-                    r"of the format (-([a-zA-Z0-9-])\.\(\d+)), for example "
-                    r"'1.2.3-my-custom-3rc.4'."
+                    f"Invalid version compatibility mode {version_compat!r}. "
+                    "Valid options are 'pep440' and 'semver'."
                 )
-            prerelease_token, prerelease_revision = pm.groups()
             log.debug(
                 "parsed prerelease_token %s, prerelease_revision %s from version "
                 "string %s",
@@ -159,6 +193,7 @@ def parse(
             ),
             build_metadata=build_metadata,
             tag_format=tag_format,
+            version_compat=version_compat,
         )
 
     @property
@@ -167,11 +202,30 @@ def is_prerelease(self) -> bool:
 
     def __str__(self) -> str:
         full = f"{self.major}.{self.minor}.{self.patch}"
-        prerelease = (
-            f"-{self.prerelease_token}.{self.prerelease_revision}"
-            if self.prerelease_revision
-            else ""
-        )
+        if self.version_compat == "semver":
+            pre_str = f"-{self.prerelease_token}.{self.prerelease_revision}"
+        elif self.version_compat == "pep440":
+            if self.prerelease_token == "dev":  # noqa: S105
+                pre_str = f".{self.prerelease_token}{self.prerelease_revision}"
+            elif self.prerelease_token in ("post", "rev", "r"):
+                pre_str = f".post{self.prerelease_revision}"
+            elif self.prerelease_token in ("rc", "c", "pre", "preview"):
+                pre_str = f"rc{self.prerelease_revision}"
+            elif self.prerelease_token in ("alpha", "a"):
+                pre_str = f"a{self.prerelease_revision}"
+            elif self.prerelease_token in ("beta", "b"):
+                pre_str = f"b{self.prerelease_revision}"
+            else:
+                raise NotImplementedError(
+                    f"Invalid prerelease token {self.prerelease_token!r}. "
+                    "Valid options are 'dev', 'post', 'rev', 'r', 'rc', 'c', 'pre', 'preview', 'alpha', 'a', 'beta', 'b'."
+                )
+        else:
+            raise NotImplementedError(
+                f"Invalid version compatibility mode {self.version_compat!r}. "
+                "Valid options are 'pep440' and 'semver'."
+            )
+        prerelease = pre_str if self.prerelease_revision else ""
         build_metadata = f"+{self.build_metadata}" if self.build_metadata else ""
         return f"{full}{prerelease}{build_metadata}"
 
@@ -381,6 +435,7 @@ def to_prerelease(
             prerelease_token=token or self.prerelease_token,
             prerelease_revision=(revision or self.prerelease_revision) or 1,
             tag_format=self.tag_format,
+            version_compat=self.version_compat,
         )
 
     def finalize_version(self) -> Version:
diff --git a/tests/e2e/cmd_version/test_version_print.py b/tests/e2e/cmd_version/test_version_print.py
index b0226387d..348144cc6 100644
--- a/tests/e2e/cmd_version/test_version_print.py
+++ b/tests/e2e/cmd_version/test_version_print.py
@@ -341,7 +341,7 @@ def test_version_print_last_released_prints_version(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
@@ -396,7 +396,7 @@ def test_version_print_last_released_prints_released_if_commits(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
@@ -487,7 +487,7 @@ def test_version_print_last_released_on_detached_head(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
@@ -534,7 +534,7 @@ def test_version_print_last_released_on_nonrelease_branch(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
@@ -753,7 +753,7 @@ def test_version_print_last_released_tag_on_detached_head(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released-tag"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released-tag"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
@@ -810,7 +810,7 @@ def test_version_print_last_released_tag_on_nonrelease_branch(
     tags_before = {tag.name for tag in repo.tags}
 
     # Act
-    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--print-last-released-tag"]
+    cli_cmd = [MAIN_PROG_NAME, VERSION_SUBCMD, "--version-compat=semver", "--print-last-released-tag"]
     result = cli_runner.invoke(main, cli_cmd[1:])
 
     # take measurement after running the version command
diff --git a/tests/unit/semantic_release/version/test_declaration.py b/tests/unit/semantic_release/version/test_declaration.py
index f39d8f3be..ea56a870b 100644
--- a/tests/unit/semantic_release/version/test_declaration.py
+++ b/tests/unit/semantic_release/version/test_declaration.py
@@ -23,7 +23,7 @@
 @pytest.mark.usefixtures(init_example_project.__name__)
 def test_pyproject_toml_version_found(example_pyproject_toml: Path):
     decl = TomlVersionDeclaration(
-        example_pyproject_toml.resolve(), "tool.poetry.version"
+        example_pyproject_toml.resolve(), "tool.poetry.version", version_compat="semver"
     )
     versions = decl.parse()
     assert len(versions) == 1
@@ -33,7 +33,9 @@ def test_pyproject_toml_version_found(example_pyproject_toml: Path):
 @pytest.mark.usefixtures(init_example_project.__name__)
 def test_setup_cfg_version_found(example_setup_cfg: Path):
     decl = PatternVersionDeclaration(
-        example_setup_cfg.resolve(), r"^version *= *(?P.*)$"
+        example_setup_cfg.resolve(),
+        r"^version *= *(?P.*)$",
+        version_compat="semver",
     )
     versions = decl.parse()
     assert len(versions) == 1
@@ -58,12 +60,12 @@ def test_setup_cfg_version_found(example_setup_cfg: Path):
 @pytest.mark.usefixtures(init_example_project.__name__)
 def test_version_replace(decl_cls, config_file, search_text):
     new_version = Version(1, 0, 0)
-    decl = decl_cls(config_file.resolve(), search_text)
+    decl = decl_cls(config_file.resolve(), search_text, version_compat="semver")
     orig_content = decl.content
     new_content = decl.replace(new_version=new_version)
     decl.write(new_content)
 
-    new_decl = decl_cls(config_file.resolve(), search_text)
+    new_decl = decl_cls(config_file.resolve(), search_text, version_compat="semver")
     assert new_decl.parse() == {new_version}
 
     d = difflib.Differ()
@@ -95,7 +97,9 @@ def test_bad_version_regex_fails(search_text):
         ValueError, match="must use 'version'"
     ):
         mock_path_exists.return_value = True
-        PatternVersionDeclaration("doesn't matter", search_text)
+        PatternVersionDeclaration(
+            "doesn't matter", search_text, version_compat="semver"
+        )
 
 
 def test_pyproject_toml_no_version(tmp_path):
@@ -109,7 +113,9 @@ def test_pyproject_toml_no_version(tmp_path):
         )
     )
 
-    decl = TomlVersionDeclaration(pyproject_toml.resolve(), "tool.poetry.version")
+    decl = TomlVersionDeclaration(
+        pyproject_toml.resolve(), "tool.poetry.version", version_compat="semver"
+    )
     assert decl.parse() == set()
 
 
@@ -125,7 +131,7 @@ def test_setup_cfg_no_version(tmp_path):
     )
 
     decl = PatternVersionDeclaration(
-        setup_cfg.resolve(), r"^version = (?P.*)$"
+        setup_cfg.resolve(), r"^version = (?P.*)$", version_compat="semver"
     )
     assert decl.parse() == set()
 
@@ -135,4 +141,8 @@ def test_setup_cfg_no_version(tmp_path):
 )
 def test_version_decl_error_on_missing_file(decl_cls):
     with pytest.raises(FileNotFoundError):
-        decl_cls("/this/is/definitely/a/missing/path/asdfghjkl", "random search text")
+        decl_cls(
+            "/this/is/definitely/a/missing/path/asdfghjkl",
+            "random search text",
+            version_compat="semver",
+        )