1
|
|
|
import os |
2
|
|
|
import re |
3
|
|
|
|
4
|
|
|
|
5
|
|
View Code Duplication |
class Versions: |
|
|
|
|
6
|
|
|
|
7
|
|
|
def __init__(self, versions_list): |
8
|
|
|
"""Sort and manipulate list of semver formatting versions.""" |
9
|
|
|
self._versions_list = versions_list |
10
|
|
|
self._versions = None |
11
|
|
|
|
12
|
|
|
@property |
13
|
|
|
def versions(self): |
14
|
|
|
"""Retrieve a dictionary of version part values from a list of versions.""" |
15
|
|
|
if not self._versions: |
16
|
|
|
self._versions = { |
17
|
|
|
tag: { |
18
|
|
|
'major': int(tag.split('.', 2)[0]), |
19
|
|
|
'minor': int(tag.split('.', 2)[1]), |
20
|
|
|
'patch': int(tag.split('.', 2)[2] if '-' not in tag else tag.split('.', 2)[2].split('-', 1)[0]), |
21
|
|
|
'cycle': '' if '-' not in tag else tag.split('.', 2)[2].split('-', 1)[1] |
22
|
|
|
} |
23
|
|
|
for tag in [s for s in self._versions_list if len(s) > 0 and not s.startswith('latest')] |
24
|
|
|
} |
25
|
|
|
return self._versions |
26
|
|
|
|
27
|
|
|
@property |
28
|
|
|
def sorted(self): |
29
|
|
|
"""Sort a list of semver formatted versions by major, minor, path and cycle.""" |
30
|
|
|
sort = [ |
31
|
|
|
k for k, v in sorted(self.versions.items(), |
32
|
|
|
reverse=True, |
33
|
|
|
key=lambda kv: (kv[1]['major'], kv[1]['minor'], kv[1]['patch'], kv[1]['cycle'])) |
34
|
|
|
] |
35
|
|
|
if 'latest' in self._versions_list: |
36
|
|
|
sort.insert(0, 'latest') |
37
|
|
|
return sort |
38
|
|
|
|
39
|
|
|
def latest(self): |
40
|
|
|
"""Retrieve the latest version.""" |
41
|
|
|
return self.sorted[0] |
42
|
|
|
|
43
|
|
|
|
44
|
|
View Code Duplication |
def get_version(source): |
|
|
|
|
45
|
|
|
""" |
46
|
|
|
Retrieve the version of a python distribution. |
47
|
|
|
|
48
|
|
|
version_file default is the <project_root>/_version.py |
49
|
|
|
|
50
|
|
|
:param source: Path to project root |
51
|
|
|
:return: Version string |
52
|
|
|
""" |
53
|
|
|
version_str_lines = open(os.path.join(source, os.path.basename(source), '_version.py'), "rt").read() |
54
|
|
|
version_str_regex = r"^__version__ = ['\"]([^'\"]*)['\"]" |
55
|
|
|
mo = re.search(version_str_regex, version_str_lines, re.M) |
56
|
|
|
if mo: |
57
|
|
|
return mo.group(1) |
58
|
|
|
else: |
59
|
|
|
raise RuntimeError("Unable to find version string in %s." % os.path.join(source, os.path.basename(source))) |
60
|
|
|
|
61
|
|
|
|
62
|
|
View Code Duplication |
def set_version(source): |
|
|
|
|
63
|
|
|
""" |
64
|
|
|
Set the version of a python distribution. |
65
|
|
|
|
66
|
|
|
version_file default is the <project_root>/_version.py |
67
|
|
|
|
68
|
|
|
:param source: Path to project root |
69
|
|
|
:return: Version string |
70
|
|
|
""" |
71
|
|
|
with open(os.path.join(source, os.path.basename(source), '_version.py'), "r+") as version_file: |
72
|
|
|
# Read existing version file |
73
|
|
|
version_str_lines = version_file.read() |
74
|
|
|
|
75
|
|
|
# Extract current version |
76
|
|
|
current_version = version_str_lines[version_str_lines.index("'") + 1:len(version_str_lines) - 2] |
77
|
|
|
parts = current_version.split('.') |
78
|
|
|
parts[-1] = str(int(parts[-1]) + 1) |
79
|
|
|
|
80
|
|
|
# Concatenate new version parts |
81
|
|
|
new_version = '.'.join(parts) |
82
|
|
|
|
83
|
|
|
# Write new version |
84
|
|
|
version_file.seek(0) |
85
|
|
|
version_file.truncate() |
86
|
|
|
version_file.write(version_str_lines.replace(current_version, new_version)) |
87
|
|
|
return new_version |
88
|
|
|
|