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 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()
146 res += "\nTraceback (most recent call last):\n"
147 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
149 res += "\n".join(traceback.format_exception_only(etype, value))
152 def format_color_exception(msg, limit=None, trace=None):
154 Format a stack trace and the exception information.
155 as traceback.format_exception(), with color
156 with traceback only if _debug or isDeveloper())
158 etype, value, tb = sys.exc_info()
159 if _debug[-1] or isDeveloper():
162 res += "<yellow>\nTraceback (most recent call last):\n"
163 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
165 res += "\n".join(traceback.format_exception_only(etype, value))
166 return res + "<reset>"
168 res = "<red>" + msg # + "<bright>"
169 res += "".join(traceback.format_exception_only(etype, value))
170 return res + "<reset>"
173 ###############################################
174 # utilitaires divers pour debug
175 ###############################################
177 class OutStream(StringIO):
179 utility class for pyconf.Config output iostream
183 because Config.__save__ calls close() stream as file
184 keep value before lost as self.value
186 self.value = self.getvalue()
189 class InStream(StringIO):
190 """utility class for pyconf.Config input iostream"""
194 """get string for environment variables representation"""
196 for i in sorted(os.environ):
197 res += "%s : %s\n" % (i, os.environ[i])
200 # save as initial Config.save() moved as Config.__save__()
201 def saveConfigStd(config, aStream):
202 """returns as file .pyconf"""
204 config.__save__(aStream, indent)
206 def getStrConfigStd(config):
207 """set string as saveConfigStd, as file .pyconf"""
208 outStream = OutStream()
209 saveConfigStd(config, outStream)
210 return outStream.value
212 def getStrConfigDbg(config):
214 set string as saveConfigDbg,
215 as (path expression evaluation) for debug
217 outStream = OutStream()
218 saveConfigDbg(config, outStream)
219 return outStream.value
221 def saveConfigDbg(config, aStream, indent=0, path=""):
222 """pyconf returns multilines (path expression evaluation) for debug"""
223 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
224 aStream.close() # as config.__save__()
226 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
227 """pyconf inspired from Mapping.__save__"""
229 nbp = nb + 1 # depth recursive
235 if nbp > 10: # protection
236 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
237 # raise Exception("!!! ERROR: Circular reference %s" % path)
238 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
241 indstr = indent * ' ' # '':no indent, ' ':indent
242 strType = str(type(config))
243 if debug: print("saveDbg Type %s %s" % (path, strType))
245 if "Sequence" in strType:
246 for i in range(len(config)):
247 _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i, nbp)
250 if "Reference" in strType:
252 #evaluate = value.resolve(config)
253 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
254 except Exception as e:
255 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, e.message))
259 try: #type config, mapping
260 order = object.__getattribute__(config, 'order')
261 data = object.__getattribute__(config, 'data')
263 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
265 for key in sorted(data): #order): # data as sort alphabetical, order as initial order
267 strType = str(type(value))
268 if debug: print('strType %s %s %s' % (path, key, strType))
269 if "Config" in strType:
270 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
272 if "Mapping" in strType:
273 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
275 if "Sequence" in strType:
276 for i in range(len(value)):
277 _saveConfigRecursiveDbg(value.data[i], aStream, indentp, path+"."+key+"[%i]" % i, nbp)
279 if "Expression" in strType:
281 evaluate = value.evaluate(config)
282 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
283 except Exception as e:
284 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
286 if "Reference" in strType:
288 evaluate = value.resolve(config)
289 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
290 except Exception as e:
291 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
293 if type(value) in [str, bool, int, type(None), unicode]:
294 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
297 aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value)))
298 except Exception as e:
299 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message))