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"] # 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 fmt = "\n#### TOFIX: %s:\n%s\n"
122 write(title, var, force, fmt)
124 def push_debug(aBool):
125 """set debug outputs activated, or not"""
129 """restore previous debug outputs status"""
133 sys.stderr.write("\nERROR: pop_debug: too much pop.")
137 def format_exception(msg, limit=None, trace=None):
139 Format a stack trace and the exception information.
140 as traceback.format_exception(), without color
141 with traceback only if (_debug) or (DBG._user in DBG._developers)
143 etype, value, tb = sys.exc_info()
144 if _debug[-1] or isDeveloper():
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))
154 res += "".join(traceback.format_exception_only(etype, value))
157 def format_color_exception(msg, limit=None, trace=None):
159 Format a stack trace and the exception information.
160 as traceback.format_exception(), with color
161 with traceback only if _debug or isDeveloper())
163 etype, value, tb = sys.exc_info()
164 if _debug[-1] or isDeveloper():
167 res += "<yellow>\nTraceback (most recent call last):\n"
168 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
170 res += "\n".join(traceback.format_exception_only(etype, value))
171 return res + "<reset>"
173 res = "<red>" + msg # + "<bright>"
174 res += "".join(traceback.format_exception_only(etype, value))
175 return res + "<reset>"
178 ###############################################
179 # utilitaires divers pour debug
180 ###############################################
182 class OutStream(StringIO):
184 utility class for pyconf.Config output iostream
188 because Config.__save__ calls close() stream as file
189 keep value before lost as self.value
191 self.value = self.getvalue()
194 class InStream(StringIO):
195 """utility class for pyconf.Config input iostream"""
199 """get string for environment variables representation"""
201 for i in sorted(os.environ):
202 res += "%s : %s\n" % (i, os.environ[i])
205 # save as initial Config.save() moved as Config.__save__()
206 def saveConfigStd(config, aStream):
207 """returns as file .pyconf"""
209 config.__save__(aStream, indent)
211 def getStrConfigStd(config):
212 """set string as saveConfigStd, as file .pyconf"""
213 outStream = OutStream()
214 saveConfigStd(config, outStream)
215 return outStream.value
217 def getStrConfigDbg(config):
219 set string as saveConfigDbg,
220 as (path expression evaluation) for debug
222 outStream = OutStream()
223 saveConfigDbg(config, outStream)
224 return outStream.value
226 def saveConfigDbg(config, aStream, indent=0, path=""):
227 """pyconf returns multilines (path expression evaluation) for debug"""
228 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
229 aStream.close() # as config.__save__()
231 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
232 """pyconf inspired from Mapping.__save__"""
234 nbp = nb + 1 # depth recursive
240 if nbp > 10: # protection
241 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
242 # raise Exception("!!! ERROR: Circular reference %s" % path)
243 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
246 indstr = indent * ' ' # '':no indent, ' ':indent
247 strType = str(type(config))
248 if debug: print("saveDbg Type %s %s" % (path, strType))
250 if "Sequence" in strType:
251 for i in range(len(config)):
252 _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i, nbp)
255 if "Reference" in strType:
257 #evaluate = value.resolve(config)
258 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
259 except Exception as e:
260 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, e.message))
264 try: #type config, mapping
265 order = object.__getattribute__(config, 'order')
266 data = object.__getattribute__(config, 'data')
268 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
270 for key in sorted(data): #order): # data as sort alphabetical, order as initial order
272 strType = str(type(value))
273 if debug: print('strType %s %s %s' % (path, key, strType))
274 if "Config" in strType:
275 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
277 if "Mapping" in strType:
278 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
280 if "Sequence" in strType:
281 for i in range(len(value)):
282 _saveConfigRecursiveDbg(value.data[i], aStream, indentp, path+"."+key+"[%i]" % i, nbp)
284 if "Expression" in strType:
286 evaluate = value.evaluate(config)
287 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
288 except Exception as e:
289 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
291 if "Reference" in strType:
293 evaluate = value.resolve(config)
294 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
295 except Exception as e:
296 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
298 if type(value) in [str, bool, int, type(None), unicode]:
299 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
302 aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value)))
303 except Exception as e:
304 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message))