Skip to content

Refactoring/#392 refactor pre commit hook package version.py into nox task #412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
uses: ./.github/actions/python-environment
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a brief description to #392 answering:

  • what we want to change
  • why we want to make this change


- 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
Expand Down
6 changes: 5 additions & 1 deletion doc/changes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@

## ✨ Features

* [#378](https://github.com/exasol/python-toolbox/pull/378/files): Add Nox task to trigger a release
* [#378](https://github.com/exasol/python-toolbox/pull/378/files): Add Nox task to trigger a release
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad 😞 should have caught last time. These should refer to the issue number.

Suggested change
* [#378](https://github.com/exasol/python-toolbox/pull/378/files): Add Nox task to trigger a release
* [#368](https://github.com/exasol/python-toolbox/issues/368): Add Nox task to trigger a release


## ⚒️ Refactorings

* [#412](https://github.com/exasol/python-toolbox/pull/412): Refactor pre commit hook package version.py into nox task
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* [#412](https://github.com/exasol/python-toolbox/pull/412): Refactor pre commit hook package version.py into nox task
* [#392](https://github.com/exasol/python-toolbox/issues/392): Refactor pre-commit hook package version.py into nox task

2 changes: 1 addition & 1 deletion exasol/toolbox/cli.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import subprocess
import argparse
import sys
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the following:

  • exasol/toolbox/pre_commit_hooks directory, as no longer has code in it
  • doc/developer_guide/modules/pre_commit_hooks.rst as no longer relevant

Please update:

  • doc/developer_guide/modules/modules.rst by removing pre_commit_hooks entry

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

# 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 <path/version.py> --fix"
# * or "poetry run -- nox version:check -- <path/version.py> --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}
Expand All @@ -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(
Expand All @@ -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(
Expand All @@ -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!"
)
Expand All @@ -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()
6 changes: 4 additions & 2 deletions exasol/toolbox/nox/_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
2 changes: 1 addition & 1 deletion exasol/toolbox/nox/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _deny_filter(files: Iterable[Path], deny_list: Iterable[str]) -> Iterable[Pa


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}")

Expand Down
2 changes: 2 additions & 0 deletions exasol/toolbox/nox/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,7 @@ def check(session: Session) -> None:
audit
)

from exasol.toolbox.nox._package_version import version_check

# isort: on
# fmt: on
106 changes: 2 additions & 104 deletions exasol/toolbox/release/__init__.py
Original file line number Diff line number Diff line change
@@ -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: '<major>.<minor>.<patch>', 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:
Expand Down
2 changes: 1 addition & 1 deletion exasol/toolbox/sphinx/multiversion/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion exasol/toolbox/sphinx/multiversion/sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
2 changes: 1 addition & 1 deletion exasol/toolbox/templates/github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<VERSION_PY>>"
echo "poetry run -- nox -s version:check -- <<VERSION_PY>>"
echo ""
echo "Note: <<VERSION_PY>> needs to point to the version file of the project (version.py)."
exit 1
Expand Down
Empty file added exasol/toolbox/util/__init__.py
Empty file.
Loading