[Zope-Checkins] SVN: Zope/branches/Zope-2_8-branch/ Collector
#1927: Don't save rendered HTML / warnings as persistent attributes.
Tres Seaver
tseaver at palladion.com
Fri Oct 21 13:30:26 EDT 2005
Log message for revision 39550:
Collector #1927: Don't save rendered HTML / warnings as persistent attributes.
Changed:
U Zope/branches/Zope-2_8-branch/doc/CHANGES.txt
U Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/ZReST.py
A Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/
A Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/__init__.py
A Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/test_ZReST.py
-=-
Modified: Zope/branches/Zope-2_8-branch/doc/CHANGES.txt
===================================================================
--- Zope/branches/Zope-2_8-branch/doc/CHANGES.txt 2005-10-21 13:31:50 UTC (rev 39549)
+++ Zope/branches/Zope-2_8-branch/doc/CHANGES.txt 2005-10-21 17:30:25 UTC (rev 39550)
@@ -26,6 +26,10 @@
Bugs Fixed
+ - Collector #1927: Modified ZReST not to store rendered / warnings
+ as persistent attributes, using volatile attributes instead as
+ a cache.
+
- Collector #1926: fixed a typo in _doAddUser when password
encryption is enabled.
Modified: Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/ZReST.py
===================================================================
--- Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/ZReST.py 2005-10-21 13:31:50 UTC (rev 39549)
+++ Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/ZReST.py 2005-10-21 17:30:25 UTC (rev 39550)
@@ -47,6 +47,7 @@
'''
meta_type = 'ReStructuredText Document'
security = ClassSecurityInfo()
+ _v_formatted = _v_warnings = None
def __init__(self, id,output_encoding=None,
input_encoding=None):
@@ -54,7 +55,7 @@
self.title = id
self.stylesheet = 'default.css'
self.report_level = '2'
- self.source = self.formatted = ''
+ self.source = ''
from reStructuredText import default_output_encoding, \
default_input_encoding
@@ -89,7 +90,7 @@
'''
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('content-type', 'text/html; charset=%s' % self.output_encoding)
- return self.formatted
+ return self.render()
security.declareProtected('View', 'source_txt')
def source_txt(self, REQUEST=None):
@@ -113,7 +114,7 @@
return self._er(data, SUBMIT, dtpref_cols, dtpref_rows, REQUEST)
if data != self.source:
self.source = data
- self.render()
+ self._clear_cache()
if REQUEST is not None:
message="Saved changes."
@@ -142,6 +143,7 @@
setCookie("dtpref_cols", cols, path='/', expires=e)
REQUEST.other.update({"dtpref_cols":cols, "dtpref_rows":rows})
return self.manage_main(self, REQUEST, __str__=self.quotedHTML(data))
+
security.declarePrivate('quotedHTML')
def quotedHTML(self,
text=None,
@@ -155,6 +157,18 @@
if text.find(re) >= 0: text=name.join(text.split(re))
return text
+ security.declarePrivate('_clear_cache')
+ def _clear_cache(self):
+ """ Forget results of rendering.
+ """
+ try:
+ del self._v_formatted
+ except AttributeError:
+ pass
+ try:
+ del self._v_warnings
+ except AttributeError:
+ pass
# handle uploads too
security.declareProtected('Edit ReStructuredText', 'manage_upload')
@@ -165,7 +179,7 @@
self.source = file
else:
self.source = file.read()
- self.render()
+ self._clear_cache()
if REQUEST is not None:
message="Saved changes."
@@ -175,57 +189,60 @@
def render(self):
''' Render the source to HTML
'''
- # format with strings
- pub = docutils.core.Publisher()
- pub.set_reader('standalone', None, 'restructuredtext')
- pub.set_writer('html')
+ if self._v_formatted is None:
+ # format with strings
+ pub = docutils.core.Publisher()
+ pub.set_reader('standalone', None, 'restructuredtext')
+ pub.set_writer('html')
- # go with the defaults
- pub.get_settings()
+ # go with the defaults
+ pub.get_settings()
- # this is needed, but doesn't seem to do anything
- pub.settings._destination = ''
+ # this is needed, but doesn't seem to do anything
+ pub.settings._destination = ''
- # use the stylesheet chosen by the user
- pub.settings.stylesheet = self.stylesheet
+ # use the stylesheet chosen by the user
+ pub.settings.stylesheet = self.stylesheet
- # set the reporting level to something sane
- pub.settings.report_level = int(self.report_level)
+ # set the reporting level to something sane
+ pub.settings.report_level = int(self.report_level)
- # disallow use of the .. include directive for security reasons
- pub.settings.file_insertion_enabled = 0
+ # disallow use of the .. include directive for security reasons
+ pub.settings.file_insertion_enabled = 0
- # don't break if we get errors
- pub.settings.halt_level = 6
+ # don't break if we get errors
+ pub.settings.halt_level = 6
- # remember warnings
- pub.settings.warning_stream = Warnings()
+ # remember warnings
+ pub.settings.warning_stream = Warnings()
- pub.source = docutils.io.StringInput(
- source=self.source, encoding=self.input_encoding)
+ pub.source = docutils.io.StringInput(
+ source=self.source, encoding=self.input_encoding)
- # output - not that it's needed
- pub.settings.output_encoding = self.output_encoding
- pub.destination = docutils.io.StringOutput(
- encoding=self.output_encoding)
+ # output - not that it's needed
+ pub.settings.output_encoding = self.output_encoding
+ pub.destination = docutils.io.StringOutput(
+ encoding=self.output_encoding)
- # parse!
- document = pub.reader.read(pub.source, pub.parser, pub.settings)
+ # parse!
+ document = pub.reader.read(pub.source, pub.parser, pub.settings)
- # transform
- pub.apply_transforms(document)
+ # transform
+ pub.apply_transforms(document)
- self.warnings = ''.join(pub.settings.warning_stream.messages)
+ self._v_warnings = ''.join(pub.settings.warning_stream.messages)
- if document.children:
- item = document.children[0]
- if item.tagname == 'title':
- self.title = item.children[0].astext()
+ if document.children:
+ item = document.children[0]
+ if item.tagname == 'title':
+ self.title = item.children[0].astext()
- # do the format
- self.formatted = pub.writer.write(document, pub.destination)
+ # do the format
+ self._v_formatted = pub.writer.write(document, pub.destination)
+ return self._v_formatted
+
security.declareProtected('Edit ReStructuredText', 'PUT', 'manage_FTPput')
def PUT(self, REQUEST, RESPONSE):
''' Handle HTTP PUT requests
@@ -247,7 +264,6 @@
pass # ignore
data = '\n'.join(new) + '\n'.join(data[i:])
self.source = data
- self.render()
RESPONSE.setStatus(204)
return RESPONSE
@@ -263,9 +279,9 @@
'.. stylesheet='+self.stylesheet,
'.. report_level='+self.report_level
]
- if self.warnings:
+ if self._v_warnings:
s.append('.. ')
- s.append('.. ' + '\n.. '.join(self.warnings.splitlines()))
+ s.append('.. ' + '\n.. '.join(self._v_warnings.splitlines()))
s.append('.. ')
return '\n'.join(s) + '\n' + self.source
@@ -290,7 +306,7 @@
def manage_editProperties(self, REQUEST):
""" re-render the page after changing the properties (encodings!!!) """
result = PropertyManager.manage_editProperties(self, REQUEST)
- self.render()
+ self._clear_cache()
return result
Added: Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/__init__.py
===================================================================
--- Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/__init__.py 2005-10-21 13:31:50 UTC (rev 39549)
+++ Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/__init__.py 2005-10-21 17:30:25 UTC (rev 39550)
@@ -0,0 +1,4 @@
+""" Unit tests for ZReST product.
+
+$Id$
+"""
Property changes on: Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/test_ZReST.py
===================================================================
--- Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/test_ZReST.py 2005-10-21 13:31:50 UTC (rev 39549)
+++ Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/test_ZReST.py 2005-10-21 17:30:25 UTC (rev 39550)
@@ -0,0 +1,38 @@
+""" Unit tests for ZReST objects
+
+$Id$
+"""
+import unittest
+
+class TestZReST(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from Products.ZReST.ZReST import ZReST
+ return ZReST
+
+ def _makeOne(self, id='test', *args, **kw):
+ return self._getTargetClass()(id=id, *args, **kw)
+
+ def test_empty(self):
+ empty = self._makeOne()
+
+ # New instances should not have non-volatile cache attributes
+ self.assertRaises(AttributeError, lambda: empty.formatted)
+ self.assertRaises(AttributeError, lambda: empty.warnings)
+
+ self.assertEqual(empty._v_formatted, None)
+ self.assertEqual(empty._v_formatted, None)
+
+ def test_formatted_ignored(self):
+ resty = self._makeOne()
+ resty.formatted = 'IGNORE ME'
+
+ self.failIf('IGNORE ME' in resty.index_html())
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestZReST))
+ return suite
+
+if __name__ == '__main__':
+ unittest.main(defaultSuite='test_suite')
Property changes on: Zope/branches/Zope-2_8-branch/lib/python/Products/ZReST/tests/test_ZReST.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the Zope-Checkins
mailing list