[Zodb-checkins] CVS: Zope3/lib/python/Persistence - IPersistentModuleManager.py:1.1 IPersistentModuleRegistry.py:1.1 Module.py:1.11

Jeremy Hylton jeremy@zope.com
Thu, 19 Sep 2002 17:37:27 -0400


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

Modified Files:
	Module.py 
Added Files:
	IPersistentModuleManager.py IPersistentModuleRegistry.py 
Log Message:
Refactor persistent modules.

This is a saner interface that decouples module management (creation /
updation) from importing.  There is a base importer, although it is
not clear how useful it is.  The test importer may end up being more
useful for ZODB applications other than Zope, although there are some
bootstrapping issues.

Disable the reload() tests.  They're not working and we're not
interested in finding out why right now.


=== Added File Zope3/lib/python/Persistence/IPersistentModuleManager.py ===
try:
    from Interface import Interface
except ImportError:
    class Interface:
        pass

class IPersistentModuleManager(Interface):

    def new(name, source):
        """Create and register a new named module from source."""

    def update(src):
        """Update the source of the existing module."""

    def remove():
        """Unregister the module and forget about it."""



=== Added File Zope3/lib/python/Persistence/IPersistentModuleRegistry.py ===
try:
    from Interface import Interface
except ImportError:
    class Interface:
        pass

class IPersistentModuleImportRegistry(Interface):

    def findModule(name):
        """Return module registered under name or None."""

class IPersistentModuleUpdateRegistry(IPersistentModuleImportRegistry):

    def setModule(name, module):
        """Register module under name.

        Raises ValueError if module is already registered.
        """

    def delModule(name):
        """Unregister module registered under name.

        Raises KeyError in module is not registered.
        """



=== Zope3/lib/python/Persistence/Module.py 1.10 => 1.11 ===
--- Zope3/lib/python/Persistence/Module.py:1.10	Thu Jul 18 18:41:57 2002
+++ Zope3/lib/python/Persistence/Module.py	Thu Sep 19 17:37:21 2002
@@ -1,6 +1,8 @@
 """Persistent Module."""
 
-import ihooks
+__metaclass__ = type
+
+import __builtin__
 # in 2.3, this will be spelled new.function
 from types import FunctionType as function
 import sys
@@ -9,6 +11,9 @@
 from Persistence.Class import PersistentMetaClass
 from Persistence.Function import PersistentFunction
 from Persistence.BTrees.OOBTree import OOBTree
+from Persistence.IPersistentModuleManager import IPersistentModuleManager
+from Persistence.IPersistentModuleRegistry \
+     import IPersistentModuleImportRegistry, IPersistentModuleUpdateRegistry 
 
 from Transaction import get_transaction
 
@@ -47,73 +52,45 @@
         state["__builtins__"] = __builtin__
         self.__dict__.update(state)
 
-class PersistentModuleLoader(ihooks.BasicModuleLoader):
+__persistent_module_registry__ = "__persistent_module_registry__"
 
-    __super_init = ihooks._Verbose.__init__
-    __super_find_module = ihooks.BasicModuleLoader.find_module
-    __super_load_module = ihooks.BasicModuleLoader.load_module
-
-    def __init__(self, modules, verbose=0):
-        self.__super_init(verbose)
-        self.modules = modules
-
-    def find_module(self, name, path=None):
-        if path is None:
-            mod = self.modules.get(name)
-            if mod is not None:
-                return mod
-        return self.__super_find_module(name, path)
+class PersistentModuleManager(Persistent):
 
-    def load_module(self, name, stuff):
-        if isinstance(stuff, PersistentModule):
-            assert stuff.__name__ == name, (stuff, stuff.__name__, name)
-            return stuff
-        return self.__super_load_module(name, stuff)
-
-    def modules_dict(self):
-        return sys.modules
-
-class PersistentModuleImporter(ihooks.ModuleImporter):
-
-    __super_init = ihooks.ModuleImporter.__init__
-
-    def __init__(self, root, name="modules", verbose=None):
-        # setup storage for module objects and source in root
-        self._root = root
-        self._name = name
-        pair = self._root.get(name, None)
-        if pair is None:
-            modules = OOBTree()
-            sources = OOBTree()
-            self._root[name] = modules, sources
-            get_transaction().commit()
-        else:
-            modules, sources = pair
-        self._modules = modules
-        self._sources = sources
-
-        self.__super_init(PersistentModuleLoader(self._modules), verbose)
-
-    def module_from_file(self, name, path):
-        assert not self.modules.has_key(name)
-        f = open(path)
-        src = f.read()
-        f.close()
-        self.module_from_source(name, src)
-
-    def module_from_source(self, name, source):
-        mod = PersistentModule(name)
-        self._modules[name] = mod
-        self.update_module(name, source)
-
-    def update_module(self, name, source):
-        self._sources[name] = source
-        m = self._modules[name]
-        copy = m.__dict__.copy()
-        exec source in m.__dict__
-        self.fixup(m.__dict__, copy, m)
+    __implements__ = (IPersistentModuleManager,
+                      IPersistentModuleUpdateRegistry)
 
-    def fixup(self, new, old, module):
+    def __init__(self, registry):
+        self._registry = registry
+        self._module = None
+
+    def findModule(self, name):
+        return self._registry.findModule(name)
+
+    def new(self, name, source):
+        if self._module is not None:
+            raise ValueError, "module already exists"
+        self._module = PersistentModule(name)
+        try:
+            self._registry.setModule(name, self._module)
+        except ValueError:
+            self._module = None
+            raise
+        self.update(source)
+
+    def update(self, source):
+        moddict = self._module.__dict__
+        copy = moddict.copy()
+        moddict[__persistent_module_registry__] = self
+        exec source in moddict
+        del moddict[__persistent_module_registry__]
+        self._fixup(moddict, copy, self._module)
+        self._module._p_changed = True
+
+    def remove(self, source):
+        self._registry.delModule(self._module.__name__)
+        self._module = None
+    
+    def _fixup(self, new, old, module):
         # Update persistent objects in place, and
         # convert new functions to persistent functions
         # XXX should convert classes, too
@@ -134,3 +111,45 @@
                     state = v.__getstate__()
                     old_v.__setstate__(state)
                     new[k] = old_v
+
+class PersistentModuleImporter:
+
+    def __init__(self):
+        self._saved_import = None
+
+    def install(self):
+        self._saved_import = __builtin__.__import__
+        __builtin__.__import__ = self.__import__
+
+    def uninstall(self):
+        __builtin__.__import__ = self._saved_import
+
+    def __import__(self, name, globals={}, locals={}, fromlist=[]):
+        registry = globals.get(__persistent_module_registry__)
+        if registry is not None:
+            mod = registry.findModule(name)
+            if mod is not None:
+                # XXX package support needed here
+                return mod
+        return self._saved_import(name, globals, locals, fromlist)
+
+class PersistentModuleRegistry(Persistent):
+
+    __implements__ = (IPersistentModuleImportRegistry,
+                      IPersistentModuleUpdateRegistry)
+
+    def __init__(self):
+        self._dict = {}
+
+    def findModule(self, name):
+        return self._dict.get(name)
+
+    def setModule(self, name, module):
+        if name in self._dict:
+            raise ValueError, name
+        self._p_changed = True
+        self._dict[name] = module
+
+    def delModule(self, name):
+        self._p_changed = True
+        del self._dict[name]