Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
605b3357
Commit
605b3357
authored
Dec 12, 2000
by
Shane Hathaway
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merged CacheManagement_branch and added help topics.
parent
85c9478a
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
950 additions
and
16 deletions
+950
-16
lib/python/DocumentTemplate/DT_String.py
lib/python/DocumentTemplate/DT_String.py
+18
-4
lib/python/OFS/Cache.py
lib/python/OFS/Cache.py
+607
-0
lib/python/OFS/DTMLMethod.py
lib/python/OFS/DTMLMethod.py
+79
-9
lib/python/OFS/Image.py
lib/python/OFS/Image.py
+14
-3
lib/python/OFS/cacheNamespaceKeys.dtml
lib/python/OFS/cacheNamespaceKeys.dtml
+6
-0
lib/python/OFS/cacheable.dtml
lib/python/OFS/cacheable.dtml
+45
-0
lib/python/OFS/cmassoc.dtml
lib/python/OFS/cmassoc.dtml
+65
-0
lib/python/Products/OFSP/help/CacheManager-associate.stx
lib/python/Products/OFSP/help/CacheManager-associate.stx
+11
-0
lib/python/Products/OFSP/help/Cacheable-properties.stx
lib/python/Products/OFSP/help/Cacheable-properties.stx
+21
-0
lib/python/Products/OFSP/help/Caching.stx
lib/python/Products/OFSP/help/Caching.stx
+84
-0
No files found.
lib/python/DocumentTemplate/DT_String.py
View file @
605b3357
...
...
@@ -82,7 +82,7 @@
# attributions are listed in the accompanying credits file.
#
##############################################################################
"$Id: DT_String.py,v 1.3
8 2000/09/01 14:00:41 brian
Exp $"
"$Id: DT_String.py,v 1.3
9 2000/12/12 21:20:25 shane
Exp $"
from
string
import
split
,
strip
import
regex
,
ts_regex
...
...
@@ -91,7 +91,7 @@ from DT_Util import ParseError, InstanceDict, TemplateDict, render_blocks, str
from
DT_Var
import
Var
,
Call
,
Comment
from
DT_Return
import
ReturnTag
,
DTReturn
_marker
=
[]
# Create a new marker object.
class
String
:
"""Document templates defined from strings.
...
...
@@ -418,6 +418,14 @@ class String:
self.globals=vars
self._vars={}
ZDocumentTemplate_beforeRender__roles__ = ()
def ZDocumentTemplate_beforeRender(self, md, default):
return default
ZDocumentTemplate_afterRender__roles__ = ()
def ZDocumentTemplate_afterRender(self, md, result):
pass
def __call__(self,client=None,mapping={},**kw):
'''
\
Generate a document from a document template.
...
...
@@ -525,8 +533,14 @@ class String:
pushed=pushed+1
try:
try: return render_blocks(self._v_blocks, md)
except DTReturn, v: return v.v
value = self.ZDocumentTemplate_beforeRender(md, _marker)
if value is _marker:
try: result = render_blocks(self._v_blocks, md)
except DTReturn, v: result = v.v
self.ZDocumentTemplate_afterRender(md, result)
return result
else:
return value
finally:
if pushed: md._pop(pushed) # Get rid of circular reference!
md.level=level # Restore previous level
...
...
lib/python/OFS/Cache.py
0 → 100644
View file @
605b3357
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__
=
"""Cacheable object and cache management base classes.
$Id: Cache.py,v 1.2 2000/12/12 21:20:26 shane Exp $"""
__version__
=
'$Revision: 1.2 $'
[
11
:
-
2
]
import
time
,
sys
from
string
import
join
import
Globals
from
Globals
import
HTMLFile
from
Acquisition
import
aq_get
,
aq_acquire
,
aq_inner
,
aq_parent
,
aq_base
from
zLOG
import
LOG
,
WARNING
from
AccessControl
import
getSecurityManager
from
AccessControl.Role
import
_isBeingUsedAsAMethod
ZCM_MANAGERS
=
'__ZCacheManager_ids__'
ViewManagementScreensPermission
=
'View management screens'
ChangeCacheSettingsPermission
=
'Change cache settings'
def
isCacheable
(
ob
):
return
getattr
(
aq_base
(
ob
),
'_isCacheable'
,
0
)
def
managersExist
(
ob
):
# Returns 1 if any CacheManagers exist in the context of ob.
if
aq_get
(
ob
,
ZCM_MANAGERS
,
None
,
1
):
return
1
return
0
def
filterCacheTab
(
ob
):
if
_isBeingUsedAsAMethod
(
ob
):
# Show tab when in a ZClass def that uses Cacheable as a base.
parent
=
aq_parent
(
aq_inner
(
ob
))
return
isCacheable
(
parent
)
else
:
return
managersExist
(
ob
)
def
filterCacheManagers
(
orig
,
container
,
name
,
value
,
extra
):
'''
This is a filter method for aq_acquire.
It causes objects to be found only if they are
in the list of cache managers.
'''
if
(
hasattr
(
aq_base
(
container
),
ZCM_MANAGERS
)
and
name
in
getattr
(
container
,
ZCM_MANAGERS
)):
return
1
return
0
def
getVerifiedManagerIds
(
container
):
'''
Gets the list of cache managers in a container, verifying each one.
'''
ids
=
getattr
(
container
,
ZCM_MANAGERS
,
())
rval
=
[]
for
id
in
ids
:
if
getattr
(
getattr
(
container
,
id
,
None
),
'_isCacheManager'
,
0
):
rval
.
append
(
id
)
return
tuple
(
rval
)
# Anytime a CacheManager is added or removed, all _v_ZCacheable_cache
# attributes must be invalidated. manager_timestamp is a way to do
# that.
manager_timestamp
=
0
class
Cacheable
:
'''Mix-in for cacheable objects.
'''
manage_options
=
({
'label'
:
'Cache'
,
'action'
:
'ZCacheable_manage'
,
'filter'
:
filterCacheTab
,
'help'
:(
'OFSP'
,
'Cacheable-properties.stx'
),
},)
__ac_permissions__
=
(
(
ViewManagementScreensPermission
,
(
'ZCacheable_manage'
,
'ZCacheable_invalidate'
,
'ZCacheable_isMethod'
,
'ZCacheable_enabled'
,
'ZCacheable_getManagerId'
,
'ZCacheable_getManagerIds'
,
'ZCacheable_configHTML'
,
)),
(
ChangeCacheSettingsPermission
,
(
'ZCacheable_setManagerId'
,
'ZCacheable_setEnabled'
,
),
(
'Manager'
,)),
)
ZCacheable_manage
=
HTMLFile
(
'cacheable'
,
globals
())
_v_ZCacheable_cache
=
None
_v_ZCacheable_manager_timestamp
=
0
__manager_id
=
None
__enabled
=
1
_isCacheable
=
1
ZCacheable_getManager__roles__
=
()
def
ZCacheable_getManager
(
self
):
'''Returns the currently associated cache manager.'''
manager_id
=
self
.
__manager_id
if
manager_id
is
None
:
return
None
try
:
return
aq_acquire
(
self
,
manager_id
,
containment
=
1
,
filter
=
filterCacheManagers
,
extra
=
None
,
default
=
None
)
except
AttributeError
:
return
None
ZCacheable_getCache__roles__
=
()
def
ZCacheable_getCache
(
self
):
'''Gets the cache associated with this object.
'''
if
self
.
__manager_id
is
None
:
return
None
c
=
self
.
_v_ZCacheable_cache
if
c
is
not
None
:
# We have a volatile reference to the cache.
if
self
.
_v_ZCacheable_manager_timestamp
==
manager_timestamp
:
return
aq_base
(
c
)
manager
=
self
.
ZCacheable_getManager
()
if
manager
is
not
None
:
c
=
aq_base
(
manager
.
ZCacheManager_getCache
())
else
:
return
None
# Set a volatile reference to the cache then return it.
self
.
_v_ZCacheable_cache
=
c
self
.
_v_ZCacheable_manager_timestamp
=
manager_timestamp
return
c
ZCacheable_isEnabled__roles__
=
()
def
ZCacheable_isEnabled
(
self
):
'''
Returns true only if associated with a cache manager and
caching of this method is enabled.
'''
return
self
.
ZCacheable_getCache
()
and
self
.
__enabled
def
ZCacheable_isAMethod
(
self
):
'''
Returns 1 when this object is a ZClass method.
'''
m
=
_isBeingUsedAsAMethod
(
self
)
return
m
ZCacheable_getObAndView__roles__
=
()
def
ZCacheable_getObAndView
(
self
,
view_name
):
"""
If this object is a method of a ZClass and we're working
with the primary view, uses the ZClass instance as ob
and our own ID as the view_name. Otherwise returns
self and view_name unchanged.
"""
ob
=
self
if
not
view_name
and
self
.
ZCacheable_isAMethod
():
# This is a ZClass method.
ob
=
aq_parent
(
aq_inner
(
self
))
if
isCacheable
(
ob
):
view_name
=
self
.
getId
()
else
:
# Both the parent and the child have to be
# cacheable.
ob
=
self
return
ob
,
view_name
ZCacheable_get__roles__
=
()
def
ZCacheable_get
(
self
,
view_name
=
''
,
keywords
=
None
,
mtime_func
=
None
,
default
=
None
):
'''Retrieves the cached view for the object under the
conditions specified by keywords. If the value is
not yet cached, returns the default.
'''
c
=
self
.
ZCacheable_getCache
()
if
c
is
not
None
and
self
.
__enabled
:
ob
,
view_name
=
self
.
ZCacheable_getObAndView
(
view_name
)
try
:
val
=
c
.
ZCache_get
(
ob
,
view_name
,
keywords
,
mtime_func
,
default
)
return
val
except
:
LOG
(
'Cache'
,
WARNING
,
'ZCache_get() exception'
,
error
=
sys
.
exc_info
())
return
default
return
default
ZCacheable_set__roles__
=
()
def
ZCacheable_set
(
self
,
data
,
view_name
=
''
,
keywords
=
None
,
mtime_func
=
None
):
'''Cacheable views should call this method after generating
cacheable results. The data argument can be of any Python type.
'''
c
=
self
.
ZCacheable_getCache
()
if
c
is
not
None
and
self
.
__enabled
:
ob
,
view_name
=
self
.
ZCacheable_getObAndView
(
view_name
)
try
:
c
.
ZCache_set
(
ob
,
data
,
view_name
,
keywords
,
mtime_func
)
except
:
LOG
(
'Cache'
,
WARNING
,
'ZCache_set() exception'
,
error
=
sys
.
exc_info
())
def
ZCacheable_invalidate
(
self
,
view_name
=
''
,
REQUEST
=
None
):
'''Called after a cacheable object is edited. Causes all
cache entries that apply to the view_name to be removed.
Returns a status message.
'''
c
=
self
.
ZCacheable_getCache
()
if
c
is
not
None
:
ob
,
view_name
=
self
.
ZCacheable_getObAndView
(
view_name
)
try
:
message
=
c
.
ZCache_invalidate
(
ob
)
if
not
message
:
message
=
'Invalidated.'
except
:
exc
=
sys
.
exc_info
()
try
:
LOG
(
'Cache'
,
WARNING
,
'ZCache_invalidate() exception'
,
error
=
exc
)
message
=
'An exception occurred: %s: %s'
%
exc
[:
2
]
finally
:
exc
=
None
else
:
message
=
'This object is not associated with a cache manager.'
if
REQUEST
is
not
None
:
return
self
.
ZCacheable_manage
(
self
,
REQUEST
,
management_view
=
'Cache'
,
manage_tabs_message
=
message
)
else
:
return
message
ZCacheable_getModTime__roles__
=
()
def
ZCacheable_getModTime
(
self
,
mtime_func
=
None
):
'''Returns the highest of the last mod times.'''
# Based on:
# mtime_func
# self.mtime
# self.__class__.mtime
# (if in a ZClass) zclass_instance.mtime
# zclass_instance.__class__.mtime
mtime
=
0
if
mtime_func
:
# Allow mtime_func to influence the mod time.
mtime
=
mtime_func
()
base
=
aq_base
(
self
)
mtime
=
max
(
getattr
(
base
,
'_p_mtime'
,
mtime
),
mtime
)
klass
=
getattr
(
base
,
'__class__'
,
None
)
if
klass
:
mtime
=
max
(
getattr
(
klass
,
'_p_mtime'
,
mtime
),
mtime
)
if
self
.
ZCacheable_isAMethod
():
# This is a ZClass method.
instance
=
aq_parent
(
aq_inner
(
self
))
base
=
aq_base
(
instance
)
mtime
=
max
(
getattr
(
base
,
'_p_mtime'
,
mtime
),
mtime
)
klass
=
getattr
(
base
,
'__class__'
,
None
)
if
klass
:
mtime
=
max
(
getattr
(
klass
,
'_p_mtime'
,
mtime
),
mtime
)
return
mtime
def
ZCacheable_getManagerId
(
self
):
'''Returns the id of the current ZCacheManager.'''
return
self
.
__manager_id
def
ZCacheable_getManagerURL
(
self
):
'''Returns the URL of the current ZCacheManager.'''
manager
=
self
.
ZCacheable_getManager
()
if
manager
is
not
None
:
return
manager
.
absolute_url
()
return
None
def
ZCacheable_getManagerIds
(
self
):
'''Returns a list of mappings containing the id and title
of the available ZCacheManagers.'''
rval
=
[]
ob
=
self
used_ids
=
{}
while
ob
is
not
None
:
if
hasattr
(
aq_base
(
ob
),
ZCM_MANAGERS
):
ids
=
getattr
(
ob
,
ZCM_MANAGERS
)
for
id
in
ids
:
manager
=
getattr
(
ob
,
id
,
None
)
if
manager
is
not
None
:
id
=
manager
.
getId
()
if
not
used_ids
.
has_key
(
id
):
title
=
getattr
(
aq_base
(
manager
),
'title'
,
''
)
rval
.
append
({
'id'
:
id
,
'title'
:
title
})
used_ids
[
id
]
=
1
ob
=
aq_parent
(
aq_inner
(
ob
))
return
tuple
(
rval
)
def
ZCacheable_setManagerId
(
self
,
manager_id
,
REQUEST
=
None
):
'''Changes the manager_id for this object.'''
self
.
ZCacheable_invalidate
()
if
not
manager_id
:
# User requested disassociation
# from the cache manager.
manager_id
=
None
else
:
manager_id
=
str
(
manager_id
)
self
.
__manager_id
=
manager_id
if
REQUEST
is
not
None
:
return
self
.
ZCacheable_manage
(
self
,
REQUEST
,
management_view
=
'Cache'
,
manage_tabs_message
=
'Cache settings changed.'
)
def
ZCacheable_enabled
(
self
):
'''Returns true if caching is enabled for this object
or method.'''
return
self
.
__enabled
def
ZCacheable_setEnabled
(
self
,
enabled
=
0
,
REQUEST
=
None
):
'''Changes the enabled flag. Normally used only when
setting up cacheable ZClass methods.'''
self
.
__enabled
=
enabled
and
1
or
0
if
REQUEST
is
not
None
:
return
self
.
ZCacheable_manage
(
self
,
REQUEST
,
management_view
=
'Cache'
,
manage_tabs_message
=
'Cache settings changed.'
)
def
ZCacheable_configHTML
(
self
):
'''Override to provide configuration of caching
behavior that can only be specific to the cacheable object.
'''
return
''
Globals
.
default__class_init__
(
Cacheable
)
def
findCacheables
(
ob
,
manager_id
,
require_assoc
,
subfolders
,
meta_types
,
rval
,
path
):
'''
Used by the CacheManager UI. Recursive. Similar to the Zope
"Find" function. Finds all Cacheable objects in a hierarchy.
'''
try
:
if
meta_types
:
subobs
=
ob
.
objectValues
(
meta_types
)
else
:
subobs
=
ob
.
objectValues
()
sm
=
getSecurityManager
()
# Add to the list of cacheable objects.
for
subob
in
subobs
:
if
not
isCacheable
(
subob
):
continue
associated
=
(
subob
.
ZCacheable_getManagerId
()
==
manager_id
)
if
require_assoc
and
not
associated
:
continue
if
not
sm
.
checkPermission
(
'Change cache settings'
,
subob
):
continue
subpath
=
path
+
(
subob
.
getId
(),)
icon
=
getattr
(
aq_base
(
subob
),
'icon'
,
''
)
info
=
{
'sortkey'
:
subpath
,
'path'
:
join
(
subpath
,
'/'
),
'title'
:
getattr
(
aq_base
(
subob
),
'title'
,
''
),
'icon'
:
icon
,
'associated'
:
associated
,}
rval
.
append
(
info
)
# Visit subfolders.
if
subfolders
:
if
meta_types
:
subobs
=
ob
.
objectValues
()
for
subob
in
subobs
:
subpath
=
path
+
(
subob
.
getId
(),)
if
hasattr
(
aq_base
(
subob
),
'objectValues'
):
if
sm
.
checkPermission
(
'Access contents information'
,
subob
):
findCacheables
(
subob
,
manager_id
,
require_assoc
,
subfolders
,
meta_types
,
rval
,
subpath
)
except
:
# Ignore exceptions.
import
traceback
traceback
.
print_exc
()
class
Cache
:
'''
A base class (and interface description) for caches.
Note that Cache objects are not intended to be visible by
restricted code.
'''
def
ZCache_invalidate
(
self
,
ob
):
raise
'Not implemented'
def
ZCache_get
(
self
,
ob
,
view_name
,
keywords
,
mtime_func
,
default
):
# view_name: If an object provides different views that would
# benefit from caching, it will set view_name.
# Otherwise view_name will be an empty string.
#
# keywords: Either None or a mapping containing keys that
# distinguish this cache entry from others even though
# ob and view_name are the same. DTMLMethods use keywords
# derived from the DTML namespace.
#
# mtime_func: When the Cache calls ZCacheable_getModTime(),
# it should pass this as an argument. It is provided to
# allow cacheable objects to provide their own computation
# of the object's modification time.
#
# default: If no entry is found, ZCache_get() should return
# default.
raise
'Not implemented'
def
ZCache_set
(
self
,
ob
,
data
,
view_name
,
keywords
,
mtime_func
):
# See ZCache_get() for parameter descriptions.
raise
'Not implemented'
class
CacheManager
:
'''
A base class for cache managers. Implement ZCacheManager_getCache().
'''
ZCacheManager_getCache__roles__
=
()
def
ZCacheManager_getCache
(
self
):
raise
'Not implemented'
_isCacheManager
=
1
__ac_permissions__
=
(
(
'Change cache settings'
,
(
'ZCacheManager_locate'
,
'ZCacheManager_setAssociations'
,
'ZCacheManager_associate'
),
(
'Manager'
,)),
)
manage_options
=
(
{
'label'
:
'Associate'
,
'action'
:
'ZCacheManager_associate'
,
'help'
:(
'OFSP'
,
'CacheManager-associate.stx'
),
},
)
def
manage_afterAdd
(
self
,
item
,
container
):
# Adds self to the list of cache managers in the container.
if
aq_base
(
self
)
is
aq_base
(
item
):
ids
=
getVerifiedManagerIds
(
container
)
id
=
self
.
getId
()
if
id
not
in
ids
:
setattr
(
container
,
ZCM_MANAGERS
,
ids
+
(
id
,))
global
manager_timestamp
manager_timestamp
=
time
.
time
()
def
manage_beforeDelete
(
self
,
item
,
container
):
# Removes self from the list of cache managers.
if
aq_base
(
self
)
is
aq_base
(
item
):
ids
=
getVerifiedManagerIds
(
container
)
id
=
self
.
getId
()
if
id
in
ids
:
setattr
(
container
,
ZCM_MANAGERS
,
filter
(
lambda
s
,
id
=
id
:
s
!=
id
,
ids
))
global
manager_timestamp
manager_timestamp
=
time
.
time
()
ZCacheManager_associate
=
HTMLFile
(
'cmassoc'
,
globals
())
def
ZCacheManager_locate
(
self
,
require_assoc
,
subfolders
,
meta_types
=
[],
REQUEST
=
None
):
'''Locates cacheable objects.
'''
ob
=
aq_parent
(
aq_inner
(
self
))
rval
=
[]
manager_id
=
self
.
getId
()
if
''
in
meta_types
:
# User selected "All".
meta_types
=
[]
findCacheables
(
ob
,
manager_id
,
require_assoc
,
subfolders
,
meta_types
,
rval
,
())
if
REQUEST
is
not
None
:
return
self
.
ZCacheManager_associate
(
self
,
REQUEST
,
show_results
=
1
,
results
=
rval
,
management_view
=
"Associate"
)
else
:
return
rval
def
ZCacheManager_setAssociations
(
self
,
props
=
None
,
REQUEST
=
None
):
'''Associates and un-associates cacheable objects with this
cache manager.
'''
addcount
=
0
remcount
=
0
parent
=
aq_parent
(
aq_inner
(
self
))
sm
=
getSecurityManager
()
my_id
=
str
(
self
.
getId
())
if
props
is
None
:
props
=
REQUEST
.
form
for
key
,
do_associate
in
props
.
items
():
if
key
[:
10
]
==
'associate_'
:
path
=
key
[
10
:]
ob
=
parent
.
restrictedTraverse
(
path
)
if
not
sm
.
checkPermission
(
'Change cache settings'
,
ob
):
raise
'Unauthorized'
if
not
isCacheable
(
ob
):
# Not a cacheable object.
continue
manager_id
=
str
(
ob
.
ZCacheable_getManagerId
())
if
do_associate
:
if
manager_id
!=
my_id
:
ob
.
ZCacheable_setManagerId
(
my_id
)
addcount
=
addcount
+
1
else
:
if
manager_id
==
my_id
:
ob
.
ZCacheable_setManagerId
(
None
)
remcount
=
remcount
+
1
if
REQUEST
is
not
None
:
return
self
.
ZCacheManager_associate
(
self
,
REQUEST
,
management_view
=
"Associate"
,
manage_tabs_message
=
'%d association(s) made, %d removed.'
%
(
addcount
,
remcount
)
)
Globals
.
default__class_init__
(
CacheManager
)
lib/python/OFS/DTMLMethod.py
View file @
605b3357
...
...
@@ -84,7 +84,7 @@
##############################################################################
"""DTML Method objects."""
__version__
=
'$Revision: 1.5
5
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.5
6
$'
[
11
:
-
2
]
import
History
from
Globals
import
HTML
,
HTMLFile
,
MessageDialog
...
...
@@ -99,18 +99,21 @@ from DateTime.DateTime import DateTime
from
urllib
import
quote
import
ts_regex
,
Globals
,
sys
,
Acquisition
from
AccessControl
import
getSecurityManager
from
Cache
import
Cacheable
_marker
=
[]
# Create a new marker object.
class
DTMLMethod
(
HTML
,
Acquisition
.
Implicit
,
RoleManager
,
ElementWithTitle
,
Item_w__name__
,
History
.
Historical
,
Cacheable
,
):
"""DTML Method objects are DocumentTemplate.HTML objects that act
as methods of their containers."""
meta_type
=
'DTML Method'
_proxy_roles
=
()
index_html
=
None
# Prevent accidental acquisition
_cache_namespace_keys
=
()
# Documents masquerade as functions:
class
func_code
:
pass
...
...
@@ -132,8 +135,9 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
+
History
.
Historical
.
manage_options
+
RoleManager
.
manage_options
+
Item_w__name__
.
manage_options
+
Cacheable
.
manage_options
)
__ac_permissions__
=
(
(
'View management screens'
,
(
'document_src'
,
'PrincipiaSearchSource'
)),
...
...
@@ -142,6 +146,8 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
'manage_edit'
,
'manage_upload'
,
'PUT'
,
'manage_historyCopy'
,
'manage_beforeHistoryCopy'
,
'manage_afterHistoryCopy'
,
'ZCacheable_configHTML'
,
'getCacheNamespaceKeys'
,
'setCacheNamespaceKeys'
,
)
),
(
'Change proxy roles'
,
(
'manage_proxyForm'
,
'manage_proxy'
)),
...
...
@@ -156,6 +162,13 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
def
__call__
(
self
,
client
=
None
,
REQUEST
=
{},
RESPONSE
=
None
,
**
kw
):
"""Render the document given a client object, REQUEST mapping,
Response, and key word arguments."""
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
...
...
@@ -164,14 +177,19 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
try
:
if
client
is
None
:
# Called as subtemplate, so don't need error prop
i
gation!
# Called as subtemplate, so don't need error prop
a
gation!
r
=
apply
(
HTML
.
__call__
,
(
self
,
client
,
REQUEST
),
kw
)
if
RESPONSE
is
None
:
return
r
return
decapitate
(
r
,
RESPONSE
)
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
(
HTML
.
__call__
,
(
self
,
client
,
REQUEST
),
kw
)
if
type
(
r
)
is
not
type
(
''
):
return
r
if
RESPONSE
is
None
:
return
r
if
type
(
r
)
is
not
type
(
''
)
or
RESPONSE
is
None
:
if
not
self
.
_cache_namespace_keys
:
self
.
ZCacheable_set
(
r
)
return
r
finally
:
security
.
removeContext
(
self
)
...
...
@@ -182,7 +200,55 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
else
:
c
,
e
=
guess_content_type
(
self
.
getId
(),
r
)
RESPONSE
.
setHeader
(
'Content-Type'
,
c
)
return
decapitate
(
r
,
RESPONSE
)
result
=
decapitate
(
r
,
RESPONSE
)
if
not
self
.
_cache_namespace_keys
:
self
.
ZCacheable_set
(
result
)
return
result
def
ZDocumentTemplate_beforeRender
(
self
,
md
,
default
):
# Tries to get a cached value.
if
self
.
_cache_namespace_keys
:
# Use the specified keys from the namespace to identify a
# cache entry.
kw
=
{}
for
key
in
self
.
_cache_namespace_keys
:
try
:
val
=
md
[
key
]
except
:
val
=
None
kw
[
key
]
=
val
return
self
.
ZCacheable_get
(
keywords
=
kw
,
default
=
default
)
return
default
def
ZDocumentTemplate_afterRender
(
self
,
md
,
result
):
# Tries to set a cache value.
if
self
.
_cache_namespace_keys
:
kw
=
{}
for
key
in
self
.
_cache_namespace_keys
:
try
:
val
=
md
[
key
]
except
:
val
=
None
kw
[
key
]
=
val
self
.
ZCacheable_set
(
result
,
keywords
=
kw
)
ZCacheable_configHTML
=
HTMLFile
(
'cacheNamespaceKeys'
,
globals
())
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
)
def
get_size
(
self
):
return
len
(
self
.
raw
)
...
...
@@ -238,6 +304,7 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
self
.
title
=
str
(
title
)
if
type
(
data
)
is
not
type
(
''
):
data
=
data
.
read
()
self
.
munge
(
data
)
self
.
ZCacheable_invalidate
()
if
REQUEST
:
message
=
"Content changed."
return
self
.
manage_main
(
self
,
REQUEST
,
manage_tabs_message
=
message
)
...
...
@@ -247,6 +314,7 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
self
.
_validateProxy
(
REQUEST
)
if
type
(
file
)
is
not
type
(
''
):
file
=
file
.
read
()
self
.
munge
(
file
)
self
.
ZCacheable_invalidate
()
if
REQUEST
:
return
MessageDialog
(
title
=
'Success!'
,
message
=
'Your changes have been saved'
,
...
...
@@ -278,6 +346,7 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
self
.
_validateProxy
(
REQUEST
,
roles
)
self
.
_validateProxy
(
REQUEST
)
self
.
_proxy_roles
=
tuple
(
roles
)
self
.
ZCacheable_invalidate
()
if
REQUEST
:
return
MessageDialog
(
title
=
'Success!'
,
message
=
'Your changes have been saved'
,
...
...
@@ -301,6 +370,7 @@ class DTMLMethod(HTML, Acquisition.Implicit, RoleManager,
body
=
REQUEST
.
get
(
'BODY'
,
''
)
self
.
_validateProxy
(
REQUEST
)
self
.
munge
(
body
)
self
.
ZCacheable_invalidate
()
RESPONSE
.
setStatus
(
204
)
return
RESPONSE
...
...
lib/python/OFS/Image.py
View file @
605b3357
...
...
@@ -84,7 +84,7 @@
##############################################################################
"""Image object"""
__version__
=
'$Revision: 1.11
7
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.11
8
$'
[
11
:
-
2
]
import
Globals
,
string
,
struct
,
content_types
from
OFS.content_types
import
guess_content_type
...
...
@@ -97,6 +97,7 @@ from cStringIO import StringIO
from
Globals
import
Persistent
from
Acquisition
import
Implicit
from
DateTime
import
DateTime
from
Cache
import
Cacheable
StringType
=
type
(
''
)
...
...
@@ -128,8 +129,8 @@ def manage_addFile(self,id,file='',title='',precondition='', content_type='',
REQUEST
[
'RESPONSE'
].
redirect
(
self
.
absolute_url
()
+
'/manage_main'
)
class
File
(
Persistent
,
Implicit
,
PropertyManager
,
RoleManager
,
Item_w__name__
):
class
File
(
Persistent
,
Implicit
,
PropertyManager
,
RoleManager
,
Item_w__name__
,
Cacheable
):
"""A File object is a content object for arbitrary files."""
meta_type
=
'File'
...
...
@@ -156,6 +157,7 @@ class File(Persistent,Implicit,PropertyManager,
)
+
RoleManager
.
manage_options
+
Item_w__name__
.
manage_options
+
Cacheable
.
manage_options
)
...
...
@@ -231,6 +233,10 @@ class File(Persistent,Implicit,PropertyManager,
RESPONSE
.
setHeader
(
'Content-Type'
,
self
.
content_type
)
RESPONSE
.
setHeader
(
'Content-Length'
,
self
.
size
)
# Don't cache the data itself, but provide an opportunity
# for a cache manager to set response headers.
self
.
ZCacheable_set
(
None
)
data
=
self
.
data
if
type
(
data
)
is
type
(
''
):
return
data
...
...
@@ -251,6 +257,7 @@ class File(Persistent,Implicit,PropertyManager,
if
size
is
None
:
size
=
len
(
data
)
self
.
size
=
size
self
.
data
=
data
self
.
ZCacheable_invalidate
()
def
manage_edit
(
self
,
title
,
content_type
,
precondition
=
''
,
REQUEST
=
None
):
"""
...
...
@@ -260,6 +267,7 @@ class File(Persistent,Implicit,PropertyManager,
self
.
content_type
=
str
(
content_type
)
if
precondition
:
self
.
precondition
=
str
(
precondition
)
elif
self
.
precondition
:
del
self
.
precondition
self
.
ZCacheable_invalidate
()
if
REQUEST
:
message
=
"Your changes have been saved"
return
self
.
manage_main
(
self
,
REQUEST
,
manage_tabs_message
=
message
)
...
...
@@ -474,6 +482,7 @@ class Image(File):
)
+
RoleManager
.
manage_options
+
Item_w__name__
.
manage_options
+
Cacheable
.
manage_options
)
manage_editForm
=
HTMLFile
(
'imageEdit'
,
globals
(),
Kind
=
'Image'
,
kind
=
'image'
)
...
...
@@ -552,6 +561,8 @@ class Image(File):
# Now we should have the correct content type, or still None
if
content_type
is
not
None
:
self
.
content_type
=
content_type
self
.
ZCacheable_invalidate
()
def
__str__
(
self
):
return
self
.
tag
()
...
...
lib/python/OFS/cacheNamespaceKeys.dtml
0 → 100644
View file @
605b3357
Names from the DTML namespace to use as cache keys:<br>
<textarea name="keys:lines" cols="40" rows="5"><dtml-in
getCacheNamespaceKeys>&dtml-sequence-item;
</dtml-in></textarea>
<br>
<input type="submit" name="setCacheNamespaceKeys:method" value="Change">
lib/python/OFS/cacheable.dtml
0 → 100644
View file @
605b3357
<html><head><title>
Cache
</title></head>
<body
bgcolor=
"#ffffff"
>
<dtml-var
manage_tabs
>
<h2>
Caching properties
</h2>
<form
action=
"&dtml-absolute_url;"
method=
"POST"
>
<dtml-if
ZCacheable_isAMethod
>
<input
type=
"checkbox"
name=
"enable"
value=
"1"
<
dtml-if
ZCacheable_enabled
>
checked="checked"
</dtml-if>
>
Cache this view of the object
<br>
<input
type=
"submit"
name=
"ZCacheable_setEnabled:method"
value=
"Change"
>
<dtml-else>
Cache this object using:
<select
name=
"manager_id"
>
<option
value=
""
>
(None)
</option>
<dtml-in
ZCacheable_getManagerIds
mapping
>
<option
value=
"&dtml-id;"
<
dtml-if
expr=
"id == ZCacheable_getManagerId()"
>
selected="selected"
</dtml-if>
>
&dtml-id;
<dtml-if
title
>
(
&dtml-title;
)
</dtml-if></option>
</dtml-in>
</select>
<input
type=
"submit"
name=
"ZCacheable_setManagerId:method"
value=
"Change"
>
<dtml-if
ZCacheable_getManagerURL
>
<p>
<a
href=
"&dtml-ZCacheable_getManagerURL;/manage_main"
>
Settings
</a>
</p>
<p>
<input
type=
"submit"
name=
"ZCacheable_invalidate:method"
value=
"Invalidate"
>
</p>
</dtml-if>
</dtml-if>
<p><dtml-var
ZCacheable_configHTML
></p>
</form>
</body>
</html>
lib/python/OFS/cmassoc.dtml
0 → 100644
View file @
605b3357
<html><head><title>
Associate cacheable objects
</title></head>
<body
bgcolor=
"#ffffff"
>
<dtml-var
manage_tabs
>
<h2>
Associate cacheable objects
</h2>
<form
action=
"&dtml-URL1;"
method=
"POST"
>
<dtml-if
show_results
>
<dtml-if
results
>
<em>
Select which objects should be cached using this cache manager. Only
those objects for which you have the "Change cache settings" permission
are shown.
</em>
<table>
<dtml-in
results
mapping
sort=
sortkey
>
<tr><td><input
type=
"checkbox"
name=
"associate_&dtml-path;:int"
value=
"1"
<
dtml-if
associated
>
checked="checked"
</dtml-if>
>
<input
type=
"hidden"
name=
"associate_&dtml-path;:int:default"
value=
"0"
>
</td>
<td><dtml-if
icon
><a
href=
"../&dtml-path;/manage_main"
><img
src=
"&dtml-icon;"
border=
"0"
></a>
</dtml-if>
<a
href=
"../&dtml-path;/manage_main"
>
&dtml-path;
</a>
<dtml-if
title
>
(
&dtml-title;
)
</dtml-if>
</td></tr>
</dtml-in>
</table>
<input
type=
"submit"
name=
"ZCacheManager_setAssociations:method"
value=
"Save changes"
>
<dtml-else>
<em>
No objects matched your query.
</em>
</dtml-if>
<hr>
</dtml-if>
<table>
<tr>
<td
valign=
"top"
>
Locate cacheable objects:
</td>
<td
valign=
"top"
>
<input
type=
"radio"
name=
"require_assoc:int"
value=
"0"
checked=
"checked"
>
All
<input
type=
"radio"
name=
"require_assoc:int"
value=
"1"
>
Associated with this cache manager
<br>
<table><tr><td
valign=
"top"
>
Meta types:
</td><td
valign=
"top"
>
<select
multiple=
"multiple"
name=
"meta_types:list"
size=
"5"
>
<option
value=
""
>
All
</option>
<dtml-in
all_meta_types
mapping
sort=
name
>
<option
value=
"&dtml-name;"
>
&dtml-name;
</option>
</dtml-in>
</select>
</td></tr></table>
<input
type=
"checkbox"
name=
"subfolders:int"
value=
"1"
checked=
"checked"
>
<input
type=
"hidden"
name=
"subfolders:int"
value=
"0"
>
Search subfolders
<br>
<input
type=
"submit"
name=
"ZCacheManager_locate:method"
value=
"Locate"
>
</td></tr></table>
</form>
</body>
</html>
lib/python/Products/OFSP/help/CacheManager-associate.stx
0 → 100644
View file @
605b3357
Cache manager associations
For background information, see the
<a href="Caching.stx">description of cache management</a>.
The 'Associate' form lets you search for cacheable objects and
make or break multiple cache management associations at once.
Simply select the search criteria then click the 'Locate'
button. Zope will return a list of cacheable objects with a
checkbox for each one. Select or unselect objects and click the
'Save changes' button when you're done.
lib/python/Products/OFSP/help/Cacheable-properties.stx
0 → 100644
View file @
605b3357
Cacheable objects
For background information, see the
<a href="Caching.stx">description of cache management</a>.
The 'Cache' tab allows you to associate a cacheable object with a
cache manager. It is only available when at least one cache manager
exists somewhere in the current context.
Use the drop-down box to select which cache manager should be
associated with the object. Some types of objects provide
additional caching options.
DTML methods can be cached according to the DTML namespace. The entry
box on the 'Cache' tab allows you to enter the names
(one per line) that Zope should look up in the namespace to create the
cache key. Note, however, that the namespace lookup operation can be
expensive, so use this feature with care. Also note that it is not
possible for accelerated HTTP cache managers to make use of this feature.
(TODO) Python scripts and SQL methods may also provide further options.
lib/python/Products/OFSP/help/Caching.stx
0 → 100644
View file @
605b3357
Cache Management: Configurable Caching
Performing some computations in Zope can take a long time or use
a lot of resources. One way to deal with expensive tasks is to
cache them. The first time the computation is requested, the results
are stored in a table or *cache*. Subsequent requests get the results
from the cache. This can result in a dramatic speed increase.
There are so many possible strategies for caching that no one could
possibly come up with them all. Caches can be
stored in memory, on disk, on other computers, or by other means.
Caches can be limited in size or unconstrained. They can be
made to work with only specific types of objects. They can be
tuned in different ways.
So instead of trying to provide for every possible caching strategy,
Zope defines an API called *cache management* that lets developers
write their own caching strategies, or *cache managers*, and lets
site administrators easily connect cacheable objects to those cache
managers.
You can use caching to speed up access to often-requested pages,
reduce disk access and network traffic, and deal with heavy loads.
All these benefits come with risks of excessive caching, however,
so it's important to fine-tune the cache settings. More on this
later.
How to set up caching
The first thing you need to do is create a cache manager instance.
In the Zope management interface, go to a folder containing objects
that would benefit from caching. From the add list, select a
cache manager type such as 'RAM Cache Manager'. Use an ID that
describes the purpose of the cache manager.
Next, visit one of the objects that you want to cache. A new tab
labeled 'Cache' should be visible. Select it. From the drop-down
box, select the cache manager you just created and press the
'Change' button.
The object is now ready to be cached. Visit the 'View' tab. If
the object is a script that takes a long time to render, the first
view will still take just as long as before. But if you're using
a RAM cache manager or similar, the second view should be much faster.
Press the *reload* button in your browser to try it out.
You can associate many objects to a cache manager at once using the
'Associate' tab of all cache managers. Visit the cache manager
object you created and select the 'Associate' tab. Press the
'Locate' button. Zope will locate all cacheable objects in the
folder. Select the checkboxes next to the objects you want to
cache and press the 'Save changes' button.
Inherent risks
Cache managers generally don't know the nature of what is being
cached, so here are some issues that can surface:
- Data that is intended for authorized viewers only can
be inadvertently cached in public caches.
- Data is cached for too long a time.
- If more than one cache is involved, data is purged from one
cache but not the other.
- A method that makes up part of the page sets the caching headers
for the entire response, fooling downstream caches into thinking
the whole response should be cached.
- Result data can depend on any number of objects. Early on it was
decided that the standard cache managers will not try to deduce
dependencies, but instead rely on the user for configuration of
simple dependencies.
Because of these risks, you should be careful when setting up caching.
You'll need to fine-tune the cache settings. Sometimes you'll find
that you can't cache one of your major pages, but that you can cache
pieces of it.
Also remember that caching can actually slow down Zope if it is
applied unscrupulously. You should perform speed tests to verify that
caching really does speed up your site.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment