From 947c57b48bee85753cf40296b98529da26bf4b58 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:39:33 -0600 Subject: [PATCH] feat(cmd-stamp): expand version stamp mechanism to support typed python variables (#1485) Implements: #1443 Co-authored-by: codejedi365 <17354856+codejedi365@users.noreply.github.com> Signed-off-by: codejedi365 * test(cmd-stamp): add unit test for stamping version on a typed python variable Co-authored-by: codejedi365 <17354856+codejedi365@users.noreply.github.com> Signed-off-by: codejedi365 * docs(configuration): document Python type annotation support for `version_variables` Co-authored-by: codejedi365 <17354856+codejedi365@users.noreply.github.com> Signed-off-by: codejedi365 --- docs/configuration/configuration.rst | 10 +++- .../version/declarations/pattern.py | 4 +- .../declarations/test_pattern_declaration.py | 52 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/docs/configuration/configuration.rst b/docs/configuration/configuration.rst index 0a11ce8a0..6d5a9ea86 100644 --- a/docs/configuration/configuration.rst +++ b/docs/configuration/configuration.rst @@ -1377,7 +1377,8 @@ version numbers. ] First, the ``__version__`` variable in ``src/semantic_release/__init__.py`` will be updated -with the next version using the `SemVer`_ number format. +with the next version using the `SemVer`_ number format. As of $NEW_RELEASE_TAG, this works +both with and without a Python type annotation on the variable: .. code-block:: diff @@ -1386,6 +1387,10 @@ with the next version using the `SemVer`_ number format. - __version__ = "0.1.0" + __version__ = "0.2.0" + # or with a type annotation ($NEW_RELEASE_TAG or greater): + - __version__: str = "0.1.0" + + __version__: str = "0.2.0" + Then, the ``version`` variable in ``docs/conf.py`` will be updated with the next version with the next version using the `SemVer`_ number format because of the explicit ``nf``. @@ -1450,6 +1455,9 @@ The regular expression generated from the ``version_variables`` definition will: the symbol. As of v10.0.0, a double-equals (``==``) operator is also supported as a valid operand symbol. As of v10.5.0, PSR can omit all operands as long as there is at least one whitespace character between the variable name and the version. + As of $NEW_RELEASE_TAG, an optional Python-style type annotation (e.g. ``: str``, + ``: typing.Final[str]``) between the variable name and the assignment operator is + also supported. 3. The value of the variable must match a `SemVer`_ regular expression and can be enclosed by single (``'``) or double (``"``) quotation marks but they must match. However, diff --git a/src/semantic_release/version/declarations/pattern.py b/src/semantic_release/version/declarations/pattern.py index 4d285b5a1..c9bc7734f 100644 --- a/src/semantic_release/version/declarations/pattern.py +++ b/src/semantic_release/version/declarations/pattern.py @@ -227,9 +227,11 @@ def from_string_definition( # Supports optional matching quotations around variable name # Negative lookbehind to ensure we don't match part of a variable name f"""(?x)(?P['"])?(?['"])?{value_replace_pattern_str}(?P=quote2)?""", ], diff --git a/tests/unit/semantic_release/version/declarations/test_pattern_declaration.py b/tests/unit/semantic_release/version/declarations/test_pattern_declaration.py index ddca3dbf6..31cd82bb1 100644 --- a/tests/unit/semantic_release/version/declarations/test_pattern_declaration.py +++ b/tests/unit/semantic_release/version/declarations/test_pattern_declaration.py @@ -268,6 +268,58 @@ def test_pattern_declaration_is_version_replacer(): """ ), ), + ( + "Python annotated variable with str type hint (number format)", + f"{test_file}:__version__:{VersionStampType.NUMBER_FORMAT.value}", + # irrelevant for this case + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with single quotes and str type annotation + """__version__: str = '1.0.0'""", + f"""__version__: str = '{next_version}'""", + ), + ( + "Python annotated variable with str type hint (tag format)", + f"{test_file}:__version__:{VersionStampType.TAG_FORMAT.value}", + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with single quotes and str type annotation + """__version__: str = 'v1.0.0'""", + f"""__version__: str = 'v{next_version}'""", + ), + ( + "Python annotated variable with quoted str type hint (number format)", + f"{test_file}:__version__:{VersionStampType.NUMBER_FORMAT.value}", + # irrelevant for this case + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with single quotes and str type annotation + """__version__: "str" = '1.0.0'""", + f"""__version__: "str" = '{next_version}'""", + ), + ( + "Python annotated variable with quoted str type hint (tag format)", + f"{test_file}:__version__:{VersionStampType.TAG_FORMAT.value}", + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with single quotes and str type annotation + """__version__: "str" = 'v1.0.0'""", + f"""__version__: "str" = 'v{next_version}'""", + ), + ( + "Python annotated variable with complex type hint", + f"{test_file}:__version__:{VersionStampType.NUMBER_FORMAT.value}", + # irrelevant for this case + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with double quotes and complex type annotation + '''__version__: typing.Final[str] = "1.0.0"''', + f'''__version__: typing.Final[str] = "{next_version}"''', + ), + ( + "Python annotated variable with complex type hint (tag format)", + f"{test_file}:__version__:{VersionStampType.TAG_FORMAT.value}", + # irrelevant for this case + lazy_fixture(default_tag_format_str.__name__), + # Uses equals separator with double quotes and complex type annotation + '''__version__: typing.Final[str] = "v1.0.0"''', + f'''__version__: typing.Final[str] = "v{next_version}"''', + ), ] ], )