4 # Copyright (C) 2018-20xx 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
21 This file contains ReturnCode class
24 | >> import returnCode as RCO
29 # global module variable
32 _NA_STATUS = "NA" # not applicable
33 _UNKNOWN_STATUS = "ND" # not defined
34 _KNOWNFAILURE_STATUS = "KF"
35 _TIMEOUT_STATUS = "TIMEOUT"
37 #####################################################
38 class ReturnCode(object):
40 assume simple return code for methods, with explanation as 'why'.
41 Obviously why is 'why it is not OK',
42 but also why is 'why it is OK' (if you want).
43 Optionaly contains a return value as self.getValue()
46 | >> import returnCode as RCO
48 | >> aValue = doSomethingToReturn()
49 | >> return RCO.ReturnCode("KO", "there is no problem here", aValue)
50 | >> return RCO.ReturnCode("KO", "there is a problem here because etc", None)
51 | >> return RCO.ReturnCode("TIMEOUT_STATUS", "too long here because etc")
52 | >> return RCO.ReturnCode("NA", "not applicable here because etc")
54 | >> rc = doSomething()
55 | >> print("short returnCode string", str(rc))
56 | >> print("long returnCode string with value", repr(rc))
58 | >> rc1 = RCO.ReturnCode("OK", ...)
59 | >> rc2 = RCO.ReturnCode("KO", ...)
60 | >> rcFinal = rc1 + rc2
61 | >> print("long returnCode string with value", repr(rcFinal)) # KO!
63 | >> rc = doSomething()
64 | >> if rc.isOk(): doSomethingAsOK()
65 | >> if not rc.isOk(): doSomethingAsKO()
67 | >> rc = doSomething().raiseIfKo() # raise Exception if KO
68 | >> doSomethingWithValue(rc.getValue()) # here i am sure that is OK
71 # redunctant but useful class variables
72 OK_STATUS = _OK_STATUS
73 KO_STATUS = _KO_STATUS
74 NA_STATUS = _NA_STATUS # not applicable
75 UNKNOWN_STATUS = _UNKNOWN_STATUS # not defined
76 KNOWNFAILURE_STATUS = _KNOWNFAILURE_STATUS
77 TIMEOUT_STATUS = _TIMEOUT_STATUS
79 # an integer for sys.exit(anInteger)
80 # OKSYS and KOSYS seems equal on linux or windows
83 NASYS = 2 # KO not applicable return code
84 NDSYS = 3 # KO not defined return code
85 KFSYS = 4 # KO known failure return code
86 TOSYS = 5 # KO time out
92 UNKNOWN_STATUS: NDSYS,
93 KNOWNFAILURE_STATUS: KFSYS,
94 TIMEOUT_STATUS: TOSYS,
96 _DEFAULT_WHY = "No given explanation"
99 def __init__(self, status=None, why=None, value=None):
100 self._why = self._DEFAULT_WHY
101 self._value = self._DEFAULT_VALUE
103 self._status = self.UNKNOWN_STATUS
105 self.setStatus(status, why, value)
108 """complete with value, 'ok, why, value' message"""
109 res = '%s: %s --value: %s' % (self._status, self._why, PP.pformat(self._value))
113 """without value, only simple 'ok, why' message"""
114 res = '%s: %s' % (self._status, self._why)
117 def indent(self, text, amount=5, ch=' '):
118 """indent multi lines message"""
119 padding = amount * ch
120 res = ''.join(padding + line for line in text.splitlines(True))
123 def __add__(self, rc2):
124 """allows expression 'returnCode1 + returnCode2 + ...' """
125 isOk = self.isOk() and rc2.isOk()
126 newWhy = self._toList(self.getWhy()) + self._toList(rc2.getWhy())
127 newValue = self._toList(self.getValue()) + self._toList(rc2.getValue())
129 return ReturnCode("OK", newWhy, newValue)
131 return ReturnCode("KO", newWhy, newValue)
133 def __radd__(self, other):
134 # see http://www.marinamele.com/2014/04/modifying-add-method-of-python-class.html
138 return self.__add__(other)
140 def _toList(self, strOrList):
142 if type(strOrList) is not list:
148 """return system return code as bash or bat"""
150 return self._TOSYS[self._status]
152 return self._TOSYS[self.NA_STATUS]
154 def toXmlPassed(self):
155 """return xml return code as '0' (passed) or '1' (not passed)"""
162 """return why as str or list if sum or some ReturnCode"""
165 def setWhy(self, why):
171 def setValue(self, value):
172 """choice as not deep copying if mutables value"""
173 # TODO deepcopy maybe for value, not yet
176 def setStatus(self, status, why=None, value=None):
178 aWhy = self._DEFAULT_WHY
182 if status in self._TOSYS.keys():
183 self._status = status
186 self._status = self.NA_STATUS
187 self._why = "Error status '%s' for '%s'" % (status, aWhy)
189 if value is not None:
190 # TODO deepcopy maybe for value, not yet
193 self._value = self._DEFAULT_VALUE
201 inexisting method isKo(), use more explicit/readability 'if not res.isOk()'
203 return (self._status == self.OK_STATUS)
207 raise an exception with message why if not ok, else return self.
208 This trick is to write usage
211 | >> rc = doSomething().raiseIfKo() # raise Exception if KO
212 | >> doSomethingWithValue(rc.getValue()) # here i am sure that is OK
217 raise Exception(self.getWhy())
219 def ReturnCodeFromList(aListOfReturnCodes):
221 Create ReturnCode from list of ReturnCode
223 convenience over "+" operand
227 for rc in aListOfReturnCodes:
230 whyes.append(str(rc))
231 reswhy = "\n ".join(whyes)
232 return ReturnCode(res, "\n " + reswhy)