-
Notifications
You must be signed in to change notification settings - Fork 226
/
bumpversion.py
121 lines (96 loc) · 3.77 KB
/
bumpversion.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
# Copyright 2023 Enzo Busseti
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Find __version__ in __init__.py in file tree (BFS) and upgrade.
Additionally, look for version string in any setup.py, pyproject.toml,
and conf.py and do the same. Version is in the format X.Y.Z,
where X, Y, and Z are integers. Take argument revision (Z -> Z+1),
minor (Y -> Y+1, Z -> 0), or major (X -> X+1, Y -> 0, Z -> 0).
Add the modifications to git staging, commit with version number and
editable message (opens git configured text editor), tag with version number,
push everything to origin.
"""
import subprocess
from ast import literal_eval
from pathlib import Path
def findversion(root='.'):
"""Find version number. Skip [env, venv, .*].
We use the first __init__.py with a __version__ that we find.
:param root: Root folder of the project.
:type root: pathlib.Path or str
:returns: Found version string.
:rtype: str
"""
p = Path(root)
for fname in p.iterdir():
if fname.name == '__init__.py':
with open(fname, encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
if '__version__' in line:
return literal_eval(line.split('=')[1])
if fname.is_dir():
if not (fname.name in ['env', 'venv'] or fname.name[0] == '.'):
result = findversion(fname)
if result:
return result
def replaceversion(new_version, version, root='.'):
"""Replace version number. Skip [env, venv, .*].
We replace in all __init__.py, conf.py, setup.py, and pyproject.toml
:param new_version: New version.
:type new_version: str
:param version: Old version.
:type version: str
:param root: Root folder of the project.
:type root: pathlib.Path or str
"""
p = Path(root)
for fname in p.iterdir():
if fname.name in ['__init__.py', 'conf.py', 'setup.py',
'pyproject.toml']:
lines = []
with open(fname, 'rt', encoding="utf-8") as fin:
for line in fin:
lines.append(line.replace(version, new_version))
with open(fname, "wt", encoding="utf-8") as fout:
for line in lines:
fout.write(line)
subprocess.run(['git', 'add', str(fname)], check=False)
if fname.is_dir():
if not (fname.name in ['env', 'venv'] or fname.name[0] == '.'):
replaceversion(new_version, version, root=fname)
if __name__ == "__main__":
while True:
print('[revision/minor/major]')
WHAT = input()
if WHAT in ['revision', 'minor', 'major']:
break
VERSION = findversion()
X, Y, Z = [int(el) for el in VERSION.split('.')]
if WHAT == 'revision':
Z += 1
if WHAT == 'minor':
Y += 1
Z = 0
if WHAT == 'major':
X += 1
Y = 0
Z = 0
NEW_VERSION = f"{X}.{Y}.{Z}"
print(NEW_VERSION)
replaceversion(NEW_VERSION, VERSION)
subprocess.run(['git', 'commit', '--no-verify', '-em',
f"version {NEW_VERSION}\n"], check=False)
subprocess.run(['git', 'tag', NEW_VERSION], check=False)
subprocess.run(
['git', 'push', '--no-verify', 'origin', NEW_VERSION], check=False)