pickleutil.py
153 lines
| 4.3 KiB
| text/x-python
|
PythonLexer
MinRK
|
r3539 | # encoding: utf-8 | ||
"""Pickle related utilities. Perhaps this should be called 'can'.""" | ||||
__docformat__ = "restructuredtext en" | ||||
#------------------------------------------------------------------------------- | ||||
# Copyright (C) 2008 The IPython Development Team | ||||
# | ||||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#------------------------------------------------------------------------------- | ||||
#------------------------------------------------------------------------------- | ||||
# Imports | ||||
#------------------------------------------------------------------------------- | ||||
MinRK
|
r3607 | import copy | ||
MinRK
|
r3664 | import sys | ||
from types import FunctionType | ||||
MinRK
|
r3607 | |||
MinRK
|
r3557 | import codeutil | ||
MinRK
|
r3539 | |||
MinRK
|
r3607 | #------------------------------------------------------------------------------- | ||
# Classes | ||||
#------------------------------------------------------------------------------- | ||||
MinRK
|
r3539 | class CannedObject(object): | ||
MinRK
|
r3546 | def __init__(self, obj, keys=[]): | ||
self.keys = keys | ||||
MinRK
|
r3607 | self.obj = copy.copy(obj) | ||
MinRK
|
r3546 | for key in keys: | ||
MinRK
|
r3607 | setattr(self.obj, key, can(getattr(obj, key))) | ||
MinRK
|
r3546 | |||
MinRK
|
r3539 | |||
MinRK
|
r3546 | def getObject(self, g=None): | ||
if g is None: | ||||
g = globals() | ||||
for key in self.keys: | ||||
setattr(self.obj, key, uncan(getattr(self.obj, key), g)) | ||||
return self.obj | ||||
MinRK
|
r3643 | class Reference(CannedObject): | ||
"""object for wrapping a remote reference by name.""" | ||||
def __init__(self, name): | ||||
if not isinstance(name, basestring): | ||||
raise TypeError("illegal name: %r"%name) | ||||
self.name = name | ||||
def __repr__(self): | ||||
return "<Reference: %r>"%self.name | ||||
def getObject(self, g=None): | ||||
if g is None: | ||||
g = globals() | ||||
try: | ||||
return g[self.name] | ||||
except KeyError: | ||||
raise NameError("name %r is not defined"%self.name) | ||||
MinRK
|
r3546 | |||
MinRK
|
r3539 | class CannedFunction(CannedObject): | ||
def __init__(self, f): | ||||
self._checkType(f) | ||||
self.code = f.func_code | ||||
MinRK
|
r3655 | self.defaults = f.func_defaults | ||
MinRK
|
r3664 | self.module = f.__module__ or '__main__' | ||
MinRK
|
r3607 | self.__name__ = f.__name__ | ||
MinRK
|
r3539 | |||
def _checkType(self, obj): | ||||
assert isinstance(obj, FunctionType), "Not a function type" | ||||
MinRK
|
r3643 | def getObject(self, g=None): | ||
MinRK
|
r3664 | # try to load function back into its module: | ||
if not self.module.startswith('__'): | ||||
try: | ||||
__import__(self.module) | ||||
except ImportError: | ||||
pass | ||||
else: | ||||
g = sys.modules[self.module].__dict__ | ||||
MinRK
|
r3539 | if g is None: | ||
g = globals() | ||||
MinRK
|
r3655 | newFunc = FunctionType(self.code, g, self.__name__, self.defaults) | ||
MinRK
|
r3539 | return newFunc | ||
MinRK
|
r3607 | #------------------------------------------------------------------------------- | ||
# Functions | ||||
#------------------------------------------------------------------------------- | ||||
MinRK
|
r3539 | def can(obj): | ||
MinRK
|
r3664 | # import here to prevent module-level circular imports | ||
MinRK
|
r3673 | from IPython.parallel import dependent | ||
MinRK
|
r3643 | if isinstance(obj, dependent): | ||
MinRK
|
r3546 | keys = ('f','df') | ||
return CannedObject(obj, keys=keys) | ||||
MinRK
|
r3643 | elif isinstance(obj, FunctionType): | ||
return CannedFunction(obj) | ||||
MinRK
|
r3539 | elif isinstance(obj,dict): | ||
return canDict(obj) | ||||
elif isinstance(obj, (list,tuple)): | ||||
return canSequence(obj) | ||||
else: | ||||
return obj | ||||
def canDict(obj): | ||||
if isinstance(obj, dict): | ||||
newobj = {} | ||||
for k, v in obj.iteritems(): | ||||
newobj[k] = can(v) | ||||
return newobj | ||||
else: | ||||
return obj | ||||
def canSequence(obj): | ||||
if isinstance(obj, (list, tuple)): | ||||
t = type(obj) | ||||
return t([can(i) for i in obj]) | ||||
else: | ||||
return obj | ||||
def uncan(obj, g=None): | ||||
MinRK
|
r3643 | if isinstance(obj, CannedObject): | ||
MinRK
|
r3546 | return obj.getObject(g) | ||
MinRK
|
r3539 | elif isinstance(obj,dict): | ||
MinRK
|
r3638 | return uncanDict(obj, g) | ||
MinRK
|
r3539 | elif isinstance(obj, (list,tuple)): | ||
MinRK
|
r3638 | return uncanSequence(obj, g) | ||
MinRK
|
r3539 | else: | ||
return obj | ||||
def uncanDict(obj, g=None): | ||||
if isinstance(obj, dict): | ||||
newobj = {} | ||||
for k, v in obj.iteritems(): | ||||
newobj[k] = uncan(v,g) | ||||
return newobj | ||||
else: | ||||
return obj | ||||
def uncanSequence(obj, g=None): | ||||
if isinstance(obj, (list, tuple)): | ||||
t = type(obj) | ||||
return t([uncan(i,g) for i in obj]) | ||||
else: | ||||
return obj | ||||
def rebindFunctionGlobals(f, glbls): | ||||
return FunctionType(f.func_code, glbls) | ||||