-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathcomponent_versions.py
executable file
·172 lines (155 loc) · 7.44 KB
/
component_versions.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env python3
# Dictionary to track version numbers for each METplus component
# The key of each entry is the coordinated release version, e.g. 6.0
# The value is another dictionary where the key is the METplus component name
# (in lower-case) and the value is a string that contains the latest
# X.Y.Z version of that component or None if no version is available.
# Add entries for a new coordinated release at the top of the dictionary.
# The versions should be updated when a bugfix release is created.
# METexpress does not include a release for the beta versions, so the value for
# METexpress should be set to None until the official coordinated release
# has been created.
import sys
VERSION_LOOKUP = {
'6.1': {
'metplus': '6.1.0',
'met': '12.1.0',
'metplotpy': '3.1.0',
'metcalcpy': '3.1.0',
'metdataio': '3.1.0',
'metviewer': '6.1.0',
'metexpress': None,
},
'6.0': {
'metplus': '6.0.0',
'met': '12.0.0',
'metplotpy': '3.0.0',
'metcalcpy': '3.0.0',
'metdataio': '3.0.0',
'metviewer': '6.0.0',
'metexpress': '6.0.0',
},
'5.1': {
'metplus': '5.1.0',
'met': '11.1.1',
'metplotpy': '2.1.0',
'metcalcpy': '2.1.0',
'metdataio': '2.1.0',
'metviewer': '5.1.0',
'metexpress': '5.3.5',
},
}
# assumes the 2nd highest version in the table is the latest
# the highest version in the table is in development
LATEST_OFFICIAL_RELEASE = sorted(VERSION_LOOKUP.keys(), reverse=True)[1]
DEFAULT_OUTPUT_FORMAT = "v{X}.{Y}.{Z}{N}"
def get_component_version(input_component, input_version, output_component,
output_format=DEFAULT_OUTPUT_FORMAT, get_dev=True,
rc_is_dev=False):
"""!Get the version of a requested METplus component given another METplus
component and its version. Parses out X.Y version numbers of input version
to find desired version. Optionally specific format of output content.
If input version ends with "-dev", then return "develop".
@param input_component name of METplus component to use to find version,
e.g. MET, METplus, or METplotpy (case-insensitive).
@param input_version version of input_component to search.
@param output_component name of METplus component to obtain version number
@param output_format (optional) format to use to output version number.
{X}, {Y}, and {Z} will be replaced with x, y, and z version numbers from
X.Y.Z. {N} will be replaced with development version if found in the
input version, e.g. "-beta3" or "-rc1"
@param get_dev (optional) if True, get corresponding -beta version.
If False, return "develop" if input is beta. Also include -rc version if
rc_is_dev is True.
@returns string of requested version number, or "develop" if input version
ends with "-dev", or None if version number could not be determined.
@param rc_is_dev (optional) if True, an -rcN version will be considered a
development version, otherwise it will not. Defaults to False because we
create a main_vX.Y branch for the rc1 release, so we do not want to use
the develop branch for rc versions.
"""
if _is_development(input_version, get_dev, rc_is_dev):
return 'develop'
coord_version = get_coordinated_version(input_component, input_version)
versions = VERSION_LOOKUP.get(coord_version)
if versions is None:
return None
output_version = versions.get(output_component.lower())
if output_version is None:
return None
x, y, z = output_version.split('.')
dev_version = input_version.split('-')[1:]
dev_version = '' if not dev_version else f"-{dev_version[0]}"
return output_format.format(X=x, Y=y, Z=z, N=dev_version)
def _is_development(input_version, get_dev, rc_is_dev):
if '-dev' in input_version or input_version == "develop":
return True
check_exts = ['-beta']
if rc_is_dev:
check_exts.append('-rc')
if not get_dev and any(ext in input_version for ext in check_exts):
return True
return False
def get_coordinated_version(component, version):
"""!Get coordinated release version number based on the X.Y version number
of a given METplus component.
@param component name of METplus component to search (case-insensitive)
@param version number of version to search for. Can be formatted with main_v
prefix and development release info, e.g. main_vX.Y or X.Y.Z-beta3.
@returns string of coordinated release version number X.Y or None.
"""
# remove main_v or v prefix, remove content after dash
search_version = version.removeprefix('main_').lstrip('v').split('-')[0]
# get X.Y only
search_version = '.'.join(search_version.split('.')[:2])
# look for component version that begins with search version
for coord_version, versions in VERSION_LOOKUP.items():
try:
if versions.get(component.lower()).startswith(search_version):
return coord_version
except AttributeError:
pass
return None
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input_component',
default='metplus',
help='Name of METplus component to use to find version.'
' Default is METplus.')
parser.add_argument('-v', '--input_version',
default=LATEST_OFFICIAL_RELEASE,
help='version of input_component to search.'
' Default is latest official release')
parser.add_argument('-o', '--output_component', required=True,
help='name of METplus component to obtain version')
parser.add_argument('-f', '--output_format',
default=DEFAULT_OUTPUT_FORMAT,
help='format to use to output version number.'
'{X}, {Y}, and {Z} will be replaced with x, y, and'
' z version numbers from X.Y.Z. {N} will be '
'replaced with development version if found in the'
' input version, e.g. "-beta3" or "-rc1".'
' Default is v{X}.{Y}.{Z}{N}')
parser.add_argument('--get_dev_version', action=argparse.BooleanOptionalAction,
default=True,
help='If True, get corresponding -beta or -rc version. '
'If False, return develop if development version.')
parser.add_argument('--rc_is_dev', action=argparse.BooleanOptionalAction,
default=False,
help='If True, an -rcN version will be considered a '
'development version, otherwise it will not. '
'Defaults to False because we create a main_vX.Y '
'branch for the rc1 release, so we do not want to '
'use the develop branch for rc versions')
args = parser.parse_args()
return get_component_version(args.input_component, args.input_version,
args.output_component, args.output_format,
args.get_dev_version, args.rc_is_dev)
def init():
if __name__ == "__main__":
out_version = main()
if not out_version:
sys.exit(1)
print(out_version)
init()