1 """Generic (shallow and deep) copying operations.
2
3 Interface summary:
4
5 import copy
6
7 x = copy.copy(y) # make a shallow copy of y
8 x = copy.deepcopy(y) # make a deep copy of y
9
10 For module specific errors, copy.Error is raised.
11
12 The difference between shallow and deep copying is only relevant for
13 compound objects (objects that contain other objects, like lists or
14 class instances).
15
16 - A shallow copy constructs a new compound object and then (to the
17 extent possible) inserts *the same objects* into it that the
18 original contains.
19
20 - A deep copy constructs a new compound object and then, recursively,
21 inserts *copies* into it of the objects found in the original.
22
23 Two problems often exist with deep copy operations that don't exist
24 with shallow copy operations:
25
26 a) recursive objects (compound objects that, directly or indirectly,
27 contain a reference to themselves) may cause a recursive loop
28
29 b) because deep copy copies *everything* it may copy too much, e.g.
30 administrative data structures that should be shared even between
31 copies
32
33 Python's deep copy operation avoids these problems by:
34
35 a) keeping a table of objects already copied during the current
36 copying pass
37
38 b) letting user-defined classes override the copying operation or the
39 set of components copied
40
41 This version does not copy types like module, class, function, method,
42 nor stack trace, stack frame, nor file, socket, window, nor array, nor
43 any similar types.
44
45 Classes can use the same interfaces to control copying that they use
46 to control pickling: they can define methods called __getinitargs__(),
47 __getstate__() and __setstate__(). See the documentation for module
48 "pickle" for information on these methods.
49 """
50
51 import types
52 from copy_reg import dispatch_table
53
56 error = Error
57
58 try:
59 from org.python.core import PyStringMap
60 except ImportError:
61 PyStringMap = None
62
63 __all__ = ["Error", "copy", "deepcopy"]
64
65 import inspect
67 for basecls in inspect.getmro(cls):
68 try:
69 return basecls.__dict__[name]
70 except:
71 pass
72 else:
73 return None
74
76 """Shallow copy operation on arbitrary Python objects.
77
78 See the module's __doc__ string for more info.
79 """
80
81 cls = type(x)
82
83 copier = _copy_dispatch.get(cls)
84 if copier:
85 return copier(x)
86
87 copier = _getspecial(cls, "__copy__")
88 if copier:
89 return copier(x)
90
91 reductor = dispatch_table.get(cls)
92 if reductor:
93 rv = reductor(x)
94 else:
95 reductor = getattr(x, "__reduce_ex__", None)
96 if reductor:
97 rv = reductor(2)
98 else:
99 reductor = getattr(x, "__reduce__", None)
100 if reductor:
101 rv = reductor()
102 else:
103 copier = getattr(x, "__copy__", None)
104 if copier:
105 return copier()
106 raise Error("un(shallow)copyable object of type %s" % cls)
107
108 return _reconstruct(x, rv, 0)
109
110
111 _copy_dispatch = d = {}
112
115 for t in (types.NoneType, int, long, float, bool, str, tuple,
116 frozenset, type, xrange, types.ClassType,
117 types.BuiltinFunctionType):
118 d[t] = _copy_immutable
119 for name in ("ComplexType", "UnicodeType", "CodeType"):
120 t = getattr(types, name, None)
121 if t is not None:
122 d[t] = _copy_immutable
123
126 for t in (list, dict, set):
127 d[t] = _copy_with_constructor
128
131 if PyStringMap is not None:
132 d[PyStringMap] = _copy_with_copy_method
133
152 d[types.InstanceType] = _copy_inst
153
154 del d
155
157 """Deep copy operation on arbitrary Python objects.
158
159 See the module's __doc__ string for more info.
160 """
161
162 if memo is None:
163 memo = {}
164
165 d = id(x)
166 y = memo.get(d, _nil)
167 if y is not _nil:
168 return y
169
170 cls = type(x)
171
172 copier = _deepcopy_dispatch.get(cls)
173 if copier:
174 y = copier(x, memo)
175 else:
176 try:
177 issc = issubclass(cls, type)
178 except TypeError:
179 issc = 0
180 if issc:
181 y = _deepcopy_atomic(x, memo)
182 else:
183 copier = _getspecial(cls, "__deepcopy__")
184 if copier:
185 y = copier(x, memo)
186 else:
187 reductor = dispatch_table.get(cls)
188 if reductor:
189 rv = reductor(x)
190 else:
191 reductor = getattr(x, "__reduce_ex__", None)
192 if reductor:
193 rv = reductor(2)
194 else:
195 reductor = getattr(x, "__reduce__", None)
196 if reductor:
197 rv = reductor()
198 else:
199 copier = getattr(x, "__deepcopy__", None)
200 if copier:
201 return copier(memo)
202 raise Error(
203 "un(deep)copyable object of type %s" % cls)
204 y = _reconstruct(x, rv, 1, memo)
205
206 memo[d] = y
207 _keep_alive(x, memo)
208 return y
209
210 _deepcopy_dispatch = d = {}
211
214 d[types.NoneType] = _deepcopy_atomic
215 d[types.IntType] = _deepcopy_atomic
216 d[types.LongType] = _deepcopy_atomic
217 d[types.FloatType] = _deepcopy_atomic
218 d[types.BooleanType] = _deepcopy_atomic
219 try:
220 d[types.ComplexType] = _deepcopy_atomic
221 except AttributeError:
222 pass
223 d[types.StringType] = _deepcopy_atomic
224 try:
225 d[types.UnicodeType] = _deepcopy_atomic
226 except AttributeError:
227 pass
228 try:
229 d[types.CodeType] = _deepcopy_atomic
230 except AttributeError:
231 pass
232 d[types.TypeType] = _deepcopy_atomic
233 d[types.XRangeType] = _deepcopy_atomic
234 d[types.ClassType] = _deepcopy_atomic
235 d[types.BuiltinFunctionType] = _deepcopy_atomic
236
238 y = []
239 memo[id(x)] = y
240 for a in x:
241 y.append(deepcopy(a, memo))
242 return y
243 d[types.ListType] = _deepcopy_list
244
246 y = []
247 for a in x:
248 y.append(deepcopy(a, memo))
249 d = id(x)
250 try:
251 return memo[d]
252 except KeyError:
253 pass
254 for i in range(len(x)):
255 if x[i] is not y[i]:
256 y = tuple(y)
257 break
258 else:
259 y = x
260 memo[d] = y
261 return y
262 d[types.TupleType] = _deepcopy_tuple
263
265 y = {}
266 memo[id(x)] = y
267 for key, value in x.iteritems():
268 y[deepcopy(key, memo)] = deepcopy(value, memo)
269 return y
270 d[types.DictionaryType] = _deepcopy_dict
271 if PyStringMap is not None:
272 d[PyStringMap] = _deepcopy_dict
273
275 """Keeps a reference to the object x in the memo.
276
277 Because we remember objects by their id, we have
278 to assure that possibly temporary objects are kept
279 alive by referencing them.
280 We store a reference at the id of the memo, which should
281 normally not be used unless someone tries to deepcopy
282 the memo itself...
283 """
284 try:
285 memo[id(memo)].append(x)
286 except KeyError:
287
288 memo[id(memo)]=[x]
289
311 d[types.InstanceType] = _deepcopy_inst
312
314 if isinstance(info, str):
315 return x
316 assert isinstance(info, tuple)
317 if memo is None:
318 memo = {}
319 n = len(info)
320 assert n in (2, 3, 4, 5)
321 callable, args = info[:2]
322 if n > 2:
323 state = info[2]
324 else:
325 state = {}
326 if n > 3:
327 listiter = info[3]
328 else:
329 listiter = None
330 if n > 4:
331 dictiter = info[4]
332 else:
333 dictiter = None
334 if deep:
335 args = deepcopy(args, memo)
336 y = callable(*args)
337 memo[id(x)] = y
338 if listiter is not None:
339 for item in listiter:
340 if deep:
341 item = deepcopy(item, memo)
342 y.append(item)
343 if dictiter is not None:
344 for key, value in dictiter:
345 if deep:
346 key = deepcopy(key, memo)
347 value = deepcopy(value, memo)
348 y[key] = value
349 if state:
350 if deep:
351 state = deepcopy(state, memo)
352 if hasattr(y, '__setstate__'):
353 y.__setstate__(state)
354 else:
355 if isinstance(state, tuple) and len(state) == 2:
356 state, slotstate = state
357 else:
358 slotstate = None
359 if state is not None:
360 y.__dict__.update(state)
361 if slotstate is not None:
362 for key, value in slotstate.iteritems():
363 setattr(y, key, value)
364 return y
365
366 del d
367
368 del types
369
370
373
375 l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'],
376 {'abc': 'ABC'}, (), [], {}]
377 l1 = copy(l)
378 print l1==l
379 l1 = map(copy, l)
380 print l1==l
381 l1 = deepcopy(l)
382 print l1==l
383 class C:
384 def __init__(self, arg=None):
385 self.a = 1
386 self.arg = arg
387 if __name__ == '__main__':
388 import sys
389 file = sys.argv[0]
390 else:
391 file = __file__
392 self.fp = open(file)
393 self.fp.close()
394 def __getstate__(self):
395 return {'a': self.a, 'arg': self.arg}
396 def __setstate__(self, state):
397 for key, value in state.iteritems():
398 setattr(self, key, value)
399 def __deepcopy__(self, memo=None):
400 new = self.__class__(deepcopy(self.arg, memo))
401 new.a = self.a
402 return new
403 c = C('argument sketch')
404 l.append(c)
405 l2 = copy(l)
406 print l == l2
407 print l
408 print l2
409 l2 = deepcopy(l)
410 print l == l2
411 print l
412 print l2
413 l.append({l[1]: l, 'xyz': l[2]})
414 l3 = copy(l)
415 import repr
416 print map(repr.repr, l)
417 print map(repr.repr, l1)
418 print map(repr.repr, l2)
419 print map(repr.repr, l3)
420 l3 = deepcopy(l)
421 import repr
422 print map(repr.repr, l)
423 print map(repr.repr, l1)
424 print map(repr.repr, l2)
425 print map(repr.repr, l3)
426
427 if __name__ == '__main__':
428 _test()
429