Skip to content

Commit e1104e0

Browse files
Refactoring/#392 refactor pre commit hook package version.py into nox task (#412)
* version-check was refactored into nox task and its usage changed --------- Co-authored-by: Ariel Schulz <[email protected]>
1 parent 373669e commit e1104e0

File tree

21 files changed

+283
-277
lines changed

21 files changed

+283
-277
lines changed

.github/workflows/checks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
uses: ./.github/actions/python-environment
2020

2121
- name: Check Version(s)
22-
run: poetry run version-check `poetry run -- python -c "from noxconfig import PROJECT_CONFIG; print(PROJECT_CONFIG.version_file)"`
22+
run: poetry run -- nox -s version:check -- `poetry run -- python -c "from noxconfig import PROJECT_CONFIG; print(PROJECT_CONFIG.version_file)"`
2323

2424
Documentation:
2525
name: Docs

doc/changes/unreleased.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
# Unreleased
2+
3+
## ⚒️ Refactorings
4+
5+
* [#412](https://github.com/exasol/python-toolbox/issues/392): Refactor pre commit hook package version.py into nox task

doc/developer_guide/modules/modules.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,3 @@ Modules
77
sphinx/sphinx
88
nox
99
nox_tasks
10-
pre_commit_hooks
11-

doc/developer_guide/modules/pre_commit_hooks.rst

Lines changed: 0 additions & 10 deletions
This file was deleted.

exasol/toolbox/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from argparse import ArgumentTypeError
22

3-
from exasol.toolbox.release import Version
3+
from exasol.toolbox.util.version import Version
44

55

66
def version(arg: str) -> Version:
Lines changed: 23 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,29 @@
1-
import subprocess
1+
import argparse
22
import sys
33
from argparse import (
44
ArgumentParser,
55
Namespace,
66
)
7-
from collections import namedtuple
8-
from collections.abc import Iterable
97
from inspect import cleandoc
108
from pathlib import Path
11-
from shutil import which
12-
from typing import (
13-
Any,
14-
Dict,
15-
Union,
16-
)
179

18-
Version = namedtuple("Version", ["major", "minor", "patch"])
10+
import nox
11+
from nox import Session
12+
13+
from exasol.toolbox.error import ToolboxError
14+
from exasol.toolbox.util.version import Version
1915

2016
_SUCCESS = 0
2117
_FAILURE = 1
2218

2319
# fmt: off
2420
_VERSION_MODULE_TEMPLATE = cleandoc('''
2521
# ATTENTION:
26-
# This file is generated by exasol/toolbox/pre_commit_hooks/package_version.py when using:
22+
# This file is generated by exasol/toolbox/nox/_package_version.py when using:
2723
# * either "poetry run -- nox -s project:fix"
28-
# * or "poetry run -- version-check <path/version.py> --fix"
24+
# * or "poetry run -- nox version:check -- <path/version.py> --fix"
2925
# Do not edit this file manually!
30-
# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
26+
# If you need to change the version, do so in the pyproject.toml, e.g. by using `poetry version X.Y.Z`.
3127
MAJOR = {major}
3228
MINOR = {minor}
3329
PATCH = {patch}
@@ -37,47 +33,10 @@
3733
# fmt: on
3834

3935

40-
def version_from_string(s: str) -> Version:
41-
"""Converts a version string of the following format major.minor.patch to a version object"""
42-
major, minor, patch = (int(number, base=0) for number in s.split("."))
43-
return Version(major, minor, patch)
44-
45-
46-
class CommitHookError(Exception):
47-
"""Indicates that this commit hook encountered an error"""
48-
49-
50-
def version_from_python_module(path: Path) -> Version:
51-
"""Retrieve version information from the `version` module"""
52-
with open(path, encoding="utf-8") as file:
53-
_locals: dict[str, Any] = {}
54-
_globals: dict[str, Any] = {}
55-
exec(file.read(), _locals, _globals)
56-
57-
try:
58-
version = _globals["VERSION"]
59-
except KeyError as ex:
60-
raise CommitHookError("Couldn't find version within module") from ex
61-
62-
return version_from_string(version)
63-
64-
65-
def version_from_poetry() -> Version:
66-
poetry = which("poetry")
67-
if not poetry:
68-
raise CommitHookError("Couldn't find poetry executable")
69-
70-
result = subprocess.run(
71-
[poetry, "version", "--no-ansi"], capture_output=True, check=False
72-
)
73-
version = result.stdout.decode().split()[1]
74-
return version_from_string(version)
75-
76-
7736
def write_version_module(version: Version, path: str, exists_ok: bool = True) -> None:
7837
version_file = Path(path)
7938
if version_file.exists() and not exists_ok:
80-
raise CommitHookError(f"Version file [{version_file}] already exists.")
39+
raise ToolboxError(f"Version file [{version_file}] already exists.")
8140
version_file.unlink(missing_ok=True)
8241
with open(version_file, "w", encoding="utf-8") as f:
8342
f.write(
@@ -88,7 +47,10 @@ def write_version_module(version: Version, path: str, exists_ok: bool = True) ->
8847

8948

9049
def _create_parser() -> ArgumentParser:
91-
parser = ArgumentParser()
50+
parser = ArgumentParser(
51+
prog="nox -s version:check --",
52+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
53+
)
9254
parser.add_argument("version_module", help="Path to version module")
9355
parser.add_argument("files", nargs="*")
9456
parser.add_argument(
@@ -109,13 +71,13 @@ def _create_parser() -> ArgumentParser:
10971

11072

11173
def _main_debug(args: Namespace) -> int:
112-
module_version = version_from_python_module(args.version_module)
113-
poetry_version = version_from_poetry()
74+
module_version = Version.from_python_module(args.version_module)
75+
poetry_version = Version.from_poetry()
11476

11577
if args.fix:
11678
write_version_module(poetry_version, args.version_module)
11779

118-
if not module_version == poetry_version:
80+
if module_version != poetry_version:
11981
print(
12082
f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!"
12183
)
@@ -138,12 +100,11 @@ def _main(args: Namespace) -> int:
138100
return _FAILURE
139101

140102

141-
def main(argv: Union[Iterable[str], None] = None) -> int:
103+
@nox.session(name="version:check", python=False)
104+
def version_check(session: Session) -> None:
105+
""""""
142106
parser = _create_parser()
143-
args = parser.parse_args()
107+
args = parser.parse_args(session.posargs)
144108
entry_point = _main if not args.debug else _main_debug
145-
return entry_point(args)
146-
147-
148-
if __name__ == "__main__":
149-
sys.exit(main())
109+
if entry_point(args):
110+
session.error()

exasol/toolbox/nox/_release.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
)
1515
from exasol.toolbox.nox.plugin import NoxTasks
1616
from exasol.toolbox.release import (
17-
ReleaseTypes,
18-
Version,
1917
extract_release_notes,
2018
new_changelog,
2119
new_changes,
2220
new_unreleased,
2321
)
22+
from exasol.toolbox.util.version import (
23+
ReleaseTypes,
24+
Version,
25+
)
2426
from noxconfig import PROJECT_CONFIG
2527

2628

exasol/toolbox/nox/_shared.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def python_files(project_root: Path) -> Iterable[Path]:
3737

3838

3939
def _version(session: Session, mode: Mode, version_file: Path) -> None:
40-
command = ["version-check"]
40+
command = ["nox", "-s", "version:check", "--"]
4141
command = command if mode == Mode.Check else command + ["--fix"]
4242
session.run(*command, f"{version_file}")
4343

exasol/toolbox/nox/tasks.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,7 @@ def check(session: Session) -> None:
8585
audit
8686
)
8787

88+
from exasol.toolbox.nox._package_version import version_check
89+
8890
# isort: on
8991
# fmt: on

exasol/toolbox/release/__init__.py

Lines changed: 2 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,10 @@
11
from __future__ import annotations
22

3-
import subprocess
4-
from dataclasses import dataclass
53
from datetime import datetime
6-
from enum import Enum
7-
from functools import (
8-
total_ordering,
9-
wraps,
10-
)
114
from inspect import cleandoc
125
from pathlib import Path
13-
from shutil import which
14-
15-
from exasol.toolbox.error import ToolboxError
16-
17-
18-
def _index_or(container, index, default):
19-
try:
20-
return container[index]
21-
except IndexError:
22-
return default
23-
24-
25-
class ReleaseTypes(Enum):
26-
Major = "major"
27-
Minor = "minor"
28-
Patch = "patch"
29-
30-
def __str__(self):
31-
return self.name.lower()
32-
33-
34-
def poetry_command(func):
35-
@wraps(func)
36-
def wrapper(*args, **kwargs):
37-
cmd = which("poetry")
38-
if not cmd:
39-
raise ToolboxError("Couldn't find poetry executable")
40-
try:
41-
return func(*args, **kwargs)
42-
except subprocess.CalledProcessError as ex:
43-
raise ToolboxError(f"Failed to execute: {ex.cmd}") from ex
44-
45-
return wrapper
46-
47-
48-
@total_ordering
49-
@dataclass(frozen=True)
50-
class Version:
51-
major: int
52-
minor: int
53-
patch: int
54-
55-
def __str__(self):
56-
return f"{self.major}.{self.minor}.{self.patch}"
57-
58-
def __lt__(self, other: object):
59-
if not isinstance(other, Version):
60-
return NotImplemented
61-
return (
62-
self.major < other.major
63-
or (self.major <= other.major and self.minor < other.minor)
64-
or (
65-
self.major <= other.major
66-
and self.minor <= other.minor
67-
and self.patch < other.patch
68-
)
69-
)
70-
71-
def __eq__(self, other: object):
72-
if not isinstance(other, Version):
73-
return NotImplemented
74-
return (
75-
self.major == other.major
76-
and self.minor == other.minor
77-
and self.patch == other.patch
78-
)
79-
80-
@staticmethod
81-
def from_string(version):
82-
parts = [int(number, base=0) for number in version.split(".")]
83-
if len(parts) > 3:
84-
raise ValueError(
85-
"Version has an invalid format, "
86-
f"expected: '<major>.<minor>.<patch>', actual: '{version}'"
87-
)
88-
version = [_index_or(parts, i, 0) for i in range(3)]
89-
return Version(*version)
90-
91-
@staticmethod
92-
@poetry_command
93-
def from_poetry():
94-
output = subprocess.run(
95-
["poetry", "version", "--no-ansi", "--short"],
96-
capture_output=True,
97-
text=True,
98-
)
99-
return Version.from_string(output.stdout.strip())
100-
101-
@staticmethod
102-
@poetry_command
103-
def upgrade_version_from_poetry(t: ReleaseTypes):
104-
output = subprocess.run(
105-
["poetry", "version", str(t), "--dry-run", "--no-ansi", "--short"],
106-
capture_output=True,
107-
text=True,
108-
)
109-
return Version.from_string(output.stdout.strip())
6+
7+
from exasol.toolbox.util.version import Version
1108

1119

11210
def extract_release_notes(file: str | Path) -> str:

0 commit comments

Comments
 (0)