-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathversion_check.py
147 lines (113 loc) · 3.9 KB
/
version_check.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import subprocess
import sys
from argparse import (
ArgumentParser,
Namespace,
)
from collections import namedtuple
from inspect import cleandoc
from pathlib import Path
from shutil import which
from typing import (
Any,
Dict,
Iterable,
Union,
)
Version = namedtuple("Version", ["major", "minor", "patch"])
_SUCCESS = 0
_FAILURE = 1
# fmt: off
_VERSION_MODULE_TEMPLATE = cleandoc('''
# ATTENTION:
# This file is generated, do not edit it manually!
# If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`.
MAJOR = {major}
MINOR = {minor}
PATCH = {patch}
VERSION = f"{{MAJOR}}.{{MINOR}}.{{PATCH}}"
''') + "\n"
# 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) 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"], capture_output=True)
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.")
version_file.unlink(missing_ok=True)
with open(version_file, "w") as f:
f.write(
_VERSION_MODULE_TEMPLATE.format(
major=version.major, minor=version.minor, patch=version.patch
)
)
def _create_parser() -> ArgumentParser:
parser = ArgumentParser()
parser.add_argument("version_module", help="Path to version module")
parser.add_argument("files", nargs="*")
parser.add_argument(
"-d",
"--debug",
action="store_true",
default=False,
help="enabled debug mode for execution.",
)
parser.add_argument(
"-f",
"--fix",
action="store_true",
default=False,
help="fix instead of check.",
)
return parser
def _main_debug(args: Namespace) -> int:
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:
print(
f"Version in pyproject.toml {poetry_version} and {args.version_module} {module_version} do not match!"
)
if args.fix:
print(
f"Updating version in file ({args.version_module}) from {module_version} to {poetry_version}"
)
return _SUCCESS
return _FAILURE
return _SUCCESS
def _main(args: Namespace) -> int:
try:
return _main_debug(args)
except Exception as ex:
print(f"Error while executing program, details: {ex}", file=sys.stderr)
return _FAILURE
def main(argv: Union[Iterable[str], None] = None) -> int:
parser = _create_parser()
args = parser.parse_args()
entry_point = _main if not args.debug else _main_debug
return entry_point(args)
if __name__ == "__main__":
sys.exit(main())