1
# -*- coding: iso-8859-1 -*-
4
Handle fatal errors by showing a message and debugging information.
6
@copyright: 2004-2005 Nir Soffer <nirs@freeshell.org>
7
@license: GNU GPL, see COPYING for details.
11
from MoinMoin import log
12
logging = log.getLogger(__name__)
14
from MoinMoin.support import cgitb
15
from MoinMoin.error import ConfigurationError
16
from traceback import extract_tb
19
class View(cgitb.View):
20
""" Display an error message and debugging information
22
Additions to cgitb.View:
23
- Multiple tracebacks support
24
- Debugging information is shown only in debug mode
25
- Moin application information
26
- General help text and links
27
- Handle multiple paragraphs in exception message
29
cgitb is heavily modified cgitb, but fully backward compatible with
30
the standard cgitb. It should not contain any moin specific code.
32
cgitb was refactored to be easy to customize by applications
33
developers. This moin specific subclass is an example.
35
debugInfoID = 'debug-info'
37
def formatContent(self):
40
self.formatStylesheet(),
44
self.formatDebugInfo(),
45
self.formatTextTraceback()
47
return ''.join(content)
51
<script type="text/javascript">
52
function toggleDebugInfo() {
53
var tb = document.getElementById('%s');
54
if (tb == null) return;
55
tb.style.display = tb.style.display ? '' : 'none';
58
''' % self.debugInfoID
61
return cgitb.View.stylesheet(self) + """
62
.cgitb .buttons {margin: 0.5em 0; padding: 5px 10px;}
63
.cgitb .buttons li {display: inline; margin: 0; padding: 0 0.25em;}
66
def formatMessage(self):
67
""" handle multiple paragraphs messages and add general help """
69
text = [self.formatExceptionMessage(self.info)]
71
if self.info[0] == ConfigurationError:
72
tbt = extract_tb(self.info[1].exceptions()[-1][2])[-1]
74
f.paragraph('Error in your configuration file "%s"'
75
' around line %d.' % tbt[:2]))
78
f.paragraph("If you want to report a bug, please save "
79
"this page and attach it to your bug report."))
82
def formatButtons(self):
83
""" Add 'buttons' to the error dialog """
85
buttons = [f.link('javascript:toggleDebugInfo()',
86
'Show debugging information')]
87
if self.info[0] != ConfigurationError:
89
f.link('http://moinmo.in/MoinMoinBugs',
92
f.link('http://moinmo.in/FrontPage',
93
'Visit MoinMoin wiki'))
94
return f.list(buttons, {'class': 'buttons'})
96
def formatDebugInfo(self):
97
""" Put debugging information in a hidden div """
98
attributes = {'id': self.debugInfoID}
99
info = [self.debugInfoHideScript(),
100
self.formatTraceback(),
101
self.formatSystemDetails(), ]
102
return self.formatter.section(''.join(info), attributes)
104
def debugInfoHideScript(self):
105
""" Hide debug info for javascript enabled browsers """
109
<script type="text/javascript">toggleDebugInfo()</script>
112
def formatTraceback(self):
113
return self.formatAllTracebacks(self.formatOneTraceback)
115
def formatTextTraceback(self):
116
template = self.textTracebackTemplate()
117
return template % self.formatAllTracebacks(self.formatOneTextTraceback)
119
def formatAllTracebacks(self, formatFuction):
120
""" Format multiple tracebacks using formatFunction """
122
for ttype, tvalue, tb in self.exceptions():
125
tracebacks.append(formatFuction((ttype, tvalue, tb)))
127
return ''.join(tracebacks)
129
def exceptions(self):
130
""" Return a list of exceptions info, starting at self.info """
132
return [self.info] + self.info[1].exceptions()
133
except AttributeError:
136
def applicationDetails(self):
137
""" Add MoinMoin details to system details """
138
from MoinMoin import version
139
return ['MoinMoin: Release %s (%s)' % (version.release,
142
def formatExceptionMessage(self, info):
143
""" Handle multiple paragraphs in exception message """
144
text = cgitb.View.exceptionMessage(self, info)
145
text = text.split('\n\n')
146
text = ''.join([self.formatter.paragraph(item) for item in text])
150
def handle(request, err):
153
Display fancy error view, or fallback to simple text traceback
155
if 'MOIN_DEBUG' in os.environ:
158
savedError = sys.exc_info()
159
logging.exception('An exception occured.')
161
debug = 'debug' in getattr(request, 'form', {})
162
# default to True here to allow an admin setting up the wiki
163
# to see the errors made in the configuration file
166
if hasattr(request, 'cfg'):
167
display = request.cfg.traceback_show
168
logdir = request.cfg.traceback_log_dir
169
handler = cgitb.Hook(file=request, display=display, logdir=logdir,
170
viewClass=View, debug=debug)
173
request.write('<pre>\n')
174
printTextException(request, savedError)
175
request.write('\nAdditionally cgitb raised this exception:\n')
176
printTextException(request)
177
request.write('</pre>\n')
180
def printTextException(request, info=None):
181
""" Simple text exception that should never fail
183
Print all exceptions in a composite error.
186
from MoinMoin import wikiutil
188
info = sys.exc_info()
190
exceptions = [info] + info[1].exceptions()
191
except AttributeError:
193
for info in exceptions:
194
text = ''.join(traceback.format_exception(*info))
195
text = wikiutil.escape(text)