SVN: CMF/trunk/C CMFCore.FSSTXMethdo: Modernized, added tests, made customization possible.

Tres Seaver <[email protected]>
Newsgroups gmane.comp.web.zope.cmf.cvs
Message-ID <20061018222951.0AB9E2032A7__17339.7743412808$1161210602$gmane$org@mail.zope.org>
Log message for revision 70793:
  CMFCore.FSSTXMethdo:  Modernized, added tests, made customization possible.
  
  

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFCore/FSSTXMethod.py
  U   CMF/trunk/CMFCore/dtml/custstx.dtml
  A   CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx
  A   CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx.metadata
  A   CMF/trunk/CMFCore/tests/test_FSSTXMethod.py

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CHANGES.txt	2006-10-18 22:29:50 UTC (rev 70793)
@@ -2,6 +2,9 @@
 
   New Features
 
+    - CMFCore.FSSTXMethdo:  Modernized, added tests, made customization
+      possible.
+
     - Portal: Added 'email_charset' property.
 
     - CMFDefault utils: Added 'makeEmail' function.

Modified: CMF/trunk/CMFCore/FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CMFCore/FSSTXMethod.py	2006-10-18 22:29:50 UTC (rev 70793)
@@ -15,44 +15,50 @@
 $Id$
 """
 
-import Globals
 from AccessControl import ClassSecurityInfo
-from StructuredText.StructuredText import HTML
+from DocumentTemplate.DT_HTML import HTML as DTML_HTML
+from Globals import DTMLFile
+from Globals import HTML as Global_HTML
+from Globals import InitializeClass
+from OFS.DTMLDocument import DTMLDocument
+from StructuredText.StructuredText import HTML as STX_HTML
 
-from DirectoryView import registerFileExtension
-from DirectoryView import registerMetaType
-from FSObject import FSObject
-from permissions import FTPAccess
-from permissions import View
-from permissions import ViewManagementScreens
-from utils import _dtmldir
+from Products.CMFCore.DirectoryView import registerFileExtension
+from Products.CMFCore.DirectoryView import registerMetaType
+from Products.CMFCore.FSObject import FSObject
+from Products.CMFCore.permissions import FTPAccess
+from Products.CMFCore.permissions import View
+from Products.CMFCore.permissions import ViewManagementScreens
+from Products.CMFCore.utils import _dtmldir
+from Products.CMFCore.utils import _checkConditionalGET
+from Products.CMFCore.utils import _setCacheHeaders
 
+_DEFAULT_TEMPLATE_DTML = """\
+<dtml-var standard_html_header>
+<dtml-var cooked>
+<dtml-var standard_html_footer>"""
 
+_CUSTOMIZED_TEMPLATE_DTML = """\
+<dtml-var standard_html_header>
+<dtml-var stx fmt="structured-text">
+<dtml-var standard_html_footer>"""
+
 class FSSTXMethod(FSObject):
-
+    """ A chunk of StructuredText, rendered as a skin method of a CMF site.
     """
-        A chunk of StructuredText, rendered as a skin method of a
-        CMFSite.
-    """
-
     meta_type = 'Filesystem STX Method'
+    _owner = None # unowned
 
-    manage_options=( { 'label'      : 'Customize'
-                     , 'action'     : 'manage_main'
-                     }
-                   , { 'label'      : 'View'
-                     , 'action'     : ''
-                     , 'help'       : ('OFSP'
-                                      ,'DTML-DocumentOrMethod_View.stx'
-                                      )
-                     }
+    manage_options=({'label' : 'Customize','action' : 'manage_main'},
+                    {'label' : 'View','action' : '',
+                     'help' : ('OFSP' ,'DTML-DocumentOrMethod_View.stx')},
                    )
 
     security = ClassSecurityInfo()
     security.declareObjectProtected(View)
 
     security.declareProtected(ViewManagementScreens, 'manage_main')
-    manage_main = Globals.DTMLFile('custstx', _dtmldir)
+    manage_main = DTMLFile('custstx', _dtmldir)
 
     #
     #   FSObject interface
@@ -61,7 +67,9 @@
         """
             Create a ZODB (editable) equivalent of this object.
         """
-        raise NotImplementedError, "See next week's model."
+        target = DTMLDocument(_CUSTOMIZED_TEMPLATE_DTML, __name__=self.getId())
+        target._setProperty('stx', self.raw, 'text')
+        return target
 
     def _readFile(self, reparse):
         """Read the data from the filesystem.
@@ -82,75 +90,79 @@
     class func_code:
         pass
 
-    func_code=func_code()
-    func_code.co_varnames= ()
-    func_code.co_argcount=0
-    func_code.__roles__=()
+    func_code = func_code()
+    func_code.co_varnames = ()
+    func_code.co_argcount = 0
+    func_code.__roles__ = ()
 
-    func_defaults__roles__=()
-    func_defaults=()
+    func_defaults__roles__ = ()
+    func_defaults = ()
 
     index_html = None   # No accidental acquisition
 
     default_content_type = 'text/html'
 
-    def cook( self ):
-        if not hasattr( self, '_v_cooked' ):
-            self._v_cooked = HTML(self.raw, level=1, header=0)
+    def cook(self):
+        if not hasattr(self, '_v_cooked'):
+            self._v_cooked = STX_HTML(self.raw, level=1, header=0)
         return self._v_cooked
 
-    _default_template = Globals.HTML( """\
-<dtml-var standard_html_header>
-<dtml-var cooked>
-<dtml-var standard_html_footer>""" )
+    _default_template = DTML_HTML(_DEFAULT_TEMPLATE_DTML)
 
     def __call__( self, REQUEST={}, RESPONSE=None, **kw ):
+        """ Return our rendered StructuredText.
         """
-            Return our rendered StructuredText.
-        """
         self._updateFromFS()
 
         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={}):
+            return ''
+
+        _setCacheHeaders(faux_wrapped, extra_context={})
+
         return self._render(REQUEST, RESPONSE, **kw)
 
-    security.declarePrivate( '_render' )
-    def _render( self, REQUEST={}, RESPONSE=None, **kw ):
+    security.declarePrivate('modified')
+    def modified(self):
+        return self.getModTime()
+
+    security.declarePrivate('_render')
+    def _render(self, REQUEST={}, RESPONSE=None, **kw):
+        """ Find the appropriate rendering template and use it to render us.
         """
-            Find the appropriate rendering template and use it to
-            render us.
-        """
-        template = getattr( self, 'stxmethod_view', self._default_template )
+        template = getattr(self, 'stxmethod_view', self._default_template)
 
-        if getattr( template, 'isDocTemp', 0 ):
-            posargs = ( self, REQUEST, RESPONSE )
+        if getattr(template, 'isDocTemp', 0):
+            #posargs = (self, REQUEST, RESPONSE)
+            posargs = (self, REQUEST)
         else:
             posargs = ()
 
-        return template(*posargs, **{ 'cooked' : self.cook() } )
+        kwargs = {'cooked': self.cook()}
+        return template(*posargs, **kwargs)
 
-    security.declareProtected( FTPAccess, 'manage_FTPget' )
-    def manage_FTPget( self ):
+    security.declareProtected(FTPAccess, 'manage_FTPget')
+    def manage_FTPget(self):
+        """ Fetch our source for delivery via FTP.
         """
-            Fetch our source for delivery via FTP.
-        """
         return self.raw
 
-    security.declareProtected( ViewManagementScreens, 'PrincipiaSearchSource' )
-    def PrincipiaSearchSource( self ):
+    security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource')
+    def PrincipiaSearchSource(self):
+        """ Fetch our source for indexing in a catalog.
         """
-            Fetch our source for indexing in a catalog.
-        """
         return self.raw
 
-    security.declareProtected( ViewManagementScreens, 'document_src' )
+    security.declareProtected(ViewManagementScreens, 'document_src')
     def document_src( self ):
+        """ Fetch our source for rendering in the ZMI.
         """
-            Fetch our source for indexing in a catalog.
-        """
         return self.raw
 
-Globals.InitializeClass( FSSTXMethod )
+InitializeClass(FSSTXMethod)
 
-registerFileExtension( 'stx', FSSTXMethod )
-registerMetaType( 'STX Method', FSSTXMethod )
+registerFileExtension('stx', FSSTXMethod)
+registerMetaType('STX Method', FSSTXMethod)

Modified: CMF/trunk/CMFCore/dtml/custstx.dtml
===================================================================
--- CMF/trunk/CMFCore/dtml/custstx.dtml	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CMFCore/dtml/custstx.dtml	2006-10-18 22:29:50 UTC (rev 70793)
@@ -13,13 +13,13 @@
 </dtml-let>
 <dtml-var manage_tabs>
 
-  <FORM ACTION="manage_doCustomize" METHOD="POST">
-    <TABLE CELLSPACING="2">
-      <TR>
-	<TH ALIGN="LEFT" VALIGN="TOP" class="form-label">Id</TH>
-	<TD ALIGN="LEFT" VALIGN="TOP" class="form-element"><dtml-var getId></TD>
-      </TR>
+  <form ACTION="manage_doCustomize" METHOD="POST">
+    <table CELLSPACING="2">
       <tr>
+	<th ALIGN="LEFT" VALIGN="TOP" class="form-label">Id</th>
+	<td ALIGN="LEFT" VALIGN="TOP" class="form-element"><dtml-var getId></td>
+      </tr>
+      <tr>
 	<th align="left" valign="top" class="form-label">
         <em>Size</em>
         </th>
@@ -58,8 +58,8 @@
           <input type="submit" name="submit" value=" Customize ">
         </td>
       </tr>
-    </TABLE>
-  </FORM>
+    </table>
+  </form>
 <table border="1" bgcolor="#cccccc"><tr><td>
 <pre>
 <dtml-var document_src>

Added: CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx
===================================================================
--- CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx	2006-10-18 22:29:50 UTC (rev 70793)
@@ -0,0 +1,6 @@
+Title Goes Here
+
+  Subhead Here
+
+    And this is a paragraph,
+    broken across lines.

Added: CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx.metadata
===================================================================
--- CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx.metadata	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CMFCore/tests/fake_skins/fake_skin/testSTX.stx.metadata	2006-10-18 22:29:50 UTC (rev 70793)
@@ -0,0 +1,2 @@
+[default]
+title=STX Method

Added: CMF/trunk/CMFCore/tests/test_FSSTXMethod.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-18 21:44:51 UTC (rev 70792)
+++ CMF/trunk/CMFCore/tests/test_FSSTXMethod.py	2006-10-18 22:29:50 UTC (rev 70793)
@@ -0,0 +1,179 @@
+##############################################################################
+#
+# Copyright (c) 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.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Unit tests for FSSTXMethod module.
+
+$Id$
+"""
+import unittest
+import os
+
+#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
+
+class FSSTXMaker(FSDVTest):
+
+    def _makeOne( self, id, filename ):
+        from Products.CMFCore.FSMetadata import FSMetadata
+        from Products.CMFCore.FSSTXMethod import FSSTXMethod
+        path = os.path.join(self.skin_path_name, filename)
+        metadata = FSMetadata(path)
+        metadata.read()
+        return FSSTXMethod( id, path, properties=metadata.getProperties() )
+
+_EXPECTED_HTML = """\
+<html>
+<body>
+
+<h1>Title Goes Here</h1>
+<h2>  Subhead Here</h2>
+<p>    And this is a paragraph,
+    broken across lines.</p>
+
+</body>
+</html>
+"""
+
+class FSSTXMethodTests(RequestTest, FSSTXMaker):
+
+    def 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)
+
+    def test___call__( self ):
+        script = self._makeOne( 'testSTX', 'testSTX.stx' )
+        script = script.__of__(self.app)
+        self.assertEqual(script(self.REQUEST), _EXPECTED_HTML)
+
+    def test_caching( self ):
+        #   Test HTTP caching headers.
+        from Products.CMFCore.tests.base.dummy import DummyCachingManager
+        self.root.caching_policy_manager = DummyCachingManager()
+        original_len = len( self.RESPONSE.headers )
+        script = self._makeOne('testSTX', 'testSTX.stx')
+        script = script.__of__(self.root)
+        script(self.REQUEST, self.RESPONSE)
+        self.failUnless( len( self.RESPONSE.headers ) >= original_len + 2 )
+        self.failUnless( 'foo' in self.RESPONSE.headers.keys() )
+        self.failUnless( 'bar' in self.RESPONSE.headers.keys() )
+
+    def test_ownership( self ):
+        script = self._makeOne( 'testSTX', 'testSTX.stx' )
+        script = script.__of__(self.root)
+        # FSSTXMethod has no owner
+        owner_tuple = script.getOwnerTuple()
+        self.assertEqual(owner_tuple, None)
+
+        # and ownership is not acquired [CMF/450]
+        self.root._owner= ('/foobar', 'baz')
+        owner_tuple = script.getOwnerTuple()
+        self.assertEqual(owner_tuple, None)
+
+    def test_304_response_from_cpm( self ):
+        # test that we get a 304 response from the cpm via this template
+        from DateTime import DateTime
+        from webdav.common import rfc1123_date
+        from Products.CMFCore.tests.base.dummy \
+            import DummyCachingManagerWithPolicy
+        from Products.CMFCore.tests.base.dummy import DummyContent
+
+        mod_time = DateTime()
+        self.root.caching_policy_manager = DummyCachingManagerWithPolicy()
+        script = self._makeOne('testSTX', 'testSTX.stx')
+        script = script.__of__(self.root)
+        self.REQUEST.environ[ 'IF_MODIFIED_SINCE'
+                            ] = '%s;' % rfc1123_date( mod_time+3600 )
+        data = script(self.REQUEST, self.RESPONSE)
+
+        self.assertEqual( data, '' )
+        self.assertEqual( self.RESPONSE.getStatus(), 304 )
+
+class FSSTXMethodCustomizationTests( SecurityTest, FSSTXMaker ):
+
+    def setUp( self ):
+        from OFS.Folder import Folder
+        FSSTXMaker.setUp(self)
+        SecurityTest.setUp( self )
+
+        self.root._setObject( 'portal_skins', Folder( 'portal_skins' ) )
+        self.skins = self.root.portal_skins
+
+        self.skins._setObject( 'custom', Folder( 'custom' ) )
+        self.custom = self.skins.custom
+
+        self.skins._setObject( 'fsdir', Folder( 'fsdir' ) )
+        self.fsdir = self.skins.fsdir
+
+        self.fsdir._setObject( 'testSTX'
+                             , self._makeOne( 'testSTX', 'testSTX.stx' ) )
+
+        self.fsSTX = self.fsdir.testSTX
+
+    def test_customize( self ):
+        from OFS.DTMLDocument import DTMLDocument
+        from Products.CMFCore.FSSTXMethod import _CUSTOMIZED_TEMPLATE_DTML
+
+        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, DTMLDocument))
+
+        propinfo = target.propdict()['stx']
+        self.assertEqual(propinfo['type'], 'text')
+        self.assertEqual(target.stx, self.fsSTX.raw)
+
+        self.assertEqual(target.document_src(), _CUSTOMIZED_TEMPLATE_DTML)
+
+    def test_customize_caching(self):
+        # Test to ensure that cache manager associations survive customizing
+        from Products.StandardCacheManagers import RAMCacheManager
+        cache_id = 'gofast'
+        RAMCacheManager.manage_addRAMCacheManager( self.root
+                                                 , cache_id
+                                                 , REQUEST=None
+                                                 )
+        self.fsSTX.ZCacheable_setManagerId(cache_id, REQUEST=None)
+
+        self.assertEqual(self.fsSTX.ZCacheable_getManagerId(), cache_id)
+
+        self.fsSTX.manage_doCustomize(folder_path='custom')
+        custom_pt = self.custom.testSTX
+
+        self.assertEqual(custom_pt.ZCacheable_getManagerId(), cache_id)
+
+    def tearDown(self):
+        SecurityTest.tearDown(self)
+        FSSTXMaker.tearDown(self)
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(FSSTXMethodTests),
+        unittest.makeSuite(FSSTXMethodCustomizationTests),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: CMF/trunk/CMFCore/tests/test_FSSTXMethod.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.