Commit 38780701 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Do not use MethodObject to pass an instance object implicitly any longer,

because this required that the class inherits from ExtensionClass.Base,
and caused troubles due to extra acquisition wrappers.

Tweak the list start more safely.




git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@8073 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 2edacfc4
...@@ -42,11 +42,9 @@ from Products.ERP5Type.Document import newTempBase ...@@ -42,11 +42,9 @@ from Products.ERP5Type.Document import newTempBase
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from copy import copy from copy import copy
from Products.ZSQLCatalog.zsqlbrain import ZSQLBrain from Products.ZSQLCatalog.zsqlbrain import ZSQLBrain
from Products.ERP5Type.Accessor.Accessor import Accessor as Method
from Products.ERP5Type.Message import Message from Products.ERP5Type.Message import Message
from Acquisition import aq_base, aq_inner, aq_parent, aq_self from Acquisition import aq_base, aq_inner, aq_parent, aq_self
import ExtensionClass
from zLOG import LOG, WARNING from zLOG import LOG, WARNING
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
...@@ -473,22 +471,12 @@ class ListBoxWidget(Widget.Widget): ...@@ -473,22 +471,12 @@ class ListBoxWidget(Widget.Widget):
ListBoxWidgetInstance = ListBoxWidget() ListBoxWidgetInstance = ListBoxWidget()
class VolatileCachingMethod(Method): class VolatileCachingMethod:
"""This class caches the result of a callable object, and behaves like a method. """This class caches the result of a callable object, and behaves like a method.
Unlike ERP5Type's CachingMethod, this cache is volatile, namely, the cached Unlike ERP5Type's CachingMethod, this cache is volatile, namely, the cached
data is removed immediately when an object which stores the cached data is deleted. data is removed immediately when an object which stores the cached data is deleted.
Naturally, the object (self) should not be a persistent object. Naturally, the object (self) should not be a persistent object.
""" """
# Some magic to omit an instance argument.
class func_code: pass
func_code = func_code()
func_code.co_varnames = ('self',)
func_code.co_argcount = 1
func_defaults = ()
_need__name__=1
index_html = None
validate = None
def __init__(self, callable_object): def __init__(self, callable_object):
"""Generate the key for the cache. """Generate the key for the cache.
""" """
...@@ -508,7 +496,17 @@ class VolatileCachingMethod(Method): ...@@ -508,7 +496,17 @@ class VolatileCachingMethod(Method):
setattr(instance, self.key, result) setattr(instance, self.key, result)
return result return result
class ListBoxRenderer(ExtensionClass.Base): class InstanceMethod:
"""This class makes it possible to pass an instance object implicitly to a method.
"""
def __init__(self, instance, method):
self.instance = instance
self.method = method
def __call__(self):
return self.method(self.instance)
class ListBoxRenderer:
"""This class deals with rendering of a ListBox field. """This class deals with rendering of a ListBox field.
In ListBox, rendering is not only viewing but also setting parameters in a selection In ListBox, rendering is not only viewing but also setting parameters in a selection
...@@ -522,6 +520,13 @@ class ListBoxRenderer(ExtensionClass.Base): ...@@ -522,6 +520,13 @@ class ListBoxRenderer(ExtensionClass.Base):
self.field = field self.field = field
self.request = REQUEST self.request = REQUEST
# Because it is not easy to pass an instance object implicitly to a method
# with no side effect, tweak VolatileCachingMethod objects here for this instance.
for k in dir(self):
v = getattr(self, k)
if isinstance(v, VolatileCachingMethod):
setattr(self, k, InstanceMethod(self, v))
def getLineClass(self): def getLineClass(self):
"""Return a class object for a line. This must be overridden. """Return a class object for a line. This must be overridden.
""" """
...@@ -539,7 +544,7 @@ class ListBoxRenderer(ExtensionClass.Base): ...@@ -539,7 +544,7 @@ class ListBoxRenderer(ExtensionClass.Base):
def getForm(self): def getForm(self):
"""Return the form which contains the ListBox. """Return the form which contains the ListBox.
""" """
return aq_inner(self.field).aq_parent return self.field.aq_parent
getForm = VolatileCachingMethod(getForm) getForm = VolatileCachingMethod(getForm)
...@@ -1521,7 +1526,7 @@ class ListBoxRenderer(ExtensionClass.Base): ...@@ -1521,7 +1526,7 @@ class ListBoxRenderer(ExtensionClass.Base):
# Tweak the line start. # Tweak the line start.
if start >= object_list_len: if start >= object_list_len:
start = object_list_len - 1 start = max(object_list_len - 1, 0)
start -= (start % max_lines) start -= (start % max_lines)
# Obtain only required objects. # Obtain only required objects.
...@@ -1574,7 +1579,9 @@ class ListBoxRenderer(ExtensionClass.Base): ...@@ -1574,7 +1579,9 @@ class ListBoxRenderer(ExtensionClass.Base):
self.current_page = 0 self.current_page = 0
else: else:
self.total_pages = int(max(self.total_size - 1, 0) / max_lines) + 1 self.total_pages = int(max(self.total_size - 1, 0) / max_lines) + 1
start = min(start, max(0, self.total_pages * max_lines - max_lines)) if start >= self.total_size:
start = max(self.total_size - 1, 0)
start -= (start % max_lines)
self.current_page = int(start / max_lines) self.current_page = int(start / max_lines)
end = min(start + max_lines, self.total_size) end = min(start + max_lines, self.total_size)
param_dict['list_start'] = start param_dict['list_start'] = start
...@@ -1625,7 +1632,7 @@ class ListBoxRenderer(ExtensionClass.Base): ...@@ -1625,7 +1632,7 @@ class ListBoxRenderer(ExtensionClass.Base):
""" """
return self.render(**kw) return self.render(**kw)
class ListBoxRendererLine(ExtensionClass.Base): class ListBoxRendererLine:
"""This class describes a line in a ListBox to assist ListBoxRenderer. """This class describes a line in a ListBox to assist ListBoxRenderer.
""" """
def __init__(self, renderer = None, obj = None, index = 0, is_summary = False, context = None, def __init__(self, renderer = None, obj = None, index = 0, is_summary = False, context = None,
...@@ -1641,6 +1648,13 @@ class ListBoxRendererLine(ExtensionClass.Base): ...@@ -1641,6 +1648,13 @@ class ListBoxRendererLine(ExtensionClass.Base):
self.domain_selection = domain_selection self.domain_selection = domain_selection
self.depth = depth self.depth = depth
# Because it is not easy to pass an instance object implicitly to a method
# with no side effect, tweak VolatileCachingMethod objects here for this instance.
for k in dir(self):
v = getattr(self, k)
if isinstance(v, VolatileCachingMethod):
setattr(self, k, InstanceMethod(self, v))
def getBrain(self): def getBrain(self):
"""Return the brain. This can be identical to a real object. """Return the brain. This can be identical to a real object.
""" """
...@@ -1649,16 +1663,10 @@ class ListBoxRendererLine(ExtensionClass.Base): ...@@ -1649,16 +1663,10 @@ class ListBoxRendererLine(ExtensionClass.Base):
def getObject(self): def getObject(self):
"""Return a real object. """Return a real object.
""" """
portal_object = self.renderer.getPortalObject()
base = aq_base(self.obj)
if base is None:
return None
#LOG('ListBox', 0, 'base = %r' % (base,))
try: try:
return base.__of__(portal_object).getObject() return self.obj.getObject()
except AttributeError: except AttributeError:
return base.__of__(portal_object) return self.obj
getObject = VolatileCachingMethod(getObject) getObject = VolatileCachingMethod(getObject)
...@@ -1760,7 +1768,7 @@ class ListBoxRendererLine(ExtensionClass.Base): ...@@ -1760,7 +1768,7 @@ class ListBoxRendererLine(ExtensionClass.Base):
processed_value = original_value processed_value = original_value
else: else:
# This is an usual line. # This is an usual line.
obj = aq_inner(self.getObject()) obj = self.getObject()
# Use a widget, if any. # Use a widget, if any.
editable_field_id = '%s_%s' % (self.renderer.getId(), alias) editable_field_id = '%s_%s' % (self.renderer.getId(), alias)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment