[Zodb-checkins] CVS: Zope3/lib/python/Persistence - Module.py:1.12

Jeremy Hylton jeremy@zope.com
Thu, 19 Sep 2002 18:06:51 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv14339

Modified Files:
	Module.py 
Log Message:
Add partial support for packages.

XXX Still don't handle package relative imports.

Fix __repr__() of PersistentModule to handle subclasses.  

Catch KeyError in __getstate__(): Empty packages don't have code
executed in them, so they don't have an __builtins__.

Add _import() helper to PersistentModuleImport to make test subclasses
easier.


=== Zope3/lib/python/Persistence/Module.py 1.11 => 1.12 ===
--- Zope3/lib/python/Persistence/Module.py:1.11	Thu Sep 19 17:37:21 2002
+++ Zope3/lib/python/Persistence/Module.py	Thu Sep 19 18:06:50 2002
@@ -36,7 +36,7 @@
         self.__name__ = name
 
     def __repr__(self):
-        return "<PersistentModule %s>" % self.__name__
+        return "<%s %s>" % (self.__class__.__name__, self.__name__)
 
     # XXX need getattr &c. hooks to update _p_changed?
     # XXX what about code that modifies __dict__ directly?
@@ -44,7 +44,10 @@
 
     def __getstate__(self):
         d = self.__dict__.copy()
-        del d["__builtins__"]
+        try:
+            del d["__builtins__"]
+        except KeyError:
+            pass
         return d
 
     def __setstate__(self, state):
@@ -52,6 +55,9 @@
         state["__builtins__"] = __builtin__
         self.__dict__.update(state)
 
+class PersistentPackage(PersistentModule):
+    pass
+
 __persistent_module_registry__ = "__persistent_module_registry__"
 
 class PersistentModuleManager(Persistent):
@@ -69,7 +75,14 @@
     def new(self, name, source):
         if self._module is not None:
             raise ValueError, "module already exists"
+        if "." in name:
+            parent = self._package(name)
+        else:
+            parent = None
         self._module = PersistentModule(name)
+        if parent is not None:
+            modname = name.split(".")[-1]
+            setattr(parent, modname, self._module)
         try:
             self._registry.setModule(name, self._module)
         except ValueError:
@@ -112,6 +125,22 @@
                     old_v.__setstate__(state)
                     new[k] = old_v
 
+    def _package(self, name):
+        parts = name.split(".")[:-1]
+        parent = None
+        for i in range(len(parts)):
+            pname = ".".join(parts[:i+1])
+            package = self._registry.findModule(pname)
+            if package is None:
+                package = PersistentPackage(pname)
+                self._registry.setModule(pname, package)
+                if parent is not None:
+                    setattr(parent, parts[i], package)
+            elif not isinstance(package, PersistentPackage):
+                raise ValueError, "%s is module" % pname
+            parent = package
+        return parent
+
 class PersistentModuleImporter:
 
     def __init__(self):
@@ -124,12 +153,25 @@
     def uninstall(self):
         __builtin__.__import__ = self._saved_import
 
+    def _import(self, registry, name, fromlist):
+        mod = registry.findModule(name)
+        if mod is not None:
+            if fromlist:
+                return mod
+            else:
+                i = name.find(".")
+                if i == -1:
+                    return mod
+                top = registry.findModule(name[:i])
+                assert top is not None, "No package for module %s" % name
+                return top
+        return None
+
     def __import__(self, name, globals={}, locals={}, fromlist=[]):
         registry = globals.get(__persistent_module_registry__)
         if registry is not None:
-            mod = registry.findModule(name)
+            mod = self._import(registry, name, fromlist)
             if mod is not None:
-                # XXX package support needed here
                 return mod
         return self._saved_import(name, globals, locals, fromlist)