cgitb.py
Go to the documentation of this file.
1 """More comprehensive traceback formatting for Python scripts.
2 
3 To enable this module, do:
4 
5  import cgitb; cgitb.enable()
6 
7 at the top of your script. The optional arguments to enable() are:
8 
9  display - if true, tracebacks are displayed in the web browser
10  logdir - if set, tracebacks are written to files in this directory
11  context - number of lines of source code to show for each stack frame
12  format - 'text' or 'html' controls the output format
13  viewClass - sub class of View. Create this if you want to customize the
14  layout of the traceback.
15  debug - may be used by viewClass to decide on level of detail
16 
17 By default, tracebacks are displayed but not saved, the context is 5 lines
18 and the output format is 'html' (for backwards compatibility with the
19 original use of this module).
20 
21 Alternatively, if you have caught an exception and want cgitb to display it
22 for you, call cgitb.handler(). The optional argument to handler() is a
23 3-item tuple (etype, evalue, etb) just like the value of sys.exc_info().
24 The default handler displays output as HTML.
25 
26 
27 2005-04-22 Nir Soffer <nirs@freeshell.org>
28 
29 Rewrite:
30  - Refactor html and text functions to View class, HTMLFormatter and
31  TextFormatter. No more duplicate formating code.
32  - Layout is done with minimal html and css, in a way it can't be
33  affected by surrounding code.
34  - Built to be easy to subclass and modify without duplicating code.
35  - Change layout, important details come first.
36  - Factor frame analyzing and formatting into separate class.
37  - Add debug argument, can be used to change error display e.g. user
38  error view, developer error view.
39  - Add viewClass argument, make it easy to customize the traceback view.
40  - Easy to customize system details and application details.
41 
42 The main goal of this rewrite was to have a traceback that can render
43 few tracebacks combined. It's needed when you wrap an expection and want
44 to print both the traceback up to the wrapper exception, and the
45 original traceback. There is no code to support this here, but it's easy
46 to add by using your own View sub class.
47 """
48 
49 __author__ = 'Ka-Ping Yee'
50 __version__ = '$Revision: 1.10 $'
51 
52 import sys, os, pydoc, inspect, linecache, tokenize, keyword
53 
54 
55 def reset():
56  """ Reset the CGI and the browser
57 
58  Return a string that resets the CGI and browser to a known state.
59  TODO: probably some of this is not needed any more.
60  """
61  return """<!--: spam
62 Content-Type: text/html
63 
64 <body><font style="color: white; font-size: 1px"> -->
65 <body><font style="color: white; font-size: 1px"> --> -->
66 </font> </font> </font> </script> </object> </blockquote> </pre>
67 </table> </table> </table> </table> </table> </font> </font> </font>
68 """
69 
70 __UNDEF__ = [] # a special sentinel object
71 
72 
74  def __repr__(self):
75  return "<HIDDEN>"
76 HiddenObject = HiddenObject()
77 
79  """ Minimal html formatter """
80 
81  def attributes(self, attributes=None):
82  if attributes:
83  result = [' %s="%s"' % (k, v) for k, v in attributes.items()]
84  return ''.join(result)
85  return ''
86 
87  def tag(self, name, text, attributes=None):
88  return '<%s%s>%s</%s>\n' % (name, self.attributes(attributes), text, name)
89 
90  def section(self, text, attributes=None):
91  return self.tag('div', text, attributes)
92 
93  def title(self, text, attributes=None):
94  return self.tag('h1', text, attributes)
95 
96  def subTitle(self, text, attributes=None):
97  return self.tag('h2', text, attributes)
98 
99  def subSubTitle(self, text, attributes=None):
100  return self.tag('h3', text, attributes)
101 
102  def paragraph(self, text, attributes=None):
103  return self.tag('p', text, attributes)
104 
105  def list(self, items, attributes=None):
106  return self.formatList('ul', items, attributes)
107 
108  def orderedList(self, items, attributes=None):
109  return self.formatList('ol', items, attributes)
110 
111  def formatList(self, name, items, attributes=None):
112  """ Send list of raw texts or formatted items. """
113  if isinstance(items, (list, tuple)):
114  items = '\n' + ''.join([self.listItem(i) for i in items])
115  return self.tag(name, items, attributes)
116 
117  def listItem(self, text, attributes=None):
118  return self.tag('li', text, attributes)
119 
120  def link(self, href, text, attributes=None):
121  if attributes is None:
122  attributes = {}
123  attributes['href'] = href
124  return self.tag('a', text, attributes)
125 
126  def strong(self, text, attributes=None):
127  return self.tag('strong', text, attributes)
128 
129  def em(self, text, attributes=None):
130  return self.tag('em', text, attributes)
131 
132  def repr(self, object):
133  return pydoc.html.repr(object)
134 
135 
137  """ Plain text formatter """
138 
139  def section(self, text, attributes=None):
140  return text
141 
142  def title(self, text, attributes=None):
143  lineBellow = '=' * len(text)
144  return '%s\n%s\n\n' % (text, lineBellow)
145 
146  def subTitle(self, text, attributes=None):
147  lineBellow = '-' * len(text)
148  return '%s\n%s\n\n' % (text, lineBellow)
149 
150  def subSubTitle(self, text, attributes=None):
151  lineBellow = '~' * len(text)
152  return '%s\n%s\n\n' % (text, lineBellow)
153 
154  def paragraph(self, text, attributes=None):
155  return text + '\n\n'
156 
157  def list(self, items, attributes=None):
158  if isinstance(items, (list, tuple)):
159  items = [' * %s\n' % i for i in items]
160  return ''.join(items) + '\n'
161  return items
162 
163  def orderedList(self, items, attributes=None):
164  if isinstance(items, (list, tuple)):
165  result = []
166  for i in range(items):
167  result.append(' %d. %s\n' % (i, items[i]))
168  return ''.join(result) + '\n'
169  return items
170 
171  def listItem(self, text, attributes=None):
172  return ' * %s\n' % text
173 
174  def link(self, href, text, attributes=None):
175  return '[[%s]]' % text
176 
177  def strong(self, text, attributes=None):
178  return text
179 
180  def em(self, text, attributes=None):
181  return text
182 
183  def repr(self, object):
184  return repr(object)
185 
186 
187 class Frame:
188  """ Analyze and format single frame in a traceback """
189 
190  def __init__(self, frame, file, lnum, func, lines, index):
191  self.frame = frame
192  self.file = file
193  self.lnum = lnum
194  self.func = func
195  self.lines = lines
196  self.index = index
197 
198  def format(self, formatter):
199  """ Return formatted content """
200  self.formatter = formatter
201  vars, highlight = self.scan()
202  items = [self.formatCall(),
203  self.formatContext(highlight),
204  self.formatVariables(vars)]
205  return ''.join(items)
206 
207  # -----------------------------------------------------------------
208  # Private - formatting
209 
210  def formatCall(self):
211  call = '%s in %s%s' % (self.formatFile(),
212  self.formatter.strong(self.func),
213  self.formatArguments(),)
214  return self.formatter.paragraph(call, {'class': 'call'})
215 
216  def formatFile(self):
217  """ Return formatted file link """
218  if not self.file:
219  return '?'
220  file = pydoc.html.escape(os.path.abspath(self.file))
221  return self.formatter.link('file://' + file, file)
222 
223  def formatArguments(self):
224  """ Return formated arguments list """
225  if self.func == '?':
226  return ''
227 
228  def formatValue(value):
229  return '=' + self.formatter.repr(value)
230 
231  args, varargs, varkw, locals = inspect.getargvalues(self.frame)
232  return inspect.formatargvalues(args, varargs, varkw, locals,
233  formatvalue=formatValue)
234 
235  def formatContext(self, highlight):
236  """ Return formatted context, next call highlighted """
237  if self.index is None:
238  return ''
239  context = []
240  i = self.lnum - self.index
241  for line in self.lines:
242  line = '%5d %s' % (i, pydoc.html.escape(line))
243  attributes = {}
244  if i in highlight:
245  attributes = {'class': 'highlight'}
246  context.append(self.formatter.listItem(line, attributes))
247  i += 1
248  context = '\n' + ''.join(context) + '\n'
249  return self.formatter.orderedList(context, {'class': 'context'})
250 
251  def formatVariables(self, vars):
252  """ Return formatted variables """
253  done = {}
254  dump = []
255  for name, where, value in vars:
256  if name in done:
257  continue
258  done[name] = 1
259  if value is __UNDEF__:
260  dump.append('%s %s' % (name, self.formatter.em('undefined')))
261  else:
262  dump.append(self.formatNameValue(name, where, value))
263  return self.formatter.list(dump, {'class': 'variables'})
264 
265  def formatNameValue(self, name, where, value):
266  """ Format variable name and value according to scope """
267  if where in ['global', 'builtin']:
268  name = '%s %s' % (self.formatter.em(where),
269  self.formatter.strong(name))
270  elif where == 'local':
271  name = self.formatter.strong(name)
272  else:
273  name = where + self.formatter.strong(name.split('.')[-1])
274  return '%s = %s' % (name, self.formatter.repr(value))
275 
276  # ---------------------------------------------------------------
277  # Private - analyzing code
278 
279  def scan(self):
280  """ Scan frame for vars while setting highlight line """
281  highlight = {}
282 
283  def reader(lnum=[self.lnum]):
284  highlight[lnum[0]] = 1
285  try:
286  return linecache.getline(self.file, lnum[0])
287  finally:
288  lnum[0] += 1
289 
290  vars = self.scanVariables(reader)
291  return vars, highlight
292 
293  def scanVariables(self, reader):
294  """ Lookup variables in one logical Python line """
295  vars, lasttoken, parent, prefix, value = [], None, None, '', __UNDEF__
296  for ttype, token, start, end, line in tokenize.generate_tokens(reader):
297  if ttype == tokenize.NEWLINE:
298  break
299  if ttype == tokenize.NAME and token not in keyword.kwlist:
300  if lasttoken == '.':
301  if parent is not __UNDEF__:
302  if self.unsafe_name(token):
303  value = HiddenObject
304  else:
305  value = getattr(parent, token, __UNDEF__)
306  vars.append((prefix + token, prefix, value))
307  else:
308  where, value = self.lookup(token)
309  vars.append((token, where, value))
310  elif token == '.':
311  prefix += lasttoken + '.'
312  parent = value
313  else:
314  parent, prefix = None, ''
315  lasttoken = token
316  return vars
317 
318  def lookup(self, name):
319  """ Return the scope and the value of name """
320  scope = None
321  value = __UNDEF__
322  locals = inspect.getargvalues(self.frame)[3]
323  if name in locals:
324  scope, value = 'local', locals[name]
325  elif name in self.frame.f_globals:
326  scope, value = 'global', self.frame.f_globals[name]
327  elif '__builtins__' in self.frame.f_globals:
328  scope = 'builtin'
329  builtins = self.frame.f_globals['__builtins__']
330  if isinstance(builtins, dict):
331  value = builtins.get(name, __UNDEF__)
332  else:
333  value = getattr(builtins, name, __UNDEF__)
334  if self.unsafe_name(name):
335  value = HiddenObject
336  return scope, value
337 
338  def unsafe_name(self, name):
339  return name in self.frame.f_globals.get("unsafe_names", ())
340 
341 class View:
342  """ Traceback view """
343 
344  frameClass = Frame # analyze and format a frame
345 
346  def __init__(self, info=None, debug=0):
347  """ Save starting info or current exception info """
348  self.info = info or sys.exc_info()
349  self.debug = debug
350 
351  def format(self, formatter, context=5):
352  self.formatter = formatter
353  self.context = context
354  return formatter.section(self.formatContent(), {'class': 'cgitb'})
355 
356  def formatContent(self):
357  """ General layout - override to change layout """
358  content = (
359  self.formatStylesheet(),
360  self.formatTitle(),
361  self.formatMessage(),
362  self.formatTraceback(),
363  self.formatSystemDetails(),
364  self.formatTextTraceback(),
365  )
366  return ''.join(content)
367 
368  # -----------------------------------------------------------------
369  # Stylesheet
370 
371  def formatStylesheet(self):
372  """ Format inline html stylesheet """
373  return '<style type="text/css">%s</style>' % self.stylesheet()
374 
375  def stylesheet(self):
376  """ Return stylesheet rules. Override to change rules.
377 
378  The rules are sparated to make it easy to extend.
379 
380  The stylesheet must work even if sorounding code define the same
381  css names, and it must not change the sorounding code look and
382  behavior. This is done by having all content in a .traceback
383  section.
384  """
385  return """
386 .cgitb {background: #E6EAF0; border: 1px solid #4D6180; direction: ltr;}
387 .cgitb p {margin: 0.5em 0; padding: 5px 10px; text-align: left;}
388 .cgitb ol {margin: 0}
389 .cgitb li {margin: 0.25em 0;}
390 .cgitb h1, .cgitb h2, .cgitb h3 {padding: 5px 10px; margin: 0; background: #4D6180; color: white;}
391 .cgitb h1 {font-size: 1.3em;}
392 .cgitb h2 {font-size: 1em; margin-top: 1em;}
393 .cgitb h3 {font-size: 1em;}
394 .cgitb .frames {margin: 0; padding: 0; color: #606060}
395 .cgitb .frames li {display: block;}
396 .cgitb .call {padding: 5px 10px; background: #A3B4CC; color: black}
397 .cgitb .context {padding: 0; font-family: monospace; }
398 .cgitb .context li {display: block; white-space: pre;}
399 .cgitb .context li.highlight {background: #C0D3F0; color: black}
400 .cgitb .variables {padding: 5px 10px; font-family: monospace;}
401 .cgitb .variables li {display: inline;}
402 .cgitb .variables li:after {content: ", ";}
403 .cgitb .variables li:last-child:after {content: "";}
404 .cgitb .exception {border: 1px solid #4D6180; margin: 10px}
405 .cgitb .exception h3 {background: #4D6180; color: white;}
406 .cgitb .exception p {color: black;}
407 .cgitb .exception ul {padding: 0 10px; font-family: monospace;}
408 .cgitb .exception li {display: block;}
409 """
410 
411  # -----------------------------------------------------------------
412  # Head
413 
414  def formatTitle(self):
415  return self.formatter.title(self.exceptionTitle(self.info))
416 
417  def formatMessage(self):
418  return self.formatter.paragraph(self.exceptionMessage(self.info))
419 
420  # -----------------------------------------------------------------
421  # Traceback
422 
423  def formatTraceback(self):
424  """ Return formatted traceback """
425  return self.formatOneTraceback(self.info)
426 
427  def formatOneTraceback(self, info):
428  """ Format one traceback
429 
430  Separate to enable formatting multiple tracebacks.
431  """
432  output = [self.formatter.subTitle('Traceback'),
433  self.formatter.paragraph(self.tracebackText(info)),
434  self.formatter.orderedList(self.tracebackFrames(info),
435  {'class': 'frames'}),
436  self.formatter.section(self.formatException(info),
437  {'class': 'exception'}), ]
438  return self.formatter.section(''.join(output), {'class': 'traceback'})
439 
440  def tracebackFrames(self, info):
441  frames = []
442  traceback = info[2]
443  for record in inspect.getinnerframes(traceback, self.context):
444  frame = self.frameClass(*record)
445  frames.append(frame.format(self.formatter))
446  del traceback
447  return frames
448 
449  def tracebackText(self, info):
450  return '''A problem occurred in a Python script. Here is the
451  sequence of function calls leading up to the error, in the
452  order they occurred.'''
453 
454  # --------------------------------------------------------------------
455  # Exception
456 
457  def formatException(self, info):
458  items = [self.formatExceptionTitle(info),
459  self.formatExceptionMessage(info),
460  self.formatExceptionAttributes(info), ]
461  return ''.join(items)
462 
463  def formatExceptionTitle(self, info):
464  return self.formatter.subSubTitle(self.exceptionTitle(info))
465 
466  def formatExceptionMessage(self, info):
467  return self.formatter.paragraph(self.exceptionMessage(info))
468 
469  def formatExceptionAttributes(self, info):
470  attribtues = []
471  for name, value in self.exceptionAttributes(info):
472  value = self.formatter.repr(value)
473  attribtues.append('%s = %s' % (name, value))
474  return self.formatter.list(attribtues)
475 
476  def exceptionAttributes(self, info):
477  """ Return list of tuples [(name, value), ...] """
478  instance = info[1]
479  attribtues = []
480  for name in dir(instance):
481  if name.startswith('_'):
482  continue
483  value = getattr(instance, name)
484  attribtues.append((name, value))
485  return attribtues
486 
487  def exceptionTitle(self, info):
488  type = info[0]
489  return getattr(type, '__name__', str(type))
490 
491  def exceptionMessage(self, info):
492  instance = info[1]
493  return pydoc.html.escape(str(instance))
494 
495 
496  # -----------------------------------------------------------------
497  # System details
498 
500  details = ['Date: %s' % self.date(),
501  'Platform: %s' % self.platform(),
502  'Python: %s' % self.python(), ]
503  details += self.applicationDetails()
504  return (self.formatter.subTitle('System Details') +
505  self.formatter.list(details, {'class': 'system'}))
506 
507  def date(self):
508  import time
509  rfc2822Date = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
510  return rfc2822Date
511 
512  def platform(self):
513  try:
514  return pydoc.html.escape(' '.join(os.uname()))
515  except:
516  return pydoc.html.escape('%s (%s)' % (sys.platform, os.name))
517 
518  def python(self):
519  return 'Python %s (%s)' % (sys.version.split()[0], sys.executable)
520 
522  """ Override for your application """
523  return []
524 
525  # -----------------------------------------------------------------
526  # Text traceback
527 
529  template = self.textTracebackTemplate()
530  return template % self.formatOneTextTraceback(self.info)
531 
532  def formatOneTextTraceback(self, info):
533  """ Separate to enable formatting multiple tracebacks. """
534  import traceback
535  return pydoc.html.escape(''.join(traceback.format_exception(*info)))
536 
538  return '''
539 
540 <!-- The above is a description of an error in a Python program,
541  formatted for a Web browser. In case you are not reading this
542  in a Web browser, here is the original traceback:
543 
544 %s
545 -->
546 '''
547 
548 
549 class Hook:
550  """A hook to replace sys.excepthook that shows tracebacks in HTML."""
551 
552  def __init__(self, display=1, logdir=None, context=5, file=None,
553  format="html", viewClass=View, debug=0):
554  self.display = display # send tracebacks to browser if true
555  self.logdir = logdir # log tracebacks to files if not None
556  self.context = context # number of source code lines per frame
557  self.file = file or sys.stdout # place to send the output
558  self.format = format
559  self.viewClass = viewClass
560  self.debug = debug
561 
562  def __call__(self, etype, evalue, etb):
563  self.handle((etype, evalue, etb))
564 
565  def handle(self, info=None):
566  info = info or sys.exc_info()
567  if self.format.lower() == "html":
568  formatter = HTMLFormatter()
569  self.file.write(reset())
570  plain = False
571  else:
572  formatter = TextFormatter()
573  plain = True
574  try:
575  view = self.viewClass(info, self.debug)
576  doc = view.format(formatter, self.context)
577  except:
578  raise
579  import traceback
580  doc = ''.join(traceback.format_exception(*info))
581  plain = True
582 
583  if self.display:
584  if plain:
585  doc = doc.replace('&', '&amp;').replace('<', '&lt;')
586  self.file.write('<pre>' + doc + '</pre>\n')
587  else:
588  self.file.write(doc + '\n')
589  else:
590  self.file.write('<p>A problem occurred in a Python script.\n')
591 
592  if self.logdir is not None:
593  import tempfile
594  suffix = ['.txt', '.html'][self.format == "html"]
595  (fd, path) = tempfile.mkstemp(suffix=suffix, dir=self.logdir)
596  try:
597  file = os.fdopen(fd, 'w')
598  file.write(doc)
599  file.close()
600  msg = '<p> %s contains the description of this error.' % path
601  except:
602  msg = '<p> Tried to save traceback to %s, but failed.' % path
603  self.file.write(msg + '\n')
604  try:
605  self.file.flush()
606  except: pass
607 
608 
609 handler = Hook().handle
610 
611 def enable(display=1, logdir=None, context=5, format="html", viewClass=View, debug=0):
612  """Install an exception handler that formats tracebacks as HTML.
613 
614  The optional argument 'display' can be set to 0 to suppress sending the
615  traceback to the browser, and 'logdir' can be set to a directory to cause
616  tracebacks to be written to files there."""
617  sys.excepthook = Hook(display=display, logdir=logdir, context=context,
618  format=format, viewClass=viewClass, debug=debug)
619 
def formatTraceback(self)
Definition: cgitb.py:423
def applicationDetails(self)
Definition: cgitb.py:521
def exceptionMessage(self, info)
Definition: cgitb.py:491
def formatNameValue(self, name, where, value)
Definition: cgitb.py:265
def format(self, formatter)
Definition: cgitb.py:198
def formatExceptionAttributes(self, info)
Definition: cgitb.py:469
def formatCall(self)
Definition: cgitb.py:210
def repr(self, object)
Definition: cgitb.py:183
def formatSystemDetails(self)
Definition: cgitb.py:499
def listItem(self, text, attributes=None)
Definition: cgitb.py:171
def __init__(self, info=None, debug=0)
Definition: cgitb.py:346
def subSubTitle(self, text, attributes=None)
Definition: cgitb.py:150
def link(self, href, text, attributes=None)
Definition: cgitb.py:174
def formatTitle(self)
Definition: cgitb.py:414
def tag(self, name, text, attributes=None)
Definition: cgitb.py:87
def subSubTitle(self, text, attributes=None)
Definition: cgitb.py:99
def section(self, text, attributes=None)
Definition: cgitb.py:90
def tracebackText(self, info)
Definition: cgitb.py:449
def attributes(self, attributes=None)
Definition: cgitb.py:81
def handle(self, info=None)
Definition: cgitb.py:565
def list(self, items, attributes=None)
Definition: cgitb.py:157
def title(self, text, attributes=None)
Definition: cgitb.py:93
def lookup(self, name)
Definition: cgitb.py:318
def exceptionAttributes(self, info)
Definition: cgitb.py:476
def strong(self, text, attributes=None)
Definition: cgitb.py:177
def scanVariables(self, reader)
Definition: cgitb.py:293
def paragraph(self, text, attributes=None)
Definition: cgitb.py:154
def subTitle(self, text, attributes=None)
Definition: cgitb.py:96
def orderedList(self, items, attributes=None)
Definition: cgitb.py:108
def section(self, text, attributes=None)
Definition: cgitb.py:139
def formatVariables(self, vars)
Definition: cgitb.py:251
def em(self, text, attributes=None)
Definition: cgitb.py:129
def formatOneTraceback(self, info)
Definition: cgitb.py:427
def formatExceptionTitle(self, info)
Definition: cgitb.py:463
def listItem(self, text, attributes=None)
Definition: cgitb.py:117
def strong(self, text, attributes=None)
Definition: cgitb.py:126
def enable(display=1, logdir=None, context=5, format="html", viewClass=View, debug=0)
Definition: cgitb.py:611
def formatException(self, info)
Definition: cgitb.py:457
def formatFile(self)
Definition: cgitb.py:216
def __init__(self, frame, file, lnum, func, lines, index)
Definition: cgitb.py:190
def list(self, items, attributes=None)
Definition: cgitb.py:105
def __init__(self, display=1, logdir=None, context=5, file=None, format="html", viewClass=View, debug=0)
Definition: cgitb.py:553
def stylesheet(self)
Definition: cgitb.py:375
def repr(self, object)
Definition: cgitb.py:132
def textTracebackTemplate(self)
Definition: cgitb.py:537
def title(self, text, attributes=None)
Definition: cgitb.py:142
def formatStylesheet(self)
Definition: cgitb.py:371
def formatContent(self)
Definition: cgitb.py:356
def formatContext(self, highlight)
Definition: cgitb.py:235
def paragraph(self, text, attributes=None)
Definition: cgitb.py:102
def orderedList(self, items, attributes=None)
Definition: cgitb.py:163
def exceptionTitle(self, info)
Definition: cgitb.py:487
def unsafe_name(self, name)
Definition: cgitb.py:338
def formatTextTraceback(self)
Definition: cgitb.py:528
def __call__(self, etype, evalue, etb)
Definition: cgitb.py:562
def format(self, formatter, context=5)
Definition: cgitb.py:351
def formatList(self, name, items, attributes=None)
Definition: cgitb.py:111
def formatMessage(self)
Definition: cgitb.py:417
def formatExceptionMessage(self, info)
Definition: cgitb.py:466
def em(self, text, attributes=None)
Definition: cgitb.py:180
def subTitle(self, text, attributes=None)
Definition: cgitb.py:146
def formatArguments(self)
Definition: cgitb.py:223
def formatOneTextTraceback(self, info)
Definition: cgitb.py:532
def link(self, href, text, attributes=None)
Definition: cgitb.py:120
def tracebackFrames(self, info)
Definition: cgitb.py:440
def platform(self)
Definition: cgitb.py:512


pyclearsilver
Author(s): Scott Noob Hassan
autogenerated on Mon Jun 10 2019 15:51:13