[Erp5-report] r29842 - in /erp5/trunk/products/ERP5/mixin: ./ cached_convertable.py

nobody at svn.erp5.org nobody at svn.erp5.org
Tue Oct 20 12:34:15 CEST 2009


Author: jp
Date: Tue Oct 20 12:34:14 2009
New Revision: 29842

URL: http://svn.erp5.org?rev=29842&view=rev
Log:
Initial upload

Added:
    erp5/trunk/products/ERP5/mixin/
    erp5/trunk/products/ERP5/mixin/cached_convertable.py

Added: erp5/trunk/products/ERP5/mixin/cached_convertable.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/mixin/cached_convertable.py?rev=29842&view=auto
==============================================================================
--- erp5/trunk/products/ERP5/mixin/cached_convertable.py (added)
+++ erp5/trunk/products/ERP5/mixin/cached_convertable.py [utf8] Tue Oct 20 12:34:14 2009
@@ -1,0 +1,169 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp at nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+import md5
+
+from AccessControl import ClassSecurityInfo
+from Products.ERP5Type import Permissions
+
+class CachedConvertableMixin:
+  """
+  This class provides a generic implementation of IConvertable.
+
+    This class provides a generic API to store in the ZODB
+    various converted versions of a file or of a string.
+
+    Versions are stored in dictionaries; the class stores also
+    generation time of every format and its mime-type string.
+    Format can be a string or a tuple (e.g. format, resolution).
+  """
+
+  # Declarative security
+  security = ClassSecurityInfo()
+
+
+  # Declarative security
+  security = ClassSecurityInfo()
+  security.declareObjectProtected(Permissions.AccessContentsInformation)
+
+  def _getCacheFactory(self):
+    """
+    """
+    if self.isTempObject():
+      return
+    cache_tool = getToolByName(self, 'portal_caches')
+    preference_tool = getToolByName(self, 'portal_preferences')
+    cache_factory_name = preference_tool.getPreferredConversionCacheFactory('document_cache_factory')
+    cache_factory = cache_tool.getRamCacheRoot().get(cache_factory_name)
+    #XXX This conditional statement should be remove as soon as
+    #Broadcasting will be enable among all zeo clients.
+    #Interaction which update portal_caches should interact with all nodes.
+    if cache_factory is None and getattr(cache_tool, cache_factory_name, None) is not None:
+      #ram_cache_root is not up to date for current node
+      cache_tool.updateCache()
+    return cache_tool.getRamCacheRoot().get(cache_factory_name)
+
+  security.declareProtected(Permissions.ModifyPortalContent, 'clearConversionCache')
+  def clearConversionCache(self):
+    """
+    """
+    if self.isTempObject():
+      self.temp_conversion_data = {}
+      return
+    for cache_plugin in self._getCacheFactory().getCachePluginList():
+      cache_plugin.delete(self.getPath(), DEFAULT_CACHE_SCOPE)
+
+  security.declareProtected(Permissions.View, 'hasConversion')
+  def hasConversion(self, **kw):
+    """
+    If you want to get conversion cache value if exists, please write
+    the code like:
+
+      try:
+        mime, data = getConversion(**kw)
+      except KeyError:
+        ...
+
+    instead of:
+
+      if self.hasConversion(**kw):
+        mime, data = self.getConversion(**kw)
+      else:
+        ...
+
+    for better performance.
+    """
+    try:
+      self.getConversion(**kw)
+      return True
+    except KeyError:
+      return False
+
+  security.declareProtected(Permissions.ModifyPortalContent, 'setConversion')
+  def setConversion(self, data, mime=None, calculation_time=None, **kw):
+    """
+    """
+    cache_id = self.generateCacheId(**kw)
+    if self.isTempObject():
+      if getattr(aq_base(self), 'temp_conversion_data', None) is None:
+        self.temp_conversion_data = {}
+      self.temp_conversion_data[cache_id] = (mime, aq_base(data))
+      return
+    cache_factory = self._getCacheFactory()
+    cache_duration = cache_factory.cache_duration
+    if data is not None:
+      for cache_plugin in cache_factory.getCachePluginList():
+        try:
+          cache_entry = cache_plugin.get(self.getPath(), DEFAULT_CACHE_SCOPE)
+          cache_dict = cache_entry.getValue()
+        except KeyError:
+          cache_dict = {}
+        cache_dict.update({cache_id: (self.getContentMd5(), mime, aq_base(data))})
+        cache_plugin.set(self.getPath(), DEFAULT_CACHE_SCOPE,
+                         cache_dict, calculation_time=calculation_time,
+                         cache_duration=cache_duration)
+
+  security.declareProtected(Permissions.View, 'getConversion')
+  def getConversion(self, **kw):
+    """
+    """
+    cache_id = self.generateCacheId(**kw)
+    if self.isTempObject():
+      return getattr(aq_base(self), 'temp_conversion_data', {})[cache_id]
+    for cache_plugin in self._getCacheFactory().getCachePluginList():
+      cache_entry = cache_plugin.get(self.getPath(), DEFAULT_CACHE_SCOPE)
+      data_list = cache_entry.getValue().get(cache_id)
+      if data_list:
+        md5sum, mime, data = data_list
+        if md5sum != self.getContentMd5():
+          raise KeyError, 'Conversion cache key is compromised for %r' % cache_id
+        return mime, data
+    raise KeyError, 'Conversion cache key does not exists for %r' % cache_id
+
+  security.declareProtected(Permissions.View, 'getConversionSize')
+  def getConversionSize(self, **kw):
+    """
+    """
+    try:
+      return len(self.getConversion(**kw))
+    except KeyError:
+      return 0
+
+  def generateCacheId(self, **kw):
+    """Generate proper cache id based on **kw.
+    Function inspired from ERP5Type.Cache
+    """
+    return str(makeSortedTuple(kw)).translate(string.maketrans('', ''), '[]()<>\'", ')
+
+  security.declareProtected(Permissions.ModifyPortalContent, 'updateContentMd5')
+  def updateContentMd5(self):
+    """Update md5 checksum from the original file
+    """
+    data = self.getData()
+    self._setContentMd5(md5.new(data).hexdigest()) #reindex is useless




More information about the Erp5-report mailing list