interface handling should be done here tls-sprint
authorsylvain.thenault@logilab.fr
Tue, 17 Feb 2009 16:43:33 +0100
branchtls-sprint
changeset 666 8ad9885ea45a
parent 665 1305da1ce3f9
child 667 15fe1d3694d1
interface handling should be done here
cwvreg.py
--- a/cwvreg.py	Tue Feb 17 16:42:58 2009 +0100
+++ b/cwvreg.py	Tue Feb 17 16:43:33 2009 +0100
@@ -48,8 +48,10 @@
     def reset(self):
         self._registries = {}
         self._lastmodifs = {}
-        # two special registries, propertydefs which care all the property definitions, and
-        # propertyvals which contains values for those properties
+        self._needs_iface = {}
+        # two special registries, propertydefs which care all the property
+        # definitions, and propertyvals which contains values for those
+        # properties
         self._registries['propertydefs'] = {}
         self._registries['propertyvalues'] = self.eprop_values = {}
         for key, propdef in self.config.eproperty_definitions():
@@ -73,42 +75,42 @@
             for objects in regcontent.values():
                 for obj in objects:
                     obj.schema = schema
+
+    def register_if_interface_found(self, obj, ifaces, **kwargs):
+        """register an object but remove it if no entity class implements one of
+        the given interfaces
+        """
+        if not isinstance(ifaces,  (tuple, list)):
+            self._needs_iface[obj] = frozenset((ifaces,))
+        else:
+            self._needs_iface[obj] = frozenset(ifaces)
+        self.register(obj, **kwargs)
+
+    def register(self, obj, **kwargs):
+        super(CubicWebRegistry, self).register(obj, **kwargs)
+        # XXX bw compat
+        ifaces = getattr(obj, 'accepts_interfaces', None)
+        if ifaces:
+            self._needs_iface[obj] = frozenset(ifaces)
         
     def register_objects(self, path, force_reload=None):
-        """overriden to handle type class cache issue"""
-        if  super(CubicWebRegistry, self).register_objects(path, force_reload):
+        """overriden to remove objects requiring a missing interface"""
+        if super(CubicWebRegistry, self).register_objects(path, force_reload):
             # clear etype cache if you don't want to run into deep weirdness
             clear_cache(self, 'etype_class')
+            # we may want to keep interface dependent objects (e.g.for i18n
+            # catalog generation)
+            if not self.config.cleanup_interface_sobjects:
+                return
             # remove vobjects that don't support any available interface
             interfaces = set()
             for classes in self.get('etypes', {}).values():
                 for cls in classes:
                     interfaces.update(cls.__implements__)
-            if not self.config.cleanup_interface_sobjects:
-                return
-            for registry, regcontent in self._registries.items():
-                if registry in ('propertydefs', 'propertyvalues', 'etypes'):
-                    continue
-                for oid, objects in regcontent.items():
-                    for obj in reversed(objects[:]):
-                        if not obj in objects:
-                            continue # obj has been kicked by a previous one
-                        accepted = set(getattr(obj, 'accepts_interfaces', ()))
-                        if accepted:
-                            for accepted_iface in accepted:
-                                for found_iface in interfaces:
-                                    if issubclass(found_iface, accepted_iface):
-                                        # consider priority if necessary
-                                        if hasattr(obj.__registerer__, 'remove_all_equivalents'):
-                                            registerer = obj.__registerer__(self, obj)
-                                            registerer.remove_all_equivalents(objects)
-                                        break
-                                else:
-                                    self.debug('kicking vobject %s (unsupported interface)', obj)
-                                    objects.remove(obj)
-                    # if objects is empty, remove oid from registry
-                    if not objects:
-                        del regcontent[oid]
+            for obj, ifaces in self._needs_iface.items():
+                if not ifaces & interfaces:
+                    self.debug('kicking vobject %s (unsupported interface)', obj)
+                    self.unregister(obj)
 
     def eid_rset(self, cursor, eid, etype=None):
         """return a result set for the given eid without doing actual query