[CMF-checkins] CVS: CMF/CMFCore - DirectoryView.py:1.32 FSDTMLMethod.py:1.13 FSFile.py:1.4 FSImage.py:1.13 FSObject.py:1.13 FSPageTemplate.py:1.17 FSPythonScript.py:1.20
Andy McKay
andy@agmweb.ca
Fri, 8 Nov 2002 19:25:23 -0500
Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv11724
Modified Files:
DirectoryView.py FSDTMLMethod.py FSFile.py FSImage.py
FSObject.py FSPageTemplate.py FSPythonScript.py
Log Message:
All these objects now have a Cacheable interface so you can cache them using a RAMCacheManager for instance. To do this you specify the cache id in the properties file:
eg: cache=SomeCache
=== CMF/CMFCore/DirectoryView.py 1.31 => 1.32 ===
--- CMF/CMFCore/DirectoryView.py:1.31 Tue Oct 22 16:58:18 2002
+++ CMF/CMFCore/DirectoryView.py Fri Nov 8 19:25:23 2002
@@ -421,6 +421,8 @@
all_meta_types = ()
_isDirectoryView = 1
+# _is_wrapperish = 1
+
security = ClassSecurityInfo()
def __init__(self, real, data, objects):
@@ -447,7 +449,7 @@
if REQUEST is not None:
REQUEST['RESPONSE'].redirect( '%s/manage_propertiesForm'
% self.absolute_url() )
-
+
security.declareProtected(AccessContentsInformation, 'getCustomizableObject')
def getCustomizableObject(self):
ob = aq_parent(aq_inner(self))
=== CMF/CMFCore/FSDTMLMethod.py 1.12 => 1.13 ===
--- CMF/CMFCore/FSDTMLMethod.py:1.12 Fri Aug 16 09:45:05 2002
+++ CMF/CMFCore/FSDTMLMethod.py Fri Nov 8 19:25:23 2002
@@ -28,12 +28,16 @@
from CMFCorePermissions import FTPAccess
from DirectoryView import registerFileExtension, registerMetaType, expandpath
from FSObject import FSObject
+
try:
# Zope 2.4.x
from AccessControl.DTML import RestrictedDTML
except ImportError:
class RestrictedDTML: pass
+from OFS.Cache import Cacheable
+
+_marker = [] # Create a new marker object.
class FSDTMLMethod(RestrictedDTML, FSObject, Globals.HTML):
"""FSDTMLMethods act like DTML methods but are not directly
@@ -47,8 +51,11 @@
{'label':'View', 'action':'',
'help':('OFSP','DTML-DocumentOrMethod_View.stx')},
)
+ +Cacheable.manage_options
)
+ _cache_namespace_keys=()
+
# Use declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(View)
@@ -105,6 +112,12 @@
self._updateFromFS()
+ if not self._cache_namespace_keys:
+ data = self.ZCacheable_get(default=_marker)
+ if data is not _marker:
+ # Return cached results.
+ return data
+
kw['document_id'] =self.getId()
kw['document_title']=self.title
@@ -117,10 +130,14 @@
r=apply(Globals.HTML.__call__, (self, client, REQUEST), kw)
if RESPONSE is None: result = r
else: result = decapitate(r, RESPONSE)
+ if not self._cache_namespace_keys:
+ self.ZCacheable_set(result)
return result
r=apply(Globals.HTML.__call__, (self, client, REQUEST), kw)
if type(r) is not type('') or RESPONSE is None:
+ if not self._cache_namespace_keys:
+ self.ZCacheable_set(result)
return r
finally: security.removeContext(self)
@@ -133,7 +150,29 @@
c, e=guess_content_type(self.getId(), r)
RESPONSE.setHeader('Content-Type', c)
result = decapitate(r, RESPONSE)
+ if not self._cache_namespace_keys:
+ self.ZCacheable_set(result)
return result
+
+ def getCacheNamespaceKeys(self):
+ '''
+ Returns the cacheNamespaceKeys.
+ '''
+ return self._cache_namespace_keys
+
+ def setCacheNamespaceKeys(self, keys, REQUEST=None):
+ '''
+ Sets the list of names that should be looked up in the
+ namespace to provide a cache key.
+ '''
+ ks = []
+ for key in keys:
+ key = strip(str(key))
+ if key:
+ ks.append(key)
+ self._cache_namespace_keys = tuple(ks)
+ if REQUEST is not None:
+ return self.ZCacheable_manage(self, REQUEST)
# Zope 2.3.x way:
def validate(self, inst, parent, name, value, md=None):
=== CMF/CMFCore/FSFile.py 1.3 => 1.4 ===
--- CMF/CMFCore/FSFile.py:1.3 Mon Nov 4 14:56:35 2002
+++ CMF/CMFCore/FSFile.py Fri Nov 8 19:25:23 2002
@@ -27,6 +27,8 @@
from FSObject import FSObject
from DirectoryView import registerFileExtension, registerMetaType, expandpath
+from OFS.Cache import Cacheable
+
class FSFile(FSObject):
"""FSFiles act like images but are not directly
modifiable from the management interface."""
@@ -36,7 +38,7 @@
manage_options=(
{'label':'Customize', 'action':'manage_main'},
- )
+ ) + Cacheable.manage_options
security = ClassSecurityInfo()
security.declareObjectProtected(View)
@@ -77,6 +79,7 @@
try: data = file.read()
finally: file.close()
if reparse or self.content_type == 'unknown/unknown':
+ self.ZCacheable_invalidate()
self.content_type=self._get_content_type(file, data, self.id)
return data
@@ -121,6 +124,7 @@
RESPONSE.setHeader('Content-Type', self.content_type)
RESPONSE.setHeader('Content-Length', len(data))
+ self.ZCacheable_set(None)
return data
security.declareProtected(View, 'getContentType')
=== CMF/CMFCore/FSImage.py 1.12 => 1.13 ===
--- CMF/CMFCore/FSImage.py:1.12 Thu Aug 1 15:05:11 2002
+++ CMF/CMFCore/FSImage.py Fri Nov 8 19:25:23 2002
@@ -28,6 +28,8 @@
from FSObject import FSObject
from DirectoryView import registerFileExtension, registerMetaType, expandpath
+from OFS.Cache import Cacheable
+
class FSImage(FSObject):
"""FSImages act like images but are not directly
modifiable from the management interface."""
@@ -39,7 +41,7 @@
manage_options=(
{'label':'Customize', 'action':'manage_main'},
- )
+ ) + Cacheable.manage_options
security = ClassSecurityInfo()
security.declareObjectProtected(View)
@@ -63,6 +65,7 @@
finally:
file.close()
if reparse or self.content_type == 'unknown/unknown':
+ self.ZCacheable_invalidate()
ct, width, height = getImageInfo( data )
self.content_type = ct
self.width = width
@@ -117,6 +120,7 @@
RESPONSE.setHeader('Content-Type', self.content_type)
RESPONSE.setHeader('Content-Length', len(data))
+ self.ZCacheable_set(None)
return data
security.declareProtected(View, 'getContentType')
=== CMF/CMFCore/FSObject.py 1.12 => 1.13 ===
--- CMF/CMFCore/FSObject.py:1.12 Thu Aug 15 16:03:09 2002
+++ CMF/CMFCore/FSObject.py Fri Nov 8 19:25:23 2002
@@ -28,7 +28,9 @@
from CMFCorePermissions import ViewManagementScreens
from CMFCorePermissions import ManagePortal
-class FSObject(Acquisition.Implicit, Item):
+from OFS.Cache import Cacheable
+
+class FSObject(Acquisition.Implicit, Item, Cacheable):
"""FSObject is a base class for all filesystem based look-alikes.
Subclasses of this class mimic ZODB based objects like Image and
@@ -53,6 +55,10 @@
if fullname and properties.get('keep_extension', 0):
id = fullname
+ cache = properties.get('cache')
+ if cache:
+ self.ZCacheable_setManagerId(cache)
+
self.id = id
self.__name__ = id # __name__ is used in traceback reporting
self._filepath = filepath
@@ -104,6 +110,8 @@
try: mtime=stat(fp)[8]
except: mtime=0
if not parsed or mtime != self._file_mod_time:
+ # if we have to read the file again, remove the cache
+ self.ZCacheable_invalidate()
self._readFile(1)
self._file_mod_time = mtime
self._parsed = 1
=== CMF/CMFCore/FSPageTemplate.py 1.16 => 1.17 ===
--- CMF/CMFCore/FSPageTemplate.py:1.16 Mon Nov 4 16:44:34 2002
+++ CMF/CMFCore/FSPageTemplate.py Fri Nov 8 19:25:23 2002
@@ -37,6 +37,10 @@
xml_detect_re = re.compile('^\s*<\?xml\s+')
+from OFS.Cache import Cacheable
+
+_marker = [] # Create a new marker object.
+
class FSPageTemplate(FSObject, Script, PageTemplate):
"Wrapper for Page Template"
@@ -47,7 +51,8 @@
{'label':'Customize', 'action':'manage_main'},
{'label':'Test', 'action':'ZScriptHTML_tryForm'},
)
- )
+ +Cacheable.manage_options
+ )
security = ClassSecurityInfo()
security.declareObjectProtected(View)
@@ -69,8 +74,8 @@
obj.write(self.read())
return obj
- def ZCacheable_isCachingEnabled(self):
- return 0
+# def ZCacheable_isCachingEnabled(self):
+# return 0
def _readFile(self, reparse):
fp = expandpath(self._filepath)
@@ -162,8 +167,49 @@
response = None
# Read file first to get a correct content_type default value.
self._updateFromFS()
- # call "inherited"
- result = self._ZPT_exec( bound_names, args, kw )
+
+ if not kw.has_key('args'):
+ kw['args'] = args
+ bound_names['options'] = kw
+
+ try:
+ response = self.REQUEST.RESPONSE
+ if not response.headers.has_key('content-type'):
+ response.setHeader('content-type', self.content_type)
+ except AttributeError:
+ pass
+
+ security=getSecurityManager()
+ bound_names['user'] = security.getUser()
+
+ # Retrieve the value from the cache.
+ keyset = None
+ if self.ZCacheable_isCachingEnabled():
+ # Prepare a cache key.
+ keyset = {
+ # Why oh why?
+ # All this code is cut and paste
+ # here to make sure that we
+ # dont call _getContext and hence can't cache
+ # Annoying huh?
+ 'here': self.aq_parent.getPhysicalPath(),
+ 'bound_names': bound_names}
+ result = self.ZCacheable_get(keywords=keyset)
+ if result is not None:
+ # Got a cached value.
+ return result
+
+ # Execute the template in a new security context.
+ security.addContext(self)
+ try:
+ result = self.pt_render(extra_context=bound_names)
+ if keyset is not None:
+ # Store the result in the cache.
+ self.ZCacheable_set(result, keywords=keyset)
+ return result
+ finally:
+ security.removeContext(self)
+
return result
# Copy over more methods
=== CMF/CMFCore/FSPythonScript.py 1.19 => 1.20 ===
--- CMF/CMFCore/FSPythonScript.py:1.19 Fri Nov 8 12:10:01 2002
+++ CMF/CMFCore/FSPythonScript.py Fri Nov 8 19:25:23 2002
@@ -30,6 +30,9 @@
from DirectoryView import registerFileExtension, registerMetaType, expandpath
from FSObject import FSObject
+from OFS.Cache import Cacheable
+
+_marker = []
class bad_func_code:
co_varnames = ()
@@ -51,6 +54,7 @@
'action':'ZScriptHTML_tryForm',
'help': ('PythonScripts', 'PythonScript_test.stx')},
)
+ + Cacheable.manage_options
)
# Use declarative security
@@ -103,6 +107,26 @@
Calling a Python Script is an actual function invocation.
"""
+ # do caching
+ keyset = None
+ if self.ZCacheable_isCachingEnabled():
+ # Prepare a cache key.
+ keyset = kw.copy()
+ asgns = self.getBindingAssignments()
+ name_context = asgns.getAssignedName('name_context', None)
+ if name_context:
+ keyset[name_context] = self.aq_parent.getPhysicalPath()
+ name_subpath = asgns.getAssignedName('name_subpath', None)
+ if name_subpath:
+ keyset[name_subpath] = self._getTraverseSubpath()
+ # Note: perhaps we should cache based on name_ns also.
+ keyset['*'] = args
+ result = self.ZCacheable_get(keywords=keyset, default=_marker)
+ if result is not _marker:
+ # Got a cached value.
+ return result
+
+
# Prepare the function.
f = self._v_f
if f is None:
@@ -131,6 +155,9 @@
security.addContext(self)
try:
result = apply(f, args, kw)
+ if keyset is not None:
+ # Store the result in the cache.
+ self.ZCacheable_set(result, keywords=keyset)
return result
finally:
security.removeContext(self)