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
21 This file assume DEBUG functionalities use.
22 Print salomeTools debug messages in sys.stderr.
23 Show pretty print debug representation from instances of SAT classes
24 (pretty print src.pyconf.Config)
26 | Warning: supposedly show messages in SAT development phase, not production
29 | >> import debug as DBG
30 | >> DBG.write("aTitle", aVariable) # not shown in production
31 | >> DBG.write("aTitle", aVariable, True) # unconditionaly shown (as show=True)
33 | to set show message as development phase:
34 | >> DBG.push_debug(True)
36 | to set no show message as production phase:
37 | >> DBG.push_debug(False)
39 | to set show message temporary as development phase, only in a method:
40 | >> def aMethodToDebug(...):
41 | >> DBG.push_debug(True) #force show as appended status
42 | >> etc. method code with some DBG.write()
43 | >> DBG.pop_debug() #restore previous status (show or not show)
46 | to set a message for future fix, as temporary problem to not forget:
47 | DBG.tofix("aTitle", aVariable, True/False) #True/False in production shown, or not
49 | in command line interface you could redirect stderr to file 'myDebug.log':
50 | >> sat compile ... 2> myDebug.log # only stderr
51 | >> sat compile ... &> myDebug.log # stdout and stderr
59 # Compatibility python 2/3 for unicode
65 # Compatibility python 2/3 for StringIO
67 from StringIO import StringIO
69 from io import StringIO
71 _debug = [False] #support push/pop for temporary activate debug outputs
73 _user = os.environ['USER']
74 # wambeke is christian at home
75 _developers = ["christian", "wambeke"] # crouzet, kloss ...
79 """if you are a developer, sometimes you want verbose traces etc."""
80 res = _user in _developers
83 def indent(text, amount=2, ch=' '):
84 """indent multi lines message"""
86 return ''.join(padding + line for line in text.splitlines(True))
88 def isTypeConfig(var):
89 """To know if var is instance from Config/pyconf"""
91 # print "isTypeConfig" ,type, dir(var)
92 if ".pyconf.Config" in typ: return True
93 if ".pyconf.Mapping" in typ: return True
94 if ".pyconf.Sequence" in typ: return True
95 # print "NOT isTypeConfig %s" % typ
98 def write(title, var="", force=None, fmt="\n#### DEBUG: %s:\n%s\n"):
99 """write sys.stderr a message if _debug[-1]==True or optionaly force=True"""
100 if _debug[-1] or force:
103 if isTypeConfig(var):
104 sys.stderr.write(fmt % (title, indent(getStrConfigDbg(var))))
106 if 'UnittestStream' in typ:
107 sys.stderr.write(fmt % (title, indent(var.getLogs())))
109 if tvar is not str and tvar is not unicode:
110 sys.stderr.write(fmt % (title, indent(PP.pformat(var))))
112 sys.stderr.write(fmt % (title, indent(var)))
116 def tofix(title, var="", force=None):
118 write sys.stderr a message if _debug[-1]==True or optionaly force=True
119 use this only if no logger accessible for classic logger.warning(message)
121 if _debug[-1] or isDeveloper():
122 fmt = "\n#### TOFIX: %s:\n%s\n"
123 write(title, var, force, fmt)
125 def push_debug(aBool):
126 """set debug outputs activated, or not"""
130 """restore previous debug outputs status"""
134 sys.stderr.write("\nERROR: pop_debug: too much pop.")
138 def format_exception(msg, limit=None, trace=None):
140 Format a stack trace and the exception information.
141 as traceback.format_exception(), without color
142 with traceback only if (_debug) or (DBG._user in DBG._developers)
144 etype, value, tb = sys.exc_info()
147 res += "\nTraceback (most recent call last):\n"
148 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
150 res += "\n".join(traceback.format_exception_only(etype, value))
153 def format_color_exception(msg, limit=None, trace=None):
155 Format a stack trace and the exception information.
156 as traceback.format_exception(), with color
157 with traceback only if _debug or isDeveloper())
159 etype, value, tb = sys.exc_info()
160 if _debug[-1] or isDeveloper():
163 res += "<yellow>\nTraceback (most recent call last):\n"
164 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
166 res += "\n".join(traceback.format_exception_only(etype, value))
167 return res + "<reset>"
169 res = "<red>" + msg # + "<bright>"
170 res += "".join(traceback.format_exception_only(etype, value))
171 return res + "<reset>"
174 ###############################################
175 # utilitaires divers pour debug
176 ###############################################
178 class OutStream(StringIO):
180 utility class for pyconf.Config output iostream
184 because Config.__save__ calls close() stream as file
185 keep value before lost as self.value
187 self.value = self.getvalue()
190 class InStream(StringIO):
191 """utility class for pyconf.Config input iostream"""
195 """get string for environment variables representation"""
197 for i in sorted(os.environ):
198 res += "%s : %s\n" % (i, os.environ[i])
201 # save as initial Config.save() moved as Config.__save__()
202 def saveConfigStd(config, aStream):
203 """returns as file .pyconf"""
205 config.__save__(aStream, indent)
207 def getStrConfigStd(config):
208 """set string as saveConfigStd, as file .pyconf"""
209 outStream = OutStream()
210 saveConfigStd(config, outStream)
211 return outStream.value
213 def getStrConfigDbg(config):
215 set string as saveConfigDbg,
216 as (path expression evaluation) for debug
218 outStream = OutStream()
219 saveConfigDbg(config, outStream)
220 return outStream.value
222 def saveConfigDbg(config, aStream, indent=0, path=""):
223 """pyconf returns multilines (path expression evaluation) for debug"""
224 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
225 aStream.close() # as config.__save__()
227 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
228 """pyconf inspired from Mapping.__save__"""
230 nbp = nb + 1 # depth recursive
236 if nbp > 10: # protection
237 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
238 # raise Exception("!!! ERROR: Circular reference %s" % path)
239 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
242 indstr = indent * ' ' # '':no indent, ' ':indent
243 strType = str(type(config))
244 if debug: print("saveDbg Type %s %s" % (path, strType))
246 if "Sequence" in strType:
247 for i in range(len(config)):
248 _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i, nbp)
251 if "Reference" in strType:
253 #evaluate = value.resolve(config)
254 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
255 except Exception as e:
256 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, e.message))
260 try: #type config, mapping
261 order = object.__getattribute__(config, 'order')
262 data = object.__getattribute__(config, 'data')
264 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
266 for key in sorted(data): #order): # data as sort alphabetical, order as initial order
268 strType = str(type(value))
269 if debug: print('strType %s %s %s' % (path, key, strType))
270 if "Config" in strType:
271 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
273 if "Mapping" in strType:
274 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
276 if "Sequence" in strType:
277 for i in range(len(value)):
278 _saveConfigRecursiveDbg(value.data[i], aStream, indentp, path+"."+key+"[%i]" % i, nbp)
280 if "Expression" in strType:
282 evaluate = value.evaluate(config)
283 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
284 except Exception as e:
285 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
287 if "Reference" in strType:
289 evaluate = value.resolve(config)
290 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
291 except Exception as e:
292 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
294 if type(value) in [str, bool, int, type(None), unicode]:
295 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
298 aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value)))
299 except Exception as e:
300 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message))