diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 4578c0f137..6d2475a6c6 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -19,7 +19,7 @@ jobs:
uses: ./.github/actions/python-environment
- name: Check Version(s)
- run: poetry run version-check `poetry run -- python -c "from noxconfig import PROJECT_CONFIG; print(PROJECT_CONFIG.version_file)"`
+ run: poetry run -- nox -s version:check -- `poetry run -- python -c "from noxconfig import PROJECT_CONFIG; print(PROJECT_CONFIG.version_file)"`
Documentation:
name: Docs
diff --git a/doc/changes/unreleased.md b/doc/changes/unreleased.md
index 79e701b844..5662f8595d 100644
--- a/doc/changes/unreleased.md
+++ b/doc/changes/unreleased.md
@@ -1 +1,5 @@
# Unreleased
+
+## ⚒️ Refactorings
+
+* [#412](https://github.com/exasol/python-toolbox/issues/392): Refactor pre commit hook package version.py into nox task
\ No newline at end of file
diff --git a/doc/developer_guide/modules/modules.rst b/doc/developer_guide/modules/modules.rst
index e241572593..0dfb809190 100644
--- a/doc/developer_guide/modules/modules.rst
+++ b/doc/developer_guide/modules/modules.rst
@@ -7,5 +7,3 @@ Modules
sphinx/sphinx
nox
nox_tasks
- pre_commit_hooks
-
diff --git a/doc/developer_guide/modules/pre_commit_hooks.rst b/doc/developer_guide/modules/pre_commit_hooks.rst
deleted file mode 100644
index 7807655d03..0000000000
--- a/doc/developer_guide/modules/pre_commit_hooks.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-pre_commit_hooks
-=================
-
-In the pre_commit_hook package contains git commit hooks and similar functionalities.
-
-.. figure:: ../../_static/nothing-to-see-here.png
- :alt: nothing to see here
- :target: https://imgflip.com/i/2a7gqa
-
- source: `imgflip.com `_
diff --git a/exasol/toolbox/cli.py b/exasol/toolbox/cli.py
index 5dbc818a7c..377572ee44 100644
--- a/exasol/toolbox/cli.py
+++ b/exasol/toolbox/cli.py
@@ -1,6 +1,6 @@
from argparse import ArgumentTypeError
-from exasol.toolbox.release import Version
+from exasol.toolbox.util.version import Version
def version(arg: str) -> Version:
diff --git a/exasol/toolbox/pre_commit_hooks/package_version.py b/exasol/toolbox/nox/_package_version.py
similarity index 50%
rename from exasol/toolbox/pre_commit_hooks/package_version.py
rename to exasol/toolbox/nox/_package_version.py
index d2d99def1e..1435f249b1 100644
--- a/exasol/toolbox/pre_commit_hooks/package_version.py
+++ b/exasol/toolbox/nox/_package_version.py
@@ -1,21 +1,17 @@
-import subprocess
+import argparse
import sys
from argparse import (
ArgumentParser,
Namespace,
)
-from collections import namedtuple
-from collections.abc import Iterable
from inspect import cleandoc
from pathlib import Path
-from shutil import which
-from typing import (
- Any,
- Dict,
- Union,
-)
-Version = namedtuple("Version", ["major", "minor", "patch"])
+import nox
+from nox import Session
+
+from exasol.toolbox.error import ToolboxError
+from exasol.toolbox.util.version import Version
_SUCCESS = 0
_FAILURE = 1
@@ -23,11 +19,11 @@
# fmt: off
_VERSION_MODULE_TEMPLATE = cleandoc('''
# ATTENTION:
- # This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using:
+ # This file is generated by exasol/toolbox/nox/_package_version.py when using:
# * either "poetry run -- nox -s project:fix"
- # * or "poetry run -- version-check --fix"
+ # * or "poetry run -- nox version:check -- --fix"
# Do not edit this file manually!
- # If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
+ # If you need to change the version, do so in the pyproject.toml, e.g. by using `poetry version X.Y.Z`.
MAJOR = {major}
MINOR = {minor}
PATCH = {patch}
@@ -37,47 +33,10 @@
# fmt: on
-def version_from_string(s: str) -> Version:
- """Converts a version string of the following format major.minor.patch to a version object"""
- major, minor, patch = (int(number, base=0) for number in s.split("."))
- return Version(major, minor, patch)
-
-
-class CommitHookError(Exception):
- """Indicates that this commit hook encountered an error"""
-
-
-def version_from_python_module(path: Path) -> Version:
- """Retrieve version information from the `version` module"""
- with open(path, encoding="utf-8") as file:
- _locals: dict[str, Any] = {}
- _globals: dict[str, Any] = {}
- exec(file.read(), _locals, _globals)
-
- try:
- version = _globals["VERSION"]
- except KeyError as ex:
- raise CommitHookError("Couldn't find version within module") from ex
-
- return version_from_string(version)
-
-
-def version_from_poetry() -> Version:
- poetry = which("poetry")
- if not poetry:
- raise CommitHookError("Couldn't find poetry executable")
-
- result = subprocess.run(
- [poetry, "version", "--no-ansi"], capture_output=True, check=False
- )
- version = result.stdout.decode().split()[1]
- return version_from_string(version)
-
-
def write_version_module(version: Version, path: str, exists_ok: bool = True) -> None:
version_file = Path(path)
if version_file.exists() and not exists_ok:
- raise CommitHookError(f"Version file [{version_file}] already exists.")
+ raise ToolboxError(f"Version file [{version_file}] already exists.")
version_file.unlink(missing_ok=True)
with open(version_file, "w", encoding="utf-8") as f:
f.write(
@@ -88,7 +47,10 @@ def write_version_module(version: Version, path: str, exists_ok: bool = True) ->
def _create_parser() -> ArgumentParser:
- parser = ArgumentParser()
+ parser = ArgumentParser(
+ prog="nox -s version:check --",
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ )
parser.add_argument("version_module", help="Path to version module")
parser.add_argument("files", nargs="*")
parser.add_argument(
@@ -109,13 +71,13 @@ def _create_parser() -> ArgumentParser:
def _main_debug(args: Namespace) -> int:
- module_version = version_from_python_module(args.version_module)
- poetry_version = version_from_poetry()
+ module_version = Version.from_python_module(args.version_module)
+ poetry_version = Version.from_poetry()
if args.fix:
write_version_module(poetry_version, args.version_module)
- if not module_version == poetry_version:
+ if module_version != poetry_version:
print(
f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!"
)
@@ -138,12 +100,11 @@ def _main(args: Namespace) -> int:
return _FAILURE
-def main(argv: Union[Iterable[str], None] = None) -> int:
+@nox.session(name="version:check", python=False)
+def version_check(session: Session) -> None:
+ """"""
parser = _create_parser()
- args = parser.parse_args()
+ args = parser.parse_args(session.posargs)
entry_point = _main if not args.debug else _main_debug
- return entry_point(args)
-
-
-if __name__ == "__main__":
- sys.exit(main())
+ if entry_point(args):
+ session.error()
diff --git a/exasol/toolbox/nox/_release.py b/exasol/toolbox/nox/_release.py
index 2d9db76008..fcd7ebe1bd 100644
--- a/exasol/toolbox/nox/_release.py
+++ b/exasol/toolbox/nox/_release.py
@@ -14,13 +14,15 @@
)
from exasol.toolbox.nox.plugin import NoxTasks
from exasol.toolbox.release import (
- ReleaseTypes,
- Version,
extract_release_notes,
new_changelog,
new_changes,
new_unreleased,
)
+from exasol.toolbox.util.version import (
+ ReleaseTypes,
+ Version,
+)
from noxconfig import PROJECT_CONFIG
diff --git a/exasol/toolbox/nox/_shared.py b/exasol/toolbox/nox/_shared.py
index d2e3e5c4d7..8f4284abdf 100644
--- a/exasol/toolbox/nox/_shared.py
+++ b/exasol/toolbox/nox/_shared.py
@@ -37,7 +37,7 @@ def python_files(project_root: Path) -> Iterable[Path]:
def _version(session: Session, mode: Mode, version_file: Path) -> None:
- command = ["version-check"]
+ command = ["nox", "-s", "version:check", "--"]
command = command if mode == Mode.Check else command + ["--fix"]
session.run(*command, f"{version_file}")
diff --git a/exasol/toolbox/nox/tasks.py b/exasol/toolbox/nox/tasks.py
index ce8f901b72..7076a4443b 100644
--- a/exasol/toolbox/nox/tasks.py
+++ b/exasol/toolbox/nox/tasks.py
@@ -85,5 +85,7 @@ def check(session: Session) -> None:
audit
)
+from exasol.toolbox.nox._package_version import version_check
+
# isort: on
# fmt: on
diff --git a/exasol/toolbox/release/__init__.py b/exasol/toolbox/release/__init__.py
index a8e5b93e6a..a20e24d0df 100644
--- a/exasol/toolbox/release/__init__.py
+++ b/exasol/toolbox/release/__init__.py
@@ -1,112 +1,10 @@
from __future__ import annotations
-import subprocess
-from dataclasses import dataclass
from datetime import datetime
-from enum import Enum
-from functools import (
- total_ordering,
- wraps,
-)
from inspect import cleandoc
from pathlib import Path
-from shutil import which
-
-from exasol.toolbox.error import ToolboxError
-
-
-def _index_or(container, index, default):
- try:
- return container[index]
- except IndexError:
- return default
-
-
-class ReleaseTypes(Enum):
- Major = "major"
- Minor = "minor"
- Patch = "patch"
-
- def __str__(self):
- return self.name.lower()
-
-
-def poetry_command(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- cmd = which("poetry")
- if not cmd:
- raise ToolboxError("Couldn't find poetry executable")
- try:
- return func(*args, **kwargs)
- except subprocess.CalledProcessError as ex:
- raise ToolboxError(f"Failed to execute: {ex.cmd}") from ex
-
- return wrapper
-
-
-@total_ordering
-@dataclass(frozen=True)
-class Version:
- major: int
- minor: int
- patch: int
-
- def __str__(self):
- return f"{self.major}.{self.minor}.{self.patch}"
-
- def __lt__(self, other: object):
- if not isinstance(other, Version):
- return NotImplemented
- return (
- self.major < other.major
- or (self.major <= other.major and self.minor < other.minor)
- or (
- self.major <= other.major
- and self.minor <= other.minor
- and self.patch < other.patch
- )
- )
-
- def __eq__(self, other: object):
- if not isinstance(other, Version):
- return NotImplemented
- return (
- self.major == other.major
- and self.minor == other.minor
- and self.patch == other.patch
- )
-
- @staticmethod
- def from_string(version):
- parts = [int(number, base=0) for number in version.split(".")]
- if len(parts) > 3:
- raise ValueError(
- "Version has an invalid format, "
- f"expected: '..', actual: '{version}'"
- )
- version = [_index_or(parts, i, 0) for i in range(3)]
- return Version(*version)
-
- @staticmethod
- @poetry_command
- def from_poetry():
- output = subprocess.run(
- ["poetry", "version", "--no-ansi", "--short"],
- capture_output=True,
- text=True,
- )
- return Version.from_string(output.stdout.strip())
-
- @staticmethod
- @poetry_command
- def upgrade_version_from_poetry(t: ReleaseTypes):
- output = subprocess.run(
- ["poetry", "version", str(t), "--dry-run", "--no-ansi", "--short"],
- capture_output=True,
- text=True,
- )
- return Version.from_string(output.stdout.strip())
+
+from exasol.toolbox.util.version import Version
def extract_release_notes(file: str | Path) -> str:
diff --git a/exasol/toolbox/sphinx/multiversion/main.py b/exasol/toolbox/sphinx/multiversion/main.py
index 694fd258a5..f183d97cc8 100644
--- a/exasol/toolbox/sphinx/multiversion/main.py
+++ b/exasol/toolbox/sphinx/multiversion/main.py
@@ -21,11 +21,11 @@
from sphinx import config as sphinx_config
from sphinx import project as sphinx_project
-from exasol.toolbox.release import Version as ExasolVersion
from exasol.toolbox.sphinx.multiversion import (
git,
sphinx,
)
+from exasol.toolbox.util.version import Version as ExasolVersion
logging.basicConfig(
level="INFO",
diff --git a/exasol/toolbox/sphinx/multiversion/sphinx.py b/exasol/toolbox/sphinx/multiversion/sphinx.py
index 18fb154880..91db2b8813 100644
--- a/exasol/toolbox/sphinx/multiversion/sphinx.py
+++ b/exasol/toolbox/sphinx/multiversion/sphinx.py
@@ -9,7 +9,7 @@
from sphinx.locale import _
from sphinx.util import i18n as sphinx_i18n
-from exasol.toolbox.release import Version as ExasolVersion
+from exasol.toolbox.util.version import Version as ExasolVersion
from exasol.toolbox.version import VERSION as PLUGIN_VERSION
logger = logging.getLogger(__name__)
diff --git a/exasol/toolbox/templates/github/workflows/checks.yml b/exasol/toolbox/templates/github/workflows/checks.yml
index b507c12165..cf650ff62f 100644
--- a/exasol/toolbox/templates/github/workflows/checks.yml
+++ b/exasol/toolbox/templates/github/workflows/checks.yml
@@ -22,7 +22,7 @@ jobs:
run: |
echo "Please enable the version check by replacing this output with shell command bellow:"
echo ""
- echo "poetry run -- version-check <>"
+ echo "poetry run -- nox -s version:check -- <>"
echo ""
echo "Note: <> needs to point to the version file of the project (version.py)."
exit 1
diff --git a/exasol/toolbox/pre_commit_hooks/__init__.py b/exasol/toolbox/util/__init__.py
similarity index 100%
rename from exasol/toolbox/pre_commit_hooks/__init__.py
rename to exasol/toolbox/util/__init__.py
diff --git a/exasol/toolbox/util/version.py b/exasol/toolbox/util/version.py
new file mode 100644
index 0000000000..d65968384d
--- /dev/null
+++ b/exasol/toolbox/util/version.py
@@ -0,0 +1,123 @@
+from __future__ import annotations
+
+import subprocess
+from dataclasses import dataclass
+from enum import Enum
+from functools import (
+ total_ordering,
+ wraps,
+)
+from pathlib import Path
+from shutil import which
+from typing import Any
+
+from exasol.toolbox.error import ToolboxError
+
+
+def _index_or(container, index, default):
+ try:
+ return container[index]
+ except IndexError:
+ return default
+
+
+class ReleaseTypes(Enum):
+ Major = "major"
+ Minor = "minor"
+ Patch = "patch"
+
+ def __str__(self):
+ return self.name.lower()
+
+
+def poetry_command(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ cmd = which("poetry")
+ if not cmd:
+ raise ToolboxError("Couldn't find poetry executable")
+ try:
+ return func(*args, **kwargs)
+ except subprocess.CalledProcessError as ex:
+ raise ToolboxError(f"Failed to execute: {ex.cmd}") from ex
+
+ return wrapper
+
+
+@total_ordering
+@dataclass(frozen=True)
+class Version:
+ major: int
+ minor: int
+ patch: int
+
+ def __str__(self):
+ return f"{self.major}.{self.minor}.{self.patch}"
+
+ def __lt__(self, other: object):
+ if not isinstance(other, Version):
+ return NotImplemented
+ return (
+ self.major < other.major
+ or (self.major <= other.major and self.minor < other.minor)
+ or (
+ self.major <= other.major
+ and self.minor <= other.minor
+ and self.patch < other.patch
+ )
+ )
+
+ def __eq__(self, other: object):
+ if not isinstance(other, Version):
+ return NotImplemented
+ return (
+ self.major == other.major
+ and self.minor == other.minor
+ and self.patch == other.patch
+ )
+
+ @staticmethod
+ def from_string(version):
+ parts = [int(number, base=0) for number in version.split(".")]
+ if len(parts) > 3:
+ raise ValueError(
+ "Version has an invalid format, "
+ f"expected: '..', actual: '{version}'"
+ )
+ version = [_index_or(parts, i, 0) for i in range(3)]
+ return Version(*version)
+
+ @staticmethod
+ @poetry_command
+ def from_poetry():
+ output = subprocess.run(
+ ["poetry", "version", "--no-ansi", "--short"],
+ capture_output=True,
+ text=True,
+ )
+ return Version.from_string(output.stdout.strip())
+
+ @staticmethod
+ @poetry_command
+ def upgrade_version_from_poetry(t: ReleaseTypes):
+ output = subprocess.run(
+ ["poetry", "version", str(t), "--dry-run", "--no-ansi", "--short"],
+ capture_output=True,
+ text=True,
+ )
+ return Version.from_string(output.stdout.strip())
+
+ @staticmethod
+ def from_python_module(path: Path) -> Version:
+ """Retrieve version information from the `version` module"""
+ with open(path, encoding="utf-8") as file:
+ _locals: dict[str, Any] = {}
+ _globals: dict[str, Any] = {}
+ exec(file.read(), _locals, _globals)
+
+ try:
+ version = _globals["VERSION"]
+ except KeyError as ex:
+ raise ToolboxError("Couldn't find version within module") from ex
+
+ return Version.from_string(version)
diff --git a/exasol/toolbox/version.py b/exasol/toolbox/version.py
index ccb7c4e012..bc4dfa29fa 100644
--- a/exasol/toolbox/version.py
+++ b/exasol/toolbox/version.py
@@ -1,9 +1,9 @@
# ATTENTION:
-# This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using:
+# This file is generated by exasol/toolbox/nox/_package_version.py when using:
# * either "poetry run -- nox -s project:fix"
-# * or "poetry run -- version-check --fix"
+# * or "poetry run -- nox version:check -- --fix"
# Do not edit this file manually!
-# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
+# If you need to change the version, do so in the pyproject.toml, e.g. by using `poetry version X.Y.Z`.
MAJOR = 1
MINOR = 1
PATCH = 0
diff --git a/project-template/{{cookiecutter.repo_name}}/exasol/{{cookiecutter.package_name}}/version.py b/project-template/{{cookiecutter.repo_name}}/exasol/{{cookiecutter.package_name}}/version.py
index 84d43669b2..7691647fdf 100644
--- a/project-template/{{cookiecutter.repo_name}}/exasol/{{cookiecutter.package_name}}/version.py
+++ b/project-template/{{cookiecutter.repo_name}}/exasol/{{cookiecutter.package_name}}/version.py
@@ -1,9 +1,9 @@
# ATTENTION:
-# This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using:
+# This file is generated by exasol/toolbox/nox/_package_version.py when using:
# * either "poetry run -- nox -s project:fix"
-# * or "poetry run -- version-check --fix"
+# * or "poetry run -- nox -s version:check -- --fix"
# Do not edit this file manually!
-# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
+# If you need to change the version, do so in the pyproject.toml, e.g. by using `poetry version X.Y.Z`.
MAJOR = 0
MINOR = 1
PATCH = 0
diff --git a/pyproject.toml b/pyproject.toml
index 5933590493..2426d13832 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -110,6 +110,5 @@ module = [
ignore_errors = true
[tool.poetry.plugins."console_scripts"]
-version-check = "exasol.toolbox.pre_commit_hooks.package_version:main"
tbx = 'exasol.toolbox.tools.tbx:CLI'
sphinx-multiversion = 'exasol.toolbox.sphinx.multiversion:main'
\ No newline at end of file
diff --git a/test/unit/cli_test.py b/test/unit/cli_test.py
index 29ed8ab65d..e97c365443 100644
--- a/test/unit/cli_test.py
+++ b/test/unit/cli_test.py
@@ -3,7 +3,7 @@
import pytest
from exasol.toolbox.cli import version
-from exasol.toolbox.release import Version
+from exasol.toolbox.util.version import Version
@pytest.mark.parametrize(
diff --git a/test/unit/release_test.py b/test/unit/release_test.py
index d1009fd423..32bb74ca18 100644
--- a/test/unit/release_test.py
+++ b/test/unit/release_test.py
@@ -1,4 +1,3 @@
-import subprocess
from datetime import datetime
from inspect import cleandoc
from subprocess import CalledProcessError
@@ -9,75 +8,15 @@
import pytest
-from exasol.toolbox.error import ToolboxError
from exasol.toolbox.nox._release import (
ReleaseError,
_trigger_release,
)
from exasol.toolbox.release import (
- ReleaseTypes,
- Version,
extract_release_notes,
new_changelog,
- poetry_command,
)
-
-
-@pytest.mark.parametrize(
- "input,expected",
- [
- ("1.2.3", Version(1, 2, 3)),
- ("1.2", Version(1, 2, 0)),
- ("1", Version(1, 0, 0)),
- ],
-)
-def test_create_version_from_string(input, expected):
- actual = Version.from_string(input)
- assert expected == actual
-
-
-@pytest.mark.parametrize(
- "old_version,new_version,expected",
- [
- (Version(1, 2, 3), Version(1, 2, 4), True),
- (Version(1, 2, 3), Version(1, 3, 3), True),
- (Version(1, 2, 3), Version(2, 2, 3), True),
- (Version(1, 2, 3), Version(1, 1, 3), False),
- (Version(1, 2, 3), Version(1, 2, 1), False),
- (Version(1, 2, 3), Version(0, 3, 3), False),
- ],
-)
-def test_is_later_version(old_version, new_version, expected):
- actual = new_version > old_version
- assert expected == actual
-
-
-@pytest.fixture
-def poetry_version():
- def set_poetry_version(version):
- return subprocess.CompletedProcess(
- args=["poetry", "version", "--no-ansi", "--short"],
- returncode=0,
- stdout=version,
- stderr="",
- )
-
- yield set_poetry_version
-
-
-@pytest.mark.parametrize(
- "version,expected",
- [
- ("1.2.3", Version(1, 2, 3)),
- ("1.2", Version(1, 2, 0)),
- ("1", Version(1, 0, 0)),
- ],
-)
-def test_version_from_poetry(poetry_version, version, expected):
- with patch("subprocess.run", return_value=poetry_version(version)):
- actual = Version.from_poetry()
-
- assert expected == actual
+from exasol.toolbox.util.version import Version
@pytest.mark.parametrize(
@@ -245,24 +184,3 @@ def simulate_fail(args, **kwargs):
with pytest.raises(ReleaseError) as ex:
_trigger_release()
assert f"release {version} already exists" in str(ex)
-
-
-@patch("exasol.toolbox.release.which", return_value=None)
-def test_poetry_decorator_no_poetry_executable(mock):
- @poetry_command
- def test():
- pass
-
- with pytest.raises(ToolboxError):
- test()
-
-
-@patch("exasol.toolbox.release.which", return_value="test/path")
-def test_poetry_decorator_subprocess(mock):
- @poetry_command
- def test():
- raise subprocess.CalledProcessError(returncode=1, cmd=["test"])
- pass
-
- with pytest.raises(ToolboxError):
- test()
diff --git a/test/unit/util/version_test.py b/test/unit/util/version_test.py
new file mode 100644
index 0000000000..caa2918551
--- /dev/null
+++ b/test/unit/util/version_test.py
@@ -0,0 +1,111 @@
+import subprocess
+from unittest.mock import (
+ patch,
+)
+
+import pytest
+
+from exasol.toolbox.error import ToolboxError
+from exasol.toolbox.util.version import (
+ Version,
+ poetry_command,
+)
+
+
+@pytest.mark.parametrize(
+ "input,expected",
+ [
+ ("1.2.3", Version(1, 2, 3)),
+ ("1.2", Version(1, 2, 0)),
+ ("1", Version(1, 0, 0)),
+ ],
+)
+def test_create_version_from_string(input, expected):
+ actual = Version.from_string(input)
+ assert expected == actual
+
+
+@pytest.mark.parametrize(
+ "old_version,new_version,expected",
+ [
+ (Version(1, 2, 3), Version(1, 2, 4), True),
+ (Version(1, 2, 3), Version(1, 3, 3), True),
+ (Version(1, 2, 3), Version(2, 2, 3), True),
+ (Version(1, 2, 3), Version(1, 1, 3), False),
+ (Version(1, 2, 3), Version(1, 2, 1), False),
+ (Version(1, 2, 3), Version(0, 3, 3), False),
+ ],
+)
+def test_is_later_version(old_version, new_version, expected):
+ actual = new_version > old_version
+ assert expected == actual
+
+
+@pytest.fixture
+def poetry_version():
+ def set_poetry_version(version):
+ return subprocess.CompletedProcess(
+ args=["poetry", "version", "--no-ansi", "--short"],
+ returncode=0,
+ stdout=version,
+ stderr="",
+ )
+
+ yield set_poetry_version
+
+
+@pytest.mark.parametrize(
+ "version,expected",
+ [
+ ("1.2.3", Version(1, 2, 3)),
+ ("1.2", Version(1, 2, 0)),
+ ("1", Version(1, 0, 0)),
+ ],
+)
+def test_version_from_poetry(poetry_version, version, expected):
+ with patch("subprocess.run", return_value=poetry_version(version)):
+ actual = Version.from_poetry()
+
+ assert expected == actual
+
+
+@patch("exasol.toolbox.util.version.which", return_value=None)
+def test_poetry_decorator_no_poetry_executable(mock):
+ @poetry_command
+ def test():
+ pass
+
+ with pytest.raises(ToolboxError):
+ test()
+
+
+@patch("exasol.toolbox.util.version.which", return_value="test/path")
+def test_poetry_decorator_subprocess(mock):
+ @poetry_command
+ def test():
+ raise subprocess.CalledProcessError(returncode=1, cmd=["test"])
+ pass
+
+ with pytest.raises(ToolboxError):
+ test()
+
+
+def test_version_from_python_module(tmp_path):
+ tmp_file = tmp_path / "file"
+ file = """
+MAJOR = 1
+MINOR = 2
+PATCH = 3
+VERSION = f"{MAJOR}.{MINOR}.{PATCH}"
+__version__ = VERSION
+ """
+ tmp_file.write_text(file)
+ assert Version.from_python_module(tmp_file) == Version.from_string("1.2.3")
+
+
+def test_version_from_python_no_module_error(tmp_path):
+ file_path = tmp_path / "file"
+ file_path.write_text("")
+ with pytest.raises(ToolboxError) as ex:
+ Version.from_python_module(file_path)
+ assert str(ex.value) == "Couldn't find version within module"