[Zodb-checkins] CVS: ZODB3/ZODB - ConflictResolution.py:1.21.8.1

Jim Fulton jim at zope.com
Fri Jan 23 15:44:53 EST 2004


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv1405/src/ZODB

Modified Files:
      Tag: zope3-zodb3-devel-branch
	ConflictResolution.py 
Log Message:
Updated to reflect the new serialization format.


=== ZODB3/ZODB/ConflictResolution.py 1.21 => 1.21.8.1 ===
--- ZODB3/ZODB/ConflictResolution.py:1.21	Fri Nov 28 11:44:49 2003
+++ ZODB3/ZODB/ConflictResolution.py	Fri Jan 23 15:44:22 2004
@@ -19,25 +19,39 @@
 from ZODB.POSException import ConflictError
 import zLOG
 
-bad_classes = {}
-
-def bad_class(class_tuple):
-    if bad_classes.has_key(class_tuple) or class_tuple[0][0] == '*':
-        # if we've seen the class before or if it's a ZClass, we know that
-        # we can't resolve the conflict
-        return 1
-
 ResolvedSerial = 'rs'
 
-def _classFactory(location, name,
-                  _silly=('__doc__',), _globals={}):
-    return getattr(__import__(location, _globals, _globals, _silly),
-                   name)
+class BadClassName(Exception):
+    pass
+
+_class_cache = {}
+_class_cache_get = _class_cache.get
+def find_global(*args):
+    cls = _class_cache_get(args, 0)
+    if cls == 0:
+        # Not cached. Try to import
+        try:
+            module = __import__(args[0], {}, {}, ['cluck'])
+        except ImportError:
+            cls = 1
+        else:
+            cls = getattr(module, args[1], 1)
+        _class_cache[args] = cls
+
+        if cls == 1:
+            zLOG.LOG("Conflict Resolution", zLOG.BLATHER,
+                     "Unable to load class", error=sys.exc_info())
+
+    if cls == 1:
+        # Not importable
+        raise BadClassName(*args)
+    return cls
 
 def state(self, oid, serial, prfactory, p=''):
     p = p or self.loadSerial(oid, serial)
     file = StringIO(p)
     unpickler = Unpickler(file)
+    unpickler.find_global = find_global
     unpickler.persistent_load = prfactory.persistent_load
     unpickler.load() # skip the class tuple
     return unpickler.load()
@@ -70,17 +84,8 @@
     if getattr(object, '__class__', 0) is not PersistentReference:
         return None
     return object.data
-
-def load_class(class_tuple):
-    try:
-        klass = _classFactory(class_tuple[0], class_tuple[1])
-    except (ImportError, AttributeError):
-        zLOG.LOG("Conflict Resolution", zLOG.BLATHER,
-                 "Unable to load class", error=sys.exc_info())
-        bad_classes[class_tuple] = 1
-        return None
-    return klass
-
+    
+_unresolvable = {}
 def tryToResolveConflict(self, oid, committedSerial, oldSerial, newpickle,
                          committedData=''):
     # class_tuple, old, committed, newstate = ('',''), 0, 0, 0
@@ -88,21 +93,28 @@
         prfactory = PersistentReferenceFactory()
         file = StringIO(newpickle)
         unpickler = Unpickler(file)
+        unpickler.find_global = find_global
         unpickler.persistent_load = prfactory.persistent_load
         meta = unpickler.load()
-        class_tuple = meta[0]
-        if bad_class(class_tuple):
+        if isinstance(meta, tuple):
+            klass = meta[0]
+            newargs = meta[1] or ()
+            if isinstance(klass, tuple):
+                klass = find_global(*klass)
+        else:
+            klass = meta
+            newargs = ()
+            
+        if klass in _unresolvable:
             return None
+
         newstate = unpickler.load()
-        klass = load_class(class_tuple)
-        if klass is None:
-            return None
-        inst = klass.__new__(klass)
+        inst = klass.__new__(klass, *newargs)
 
         try:
             resolve = inst._p_resolveConflict
         except AttributeError:
-            bad_classes[class_tuple] = 1
+            _unresolvable[klass] = 1
             return None
 
         old = state(self, oid, oldSerial, prfactory)
@@ -116,7 +128,7 @@
         pickler.dump(meta)
         pickler.dump(resolved)
         return file.getvalue(1)
-    except ConflictError:
+    except (ConflictError, BadClassName):
         return None
     except:
         # If anything else went wrong, catch it here and avoid passing an




More information about the Zodb-checkins mailing list