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
61 # Compatibility python 2/3 for unicode
67 # Compatibility python 2/3 for StringIO
69 from StringIO import StringIO
71 from io import StringIO
73 _debug = [False] # support push/pop for temporary activate debug outputs
78 if you are a developer, sometimes you want verbose traces unconditionally
79 export SAT_DEVELOPER_MODE=1 before launch sat command to do that
81 res = os.getenv("SAT_DEVELOPER_MODE", "0")
82 if res in "YES yes 1 Y y".split():
88 def indent(text, amount=2, ch=" "):
89 """indent multi lines message"""
91 return "".join(padding + line for line in text.splitlines(True))
94 def isTypeConfig(var):
95 """To know if var is instance from Config/pyconf"""
97 # print "isTypeConfig" ,type, dir(var)
98 if ".pyconf.Config" in typ:
100 if ".pyconf.Mapping" in typ:
102 if ".pyconf.Sequence" in typ:
104 # print "NOT isTypeConfig %s" % typ
108 def write(title, var="", force=None, fmt=" %s:\n%s\n####\n"):
109 """write sys.stderr a message if _debug[-1]==True or optionaly force=True"""
110 if _debug[-1] or force:
111 callerframerecord = inspect.stack()[1] # get info of the caller
112 frame = callerframerecord[0]
113 info = inspect.getframeinfo(frame)
115 "\n#### DEBUG - %s:%s (%s) ####\n"
116 % (info.filename, info.lineno, info.function)
120 if isTypeConfig(var):
121 sys.stderr.write(fmt % (title, indent(getStrConfigDbg(var))))
123 if "UnittestStream" in typ:
124 sys.stderr.write(fmt % (title, indent(var.getLogs())))
126 if tvar is not str and tvar is not unicode:
127 sys.stderr.write(fmt % (title, indent(PP.pformat(var))))
129 sys.stderr.write(fmt % (title, indent(var)))
134 def tofix(title, var="", force=None):
136 write sys.stderr a message if _debug[-1]==True or optionaly force=True
137 use this only if no logger accessible for classic logger.warning(message)
139 if _debug[-1] or isDeveloper():
140 callerframerecord = inspect.stack()[1] # get info of the caller
141 frame = callerframerecord[0]
142 info = inspect.getframeinfo(frame)
150 + ") ####\n %s:\n%s\n"
152 write(title, var, force, fmt)
155 def push_debug(aBool):
156 """set debug outputs activated, or not"""
161 """restore previous debug outputs status"""
165 sys.stderr.write("\nERROR: pop_debug: too much pop.")
169 def format_exception(msg, limit=None, trace=None):
171 Format a stack trace and the exception information.
172 as traceback.format_exception(), without color
173 with traceback only if (_debug) or (DBG.isDeveloper())
175 etype, value, tb = sys.exc_info()
178 res += "\nTraceback (most recent call last):\n"
179 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
181 res += "\n".join(traceback.format_exception_only(etype, value))
185 def format_color_exception(msg, limit=None, trace=None):
187 Format a stack trace and the exception information.
188 as traceback.format_exception(), with color
189 with traceback only if _debug or isDeveloper())
191 etype, value, tb = sys.exc_info()
192 if _debug[-1] or isDeveloper():
195 res += "<yellow>\nTraceback (most recent call last):\n"
196 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
198 res += "\n".join(traceback.format_exception_only(etype, value))
199 return res + "<reset>"
201 res = "<red>" + msg # + "<bright>"
202 res += "".join(traceback.format_exception_only(etype, value))
203 return res + "<reset>"
206 ###############################################
207 # utilitaires divers pour debug
208 ###############################################
211 class OutStream(StringIO):
213 utility class for pyconf.Config output iostream
218 because Config.__save__ calls close() stream as file
219 keep value before lost as self.value
221 self.value = self.getvalue()
225 class InStream(StringIO):
226 """utility class for pyconf.Config input iostream"""
232 """get string for environment variables representation"""
234 for i in sorted(os.environ):
235 res += "%s : %s\n" % (i, os.environ[i])
239 # save as initial Config.save() moved as Config.__save__()
240 def saveConfigStd(config, aStream):
241 """returns as file .pyconf"""
243 config.__save__(aStream, indent)
246 def getStrConfigStd(config):
247 """set string as saveConfigStd, as file .pyconf"""
248 outStream = OutStream()
249 saveConfigStd(config, outStream)
250 return outStream.value
253 def getStrConfigDbg(config):
255 set string as saveConfigDbg,
256 as (path expression evaluation) for debug
258 outStream = OutStream()
259 saveConfigDbg(config, outStream)
260 return outStream.value
263 def saveConfigDbg(config, aStream, indent=0, path=""):
264 """pyconf returns multilines (path expression evaluation) for debug"""
265 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
266 aStream.close() # as config.__save__()
269 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
270 """pyconf inspired from Mapping.__save__"""
272 nbp = nb + 1 # depth recursive
278 if nbp > 10: # protection
279 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
280 # raise Exception("!!! ERROR: Circular reference %s" % path)
281 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
284 indstr = indent * " " # '':no indent, ' ':indent
285 strType = str(type(config))
287 print("saveDbg Type %s %s" % (path, strType))
289 if "Sequence" in strType:
290 for i in range(len(config)):
291 _saveConfigRecursiveDbg(config[i], aStream, indentp, path + "[%i]" % i, nbp)
294 if "Reference" in strType:
296 #evaluate = value.resolve(config)
297 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
298 except Exception as e:
299 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, str(e)))
303 try: # type config, mapping
304 order = object.__getattribute__(config, "order")
305 data = object.__getattribute__(config, "data")
307 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
311 ): # order): # data as sort alphabetical, order as initial order
313 strType = str(type(value))
315 print("strType %s %s %s" % (path, key, strType))
316 if "Config" in strType:
317 _saveConfigRecursiveDbg(value, aStream, indentp, path + "." + key, nbp)
319 if "Mapping" in strType:
320 _saveConfigRecursiveDbg(value, aStream, indentp, path + "." + key, nbp)
322 if "Sequence" in strType:
323 for i in range(len(value)):
324 _saveConfigRecursiveDbg(
325 value.data[i], aStream, indentp, path + "." + key + "[%i]" % i, nbp
328 if "Expression" in strType:
330 evaluate = value.evaluate(config)
332 "%s%s.%s : %s --> '%s'\n"
333 % (indstr, path, key, str(value), evaluate)
335 except Exception as e:
337 "%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, str(e))
340 if "Reference" in strType:
342 evaluate = value.resolve(config)
344 "%s%s.%s : %s --> '%s'\n"
345 % (indstr, path, key, str(value), evaluate)
347 except Exception as e:
349 "%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, str(e))
352 if type(value) in [str, bool, int, type(None), unicode]:
353 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
357 "!!! TODO fix that %s %s%s.%s : %s\n"
358 % (type(value), indstr, path, key, str(value))
360 except Exception as e:
361 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, str(e)))