1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# Copyright 2005 Canonical Ltd. All rights reserved.
"""Handlers for warnings, to be installed when testing."""
__metaclass__ = type
import atexit
import warnings
import sys
import inspect
import StringIO
class WarningReport:
def __init__(self, message, info):
self.message = message
self.info = info
def __str__(self):
info = str(self.info)
if info:
return info
else:
return self.message
class ImportantInfo:
def __init__(self, expressiontext, viewclassname, templatefilename,
requesturl, viewclassfilename, viewclasslineno, viewclassfunc,
doctestname, doctestline):
self.expressiontext = expressiontext
self.viewclassname = viewclassname
self.viewclassfilename = viewclassfilename
self.viewclasslineno = viewclasslineno
self.templatefilename = templatefilename
self.requesturl = requesturl
self.viewclassfunc = viewclassfunc
self.doctestname = doctestname
self.doctestline = doctestline
def __str__(self):
L = []
if self.expressiontext:
L.append('The expression: %s in %s' % (
self.expressiontext, self.templatefilename))
if self.viewclassname:
L.append('The method %s.%s' % (
self.viewclassname, self.viewclassfunc))
#L.append('at line %s of file %s' % (
# self.viewclasslineno, self.viewclassfilename)
if self.doctestname:
L.append("The doctest %s, at the line:" % self.doctestname)
L.append(" >>> %s" % self.doctestline)
if self.requesturl:
L.append('request url: %s' % self.requesturl)
return '\n'.join(L)
# PageTemplateFile has .filename.
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
# PythonExpr has .text, the text of the expression.
from zope.tales.pythonexpr import PythonExpr
# TrustedZopeContext has self.contexts, a dict with template, view, context,
# request, etc.
from zope.app.pagetemplate.engine import TrustedZopeContext
# TALInterpreter has self.sourceFile, a filename of a page template.
from zope.tal.talinterpreter import TALInterpreter
from zope.app.pagetemplate.simpleviewclass import simple
def find_important_info():
stack = inspect.stack()
try:
important_classes = set([
PythonExpr,
TrustedZopeContext,
TALInterpreter,
ViewPageTemplateFile,
simple
])
important_objects = {}
metadata = {} # cls -> (filename, lineno, funcname)
for frame, filename, lineno, func_name, context, lineidx in stack:
try:
if (filename.startswith('<doctest ') and
"doctest" not in important_objects):
# Very fragile inspection of the state of the doctest
# runner. So, enclosed in a try-except so it will at
# least fail gracefully if it fails.
try:
line = frame.f_back.f_locals['example'].source
except KeyboardInterrupt:
pass
except Exception:
line = "# cannot get line of code"
important_objects["doctest"] = (filename, line)
metadata["doctest"] = (filename, lineno, func_name)
if 'self' in frame.f_locals:
fself = frame.f_locals['self']
ftype = type(fself)
for cls in list(important_classes):
if isinstance(fself, cls):
important_objects[cls] = fself
metadata[cls] = (filename, lineno, func_name)
important_classes.remove(cls)
finally:
del frame
finally:
del stack
expressiontext = ''
if PythonExpr in important_objects:
expressiontext = important_objects[PythonExpr].text
viewclassname = ''
viewclassfilename = ''
viewclasslineno = ''
viewclassfunc = ''
doctestname = ''
doctestline = ''
if simple in important_objects:
cls = important_objects[simple].__class__
if cls is not simple:
viewclassname = cls.__mro__[1].__name__
viewclassfilename, viewclasslineno, viewclassfunc = (
metadata[simple])
templatefilename = ''
if ViewPageTemplateFile in important_objects:
templatefilename = important_objects[ViewPageTemplateFile].filename
templatefilename = templatefilename.split('/')[-1]
requesturl = ''
if TrustedZopeContext in important_objects:
ptcontexts = important_objects[TrustedZopeContext].contexts
requesturl = ptcontexts['request'].getURL()
if "doctest" in important_objects:
doctestname, doctestline = important_objects["doctest"]
return ImportantInfo(expressiontext, viewclassname, templatefilename,
requesturl, viewclassfilename, viewclasslineno, viewclassfunc,
doctestname, doctestline)
need_page_titles = []
no_order_by = []
other_warnings = []
old_show_warning = warnings.showwarning
def launchpad_showwarning(message, category, filename, lineno, file=None):
if file is None:
file = sys.stderr
stream = StringIO.StringIO()
old_show_warning(message, category, filename, lineno, stream)
warning_message = stream.getvalue()
important_info = find_important_info()
if isinstance(message, UserWarning):
args = message.args
if args:
arg = args[0]
if arg.startswith('No page title in '):
global need_page_titles
need_page_titles.append(arg)
return
if arg == 'Getting a slice of an unordered set is unpredictable.':
# find the page template and view class, if any
# show these, plus the request.
global no_order_by
no_order_by.append(
WarningReport(warning_message, important_info)
)
return
other_warnings.append(WarningReport(warning_message, important_info))
def report_need_page_titles():
global need_page_titles
if need_page_titles:
print
print "The following pages need titles."
for message in need_page_titles:
print " ", message
def report_no_order_by():
global no_order_by
if no_order_by:
print
print ("The following code has issues with"
" ambiguous select results ordering.")
for report in no_order_by:
print
print report
def report_other_warnings():
global other_warnings
if other_warnings:
print
print "General warnings."
for warninginfo in other_warnings:
print
print warninginfo.message,
print warninginfo
def report_warnings():
report_need_page_titles()
report_no_order_by()
report_other_warnings()
def install_warning_handler():
warnings.showwarning = launchpad_showwarning
atexit.register(report_warnings)
|