-
Notifications
You must be signed in to change notification settings - Fork 257
/
bumpversion.py
124 lines (99 loc) · 3.91 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
122
123
124
# Copyright (C) 2023-2024 Enzo Busseti
#
# This file is part of Cvxportfolio.
#
# Cvxportfolio is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Cvxportfolio is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# Cvxportfolio. If not, see <https://www.gnu.org/licenses/>.
"""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)