[Zope-Checkins] CVS: Zope3/lib/python/Persistence - Function.py:1.1 Module.py:1.1
Jeremy Hylton
jeremy@zope.com
Fri, 21 Jun 2002 15:06:48 -0400
Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv9075
Added Files:
Function.py Module.py
Log Message:
Minimally functional persistent modules.
=== Added File Zope3/lib/python/Persistence/Function.py ===
"""Persistent functions."""
import new
import sys
from Persistence import Persistent
def get_code_args(co):
"""Return args from code object suitable for passing to constructor."""
return (co.co_argcount,
co.co_nlocals,
co.co_stacksize,
co.co_flags,
co.co_code,
co.co_consts,
co.co_names,
co.co_varnames,
co.co_filename,
co.co_name,
co.co_firstlineno,
co.co_lnotab,
co.co_freevars,
co.co_cellvars)
class PersistentFunction(Persistent):
def __init__(self, func, module):
self._func = func
self._module = module
self._code = {}
def __call__(self, *args, **kwargs):
return self._func(*args, **kwargs)
def __getstate__(self):
# If func_dict is empty, store None to avoid creating a dict
# unnecessarily when the function is unpickled
# XXX new.function doesn't accept a closure
func_state = self._func.func_defaults, self._func.func_dict or None
# Store the code separately from the function
code = self._func.func_code
# The code object is can only be reused in an interpreter
# running the same version of Python and with the same
# __debug__ value. Store code in a dict keyed by these two values.
# The code object is only valid if the module hasn't been
# changed. If the module is changed, then the code object
# must be reloaded from the module. To detect this change,
# store the serial number of the module.
key = sys.version_info, __debug__
if key not in self._code:
self._code[key] = get_code_args(code), self._module._p_serial
return func_state, self._code, self._module
def __setstate__(self, (func, code, mod)):
self._code = code
self._module = mod
# recreate the code object
code = None
key = sys.version_info, __debug__
co_args, serial = self._code.get(key, (None, None))
if serial is not None:
if serial != mod._p_serial:
del self._code[key]
else:
code = new.code(*co_args)
if code is None:
# XXX get it from the module
assert False, "not implemented"
func_defaults, func_dict = func
func = new.function(code, mod.__dict__, func_defaults)
if func_dict:
func.func_dict.update(func_dict)
self._func = func
=== Added File Zope3/lib/python/Persistence/Module.py ===
"""Persistent Module."""
import ihooks
from new import function
import sys
from Persistence import Persistent
from Persistence.Function import PersistentFunction
from Persistence.BTrees.OOBTree import OOBTree
from Transaction import get_transaction
class PersistentModule(Persistent):
def __init__(self, name):
self.__name__ = name
def __getstate__(self):
d = self.__dict__.copy()
del d["__builtins__"]
return d
def __setstate__(self, state):
import __builtin__
state["__builtins__"] = state
self.__dict__.update(state)
class PersistentModuleLoader(ihooks.BasicModuleLoader):
__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)
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, "rb")
src = f.read()
f.close()
self.module_from_source(name, src)
def module_from_source(self, name, source):
m = self._modules[name] = PersistentModule(name)
self._sources[name] = source
exec source in m.__dict__
self.fixup(m)
def fixup(self, m):
# Converts function objects in module m to persistent functions
# XXX should do classes, too
for k, v in m.__dict__.items():
if isinstance(v, function):
m.__dict__[k] = PersistentFunction(v, m)