Back to index

plone3  3.1.7
FSReSTMethod.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001, 2006 Zope Corporation and Contributors.
00004 # All Rights Reserved.
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00008 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00009 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00010 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00011 # FOR A PARTICULAR PURPOSE.
00012 #
00013 ##############################################################################
00014 """ FSReSTMethod: Filesystem methodish Structured Text document.
00015 
00016 $Id: FSReSTMethod.py 70816 2006-10-19 17:35:41Z tseaver $
00017 """
00018 
00019 from AccessControl import ClassSecurityInfo
00020 from docutils.core import publish_parts
00021 from docutils.writers.html4css1 import Writer
00022 from Globals import DTMLFile
00023 from Globals import InitializeClass
00024 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
00025 from Products.ZReST.ZReST import Warnings
00026 
00027 from Products.CMFCore.DirectoryView import registerFileExtension
00028 from Products.CMFCore.DirectoryView import registerMetaType
00029 from Products.CMFCore.FSObject import FSObject
00030 from Products.CMFCore.permissions import FTPAccess
00031 from Products.CMFCore.permissions import View
00032 from Products.CMFCore.permissions import ViewManagementScreens
00033 from Products.CMFCore.utils import _dtmldir
00034 from Products.CMFCore.utils import _checkConditionalGET
00035 from Products.CMFCore.utils import _setCacheHeaders
00036 from Products.CMFCore.utils import _ViewEmulator
00037 
00038 _DEFAULT_TEMPLATE_ZPT = """\
00039 <html metal:use-macro="context/main_template/macros/main">
00040 <body>
00041 
00042 <metal:block metal:fill-slot="body"
00043 ><div tal:replace="structure options/cooked">
00044 COOKED TEXT HERE
00045 </div>
00046 </metal:block>
00047 
00048 </body>
00049 </html>
00050 """
00051 
00052 _CUSTOMIZED_TEMPLATE_ZPT = """\
00053 <html metal:use-macro="context/main_template/macros/master">
00054 <body>
00055 
00056 <metal:block metal:fill-slot="body"
00057 ><div tal:define="std modules/Products/PythonScripts/standard;
00058                   rest nocall:std/restructured_text;"
00059       tal:replace="structure python:rest(template.rest)">
00060 COOKED TEXT HERE
00061 </div>
00062 </metal:block>
00063 
00064 </body>
00065 </html>
00066 """
00067 
00068 class FSReSTMethod(FSObject):
00069     """ A chunk of StructuredText, rendered as a skin method of a CMF site.
00070     """
00071     meta_type = 'Filesystem ReST Method'
00072     _owner = None # unowned
00073     report_level = 1
00074     input_encoding = 'ascii'
00075     output_encoding = 'utf8'
00076 
00077     manage_options=({'label' : 'Customize','action' : 'manage_main'},
00078                     {'label' : 'View','action' : '',
00079                      'help' : ('OFSP' ,'DTML-DocumentOrMethod_View.stx')},
00080                    )
00081 
00082     security = ClassSecurityInfo()
00083     security.declareObjectProtected(View)
00084 
00085     security.declareProtected(ViewManagementScreens, 'manage_main')
00086     manage_main = DTMLFile('custstx', _dtmldir)
00087 
00088     #
00089     #   FSObject interface
00090     #
00091     def _createZODBClone(self):
00092         """
00093             Create a ZODB (editable) equivalent of this object.
00094         """
00095         target = ZopePageTemplate(self.getId(), _CUSTOMIZED_TEMPLATE_ZPT)
00096         target._setProperty('rest', self.raw, 'text')
00097         return target
00098 
00099     def _readFile(self, reparse):
00100         """Read the data from the filesystem.
00101         """
00102         file = open(self._filepath, 'r') # not 'rb', as this is a text file!
00103         try:
00104             data = file.read()
00105         finally:
00106             file.close()
00107         self.raw = data
00108 
00109         if reparse:
00110             self.cook()
00111 
00112     #
00113     #   "Wesleyan" interface (we need to be "methodish").
00114     #
00115     class func_code:
00116         pass
00117 
00118     func_code = func_code()
00119     func_code.co_varnames = ()
00120     func_code.co_argcount = 0
00121     func_code.__roles__ = ()
00122 
00123     func_defaults__roles__ = ()
00124     func_defaults = ()
00125 
00126     index_html = None   # No accidental acquisition
00127 
00128     default_content_type = 'text/html'
00129 
00130     def cook(self):
00131         if not hasattr(self, '_v_cooked'):
00132             settings = {
00133                 'halt_level': 6,
00134                 'report_level' : self.report_level,
00135                 'input_encoding': self.input_encoding,
00136                 'output_encoding': self.output_encoding,
00137                 'initial_header_level' : 1,
00138                 'stylesheet' : None,
00139                 'stylesheet_path' : None,
00140                 'pub.settings.warning_stream' :  Warnings(),
00141                 'file_insertion_enabled' : 0,
00142                 'raw_enabled' : 0,
00143                 }
00144 
00145             parts = publish_parts(self.raw, writer=Writer(),
00146                                 settings_overrides=settings)
00147             self._v_cooked = parts['html_body']
00148         return self._v_cooked
00149 
00150     _default_template = ZopePageTemplate('restmethod_view',
00151                                          _DEFAULT_TEMPLATE_ZPT, 'text/html')
00152 
00153     def __call__( self, REQUEST={}, RESPONSE=None, **kw ):
00154         """ Return our rendered StructuredText.
00155         """
00156         self._updateFromFS()
00157 
00158         if RESPONSE is not None:
00159             RESPONSE.setHeader( 'Content-Type', 'text/html' )
00160 
00161         view = _ViewEmulator(self.getId()).__of__(self)
00162         if _checkConditionalGET(view, extra_context={}):
00163             return ''
00164 
00165         _setCacheHeaders(view, extra_context={})
00166 
00167         return self._render(REQUEST, RESPONSE, **kw)
00168 
00169     security.declarePrivate('modified')
00170     def modified(self):
00171         return self.getModTime()
00172 
00173     security.declarePrivate('_render')
00174     def _render(self, REQUEST={}, RESPONSE=None, **kw):
00175         """ Find the appropriate rendering template and use it to render us.
00176         """
00177         template = getattr(self, 'restmethod_view', self._default_template)
00178 
00179         if getattr(template, 'isDocTemp', 0):
00180             #posargs = (self, REQUEST, RESPONSE)
00181             posargs = (self, REQUEST)
00182         else:
00183             posargs = ()
00184 
00185         kwargs = {'cooked': self.cook()}
00186         return template(*posargs, **kwargs)
00187 
00188     security.declareProtected(FTPAccess, 'manage_FTPget')
00189     def manage_FTPget(self):
00190         """ Fetch our source for delivery via FTP.
00191         """
00192         return self.raw
00193 
00194     security.declareProtected(ViewManagementScreens, 'PrincipiaSearchSource')
00195     def PrincipiaSearchSource(self):
00196         """ Fetch our source for indexing in a catalog.
00197         """
00198         return self.raw
00199 
00200     security.declareProtected(ViewManagementScreens, 'document_src')
00201     def document_src( self ):
00202         """ Fetch our source for rendering in the ZMI.
00203         """
00204         return self.raw
00205 
00206 InitializeClass(FSReSTMethod)
00207 
00208 registerFileExtension('rst', FSReSTMethod)
00209 registerMetaType('ReST Method', FSReSTMethod)