[Zope3-checkins] CVS: Zope3/src/zodb/code - patch.py:1.8 class_.py:1.11

Jeremy Hylton jeremy@zope.com
Thu, 6 Feb 2003 12:41:21 -0500


Update of /cvs-repository/Zope3/src/zodb/code
In directory cvs.zope.org:/tmp/cvs-serv8006

Modified Files:
	patch.py class_.py 
Log Message:
Chasing 2.3 compatibility.

Classes now have a descriptor for __dict__.  Make sure it does not get
passed to PersistentClassMetaClass when creating a persistent class
from a regular class.

Add a clearer test for a function's module to patch's
save_function().  In 2.3 functions defined in a module but not at the
top-level will return a valid module name instead of __main__.  Write
a new whichmodule() with that in mind that still does the right thing
for 2.2.

[Accidentally checked this in a branch a short while ago.]


=== Zope3/src/zodb/code/patch.py 1.7 => 1.8 ===
--- Zope3/src/zodb/code/patch.py:1.7	Thu Jan 30 13:50:15 2003
+++ Zope3/src/zodb/code/patch.py	Thu Feb  6 12:41:19 2003
@@ -88,6 +88,7 @@
 from copy_reg import dispatch_table
 from cStringIO import StringIO
 import pickle
+import sys
 from types import *
 
 from zodb.code.class_ import PersistentClassMetaClass, PersistentDescriptor
@@ -141,10 +142,37 @@
 
 marker = object()
 
+_module_cache = {}
+
+def whichmodule(func, funcname):
+    """Return a likely candidate for the module that defines obj,
+    where context is the name of the module in which obj was found.
+
+    Use a trick suggested by Guido to make sure we found the right
+    module: Compare the function's globals with the module's globals.
+    You've found the right module only when they match.
+    """
+    mod = getattr(func, "__module__", None)
+    if mod is not None:
+        return mod
+    mod = _module_cache.get(func)
+    if mod is not None:
+        return mod
+    for name, module in sys.modules.items():
+        if module is None:
+            continue # skip dummy package entries
+        if getattr(module, funcname, None) is func:
+            if module.__dict__ is func.func_globals:
+                break
+    else:
+        name = '__main__'
+    _module_cache[func] = name
+    return name
+    
+
 class Pickler(pickle.Pickler):
 
-    dispatch = {}
-    dispatch.update(pickle.Pickler.dispatch)
+    dispatch = pickle.Pickler.dispatch.copy()
 
     def __init__(self, file, module, memo, replacements):
         # The pickler must be created in binary mode, because
@@ -210,7 +238,8 @@
     dispatch[PersistentClassMetaClass] = save_type
 
     def save_function(self, func):
-        if pickle.whichmodule(func, func.__name__) == "__main__":
+        modname = whichmodule(func, func.__name__)
+        if modname == self._module_name or modname == "__main__":
             self.save_reduce(self.wrap(FunctionWrapper, func),
                              (func.func_defaults, func.func_dict))
             memo_len = len(self.memo)


=== Zope3/src/zodb/code/class_.py 1.10 => 1.11 ===
--- Zope3/src/zodb/code/class_.py:1.10	Thu Jan 30 13:50:15 2003
+++ Zope3/src/zodb/code/class_.py	Thu Feb  6 12:41:19 2003
@@ -238,6 +238,8 @@
     # GHOST instead of UPTODATE.  See __getnewargs__().
 
     def __new__(meta, name, bases, dict, state=UPTODATE):
+        if "__dict__" in dict:
+            del dict["__dict__"]
         cls = super(PersistentClassMetaClass, meta).__new__(
             meta, name, bases, dict)
         cls._pc_init = False