Salome HOME
sat launcher : nouvelle option -p qui permet de générer un lanceur pour un sous ensem...
[tools/sat.git] / src / versionMinorMajorPatch.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3
4 #  Copyright (C) 2010-2018  CEA/DEN
5 #
6 #  This library is free software; you can redistribute it and/or
7 #  modify it under the terms of the GNU Lesser General Public
8 #  License as published by the Free Software Foundation; either
9 #  version 2.1 of the License.
10 #
11 #  This library is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #  Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public
17 #  License along with this library; if not, write to the Free Software
18 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19
20
21 """\
22 class and utilities to define a version as MAJOR.MINOR.PATCH,
23 and range of versions
24
25 | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
26 | increment the
27 | MAJOR version when you make incompatible API changes,
28 | MINOR version when you add functionality in a backwards-compatible manner,
29 | PATCH version when you make backwards-compatible bug fixes.
30 """
31
32 import os
33 import sys
34
35 verbose = False # True
36
37 #############################################
38 def only_numbers(aStr):
39   """
40   Remove non numericals characters from string,
41
42   :param aStr: string to work
43   :return: None if no number presence
44   """
45   res = ''.join([nb for nb in aStr if nb in '0123456789'])
46   if res == "":
47     return None
48   else:
49     return res
50
51 #############################################
52 def remove_startswith(aStr, startsToCheck):
53   """
54   remove starting strings, if begining of aStr correspond
55   order of list startsToCheck matter
56   do the stuff only for the first correspondence in startsToCheck
57   """
58   for s in startsToCheck:
59     if aStr.startswith(s):
60       return aStr[len(s):]
61   return aStr
62
63 #############################################
64 def toList_majorMinorPatch(aStr, verbose=False):
65   """
66   Returns list of integer as  [major, minor, patch] from a string,
67
68   | accepts '1.2.3' '1_2_3' 'version_1.2.3' 'version1.2.3' 'v1.2.3',
69   | completion '123' means '123.0.0', '1.2' means '1.2.0'
70   | lower or upper
71   | raise exception if problem
72   """
73   if verbose: print("toList_majorMinorPatch('%s')" % aStr)
74   res = aStr.replace(" ", "")
75   res = res.lower()
76   res = remove_startswith(res, "version_ version v".split())
77   res = res.replace(".", "_").split("_")
78   if len(res) > 3:
79     msg = "Not a major_minor_patch correct syntax: '%s'" % aStr
80     raise Exception(msg)
81   if len(res) == 0:
82     msg = "An empty string is not a major_minor_patch syntax"
83     raise Exception(msg)
84
85   # complete MINOR.PATCH if not existing
86   if len(res) == 1:
87     res.append("0")
88   if len(res) == 2:
89     res.append("0")
90
91   try:
92     ii = int(res[0])
93   except:
94     msg = "major in major_minor_patch is not integer: '%s'" % aStr
95     raise Exception(msg)
96   if ii < 0:
97     msg = "major in major_minor_patch is negative integer: '%s'" % aStr
98     raise Exception(msg)
99
100   try:
101     ii = int(res[1])
102   except:
103     msg = "minor in major_minor_patch is not integer: '%s'" % aStr
104     raise Exception(msg)
105   if ii < 0:
106     msg = "minor in major_minor_patch is negative integer: '%s'" % aStr
107     raise Exception(msg)
108
109   try:
110     ii = int(res[2])
111   except:
112     msg = "patch in major_minor_patch is not integer: '%s'" % aStr
113     raise Exception(msg)
114   if ii < 0:
115     msg = "patch in major_minor_patch is negative integer: '%s'" % aStr
116     raise Exception(msg)
117
118   return [int(i) for i in res]
119
120 #############################################
121 def toCompactStr_majorMinorPatch(version):
122   """
123   parameter version is list of integer as  [major, minor, patch]
124
125   | returns "789" for [7, 8, 9]
126   | warning:
127   |   minor, pach have to be integer less than 10
128   |   raise exception for [7, 10, 11]
129   |   (which returns "71011" as ambigous 710.1.1 for example)
130   """
131   if len(version) != 3:
132     msg = "version major_minor_patch is incorrect: '%s'" % version
133     raise Exception(msg)
134
135   aStr = '_'.join([str(i) for i in version])
136   toList_majorMinorPatch(aStr) # will raise error if problem (as too much or negative values)
137
138   res = "".join([str(i) for i in version])
139   if version[1] > 9 or version[2] > 9:
140      raise Exception("ambigous major_minor_patch compact representation '%s' from '%s'" % (res, version))
141
142   return res
143
144 #############################################
145 def getRange_majorMinorPatch(aStr, verbose=False):
146   """
147   extract from aStr a version range, defined as
148   '*_from_aMinVersionTag_to_aMaxVersionTag' or
149   '*version_aMinVersionTag_to_aMaxVersionTag'.
150
151   where aMinVersionTag and aMaxVersionTag are compatible with MinorMajorPatch class syntaxes
152   '1.2.3' or '1_2_3' etc.
153   if not found '_from_' or 'version_' first then aMinVersionTag is '0.0.0'
154
155   :param aStr: string to work
156   :return: list [min, max], where min, max are MinorMajorPatch instances.
157            else None if not found
158   """
159   tmp1 = aStr.lower().split("_to_")
160
161   if len(tmp1) < 2:
162     return None # no '_to_'
163   if len(tmp1) > 2:
164     msg = "more than one '_to_' is incorrect for version range: '%s'" % aStr
165     raise Exception(msg)
166   aMax = tmp1[1]
167
168   # accept older syntax as 'version_1_0_0_to_2_0_0', (as '_from_1_0_0_to_2_0_0')
169   if "version_" in tmp1[0] and "_from_" not in tmp1[0]:
170     aStr_with_from = aStr.lower().replace("version_", "_from_", 1)
171   else:
172     aStr_with_from = aStr.lower()
173
174   # print("aStr_with_from '%s' -> '%s'" % (aStr, aStr_with_from))
175
176   tmp0 = aStr_with_from.split("_from_")
177   tmp1 = aStr_with_from.split("_to_")
178
179   if len(tmp0) > 2:
180     msg = "more than one '_from_' is incorrect for version range: '%s'" % aStr
181     raise Exception(msg)
182
183   tmp2 = tmp1[0].split("_from_")
184
185   if len(tmp2) == 2:
186     aMin = tmp2[1]
187   else:
188     aMin ="0.0.0"
189
190   if verbose:
191     msg = "version min '%s' and version max '%s' in version range: '%s'" % (aMin, aMax, aStr)
192     print(msg)
193
194   try:
195     rMin = MinorMajorPatch(aMin)
196     rMax = MinorMajorPatch(aMax)
197   except:
198     msg = "problem version range in '%s'" % aStr
199     raise Exception(msg)
200     """if verbose:
201       print("WARNING: problem version range in '%s'" % aStr)
202     return None"""
203
204   if rMin > rMax:
205     msg = "version min '%s' > version max '%s' in version range: '%s'" % (rMin, rMax, aStr)
206     raise Exception(msg)
207
208   return [rMin, rMax]
209
210 #############################################
211 class MinorMajorPatch(object):
212   """\
213   class to define a version as MAJOR.MINOR.PATCH
214
215   | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
216   | increment the
217   | MAJOR version when you make incompatible API changes,
218   | MINOR version when you add functionality in a backwards-compatible manner,
219   | PATCH version when you make backwards-compatible bug fixes.
220   """
221
222   def __init__(self, version):
223     if type(version) == list:
224       aStr = '_'.join([str(i) for i in version])
225       v = toList_majorMinorPatch(aStr)
226     else:
227       v = toList_majorMinorPatch(version)
228     self.major = v[0]
229     self.minor = v[1]
230     self.patch = v[2]
231
232   def __repr__(self, sep="_"):
233     """example is 'version_1_2_3' """
234     res = "version_%i%s%i%s%i" % (self.major, sep, self.minor, sep, self.patch)
235     return res
236
237   def __str__(self, sep="."):
238     """example is '1.2.3' """
239     res = "%i%s%i%s%i" % (self.major, sep, self.minor, sep, self.patch)
240     return res
241
242   def strSalome(self):
243     """example is '1_2_3' """
244     return self.__str__(sep="_")
245
246   def strClassic(self):
247     """example is '1.2.3' """
248     return self.__str__(sep=".")
249
250   def strCompact(self):
251     """example is '123' from '1.2.3' """
252     return toCompactStr_majorMinorPatch(self.toList())
253
254   def toList(self):
255     """example is list of integer [1, 2, 3] from '1.2.3' """
256     return [self.major, self.minor, self.patch]
257
258   def __lt__(self, other):
259     res = (self.toList() < other.toList())
260     return res
261
262   def __le__(self, other):
263     res = (self.toList() <= other.toList())
264     return res
265
266   def __gt__(self, other):
267     res = (self.toList() > other.toList())
268     return res
269
270   def __ge__(self, other):
271     res = (self.toList() >= other.toList())
272     return res
273
274   def __eq__(self, other):
275     res = (self.toList() == other.toList())
276     return res
277
278   def __ne__(self, other):
279     res = (self.toList() != other.toList())
280     return res
281
282