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
57 import StringIO as SIO
60 _debug = [False] #support push/pop for temporary activate debug outputs
62 _user = os.environ['USER']
63 # wambeke is christian at home
64 _developers = ["christian", "wambeke", "crouzet"] # crouzet, kloss ...
68 """if you are a developer, sometimes you want verbose traces etc."""
69 res = _user in _developers
72 def indent(text, amount=2, ch=' '):
73 """indent multi lines message"""
75 return ''.join(padding + line for line in text.splitlines(True))
77 def isTypeConfig(var):
78 """To know if var is instance from Config/pyconf"""
80 # print "isTypeConfig" ,type, dir(var)
81 if ".pyconf.Config" in typ: return True
82 if ".pyconf.Mapping" in typ: return True
83 if ".pyconf.Sequence" in typ: return True
84 # print "NOT isTypeConfig %s" % typ
87 def write(title, var="", force=None, fmt="\n#### DEBUG: %s:\n%s\n"):
88 """write sys.stderr a message if _debug[-1]==True or optionaly force=True"""
89 if _debug[-1] or force:
93 sys.stderr.write(fmt % (title, indent(getStrConfigDbg(var))))
95 if 'UnittestStream' in typ:
96 sys.stderr.write(fmt % (title, indent(var.getLogs())))
98 if tvar is not str and tvar is not unicode:
99 sys.stderr.write(fmt % (title, indent(PP.pformat(var))))
101 sys.stderr.write(fmt % (title, indent(var)))
105 def tofix(title, var="", force=None):
107 write sys.stderr a message if _debug[-1]==True or optionaly force=True
108 use this only if no logger accessible for classic logger.warning(message)
110 fmt = "\n#### TOFIX: %s:\n%s\n"
111 write(title, var, force, fmt)
113 def push_debug(aBool):
114 """set debug outputs activated, or not"""
118 """restore previous debug outputs status"""
122 sys.stderr.write("\nERROR: pop_debug: too much pop.")
126 def format_exception(msg, limit=None, trace=None):
128 Format a stack trace and the exception information.
129 as traceback.format_exception(), without color
130 with traceback only if (_debug) or (DBG._user in DBG._developers)
132 etype, value, tb = sys.exc_info()
133 if _debug[-1] or isDeveloper():
136 res += "\nTraceback (most recent call last):\n"
137 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
139 res += "\n".join(traceback.format_exception_only(etype, value))
143 res += "".join(traceback.format_exception_only(etype, value))
146 def format_color_exception(msg, limit=None, trace=None):
148 Format a stack trace and the exception information.
149 as traceback.format_exception(), with color
150 with traceback only if _debug or isDeveloper())
152 etype, value, tb = sys.exc_info()
153 if _debug[-1] or isDeveloper():
156 res += "<yellow>\nTraceback (most recent call last):\n"
157 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
159 res += "\n".join(traceback.format_exception_only(etype, value))
160 return res + "<reset>"
162 res = "<red>" + msg # + "<bright>"
163 res += "".join(traceback.format_exception_only(etype, value))
164 return res + "<reset>"
167 ###############################################
168 # utilitaires divers pour debug
169 ###############################################
171 class OutStream(SIO.StringIO):
173 utility class for pyconf.Config output iostream
177 because Config.__save__ calls close() stream as file
178 keep value before lost as self.value
180 self.value = self.getvalue()
181 SIO.StringIO.close(self)
183 class InStream(SIO.StringIO):
184 """utility class for pyconf.Config input iostream"""
188 """get string for environment variables representation"""
190 for i in sorted(os.environ):
191 res += "%s : %s\n" % (i, os.environ[i])
194 # save as initial Config.save() moved as Config.__save__()
195 def saveConfigStd(config, aStream):
196 """returns as file .pyconf"""
198 config.__save__(aStream, indent)
200 def getStrConfigStd(config):
201 """set string as saveConfigStd, as file .pyconf"""
202 outStream = OutStream()
203 saveConfigStd(config, outStream)
204 return outStream.value
206 def getStrConfigDbg(config):
208 set string as saveConfigDbg,
209 as (path expression evaluation) for debug
211 outStream = OutStream()
212 saveConfigDbg(config, outStream)
213 return outStream.value
215 def saveConfigDbg(config, aStream, indent=0, path=""):
216 """pyconf returns multilines (path expression evaluation) for debug"""
217 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
218 aStream.close() # as config.__save__()
220 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
221 """pyconf inspired from Mapping.__save__"""
223 nbp = nb + 1 # depth recursive
229 if nbp > 10: # protection
230 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
231 # raise Exception("!!! ERROR: Circular reference %s" % path)
232 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
235 indstr = indent * ' ' # '':no indent, ' ':indent
236 strType = str(type(config))
237 if debug: print("saveDbg Type %s %s" % (path, strType))
239 if "Sequence" in strType:
240 for i in range(len(config)):
241 _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i, nbp)
244 if "Reference" in strType:
246 #evaluate = value.resolve(config)
247 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
248 except Exception as e:
249 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, e.message))
253 try: #type config, mapping
254 order = object.__getattribute__(config, 'order')
255 data = object.__getattribute__(config, 'data')
257 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
259 for key in sorted(data): #order): # data as sort alphabetical, order as initial order
261 strType = str(type(value))
262 if debug: print('strType %s %s %s' % (path, key, strType))
263 if "Config" in strType:
264 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
266 if "Mapping" in strType:
267 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
269 if "Sequence" in strType:
270 for i in range(len(value)):
271 _saveConfigRecursiveDbg(value.data[i], aStream, indentp, path+"."+key+"[%i]" % i, nbp)
273 if "Expression" in strType:
275 evaluate = value.evaluate(config)
276 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
277 except Exception as e:
278 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
280 if "Reference" in strType:
282 evaluate = value.resolve(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 type(value) in [str, bool, int, type(None), unicode]:
288 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
291 aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value)))
292 except Exception as e:
293 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message))