8687.15.17
by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/. |
1 |
# Copyright 2009 Canonical Ltd. This software is licensed under the
|
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
3 |
|
4 |
"""Handlers for warnings, to be installed when testing."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7 |
||
8 |
import atexit |
|
9 |
import inspect |
|
10 |
import StringIO |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
11 |
import sys |
12 |
import warnings |
|
13 |
||
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
14 |
|
15 |
class WarningReport: |
|
16 |
||
17 |
def __init__(self, message, info): |
|
18 |
self.message = message |
|
19 |
self.info = info |
|
20 |
||
21 |
def __str__(self): |
|
22 |
info = str(self.info) |
|
23 |
if info: |
|
24 |
return info |
|
25 |
else: |
|
26 |
return self.message |
|
27 |
||
28 |
class ImportantInfo: |
|
29 |
||
30 |
def __init__(self, expressiontext, viewclassname, templatefilename, |
|
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
31 |
requesturl, viewclassfilename, viewclasslineno, viewclassfunc, |
32 |
doctestname, doctestline): |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
33 |
self.expressiontext = expressiontext |
34 |
self.viewclassname = viewclassname |
|
35 |
self.viewclassfilename = viewclassfilename |
|
36 |
self.viewclasslineno = viewclasslineno |
|
37 |
self.templatefilename = templatefilename |
|
38 |
self.requesturl = requesturl |
|
39 |
self.viewclassfunc = viewclassfunc |
|
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
40 |
self.doctestname = doctestname |
41 |
self.doctestline = doctestline |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
42 |
|
43 |
def __str__(self): |
|
44 |
L = [] |
|
45 |
if self.expressiontext: |
|
46 |
L.append('The expression: %s in %s' % ( |
|
47 |
self.expressiontext, self.templatefilename)) |
|
48 |
if self.viewclassname: |
|
49 |
L.append('The method %s.%s' % ( |
|
50 |
self.viewclassname, self.viewclassfunc)) |
|
51 |
#L.append('at line %s of file %s' % (
|
|
52 |
# self.viewclasslineno, self.viewclassfilename)
|
|
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
53 |
if self.doctestname: |
54 |
L.append("The doctest %s, at the line:" % self.doctestname) |
|
55 |
L.append(" >>> %s" % self.doctestline) |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
56 |
if self.requesturl: |
57 |
L.append('request url: %s' % self.requesturl) |
|
58 |
return '\n'.join(L) |
|
59 |
||
60 |
# PageTemplateFile has .filename.
|
|
7849.16.4
by Sidnei da Silva
- Import ViewPageTemplateFile from z3c.pt everywhere |
61 |
from z3c.ptcompat import PageTemplateFile, ViewPageTemplateFile |
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
62 |
|
63 |
# PythonExpr has .text, the text of the expression.
|
|
64 |
from zope.tales.pythonexpr import PythonExpr |
|
65 |
||
66 |
# TrustedZopeContext has self.contexts, a dict with template, view, context,
|
|
67 |
# request, etc.
|
|
68 |
from zope.app.pagetemplate.engine import TrustedZopeContext |
|
69 |
||
70 |
# TALInterpreter has self.sourceFile, a filename of a page template.
|
|
71 |
from zope.tal.talinterpreter import TALInterpreter |
|
72 |
||
73 |
from zope.app.pagetemplate.simpleviewclass import simple |
|
74 |
||
75 |
def find_important_info(): |
|
76 |
stack = inspect.stack() |
|
77 |
try: |
|
78 |
important_classes = set([ |
|
79 |
PythonExpr, |
|
80 |
TrustedZopeContext, |
|
81 |
TALInterpreter, |
|
82 |
ViewPageTemplateFile, |
|
83 |
simple
|
|
84 |
])
|
|
85 |
important_objects = {} |
|
86 |
metadata = {} # cls -> (filename, lineno, funcname) |
|
87 |
||
88 |
for frame, filename, lineno, func_name, context, lineidx in stack: |
|
89 |
try: |
|
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
90 |
if (filename.startswith('<doctest ') and |
91 |
"doctest" not in important_objects): |
|
92 |
# Very fragile inspection of the state of the doctest
|
|
93 |
# runner. So, enclosed in a try-except so it will at
|
|
94 |
# least fail gracefully if it fails.
|
|
95 |
try: |
|
96 |
line = frame.f_back.f_locals['example'].source |
|
97 |
except KeyboardInterrupt: |
|
98 |
pass
|
|
99 |
except Exception: |
|
100 |
line = "# cannot get line of code" |
|
101 |
important_objects["doctest"] = (filename, line) |
|
102 |
metadata["doctest"] = (filename, lineno, func_name) |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
103 |
if 'self' in frame.f_locals: |
104 |
fself = frame.f_locals['self'] |
|
105 |
ftype = type(fself) |
|
106 |
for cls in list(important_classes): |
|
107 |
if isinstance(fself, cls): |
|
108 |
important_objects[cls] = fself |
|
109 |
metadata[cls] = (filename, lineno, func_name) |
|
110 |
important_classes.remove(cls) |
|
111 |
finally: |
|
112 |
del frame |
|
113 |
finally: |
|
114 |
del stack |
|
115 |
||
116 |
expressiontext = '' |
|
117 |
if PythonExpr in important_objects: |
|
118 |
expressiontext = important_objects[PythonExpr].text |
|
119 |
||
120 |
viewclassname = '' |
|
121 |
viewclassfilename = '' |
|
122 |
viewclasslineno = '' |
|
123 |
viewclassfunc = '' |
|
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
124 |
doctestname = '' |
125 |
doctestline = '' |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
126 |
if simple in important_objects: |
127 |
cls = important_objects[simple].__class__ |
|
128 |
if cls is not simple: |
|
129 |
viewclassname = cls.__mro__[1].__name__ |
|
130 |
viewclassfilename, viewclasslineno, viewclassfunc = ( |
|
131 |
metadata[simple]) |
|
132 |
||
133 |
templatefilename = '' |
|
134 |
if ViewPageTemplateFile in important_objects: |
|
135 |
templatefilename = important_objects[ViewPageTemplateFile].filename |
|
136 |
templatefilename = templatefilename.split('/')[-1] |
|
137 |
||
138 |
requesturl = '' |
|
139 |
if TrustedZopeContext in important_objects: |
|
140 |
ptcontexts = important_objects[TrustedZopeContext].contexts |
|
141 |
requesturl = ptcontexts['request'].getURL() |
|
142 |
||
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
143 |
if "doctest" in important_objects: |
144 |
doctestname, doctestline = important_objects["doctest"] |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
145 |
return ImportantInfo(expressiontext, viewclassname, templatefilename, |
2419
by Canonical.com Patch Queue Manager
[trivial] improved warning output for warnings that occur in doctests. the now show the offending line of code. |
146 |
requesturl, viewclassfilename, viewclasslineno, viewclassfunc, |
147 |
doctestname, doctestline) |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
148 |
|
149 |
need_page_titles = [] |
|
150 |
no_order_by = [] |
|
11296.1.2
by Jonathan Lange
Better uniquifying |
151 |
|
152 |
# Maps (category, filename, lineno) to WarningReport
|
|
153 |
other_warnings = {} |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
154 |
|
155 |
old_show_warning = warnings.showwarning |
|
11220.3.2
by Jonathan Lange
Update to support new 'line' argument. Only print one copy of each warning |
156 |
def launchpad_showwarning(message, category, filename, lineno, file=None, |
157 |
line=None): |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
158 |
if file is None: |
159 |
file = sys.stderr |
|
160 |
stream = StringIO.StringIO() |
|
13269.2.9
by Jonathan Lange
We have ceased supporting Python 2.5 |
161 |
old_show_warning(message, category, filename, lineno, stream, line=line) |
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
162 |
warning_message = stream.getvalue() |
163 |
important_info = find_important_info() |
|
164 |
||
165 |
if isinstance(message, UserWarning): |
|
166 |
args = message.args |
|
167 |
if args: |
|
168 |
arg = args[0] |
|
169 |
if arg.startswith('No page title in '): |
|
170 |
global need_page_titles |
|
171 |
need_page_titles.append(arg) |
|
172 |
return
|
|
173 |
if arg == 'Getting a slice of an unordered set is unpredictable.': |
|
174 |
# find the page template and view class, if any
|
|
175 |
# show these, plus the request.
|
|
176 |
global no_order_by |
|
177 |
no_order_by.append( |
|
178 |
WarningReport(warning_message, important_info) |
|
179 |
)
|
|
180 |
return
|
|
11296.1.2
by Jonathan Lange
Better uniquifying |
181 |
other_warnings[(category, filename, lineno)] = WarningReport( |
182 |
warning_message, important_info) |
|
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
183 |
|
184 |
def report_need_page_titles(): |
|
185 |
global need_page_titles |
|
186 |
if need_page_titles: |
|
187 |
print
|
|
188 |
print "The following pages need titles." |
|
189 |
for message in need_page_titles: |
|
190 |
print " ", message |
|
191 |
||
192 |
def report_no_order_by(): |
|
193 |
global no_order_by |
|
194 |
if no_order_by: |
|
195 |
print
|
|
196 |
print ("The following code has issues with" |
|
197 |
" ambiguous select results ordering.") |
|
198 |
for report in no_order_by: |
|
199 |
print
|
|
200 |
print report |
|
201 |
||
202 |
def report_other_warnings(): |
|
203 |
global other_warnings |
|
204 |
if other_warnings: |
|
205 |
print
|
|
2482
by Canonical.com Patch Queue Manager
r=kiko + some [trivial] various menus landings. |
206 |
print "General warnings." |
11296.1.2
by Jonathan Lange
Better uniquifying |
207 |
for warninginfo in other_warnings.itervalues(): |
2103
by Canonical.com Patch Queue Manager
[trivial] improved warning output for tests, and fixed a bunch of ambiguous use of select results warnings. some xxx comments left in person code. one untested codepath in hct backend. |
208 |
print
|
209 |
print warninginfo |
|
210 |
||
211 |
def report_warnings(): |
|
212 |
report_need_page_titles() |
|
213 |
report_no_order_by() |
|
214 |
report_other_warnings() |
|
215 |
||
216 |
def install_warning_handler(): |
|
217 |
warnings.showwarning = launchpad_showwarning |
|
218 |
atexit.register(report_warnings) |