Module copy
[hide private]
[frames] | no frames]

Source Code for Module copy

  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   
54 -class Error(Exception):
55 pass
56 error = Error # backward compatibility 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
66 -def _getspecial(cls, name):
67 for basecls in inspect.getmro(cls): 68 try: 69 return basecls.__dict__[name] 70 except: 71 pass 72 else: 73 return None
74
75 -def copy(x):
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
113 -def _copy_immutable(x):
114 return x
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
124 -def _copy_with_constructor(x):
125 return type(x)(x)
126 for t in (list, dict, set): 127 d[t] = _copy_with_constructor 128
129 -def _copy_with_copy_method(x):
130 return x.copy()
131 if PyStringMap is not None: 132 d[PyStringMap] = _copy_with_copy_method 133
134 -def _copy_inst(x):
135 if hasattr(x, '__copy__'): 136 return x.__copy__() 137 if hasattr(x, '__getinitargs__'): 138 args = x.__getinitargs__() 139 y = x.__class__(*args) 140 else: 141 y = _EmptyClass() 142 y.__class__ = x.__class__ 143 if hasattr(x, '__getstate__'): 144 state = x.__getstate__() 145 else: 146 state = x.__dict__ 147 if hasattr(y, '__setstate__'): 148 y.__setstate__(state) 149 else: 150 y.__dict__.update(state) 151 return y
152 d[types.InstanceType] = _copy_inst 153 154 del d 155
156 -def deepcopy(x, memo=None, _nil=[]):
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: # cls is not a class (old Boost; see SF #502085) 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) # Make sure x lives at least as long as d 208 return y
209 210 _deepcopy_dispatch = d = {} 211
212 -def _deepcopy_atomic(x, memo):
213 return x
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
237 -def _deepcopy_list(x, memo):
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
245 -def _deepcopy_tuple(x, memo):
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
264 -def _deepcopy_dict(x, memo):
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
274 -def _keep_alive(x, memo):
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 # aha, this is the first one :-) 288 memo[id(memo)]=[x]
289
290 -def _deepcopy_inst(x, memo):
291 if hasattr(x, '__deepcopy__'): 292 return x.__deepcopy__(memo) 293 if hasattr(x, '__getinitargs__'): 294 args = x.__getinitargs__() 295 args = deepcopy(args, memo) 296 y = x.__class__(*args) 297 else: 298 y = _EmptyClass() 299 y.__class__ = x.__class__ 300 memo[id(x)] = y 301 if hasattr(x, '__getstate__'): 302 state = x.__getstate__() 303 else: 304 state = x.__dict__ 305 state = deepcopy(state, memo) 306 if hasattr(y, '__setstate__'): 307 y.__setstate__(state) 308 else: 309 y.__dict__.update(state) 310 return y
311 d[types.InstanceType] = _deepcopy_inst 312
313 -def _reconstruct(x, info, deep, memo=None):
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 # Helper for instance creation without calling __init__
371 -class _EmptyClass:
372 pass
373
374 -def _test():
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