4 # Copyright (C) 2010-2018 CEA/DEN
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.
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.
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
22 class and utilities to define a version as MAJOR.MINOR.PATCH
24 | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
26 | MAJOR version when you make incompatible API changes,
27 | MINOR version when you add functionality in a backwards-compatible manner,
28 | PATCH version when you make backwards-compatible bug fixes.
34 verbose = False # True
36 #############################################
37 def only_numbers(aStr):
39 Remove non numericals characters from string,
40 returns None if no numbers
42 res = ''.join([nb for nb in aStr if nb in '0123456789'])
48 #############################################
49 def toList_majorMinorPatch(aStr):
51 Returns list of integer as [major, minor, patch] from a string,
52 raise exception if problem
54 if verbose: print("toList_majorMinorPatch('%s')" % aStr)
55 res = aStr.replace(" ", "").replace(".", "_").split("_")
57 msg = "Not a major_minor_patch correct syntax: '%s'" % aStr
60 msg = "An empty string is not a major_minor_patch syntax"
62 # complete MINOR.PATCH if not existing
71 msg = "major in major_minor_patch is not integer: '%s'" % aStr
74 msg = "major in major_minor_patch is negative integer: '%s'" % aStr
80 msg = "minor in major_minor_patch is not integer: '%s'" % aStr
83 msg = "minor in major_minor_patch is negative integer: '%s'" % aStr
89 msg = "patch in major_minor_patch is not integer: '%s'" % aStr
92 msg = "patch in major_minor_patch is negative integer: '%s'" % aStr
95 return [int(i) for i in res]
97 #############################################
98 def toCompactStr_majorMinorPatch(version):
100 parameter version is list of integer as [major, minor, patch]
102 | returns "789" for [7, 8, 9]
104 | minor, pach have to be integer less than 10
105 | raise exception for [7, 10, 11]
106 | (which returns "71011" as ambigous 710.1.1 for example)
108 if len(version) != 3:
109 msg = "version major_minor_patch is incorrect: '%s'" % version
112 aStr = '_'.join([str(i) for i in version])
113 toList_majorMinorPatch(aStr) # will raise error if problem (as too much or negative values)
115 res = "".join([str(i) for i in version])
116 if version[1] > 9 or version[2] > 9:
117 raise Exception("ambigous major_minor_patch compact representation '%s' from '%s'" % (res, version))
122 #############################################
123 class MinorMajorPatch(object):
125 class to define a version as MAJOR.MINOR.PATCH
127 | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
129 | MAJOR version when you make incompatible API changes,
130 | MINOR version when you add functionality in a backwards-compatible manner,
131 | PATCH version when you make backwards-compatible bug fixes.
134 def __init__(self, version):
135 if type(version) == list:
136 aStr = '_'.join([str(i) for i in version])
137 v = toList_majorMinorPatch(aStr)
139 v = toList_majorMinorPatch(version)
144 def __repr__(self, sep="_"):
145 """example is 'version_1_2_3' """
146 res = "version_%i%s%i%s%i" % (self.major, sep, self.minor, sep, self.patch)
149 def __str__(self, sep="."):
150 """example is '1.2.3' """
151 res = "%i%s%i%s%i" % (self.major, sep, self.minor, sep, self.patch)
155 """example is '1_2_3' """
156 return self.__str__(sep="_")
158 def strClassic(self):
159 """example is '1.2.3' """
160 return self.__str__(sep=".")
162 def strCompact(self):
163 """example is '123' from '1.2.3' """
164 return toCompactStr_majorMinorPatch(self.toList())
167 """example is list of integer [1, 2, 3] from '1.2.3' """
168 return [self.major, self.minor, self.patch]
170 def __lt__(self, other):
171 res = (self.toList() < other.toList())
174 def __le__(self, other):
175 res = (self.toList() <= other.toList())
178 def __gt__(self, other):
179 res = (self.toList() > other.toList())
182 def __ge__(self, other):
183 res = (self.toList() >= other.toList())
186 def __eq__(self, other):
187 res = (self.toList() == other.toList())
190 def __ne__(self, other):
191 res = (self.toList() != other.toList())
194 #############################################
199 class TestCase(unittest.TestCase):
200 "Test the versionMajorMinorPatch.py"""
203 if verbose: print(PP.pformat(dir(self)))
204 self.assertTrue(only_numbers("") is None)
205 self.assertEqual(only_numbers("1.2.3"), "123")
206 self.assertEqual(only_numbers("\n11.12.13\n"), "111213")
207 self.assertEqual(only_numbers(" \n 11.\t\n\t..12.13-rc2\n"), "1112132")
210 res = [11, 222, 3333]
211 self.assertEqual(toList_majorMinorPatch("11.222.3333"), res)
212 self.assertEqual(toList_majorMinorPatch("11_222_3333"), res)
213 self.assertEqual(toList_majorMinorPatch("11.222_3333"), res)
214 self.assertEqual(toList_majorMinorPatch(" 11. 222 . 3333 "), res)
215 self.assertEqual(toList_majorMinorPatch("\n 11 . 222 . 3333 \n"), res)
216 self.assertEqual(toList_majorMinorPatch(" \n11.\t222.\r3333\n "), res) # could be tricky
218 self.assertEqual(toList_majorMinorPatch("11"), [11, 0, 0])
219 self.assertEqual(toList_majorMinorPatch("11.0"), [11, 0, 0])
220 self.assertEqual(toList_majorMinorPatch("11.2"), [11, 2, 0])
221 self.assertEqual(toList_majorMinorPatch("\n1 . 2 \n"), [1, 2, 0])
223 with self.assertRaises(Exception): toList_majorMinorPatch("")
224 with self.assertRaises(Exception): toList_majorMinorPatch("11.")
225 with self.assertRaises(Exception): toList_majorMinorPatch("11.2.")
226 with self.assertRaises(Exception): toList_majorMinorPatch("11.2.3.")
227 with self.assertRaises(Exception): toList_majorMinorPatch(".11")
228 with self.assertRaises(Exception): toList_majorMinorPatch("1_2_3_4")
229 with self.assertRaises(Exception): toList_majorMinorPatch("_1_2_3_")
230 with self.assertRaises(Exception): toList_majorMinorPatch(" \n 11...22.333-rc2\n")
231 with self.assertRaises(Exception): toList_majorMinorPatch(" \n 11...22.333-rc2\n")
232 with self.assertRaises(Exception): toList_majorMinorPatch(" \n 11...22.333-rc2\n")
236 self.assertEqual(toCompactStr_majorMinorPatch([1, 2, 3]), "123")
237 self.assertEqual(toCompactStr_majorMinorPatch([11, 2, 3]), "1123")
238 self.assertEqual(toCompactStr_majorMinorPatch([1, 9, 9]), "199")
240 with self.assertRaises(Exception): toCompactStr_majorMinorPatch([1, 2, 10])
241 with self.assertRaises(Exception): toCompactStr_majorMinorPatch([1, 10, 3])
242 with self.assertRaises(Exception): toCompactStr_majorMinorPatch([10, 10, 10])
245 MMP = MinorMajorPatch
247 self.assertEqual(MMP(v).__str__(), "1.2.3")
248 self.assertEqual(MMP(v).__str__(sep="_"), "1_2_3")
249 self.assertEqual(str(MMP(v)), "1.2.3")
251 self.assertEqual(MMP(v).__repr__(), "version_1_2_3")
252 self.assertEqual(MMP(v).__repr__(sep="."), "version_1.2.3")
254 self.assertEqual(MMP(v).strSalome(), "1_2_3")
255 self.assertEqual(MMP(v).strClassic(), "1.2.3")
257 self.assertEqual(MMP([' 123 \n', 2, 10]).strClassic(), "123.2.10")
258 self.assertEqual(MMP([' 123 \n', 2, 10]).strSalome(), "123_2_10")
259 self.assertEqual(MMP([' 123 \n', 2, 9]).strCompact(), "12329") # no ambigous
261 with self.assertRaises(Exception): MMP([-5, 2, 10])
262 with self.assertRaises(Exception): MMP([5, -2, 10])
263 with self.assertRaises(Exception): MMP([5, 2, -10])
264 with self.assertRaises(Exception): MMP(['-123', 2, 10])
265 with self.assertRaises(Exception): MMP([123, 2, 10].strCompact()) # ambigous
268 MMP = MinorMajorPatch
276 self.assertTrue(va == vb)
277 self.assertTrue(va >= vb)
278 self.assertTrue(va <= vb)
279 self.assertFalse(va != vb)
280 self.assertFalse(va > vb)
281 self.assertFalse(va < vb)
285 self.assertFalse(va == vb)
286 self.assertFalse(va >= vb)
287 self.assertTrue(va <= vb)
288 self.assertTrue(va != vb)
289 self.assertFalse(va > vb)
290 self.assertTrue(va < vb)
293 if __name__ == '__main__':
294 unittest.main(exit=False)