[CMF-checkins] SVN: CMF/trunk/CMFCore/ Add option to template FSSTXMethods with ZPT, and make it the default.

Tres Seaver tseaver at palladion.com
Thu Oct 19 13:01:53 EDT 2006


Log message for revision 70814:
  Add option to template FSSTXMethods with ZPT, and make it the default.
  

Changed:
  U   CMF/trunk/CMFCore/FSSTXMethod.py
  U   CMF/trunk/CMFCore/tests/test_FSSTXMethod.py

-=-
Modified: CMF/trunk/CMFCore/FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-19 15:46:15 UTC (rev 70813)
+++ CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-19 17:01:51 UTC (rev 70814)
@@ -1,6 +1,7 @@
 ##############################################################################
 #
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2001, 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
@@ -22,6 +23,7 @@
 from Globals import InitializeClass
 from OFS.DTMLDocument import DTMLDocument
 from StructuredText.StructuredText import HTML as STX_HTML
+from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
 
 from Products.CMFCore.DirectoryView import registerFileExtension
 from Products.CMFCore.DirectoryView import registerMetaType
@@ -32,7 +34,10 @@
 from Products.CMFCore.utils import _dtmldir
 from Products.CMFCore.utils import _checkConditionalGET
 from Products.CMFCore.utils import _setCacheHeaders
+from Products.CMFCore.utils import _ViewEmulator
 
+_STX_TEMPLATE = 'ZPT'  # or 'DTML'
+
 _DEFAULT_TEMPLATE_DTML = """\
 <dtml-var standard_html_header>
 <dtml-var cooked>
@@ -43,6 +48,50 @@
 <dtml-var stx fmt="structured-text">
 <dtml-var standard_html_footer>"""
 
+_DEFAULT_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/main">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:replace="structure options/cooked">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
+_DEFAULT_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/master">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:replace="structure options/cooked">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
+_CUSTOMIZED_TEMPLATE_ZPT = """\
+<html metal:use-macro="context/main_template/macros/master">
+<body>
+
+<metal:block metal:fill-slot="body"
+><div tal:define="std modules/Products/PythonScripts/standard;
+                  stx nocall:std/structured_text;"
+      tal:replace="structure python:stx(template.stx)">
+COOKED TEXT HERE
+</div>
+</metal:block>
+
+</body>
+</html>
+"""
+
 class FSSTXMethod(FSObject):
     """ A chunk of StructuredText, rendered as a skin method of a CMF site.
     """
@@ -67,7 +116,12 @@
         """
             Create a ZODB (editable) equivalent of this object.
         """
-        target = DTMLDocument(_CUSTOMIZED_TEMPLATE_DTML, __name__=self.getId())
+        if _STX_TEMPLATE == 'DTML':
+            target = DTMLDocument(_CUSTOMIZED_TEMPLATE_DTML,
+                                  __name__=self.getId())
+        elif _STX_TEMPLATE == 'ZPT':
+            target = ZopePageTemplate(self.getId(), _CUSTOMIZED_TEMPLATE_ZPT)
+
         target._setProperty('stx', self.raw, 'text')
         return target
 
@@ -107,7 +161,9 @@
             self._v_cooked = STX_HTML(self.raw, level=1, header=0)
         return self._v_cooked
 
-    _default_template = DTML_HTML(_DEFAULT_TEMPLATE_DTML)
+    _default_DTML_template = DTML_HTML(_DEFAULT_TEMPLATE_DTML)
+    _default_ZPT_template = ZopePageTemplate('stxmethod_view',
+                                             _DEFAULT_TEMPLATE_ZPT, 'text/html')
 
     def __call__( self, REQUEST={}, RESPONSE=None, **kw ):
         """ Return our rendered StructuredText.
@@ -117,11 +173,11 @@
         if RESPONSE is not None:
             RESPONSE.setHeader( 'Content-Type', 'text/html' )
 
-        faux_wrapped = self.__of__(self) # we are our own "content"
-        if _checkConditionalGET(faux_wrapped, extra_context={}):
+        view = _ViewEmulator(self.getId()).__of__(self)
+        if _checkConditionalGET(view, extra_context={}):
             return ''
 
-        _setCacheHeaders(faux_wrapped, extra_context={})
+        _setCacheHeaders(view, extra_context={})
 
         return self._render(REQUEST, RESPONSE, **kw)
 
@@ -133,8 +189,15 @@
     def _render(self, REQUEST={}, RESPONSE=None, **kw):
         """ Find the appropriate rendering template and use it to render us.
         """
-        template = getattr(self, 'stxmethod_view', self._default_template)
+        if _STX_TEMPLATE == 'DTML':
+            default_template = self._default_DTML_template
+        elif _STX_TEMPLATE == 'ZPT':
+            default_template = self._default_ZPT_template
+        else:
+            raise TypeError('Invalid STX template: %s' % _STX_TEMPLATE)
 
+        template = getattr(self, 'stxmethod_view', default_template)
+
         if getattr(template, 'isDocTemp', 0):
             #posargs = (self, REQUEST, RESPONSE)
             posargs = (self, REQUEST)

Modified: CMF/trunk/CMFCore/tests/test_FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-19 15:46:15 UTC (rev 70813)
+++ CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-19 17:01:51 UTC (rev 70814)
@@ -16,9 +16,8 @@
 """
 import unittest
 import os
+import re
 
-#import Testing
-
 from Products.CMFCore.tests.base.testcase import FSDVTest
 from Products.CMFCore.tests.base.testcase import RequestTest
 from Products.CMFCore.tests.base.testcase import SecurityTest
@@ -46,28 +45,81 @@
 </html>
 """
 
-class FSSTXMethodTests(RequestTest, FSSTXMaker):
+_TEST_MAIN_TEMPLATE = """\
+<html metal:define-macro="main">
+<body>
 
+<metal:block define-slot="body">
+<h1>Title Goes Here</h1>
+<h2>  Subhead Here</h2>
+<p>    And this is a paragraph,
+    broken across lines.</p>
+</metal:block>
+</body>
+</html>
+"""
+
+WS = re.compile(r'\s+')
+
+def _normalize_whitespace(text):
+    return ' '.join(WS.split(text))
+
+
+class _TemplateSwitcher:
+
     def setUp(self):
+        import Products.CMFCore.FSSTXMethod
+        self._old_STX_TEMPLATE = Products.CMFCore.FSSTXMethod._STX_TEMPLATE
+
+    def tearDown(self):
+        RequestTest.tearDown(self)
+        FSSTXMaker.tearDown(self)
+        self._setWhichTemplate(self._old_STX_TEMPLATE)
+
+    def _setWhichTemplate(self, which):
+        import Products.CMFCore.FSSTXMethod
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+        Products.CMFCore.FSSTXMethod._STX_TEMPLATE = which
+
+        if which == 'DTML':
+            self.root.standard_html_header = (
+                    lambda *args, **kw: '<html>\n<body>\n')
+            self.root.standard_html_footer = (
+                    lambda *args, **kw: '</body>\n</html>\n')
+        elif which == 'ZPT':
+            main = ZopePageTemplate('main_template', _TEST_MAIN_TEMPLATE)
+            self.root._setOb('main_template', main)
+
+class FSSTXMethodTests(RequestTest, FSSTXMaker, _TemplateSwitcher):
+
+    def setUp(self):
+        _TemplateSwitcher.setUp(self)
         FSSTXMaker.setUp(self)
         RequestTest.setUp(self)
-        self.root.standard_html_header = (
-                lambda *args, **kw: '<html>\n<body>\n')
-        self.root.standard_html_footer = (
-                lambda *args, **kw: '</body>\n</html>\n')
 
     def tearDown(self):
         RequestTest.tearDown(self)
         FSSTXMaker.tearDown(self)
+        _TemplateSwitcher.tearDown(self)
 
-    def test___call__( self ):
+    def test___call___with_DTML( self ):
+        self._setWhichTemplate('DTML')
         script = self._makeOne( 'testSTX', 'testSTX.stx' )
         script = script.__of__(self.app)
-        self.assertEqual(script(self.REQUEST), _EXPECTED_HTML)
+        self.assertEqual(_normalize_whitespace(script(self.REQUEST)),
+                         _normalize_whitespace(_EXPECTED_HTML))
 
+    def test___call___with_ZPT( self ):
+        self._setWhichTemplate('ZPT')
+        script = self._makeOne( 'testSTX', 'testSTX.stx' )
+        script = script.__of__(self.app)
+        self.assertEqual(_normalize_whitespace(script(self.REQUEST)),
+                         _normalize_whitespace(_EXPECTED_HTML))
+
     def test_caching( self ):
         #   Test HTTP caching headers.
         from Products.CMFCore.tests.base.dummy import DummyCachingManager
+        self._setWhichTemplate('DTML')
         self.root.caching_policy_manager = DummyCachingManager()
         original_len = len( self.RESPONSE.headers )
         script = self._makeOne('testSTX', 'testSTX.stx')
@@ -108,12 +160,22 @@
         self.assertEqual( data, '' )
         self.assertEqual( self.RESPONSE.getStatus(), 304 )
 
-class FSSTXMethodCustomizationTests( SecurityTest, FSSTXMaker ):
+ADD_ZPT = 'Add page templates'
+ZPT_META_TYPES = ( { 'name'        : 'Page Template'
+                   , 'action'      : 'manage_addPageTemplate'
+                   , 'permission'  : ADD_ZPT
+                   }
+                 ,
+                 )
 
+class FSSTXMethodCustomizationTests( SecurityTest, FSSTXMaker,
+                                     _TemplateSwitcher ):
+
     def setUp( self ):
         from OFS.Folder import Folder
         FSSTXMaker.setUp(self)
         SecurityTest.setUp( self )
+        _TemplateSwitcher.setUp( self )
 
         self.root._setObject( 'portal_skins', Folder( 'portal_skins' ) )
         self.skins = self.root.portal_skins
@@ -129,10 +191,17 @@
 
         self.fsSTX = self.fsdir.testSTX
 
-    def test_customize( self ):
+    def tearDown( self ):
+        _TemplateSwitcher.tearDown( self )
+        FSSTXMaker.tearDown( self )
+        SecurityTest.tearDown( self )
+
+    def test_customize_with_DTML( self ):
         from OFS.DTMLDocument import DTMLDocument
         from Products.CMFCore.FSSTXMethod import _CUSTOMIZED_TEMPLATE_DTML
 
+        self._setWhichTemplate('DTML')
+
         self.fsSTX.manage_doCustomize(folder_path='custom')
 
         self.assertEqual(len(self.custom.objectIds()), 1)
@@ -147,10 +216,33 @@
 
         self.assertEqual(target.document_src(), _CUSTOMIZED_TEMPLATE_DTML)
 
+    def test_customize_with_ZPT( self ):
+        from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+        from Products.CMFCore.FSSTXMethod import _CUSTOMIZED_TEMPLATE_ZPT
+
+        self._setWhichTemplate('ZPT')
+        self.custom.all_meta_types = ZPT_META_TYPES
+
+        self.fsSTX.manage_doCustomize(folder_path='custom')
+
+        self.assertEqual(len(self.custom.objectIds()), 1)
+        self.failUnless('testSTX' in self.custom.objectIds())
+        target = self.custom._getOb('testSTX')
+
+        self.failUnless(isinstance(target, ZopePageTemplate))
+
+        propinfo = target.propdict()['stx']
+        self.assertEqual(propinfo['type'], 'text')
+        self.assertEqual(target.stx, self.fsSTX.raw)
+
+        self.assertEqual(target.document_src(), _CUSTOMIZED_TEMPLATE_ZPT)
+
     def test_customize_caching(self):
         # Test to ensure that cache manager associations survive customizing
         from Products.StandardCacheManagers import RAMCacheManager
         cache_id = 'gofast'
+        self._setWhichTemplate('ZPT')
+        self.custom.all_meta_types = ZPT_META_TYPES
         RAMCacheManager.manage_addRAMCacheManager( self.root
                                                  , cache_id
                                                  , REQUEST=None



More information about the CMF-checkins mailing list