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 _developpers = ["christian", "wambeke", "crouzet"] # crouzet, kloss ...
67 def indent(text, amount=2, ch=' '):
68 """indent multi lines message"""
70 return ''.join(padding + line for line in text.splitlines(True))
72 def isTypeConfig(var):
73 """To know if var is instance from Config/pyconf"""
75 # print "isTypeConfig" ,type, dir(var)
76 if ".pyconf.Config" in typ: return True
77 if ".pyconf.Mapping" in typ: return True
78 if ".pyconf.Sequence" in typ: return True
79 # print "NOT isTypeConfig %s" % typ
82 def write(title, var="", force=None, fmt="\n#### DEBUG: %s:\n%s\n"):
83 """write sys.stderr a message if _debug[-1]==True or optionaly force=True"""
84 if _debug[-1] or force:
88 sys.stderr.write(fmt % (title, indent(COLS.toColor(getStrConfigDbg(var)))))
90 if 'UnittestStream' in typ:
91 sys.stderr.write(fmt % (title, indent(var.getLogs())))
93 if tvar is not str and tvar is not unicode:
94 sys.stderr.write(fmt % (title, indent(PP.pformat(var))))
96 sys.stderr.write(fmt % (title, indent(var)))
100 def tofix(title, var="", force=None):
102 write sys.stderr a message if _debug[-1]==True or optionaly force=True
103 use this only if no logger accessible for classic logger.warning(message)
105 fmt = "\n#### TOFIX: %s:\n%s\n"
106 write(title, var, force, fmt)
108 def push_debug(aBool):
109 """set debug outputs activated, or not"""
113 """restore previous debug outputs status"""
117 sys.stderr.write("\nERROR: pop_debug: too much pop.")
121 def format_exception(msg, limit=None, trace=None):
123 Format a stack trace and the exception information.
124 as traceback.format_exception(), without color
125 with traceback only if (_debug) or (DBG._user in DBG._developpers)
127 etype, value, tb = sys.exc_info()
128 if (_debug[-1]) or (_user in _developpers):
131 res += "\nTraceback (most recent call last):\n"
132 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
134 res += "\n".join(traceback.format_exception_only(etype, value))
138 res += "".join(traceback.format_exception_only(etype, value))
141 def format_color_exception(msg, limit=None, trace=None):
143 Format a stack trace and the exception information.
144 as traceback.format_exception(), with color
145 with traceback only if (_debug) or (DBG._user in DBG._developpers)
147 etype, value, tb = sys.exc_info()
148 if (_debug[-1]) or (_user in _developpers):
151 res += "<yellow>\nTraceback (most recent call last):\n"
152 res += "".join(traceback.format_tb(tb, limit)) # [:-1])
154 res += "\n".join(traceback.format_exception_only(etype, value))
155 return res + "<reset>"
157 res = "<red>" + msg # + "<bright>"
158 res += "".join(traceback.format_exception_only(etype, value))
159 return res + "<reset>"
162 ###############################################
163 # utilitaires divers pour debug
164 ###############################################
166 class OutStream(SIO.StringIO):
168 utility class for pyconf.Config output iostream
172 because Config.__save__ calls close() stream as file
173 keep value before lost as self.value
175 self.value = self.getvalue()
176 SIO.StringIO.close(self)
178 class InStream(SIO.StringIO):
179 """utility class for pyconf.Config input iostream"""
183 """get string for environment variables representation"""
185 for i in sorted(os.environ):
186 res += "%s : %s\n" % (i, os.environ[i])
189 # save as initial Config.save() moved as Config.__save__()
190 def saveConfigStd(config, aStream):
191 """returns as file .pyconf"""
193 config.__save__(aStream, indent)
195 def getStrConfigStd(config):
196 """set string as saveConfigStd, as file .pyconf"""
197 outStream = OutStream()
198 saveConfigStd(config, outStream)
199 return outStream.value
201 def getStrConfigDbg(config):
203 set string as saveConfigDbg,
204 as (path expression evaluation) for debug
206 outStream = OutStream()
207 saveConfigDbg(config, outStream)
208 return outStream.value
210 def saveConfigDbg(config, aStream, indent=0, path=""):
211 """pyconf returns multilines (path expression evaluation) for debug"""
212 _saveConfigRecursiveDbg(config, aStream, indent, path, 0)
213 aStream.close() # as config.__save__()
215 def _saveConfigRecursiveDbg(config, aStream, indent, path, nb):
216 """pyconf inspired from Mapping.__save__"""
218 nbp = nb + 1 # depth recursive
224 if nbp > 10: # protection
225 # raise Exception("!!! ERROR: Circular reference after %s" % aStream.getvalue())
226 # raise Exception("!!! ERROR: Circular reference %s" % path)
227 aStream.write("<red>!!! ERROR: Circular reference after %s<reset>\n" % path)
230 indstr = indent * ' ' # '':no indent, ' ':indent
231 strType = str(type(config))
232 if debug: print "saveDbg Type", path, strType
234 if "Sequence" in strType:
235 for i in range(len(config)):
236 _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i, nbp)
239 if "Reference" in strType:
241 #evaluate = value.resolve(config)
242 aStream.write("<header>%s%s<reset> : %s <yellow>--> '%s'<reset>\n" % (indstr, path, config, str(config)))
243 except Exception as e:
244 aStream.write("<header>%s%s<reset> : <red>!!! ERROR: %s !!!<reset>\n" % (indstr, path, e.message))
248 try: #type config, mapping
249 order = object.__getattribute__(config, 'order')
250 data = object.__getattribute__(config, 'data')
252 aStream.write("%s%s : '%s'\n" % (indstr, path, str(config)))
254 for key in sorted(data): #order): # data as sort alphabetical, order as initial order
256 strType = str(type(value))
257 if debug: print 'strType', path, key, strType
258 if "Config" in strType:
259 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
261 if "Mapping" in strType:
262 _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key, nbp)
264 if "Sequence" in strType:
265 for i in range(len(value)):
266 _saveConfigRecursiveDbg(value.data[i], aStream, indentp, path+"."+key+"[%i]" % i, nbp)
268 if "Expression" in strType:
270 evaluate = value.evaluate(config)
271 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
272 except Exception as e:
273 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
275 if "Reference" in strType:
277 evaluate = value.resolve(config)
278 aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate))
279 except Exception as e:
280 aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message))
282 if type(value) in [str, bool, int, type(None), unicode]:
283 aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value)))
286 aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value)))
287 except Exception as e:
288 aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message))