[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 21 Jan 2011 11:48:19 +0100
branchstable
changeset 6864 ea95004494a2
parent 6863 2e52db5cdbde
child 6865 89ecbae8f9be
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
entities/adapters.py
view.py
web/views/calendar.py
web/views/editcontroller.py
web/views/embedding.py
web/views/igeocodable.py
web/views/isioc.py
web/views/navigation.py
web/views/old_calendar.py
web/views/xmlrss.py
--- a/entities/adapters.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/entities/adapters.py	Fri Jan 21 11:48:19 2011 +0100
@@ -68,6 +68,7 @@
 
 
 class INotifiableAdapter(EntityAdapter):
+    __needs_bw_compat__ = True
     __regid__ = 'INotifiable'
     __select__ = is_instance('Any')
 
@@ -157,6 +158,7 @@
 
 class IDownloadableAdapter(EntityAdapter):
     """interface for downloadable entities"""
+    __needs_bw_compat__ = True
     __regid__ = 'IDownloadable'
     __select__ = implements(IDownloadable, warn=False) # XXX for bw compat, else should be abstract
 
@@ -208,6 +210,7 @@
     .. automethod: children_rql
     .. automethod: path
     """
+    __needs_bw_compat__ = True
     __regid__ = 'ITree'
     __select__ = implements(ITree, warn=False) # XXX for bw compat, else should be abstract
 
@@ -335,8 +338,8 @@
             for entity in child.cw_adapt_to('ITree').prefixiter(_done):
                 yield entity
 
+    @implements_adapter_compat('ITree')
     @cached
-    @implements_adapter_compat('ITree')
     def path(self):
         """Returns the list of eids from the root object to this object."""
         path = []
@@ -366,6 +369,7 @@
     You should at least override progress_info an in_progress methods on concret
     implementations.
     """
+    __needs_bw_compat__ = True
     __regid__ = 'IProgress'
     __select__ = implements(IProgress, warn=False) # XXX for bw compat, should be abstract
 
@@ -434,6 +438,7 @@
 
 
 class IMileStoneAdapter(IProgressAdapter):
+    __needs_bw_compat__ = True
     __regid__ = 'IMileStone'
     __select__ = implements(IMileStone, warn=False) # XXX for bw compat, should be abstract
 
--- a/view.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/view.py	Fri Jan 21 11:48:19 2011 +0100
@@ -20,6 +20,7 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
+import types, new
 from cStringIO import StringIO
 from warnings import warn
 
@@ -542,17 +543,6 @@
     __registry__ = 'adapters'
 
 
-class EntityAdapter(Adapter):
-    """base class for entity adapters (eg adapt an entity to an interface)"""
-    def __init__(self, _cw, **kwargs):
-        try:
-            self.entity = kwargs.pop('entity')
-        except KeyError:
-            self.entity = kwargs['rset'].get_entity(kwargs.get('row') or 0,
-                                                    kwargs.get('col') or 0)
-        Adapter.__init__(self, _cw, **kwargs)
-
-
 def implements_adapter_compat(iface):
     def _pre39_compat(func):
         def decorated(self, *args, **kwargs):
@@ -567,5 +557,35 @@
                     return member(*args, **kwargs)
                 return member
             return func(self, *args, **kwargs)
+        decorated.decorated = func
         return decorated
     return _pre39_compat
+
+
+def unwrap_adapter_compat(cls):
+    parent = cls.__bases__[0]
+    for member_name in dir(parent):
+        member = getattr(parent, member_name)
+        if isinstance(member, types.MethodType) and hasattr(member.im_func, 'decorated') and not member_name in cls.__dict__:
+            method = new.instancemethod(member.im_func.decorated, None, cls)
+            setattr(cls, member_name, method)
+
+
+class auto_unwrap_bw_compat(type):
+    def __new__(mcs, name, bases, classdict):
+        cls = type.__new__(mcs, name, bases, classdict)
+        if not classdict.get('__needs_bw_compat__'):
+            unwrap_adapter_compat(cls)
+        return cls
+
+
+class EntityAdapter(Adapter):
+    """base class for entity adapters (eg adapt an entity to an interface)"""
+    __metaclass__ = auto_unwrap_bw_compat
+    def __init__(self, _cw, **kwargs):
+        try:
+            self.entity = kwargs.pop('entity')
+        except KeyError:
+            self.entity = kwargs['rset'].get_entity(kwargs.get('row') or 0,
+                                                    kwargs.get('col') or 0)
+        Adapter.__init__(self, _cw, **kwargs)
--- a/web/views/calendar.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/calendar.py	Fri Jan 21 11:48:19 2011 +0100
@@ -31,6 +31,7 @@
 
 
 class ICalendarableAdapter(EntityAdapter):
+    __needs_bw_compat__ = True
     __regid__ = 'ICalendarable'
     __select__ = implements(ICalendarable, warn=False) # XXX for bw compat, should be abstract
 
--- a/web/views/editcontroller.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/editcontroller.py	Fri Jan 21 11:48:19 2011 +0100
@@ -34,6 +34,7 @@
 
 
 class IEditControlAdapter(EntityAdapter):
+    __needs_bw_compat__ = True
     __regid__ = 'IEditControl'
     __select__ = is_instance('Any')
 
--- a/web/views/embedding.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/embedding.py	Fri Jan 21 11:48:19 2011 +0100
@@ -41,6 +41,7 @@
 
 class IEmbedableAdapter(EntityAdapter):
     """interface for embedable entities"""
+    __needs_bw_compat__ = True
     __regid__ = 'IEmbedable'
     __select__ = implements(IEmbedable, warn=False) # XXX for bw compat, should be abstract
 
--- a/web/views/igeocodable.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/igeocodable.py	Fri Jan 21 11:48:19 2011 +0100
@@ -26,6 +26,7 @@
 
 class IGeocodableAdapter(EntityAdapter):
     """interface required by geocoding views such as gmap-view"""
+    __needs_bw_compat__ = True
     __regid__ = 'IGeocodable'
     __select__ = implements(IGeocodable, warn=False) # XXX for bw compat, should be abstract
 
--- a/web/views/isioc.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/isioc.py	Fri Jan 21 11:48:19 2011 +0100
@@ -32,6 +32,7 @@
 
 class ISIOCItemAdapter(EntityAdapter):
     """interface for entities which may be represented as an ISIOC items"""
+    __needs_bw_compat__ = True
     __regid__ = 'ISIOCItem'
     __select__ = implements(ISiocItem, warn=False) # XXX for bw compat, should be abstract
 
@@ -63,6 +64,7 @@
 
 class ISIOCContainerAdapter(EntityAdapter):
     """interface for entities which may be represented as an ISIOC container"""
+    __needs_bw_compat__ = True
     __regid__ = 'ISIOCContainer'
     __select__ = implements(ISiocContainer, warn=False) # XXX for bw compat, should be abstract
 
--- a/web/views/navigation.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/navigation.py	Fri Jan 21 11:48:19 2011 +0100
@@ -187,6 +187,7 @@
     """interface for entities which can be linked to a previous and/or next
     entity
     """
+    __needs_bw_compat__ = True
     __regid__ = 'IPrevNext'
     __select__ = implements(IPrevNext, warn=False) # XXX for bw compat, else should be abstract
 
--- a/web/views/old_calendar.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/old_calendar.py	Fri Jan 21 11:48:19 2011 +0100
@@ -32,6 +32,7 @@
 
 class ICalendarViewsAdapter(EntityAdapter):
     """calendar views interface"""
+    __needs_bw_compat__ = True
     __regid__ = 'ICalendarViews'
     __select__ = implements(ICalendarViews, warn=False) # XXX for bw compat, should be abstract
 
--- a/web/views/xmlrss.py	Thu Jan 20 17:14:28 2011 +0100
+++ b/web/views/xmlrss.py	Fri Jan 21 11:48:19 2011 +0100
@@ -122,6 +122,7 @@
 # RSS stuff ###################################################################
 
 class IFeedAdapter(EntityAdapter):
+    __needs_bw_compat__ = True
     __regid__ = 'IFeed'
     __select__ = is_instance('Any')