summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarius Gedminas <marius@gedmin.as>2012-12-12 17:26:15 +0000
committerMarius Gedminas <marius@gedmin.as>2012-12-12 17:26:15 +0000
commite52caace792b6d399525d6f905f27d89415eb0df (patch)
treeb8df96059d45aa81cedcaf80f5efec18d81544d0 /src
parentacafb04f3d7de3e582ddfd17658f2b961e39748b (diff)
downloadzope-pagetemplate-e52caace792b6d399525d6f905f27d89415eb0df.tar.gz
Workaround for CPU-burning pt_errors() on a recursive template.
See https://bugs.launchpad.net/zope.pagetemplate/+bug/732972 This implements the short workaround version of the solution mentioned in the bug: let's skip macro expansion checking while we're formatting an error traceback (with the default recursion limit of 100 this still burns a lot of CPU: ~20 seconds on a 2.5 GHz Core i5). The test can be easily extended for the better suggested solution (some time in the future): just drop check_macro_expansion=False and make sure METAL silently stops recursing iff it notices a loop and TAL evaluation is disabled.
Diffstat (limited to 'src')
-rw-r--r--src/zope/pagetemplate/pagetemplate.py13
-rw-r--r--src/zope/pagetemplate/tests/input/recursive.html7
-rw-r--r--src/zope/pagetemplate/tests/output/recursive.html14
-rw-r--r--src/zope/pagetemplate/tests/test_htmltests.py14
4 files changed, 42 insertions, 6 deletions
diff --git a/src/zope/pagetemplate/pagetemplate.py b/src/zope/pagetemplate/pagetemplate.py
index 9275737..f69e7b0 100644
--- a/src/zope/pagetemplate/pagetemplate.py
+++ b/src/zope/pagetemplate/pagetemplate.py
@@ -132,15 +132,16 @@ class PageTemplate(object):
strictinsert=0, sourceAnnotations=sourceAnnotations
)
- def pt_errors(self, namespace):
+ def pt_errors(self, namespace, check_macro_expansion=True):
self._cook_check()
err = self._v_errors
if err:
return err
- try:
- self.pt_render(namespace, source=1)
- except:
- return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
+ if check_macro_expansion:
+ try:
+ self.pt_render(namespace, source=1)
+ except:
+ return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
def write(self, text):
# We accept both, since the text can either come from a file (and the
@@ -261,6 +262,6 @@ class PageTemplateTracebackSupplement(object):
def __init__(self, pt, namespace):
self.manageable_object = pt
self.warnings = []
- e = pt.pt_errors(namespace)
+ e = pt.pt_errors(namespace, check_macro_expansion=False)
if e:
self.warnings.extend(e)
diff --git a/src/zope/pagetemplate/tests/input/recursive.html b/src/zope/pagetemplate/tests/input/recursive.html
new file mode 100644
index 0000000..9726867
--- /dev/null
+++ b/src/zope/pagetemplate/tests/input/recursive.html
@@ -0,0 +1,7 @@
+<!-- See https://bugs.launchpad.net/zope.pagetemplate/+bug/732972 -->
+<ul metal:define-macro="tree">
+ <li tal:content="context/name" />
+ <li tal:repeat="context context/children">
+ <ul metal:use-macro="template/macros/tree" />
+ </li>
+</ul>
diff --git a/src/zope/pagetemplate/tests/output/recursive.html b/src/zope/pagetemplate/tests/output/recursive.html
new file mode 100644
index 0000000..a251dcf
--- /dev/null
+++ b/src/zope/pagetemplate/tests/output/recursive.html
@@ -0,0 +1,14 @@
+<!-- See https://bugs.launchpad.net/zope.pagetemplate/+bug/732972 -->
+<ul>
+ <li>root</li>
+ <li>
+ <ul>
+ <li>first</li>
+</ul>
+ </li>
+ <li>
+ <ul>
+ <li>second</li>
+</ul>
+ </li>
+</ul>
diff --git a/src/zope/pagetemplate/tests/test_htmltests.py b/src/zope/pagetemplate/tests/test_htmltests.py
index 34895f0..e0dc5ae 100644
--- a/src/zope/pagetemplate/tests/test_htmltests.py
+++ b/src/zope/pagetemplate/tests/test_htmltests.py
@@ -133,6 +133,20 @@ class HTMLTests(unittest.TestCase):
out = t(msg=msg)
util.check_html(expect, out)
+ def test_recursion(self):
+ t = self.folder.t
+ t.write(util.read_input('recursive.html'))
+ expect = util.read_output('recursive.html')
+ context = dict(name='root',
+ children=[dict(name='first', children=[]),
+ dict(name='second', children=[])])
+ namespace = dict(template=t, options={}, args=(),
+ nothing=None, context=context)
+ out = t.pt_render(namespace)
+ util.check_html(expect, out)
+ # https://bugs.launchpad.net/zope.pagetemplate/+bug/732972
+ errors = t.pt_errors(namespace, check_macro_expansion=False)
+ self.assertFalse(errors)
def test_suite():
return unittest.makeSuite(HTMLTests)