vregistry.py
changeset 2655 48cd71bdb5cd
parent 2650 18aec79ec3a3
parent 2653 51bf32bbe78d
child 2656 a93ae0f6c0ad
--- a/vregistry.py	Mon Aug 03 10:50:57 2009 +0200
+++ b/vregistry.py	Mon Aug 03 10:53:31 2009 +0200
@@ -31,8 +31,15 @@
 from logilab.common.deprecation import deprecated
 
 from cubicweb import CW_SOFTWARE_ROOT, set_log_methods
-from cubicweb import RegistryNotFound, ObjectNotFound, NoSelectableObject
+from cubicweb import (RegistryNotFound, ObjectNotFound, NoSelectableObject,
+                      RegistryOutOfDate)
 
+# XXX depending on cubicweb.web is ugly, we should deal with uicfg
+#     reset with a good old event / callback system
+try:
+    from cubicweb.web import uicfg
+except ImportError: # cubicweb.web not installed
+    uicfg = None
 
 def _toload_info(path, extrapath, _toload=None):
     """return a dictionary of <modname>: <modpath> and an ordered list of
@@ -282,6 +289,8 @@
     def reset(self):
         self.clear()
         self._lastmodifs = {}
+        if uicfg is not None:
+            reload(uicfg)
 
     def __getitem__(self, name):
         """return the registry (dictionary of class objects) associated to
@@ -372,7 +381,6 @@
             vname = obj.__class__.__name__
         self.debug('registered vobject %s in registry %s with id %s',
                    vname, registryname, oid)
-        # automatic reloading management
         self._loadedmods[obj.__module__]['%s.%s' % (obj.__module__, oid)] = obj
 
     def unregister(self, obj, registryname=None):
@@ -386,6 +394,9 @@
     def init_registration(self, path, extrapath=None):
         # compute list of all modules that have to be loaded
         self._toloadmods, filemods = _toload_info(path, extrapath)
+        # XXX is _loadedmods still necessary ? It seems like it's useful
+        #     to avoid loading same module twice, especially with the
+        #     _load_ancestors_then_object logic but this needs to be checked
         self._loadedmods = {}
         return filemods
 
@@ -417,7 +428,7 @@
         return change
 
     def load_file(self, filepath, modname, force_reload=False):
-        """load visual objects from a python file"""
+        """load app objects from a python file"""
         from logilab.common.modutils import load_module_from_name
         if modname in self._loadedmods:
             return
@@ -433,22 +444,12 @@
             # only load file if it was modified
             if modified_on <= self._lastmodifs[filepath]:
                 return
-            # if it was modified, unregister all exisiting objects
-            # from this module, and keep track of what was unregistered
-            unregistered = self.unregister_module_vobjects(modname)
-        else:
-            unregistered = None
+            # if it was modified, raise RegistryOutOfDate to reload everything
+            self.info('File %s changed since last visit', filepath)
+            raise RegistryOutOfDate()
         # load the module
         module = load_module_from_name(modname, use_sys=not force_reload)
         self.load_module(module)
-        # if something was unregistered, we need to update places where it was
-        # referenced
-        if unregistered:
-            # oldnew_mapping = {}
-            registered = self._loadedmods[modname]
-            oldnew_mapping = dict((unregistered[name], registered[name])
-                                  for name in unregistered if name in registered)
-            self.update_registered_subclasses(oldnew_mapping)
         self._lastmodifs[filepath] = modified_on
         return True
 
@@ -510,68 +511,6 @@
             return
         self.register(cls)
 
-    def unregister_module_vobjects(self, modname):
-        """removes registered objects coming from a given module
-
-        returns a dictionnary classid/class of all classes that will need
-        to be updated after reload (i.e. vobjects referencing classes defined
-        in the <modname> module)
-        """
-        unregistered = {}
-        # browse each registered object
-        for registry, objdict in self.items():
-            for oid, objects in objdict.items():
-                for obj in objects[:]:
-                    objname = obj.classid()
-                    # if the vobject is defined in this module, remove it
-                    if objname.startswith(modname):
-                        unregistered[objname] = obj
-                        objects.remove(obj)
-                        self.debug('unregistering %s in %s registry',
-                                  objname, registry)
-                    # if not, check if the vobject can be found in baseclasses
-                    # (because we also want subclasses to be updated)
-                    else:
-                        if not isinstance(obj, type):
-                            obj = obj.__class__
-                        for baseclass in obj.__bases__:
-                            if hasattr(baseclass, 'classid'):
-                                baseclassid = baseclass.classid()
-                                if baseclassid.startswith(modname):
-                                    unregistered[baseclassid] = baseclass
-                # update oid entry
-                if objects:
-                    objdict[oid] = objects
-                else:
-                    del objdict[oid]
-        return unregistered
-
-    def update_registered_subclasses(self, oldnew_mapping):
-        """updates subclasses of re-registered vobjects
-
-        if baseviews.PrimaryView is changed, baseviews.py will be reloaded
-        automatically and the new version of PrimaryView will be registered.
-        But all existing subclasses must also be notified of this change, and
-        that's what this method does
-
-        :param oldnew_mapping: a dict mapping old version of a class to
-                               the new version
-        """
-        # browse each registered object
-        for objdict in self.values():
-            for objects in objdict.values():
-                for obj in objects:
-                    if not isinstance(obj, type):
-                        obj = obj.__class__
-                    # build new baseclasses tuple
-                    newbases = tuple(oldnew_mapping.get(baseclass, baseclass)
-                                     for baseclass in obj.__bases__)
-                    # update obj's baseclasses tuple (__bases__) if needed
-                    if newbases != obj.__bases__:
-                        self.debug('updating %s.%s base classes',
-                                  obj.__module__, obj.__name__)
-                        obj.__bases__ = newbases
-
 # init logging
 set_log_methods(VObject, getLogger('cubicweb.appobject'))
 set_log_methods(VRegistry, getLogger('cubicweb.vreg'))