forked from ipython/ipython
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpickleutil.py
More file actions
153 lines (124 loc) · 4.24 KB
/
Copy pathpickleutil.py
File metadata and controls
153 lines (124 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# encoding: utf-8
"""Pickle related utilities. Perhaps this should be called 'can'."""
__docformat__ = "restructuredtext en"
#-------------------------------------------------------------------------------
# Copyright (C) 2008-2011 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
#-------------------------------------------------------------------------------
import copy
import sys
from types import FunctionType
import codeutil
#-------------------------------------------------------------------------------
# Classes
#-------------------------------------------------------------------------------
class CannedObject(object):
def __init__(self, obj, keys=[]):
self.keys = keys
self.obj = copy.copy(obj)
for key in keys:
setattr(self.obj, key, can(getattr(obj, key)))
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
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)
class CannedFunction(CannedObject):
def __init__(self, f):
self._checkType(f)
self.code = f.func_code
self.defaults = f.func_defaults
self.module = f.__module__ or '__main__'
self.__name__ = f.__name__
def _checkType(self, obj):
assert isinstance(obj, FunctionType), "Not a function type"
def getObject(self, g=None):
# 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__
if g is None:
g = globals()
newFunc = FunctionType(self.code, g, self.__name__, self.defaults)
return newFunc
#-------------------------------------------------------------------------------
# Functions
#-------------------------------------------------------------------------------
def can(obj):
# import here to prevent module-level circular imports
from IPython.parallel import dependent
if isinstance(obj, dependent):
keys = ('f','df')
return CannedObject(obj, keys=keys)
elif isinstance(obj, FunctionType):
return CannedFunction(obj)
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):
if isinstance(obj, CannedObject):
return obj.getObject(g)
elif isinstance(obj,dict):
return uncanDict(obj, g)
elif isinstance(obj, (list,tuple)):
return uncanSequence(obj, g)
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)