Salome HOME
add src/versionMinorMajorPatch.py, not used
[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
24 | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
25 | increment the
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.
29 """
30
31 import os
32 import sys
33
34 verbose = False # True
35
36 #############################################
37 def only_numbers(aStr):
38   """
39   Remove non numericals characters from string,
40   returns None if no numbers
41   """
42   res = ''.join([nb for nb in aStr if nb in '0123456789'])
43   if res == "":
44     return None
45   else:
46     return res
47
48 #############################################
49 def toList_majorMinorPatch(aStr):
50   """
51   Returns list of integer as  [major, minor, patch] from a string,
52   raise exception if problem
53   """
54   if verbose: print("toList_majorMinorPatch('%s')" % aStr)
55   res = aStr.replace(" ", "").replace(".", "_").split("_")
56   if len(res) > 3:
57     msg = "Not a major_minor_patch correct syntax: '%s'" % aStr
58     raise Exception(msg)
59   if len(res) == 0:
60     msg = "An empty string is not a major_minor_patch syntax"
61     raise Exception(msg)
62   # complete MINOR.PATCH if not existing
63   if len(res) == 1:
64     res.append("0")
65   if len(res) == 2:
66     res.append("0")
67
68   try:
69     ii = int(res[0])
70   except:
71     msg = "major in major_minor_patch is not integer: '%s'" % aStr
72     raise Exception(msg)
73   if ii < 0:
74     msg = "major in major_minor_patch is negative integer: '%s'" % aStr
75     raise Exception(msg)
76
77   try:
78     ii = int(res[1])
79   except:
80     msg = "minor in major_minor_patch is not integer: '%s'" % aStr
81     raise Exception(msg)
82   if ii < 0:
83     msg = "minor in major_minor_patch is negative integer: '%s'" % aStr
84     raise Exception(msg)
85
86   try:
87     ii = int(res[2])
88   except:
89     msg = "patch in major_minor_patch is not integer: '%s'" % aStr
90     raise Exception(msg)
91   if ii < 0:
92     msg = "patch in major_minor_patch is negative integer: '%s'" % aStr
93     raise Exception(msg)
94
95   return [int(i) for i in res]
96
97 #############################################
98 def toCompactStr_majorMinorPatch(version):
99   """
100   parameter version is list of integer as  [major, minor, patch]
101
102   | returns "789" for [7, 8, 9]
103   | warning:
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)
107   """
108   if len(version) != 3:
109     msg = "version major_minor_patch is incorrect: '%s'" % version
110     raise Exception(msg)
111
112   aStr = '_'.join([str(i) for i in version])
113   toList_majorMinorPatch(aStr) # will raise error if problem (as too much or negative values)
114
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))
118
119   return res
120
121
122 #############################################
123 class MinorMajorPatch(object):
124   """\
125   class to define a version as MAJOR.MINOR.PATCH
126
127   | Given a version number MAJOR.MINOR.PATCH separator "_" or "."
128   | increment the
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.
132   """
133
134   def __init__(self, version):
135     if type(version) == list:
136       aStr = '_'.join([str(i) for i in version])
137       v = toList_majorMinorPatch(aStr)
138     else:
139       v = toList_majorMinorPatch(version)
140     self.major = v[0]
141     self.minor = v[1]
142     self.patch = v[2]
143
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)
147     return res
148
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)
152     return res
153
154   def strSalome(self):
155     """example is '1_2_3' """
156     return self.__str__(sep="_")
157
158   def strClassic(self):
159     """example is '1.2.3' """
160     return self.__str__(sep=".")
161
162   def strCompact(self):
163     """example is '123' from '1.2.3' """
164     return toCompactStr_majorMinorPatch(self.toList())
165
166   def toList(self):
167     """example is list of integer [1, 2, 3] from '1.2.3' """
168     return [self.major, self.minor, self.patch]
169
170   def __lt__(self, other):
171     res = (self.toList() < other.toList())
172     return res
173
174   def __le__(self, other):
175     res = (self.toList() <= other.toList())
176     return res
177
178   def __gt__(self, other):
179     res = (self.toList() > other.toList())
180     return res
181
182   def __ge__(self, other):
183     res = (self.toList() >= other.toList())
184     return res
185
186   def __eq__(self, other):
187     res = (self.toList() == other.toList())
188     return res
189
190   def __ne__(self, other):
191     res = (self.toList() != other.toList())
192     return res
193
194 #############################################
195 import unittest
196 import pprint as PP
197
198
199 class TestCase(unittest.TestCase):
200   "Test the versionMajorMinorPatch.py"""
201
202   def test_010(self):
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")
208
209   def test_020(self):
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
217
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])
222
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")
233
234
235   def test_030(self):
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")
239
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])
243
244   def test_040(self):
245     MMP = MinorMajorPatch
246     v = [1, 2, 3]
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")
250
251     self.assertEqual(MMP(v).__repr__(), "version_1_2_3")
252     self.assertEqual(MMP(v).__repr__(sep="."), "version_1.2.3")
253
254     self.assertEqual(MMP(v).strSalome(), "1_2_3")
255     self.assertEqual(MMP(v).strClassic(), "1.2.3")
256
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
260
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
266
267   def test_040(self):
268     MMP = MinorMajorPatch
269     v000 = MMP("0.0.0")
270     v010 = MMP("0.1.0")
271     v100 = MMP("1.0.0")
272     v101 = MMP("1.0.1")
273
274     va = v000
275     vb = MMP("0.0.0")
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)
282
283     va = v000
284     vb = v010
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)
291
292
293 if __name__ == '__main__':
294   unittest.main(exit=False)
295   pass
296