1*cda5da8dSAndroid Build Coastguard Worker"""Generic (shallow and deep) copying operations. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerInterface summary: 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Worker import copy 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Worker x = copy.copy(y) # make a shallow copy of y 8*cda5da8dSAndroid Build Coastguard Worker x = copy.deepcopy(y) # make a deep copy of y 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard WorkerFor module specific errors, copy.Error is raised. 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard WorkerThe difference between shallow and deep copying is only relevant for 13*cda5da8dSAndroid Build Coastguard Workercompound objects (objects that contain other objects, like lists or 14*cda5da8dSAndroid Build Coastguard Workerclass instances). 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Worker- A shallow copy constructs a new compound object and then (to the 17*cda5da8dSAndroid Build Coastguard Worker extent possible) inserts *the same objects* into it that the 18*cda5da8dSAndroid Build Coastguard Worker original contains. 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard Worker- A deep copy constructs a new compound object and then, recursively, 21*cda5da8dSAndroid Build Coastguard Worker inserts *copies* into it of the objects found in the original. 22*cda5da8dSAndroid Build Coastguard Worker 23*cda5da8dSAndroid Build Coastguard WorkerTwo problems often exist with deep copy operations that don't exist 24*cda5da8dSAndroid Build Coastguard Workerwith shallow copy operations: 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker a) recursive objects (compound objects that, directly or indirectly, 27*cda5da8dSAndroid Build Coastguard Worker contain a reference to themselves) may cause a recursive loop 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker b) because deep copy copies *everything* it may copy too much, e.g. 30*cda5da8dSAndroid Build Coastguard Worker administrative data structures that should be shared even between 31*cda5da8dSAndroid Build Coastguard Worker copies 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard WorkerPython's deep copy operation avoids these problems by: 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker a) keeping a table of objects already copied during the current 36*cda5da8dSAndroid Build Coastguard Worker copying pass 37*cda5da8dSAndroid Build Coastguard Worker 38*cda5da8dSAndroid Build Coastguard Worker b) letting user-defined classes override the copying operation or the 39*cda5da8dSAndroid Build Coastguard Worker set of components copied 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard WorkerThis version does not copy types like module, class, function, method, 42*cda5da8dSAndroid Build Coastguard Workernor stack trace, stack frame, nor file, socket, window, nor any 43*cda5da8dSAndroid Build Coastguard Workersimilar types. 44*cda5da8dSAndroid Build Coastguard Worker 45*cda5da8dSAndroid Build Coastguard WorkerClasses can use the same interfaces to control copying that they use 46*cda5da8dSAndroid Build Coastguard Workerto control pickling: they can define methods called __getinitargs__(), 47*cda5da8dSAndroid Build Coastguard Worker__getstate__() and __setstate__(). See the documentation for module 48*cda5da8dSAndroid Build Coastguard Worker"pickle" for information on these methods. 49*cda5da8dSAndroid Build Coastguard Worker""" 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Workerimport types 52*cda5da8dSAndroid Build Coastguard Workerimport weakref 53*cda5da8dSAndroid Build Coastguard Workerfrom copyreg import dispatch_table 54*cda5da8dSAndroid Build Coastguard Worker 55*cda5da8dSAndroid Build Coastguard Workerclass Error(Exception): 56*cda5da8dSAndroid Build Coastguard Worker pass 57*cda5da8dSAndroid Build Coastguard Workererror = Error # backward compatibility 58*cda5da8dSAndroid Build Coastguard Worker 59*cda5da8dSAndroid Build Coastguard Workertry: 60*cda5da8dSAndroid Build Coastguard Worker from org.python.core import PyStringMap 61*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 62*cda5da8dSAndroid Build Coastguard Worker PyStringMap = None 63*cda5da8dSAndroid Build Coastguard Worker 64*cda5da8dSAndroid Build Coastguard Worker__all__ = ["Error", "copy", "deepcopy"] 65*cda5da8dSAndroid Build Coastguard Worker 66*cda5da8dSAndroid Build Coastguard Workerdef copy(x): 67*cda5da8dSAndroid Build Coastguard Worker """Shallow copy operation on arbitrary Python objects. 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Worker See the module's __doc__ string for more info. 70*cda5da8dSAndroid Build Coastguard Worker """ 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Worker cls = type(x) 73*cda5da8dSAndroid Build Coastguard Worker 74*cda5da8dSAndroid Build Coastguard Worker copier = _copy_dispatch.get(cls) 75*cda5da8dSAndroid Build Coastguard Worker if copier: 76*cda5da8dSAndroid Build Coastguard Worker return copier(x) 77*cda5da8dSAndroid Build Coastguard Worker 78*cda5da8dSAndroid Build Coastguard Worker if issubclass(cls, type): 79*cda5da8dSAndroid Build Coastguard Worker # treat it as a regular class: 80*cda5da8dSAndroid Build Coastguard Worker return _copy_immutable(x) 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Worker copier = getattr(cls, "__copy__", None) 83*cda5da8dSAndroid Build Coastguard Worker if copier is not None: 84*cda5da8dSAndroid Build Coastguard Worker return copier(x) 85*cda5da8dSAndroid Build Coastguard Worker 86*cda5da8dSAndroid Build Coastguard Worker reductor = dispatch_table.get(cls) 87*cda5da8dSAndroid Build Coastguard Worker if reductor is not None: 88*cda5da8dSAndroid Build Coastguard Worker rv = reductor(x) 89*cda5da8dSAndroid Build Coastguard Worker else: 90*cda5da8dSAndroid Build Coastguard Worker reductor = getattr(x, "__reduce_ex__", None) 91*cda5da8dSAndroid Build Coastguard Worker if reductor is not None: 92*cda5da8dSAndroid Build Coastguard Worker rv = reductor(4) 93*cda5da8dSAndroid Build Coastguard Worker else: 94*cda5da8dSAndroid Build Coastguard Worker reductor = getattr(x, "__reduce__", None) 95*cda5da8dSAndroid Build Coastguard Worker if reductor: 96*cda5da8dSAndroid Build Coastguard Worker rv = reductor() 97*cda5da8dSAndroid Build Coastguard Worker else: 98*cda5da8dSAndroid Build Coastguard Worker raise Error("un(shallow)copyable object of type %s" % cls) 99*cda5da8dSAndroid Build Coastguard Worker 100*cda5da8dSAndroid Build Coastguard Worker if isinstance(rv, str): 101*cda5da8dSAndroid Build Coastguard Worker return x 102*cda5da8dSAndroid Build Coastguard Worker return _reconstruct(x, None, *rv) 103*cda5da8dSAndroid Build Coastguard Worker 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker_copy_dispatch = d = {} 106*cda5da8dSAndroid Build Coastguard Worker 107*cda5da8dSAndroid Build Coastguard Workerdef _copy_immutable(x): 108*cda5da8dSAndroid Build Coastguard Worker return x 109*cda5da8dSAndroid Build Coastguard Workerfor t in (type(None), int, float, bool, complex, str, tuple, 110*cda5da8dSAndroid Build Coastguard Worker bytes, frozenset, type, range, slice, property, 111*cda5da8dSAndroid Build Coastguard Worker types.BuiltinFunctionType, type(Ellipsis), type(NotImplemented), 112*cda5da8dSAndroid Build Coastguard Worker types.FunctionType, weakref.ref): 113*cda5da8dSAndroid Build Coastguard Worker d[t] = _copy_immutable 114*cda5da8dSAndroid Build Coastguard Workert = getattr(types, "CodeType", None) 115*cda5da8dSAndroid Build Coastguard Workerif t is not None: 116*cda5da8dSAndroid Build Coastguard Worker d[t] = _copy_immutable 117*cda5da8dSAndroid Build Coastguard Worker 118*cda5da8dSAndroid Build Coastguard Workerd[list] = list.copy 119*cda5da8dSAndroid Build Coastguard Workerd[dict] = dict.copy 120*cda5da8dSAndroid Build Coastguard Workerd[set] = set.copy 121*cda5da8dSAndroid Build Coastguard Workerd[bytearray] = bytearray.copy 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Workerif PyStringMap is not None: 124*cda5da8dSAndroid Build Coastguard Worker d[PyStringMap] = PyStringMap.copy 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Workerdel d, t 127*cda5da8dSAndroid Build Coastguard Worker 128*cda5da8dSAndroid Build Coastguard Workerdef deepcopy(x, memo=None, _nil=[]): 129*cda5da8dSAndroid Build Coastguard Worker """Deep copy operation on arbitrary Python objects. 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker See the module's __doc__ string for more info. 132*cda5da8dSAndroid Build Coastguard Worker """ 133*cda5da8dSAndroid Build Coastguard Worker 134*cda5da8dSAndroid Build Coastguard Worker if memo is None: 135*cda5da8dSAndroid Build Coastguard Worker memo = {} 136*cda5da8dSAndroid Build Coastguard Worker 137*cda5da8dSAndroid Build Coastguard Worker d = id(x) 138*cda5da8dSAndroid Build Coastguard Worker y = memo.get(d, _nil) 139*cda5da8dSAndroid Build Coastguard Worker if y is not _nil: 140*cda5da8dSAndroid Build Coastguard Worker return y 141*cda5da8dSAndroid Build Coastguard Worker 142*cda5da8dSAndroid Build Coastguard Worker cls = type(x) 143*cda5da8dSAndroid Build Coastguard Worker 144*cda5da8dSAndroid Build Coastguard Worker copier = _deepcopy_dispatch.get(cls) 145*cda5da8dSAndroid Build Coastguard Worker if copier is not None: 146*cda5da8dSAndroid Build Coastguard Worker y = copier(x, memo) 147*cda5da8dSAndroid Build Coastguard Worker else: 148*cda5da8dSAndroid Build Coastguard Worker if issubclass(cls, type): 149*cda5da8dSAndroid Build Coastguard Worker y = _deepcopy_atomic(x, memo) 150*cda5da8dSAndroid Build Coastguard Worker else: 151*cda5da8dSAndroid Build Coastguard Worker copier = getattr(x, "__deepcopy__", None) 152*cda5da8dSAndroid Build Coastguard Worker if copier is not None: 153*cda5da8dSAndroid Build Coastguard Worker y = copier(memo) 154*cda5da8dSAndroid Build Coastguard Worker else: 155*cda5da8dSAndroid Build Coastguard Worker reductor = dispatch_table.get(cls) 156*cda5da8dSAndroid Build Coastguard Worker if reductor: 157*cda5da8dSAndroid Build Coastguard Worker rv = reductor(x) 158*cda5da8dSAndroid Build Coastguard Worker else: 159*cda5da8dSAndroid Build Coastguard Worker reductor = getattr(x, "__reduce_ex__", None) 160*cda5da8dSAndroid Build Coastguard Worker if reductor is not None: 161*cda5da8dSAndroid Build Coastguard Worker rv = reductor(4) 162*cda5da8dSAndroid Build Coastguard Worker else: 163*cda5da8dSAndroid Build Coastguard Worker reductor = getattr(x, "__reduce__", None) 164*cda5da8dSAndroid Build Coastguard Worker if reductor: 165*cda5da8dSAndroid Build Coastguard Worker rv = reductor() 166*cda5da8dSAndroid Build Coastguard Worker else: 167*cda5da8dSAndroid Build Coastguard Worker raise Error( 168*cda5da8dSAndroid Build Coastguard Worker "un(deep)copyable object of type %s" % cls) 169*cda5da8dSAndroid Build Coastguard Worker if isinstance(rv, str): 170*cda5da8dSAndroid Build Coastguard Worker y = x 171*cda5da8dSAndroid Build Coastguard Worker else: 172*cda5da8dSAndroid Build Coastguard Worker y = _reconstruct(x, memo, *rv) 173*cda5da8dSAndroid Build Coastguard Worker 174*cda5da8dSAndroid Build Coastguard Worker # If is its own copy, don't memoize. 175*cda5da8dSAndroid Build Coastguard Worker if y is not x: 176*cda5da8dSAndroid Build Coastguard Worker memo[d] = y 177*cda5da8dSAndroid Build Coastguard Worker _keep_alive(x, memo) # Make sure x lives at least as long as d 178*cda5da8dSAndroid Build Coastguard Worker return y 179*cda5da8dSAndroid Build Coastguard Worker 180*cda5da8dSAndroid Build Coastguard Worker_deepcopy_dispatch = d = {} 181*cda5da8dSAndroid Build Coastguard Worker 182*cda5da8dSAndroid Build Coastguard Workerdef _deepcopy_atomic(x, memo): 183*cda5da8dSAndroid Build Coastguard Worker return x 184*cda5da8dSAndroid Build Coastguard Workerd[type(None)] = _deepcopy_atomic 185*cda5da8dSAndroid Build Coastguard Workerd[type(Ellipsis)] = _deepcopy_atomic 186*cda5da8dSAndroid Build Coastguard Workerd[type(NotImplemented)] = _deepcopy_atomic 187*cda5da8dSAndroid Build Coastguard Workerd[int] = _deepcopy_atomic 188*cda5da8dSAndroid Build Coastguard Workerd[float] = _deepcopy_atomic 189*cda5da8dSAndroid Build Coastguard Workerd[bool] = _deepcopy_atomic 190*cda5da8dSAndroid Build Coastguard Workerd[complex] = _deepcopy_atomic 191*cda5da8dSAndroid Build Coastguard Workerd[bytes] = _deepcopy_atomic 192*cda5da8dSAndroid Build Coastguard Workerd[str] = _deepcopy_atomic 193*cda5da8dSAndroid Build Coastguard Workerd[types.CodeType] = _deepcopy_atomic 194*cda5da8dSAndroid Build Coastguard Workerd[type] = _deepcopy_atomic 195*cda5da8dSAndroid Build Coastguard Workerd[range] = _deepcopy_atomic 196*cda5da8dSAndroid Build Coastguard Workerd[types.BuiltinFunctionType] = _deepcopy_atomic 197*cda5da8dSAndroid Build Coastguard Workerd[types.FunctionType] = _deepcopy_atomic 198*cda5da8dSAndroid Build Coastguard Workerd[weakref.ref] = _deepcopy_atomic 199*cda5da8dSAndroid Build Coastguard Workerd[property] = _deepcopy_atomic 200*cda5da8dSAndroid Build Coastguard Worker 201*cda5da8dSAndroid Build Coastguard Workerdef _deepcopy_list(x, memo, deepcopy=deepcopy): 202*cda5da8dSAndroid Build Coastguard Worker y = [] 203*cda5da8dSAndroid Build Coastguard Worker memo[id(x)] = y 204*cda5da8dSAndroid Build Coastguard Worker append = y.append 205*cda5da8dSAndroid Build Coastguard Worker for a in x: 206*cda5da8dSAndroid Build Coastguard Worker append(deepcopy(a, memo)) 207*cda5da8dSAndroid Build Coastguard Worker return y 208*cda5da8dSAndroid Build Coastguard Workerd[list] = _deepcopy_list 209*cda5da8dSAndroid Build Coastguard Worker 210*cda5da8dSAndroid Build Coastguard Workerdef _deepcopy_tuple(x, memo, deepcopy=deepcopy): 211*cda5da8dSAndroid Build Coastguard Worker y = [deepcopy(a, memo) for a in x] 212*cda5da8dSAndroid Build Coastguard Worker # We're not going to put the tuple in the memo, but it's still important we 213*cda5da8dSAndroid Build Coastguard Worker # check for it, in case the tuple contains recursive mutable structures. 214*cda5da8dSAndroid Build Coastguard Worker try: 215*cda5da8dSAndroid Build Coastguard Worker return memo[id(x)] 216*cda5da8dSAndroid Build Coastguard Worker except KeyError: 217*cda5da8dSAndroid Build Coastguard Worker pass 218*cda5da8dSAndroid Build Coastguard Worker for k, j in zip(x, y): 219*cda5da8dSAndroid Build Coastguard Worker if k is not j: 220*cda5da8dSAndroid Build Coastguard Worker y = tuple(y) 221*cda5da8dSAndroid Build Coastguard Worker break 222*cda5da8dSAndroid Build Coastguard Worker else: 223*cda5da8dSAndroid Build Coastguard Worker y = x 224*cda5da8dSAndroid Build Coastguard Worker return y 225*cda5da8dSAndroid Build Coastguard Workerd[tuple] = _deepcopy_tuple 226*cda5da8dSAndroid Build Coastguard Worker 227*cda5da8dSAndroid Build Coastguard Workerdef _deepcopy_dict(x, memo, deepcopy=deepcopy): 228*cda5da8dSAndroid Build Coastguard Worker y = {} 229*cda5da8dSAndroid Build Coastguard Worker memo[id(x)] = y 230*cda5da8dSAndroid Build Coastguard Worker for key, value in x.items(): 231*cda5da8dSAndroid Build Coastguard Worker y[deepcopy(key, memo)] = deepcopy(value, memo) 232*cda5da8dSAndroid Build Coastguard Worker return y 233*cda5da8dSAndroid Build Coastguard Workerd[dict] = _deepcopy_dict 234*cda5da8dSAndroid Build Coastguard Workerif PyStringMap is not None: 235*cda5da8dSAndroid Build Coastguard Worker d[PyStringMap] = _deepcopy_dict 236*cda5da8dSAndroid Build Coastguard Worker 237*cda5da8dSAndroid Build Coastguard Workerdef _deepcopy_method(x, memo): # Copy instance methods 238*cda5da8dSAndroid Build Coastguard Worker return type(x)(x.__func__, deepcopy(x.__self__, memo)) 239*cda5da8dSAndroid Build Coastguard Workerd[types.MethodType] = _deepcopy_method 240*cda5da8dSAndroid Build Coastguard Worker 241*cda5da8dSAndroid Build Coastguard Workerdel d 242*cda5da8dSAndroid Build Coastguard Worker 243*cda5da8dSAndroid Build Coastguard Workerdef _keep_alive(x, memo): 244*cda5da8dSAndroid Build Coastguard Worker """Keeps a reference to the object x in the memo. 245*cda5da8dSAndroid Build Coastguard Worker 246*cda5da8dSAndroid Build Coastguard Worker Because we remember objects by their id, we have 247*cda5da8dSAndroid Build Coastguard Worker to assure that possibly temporary objects are kept 248*cda5da8dSAndroid Build Coastguard Worker alive by referencing them. 249*cda5da8dSAndroid Build Coastguard Worker We store a reference at the id of the memo, which should 250*cda5da8dSAndroid Build Coastguard Worker normally not be used unless someone tries to deepcopy 251*cda5da8dSAndroid Build Coastguard Worker the memo itself... 252*cda5da8dSAndroid Build Coastguard Worker """ 253*cda5da8dSAndroid Build Coastguard Worker try: 254*cda5da8dSAndroid Build Coastguard Worker memo[id(memo)].append(x) 255*cda5da8dSAndroid Build Coastguard Worker except KeyError: 256*cda5da8dSAndroid Build Coastguard Worker # aha, this is the first one :-) 257*cda5da8dSAndroid Build Coastguard Worker memo[id(memo)]=[x] 258*cda5da8dSAndroid Build Coastguard Worker 259*cda5da8dSAndroid Build Coastguard Workerdef _reconstruct(x, memo, func, args, 260*cda5da8dSAndroid Build Coastguard Worker state=None, listiter=None, dictiter=None, 261*cda5da8dSAndroid Build Coastguard Worker *, deepcopy=deepcopy): 262*cda5da8dSAndroid Build Coastguard Worker deep = memo is not None 263*cda5da8dSAndroid Build Coastguard Worker if deep and args: 264*cda5da8dSAndroid Build Coastguard Worker args = (deepcopy(arg, memo) for arg in args) 265*cda5da8dSAndroid Build Coastguard Worker y = func(*args) 266*cda5da8dSAndroid Build Coastguard Worker if deep: 267*cda5da8dSAndroid Build Coastguard Worker memo[id(x)] = y 268*cda5da8dSAndroid Build Coastguard Worker 269*cda5da8dSAndroid Build Coastguard Worker if state is not None: 270*cda5da8dSAndroid Build Coastguard Worker if deep: 271*cda5da8dSAndroid Build Coastguard Worker state = deepcopy(state, memo) 272*cda5da8dSAndroid Build Coastguard Worker if hasattr(y, '__setstate__'): 273*cda5da8dSAndroid Build Coastguard Worker y.__setstate__(state) 274*cda5da8dSAndroid Build Coastguard Worker else: 275*cda5da8dSAndroid Build Coastguard Worker if isinstance(state, tuple) and len(state) == 2: 276*cda5da8dSAndroid Build Coastguard Worker state, slotstate = state 277*cda5da8dSAndroid Build Coastguard Worker else: 278*cda5da8dSAndroid Build Coastguard Worker slotstate = None 279*cda5da8dSAndroid Build Coastguard Worker if state is not None: 280*cda5da8dSAndroid Build Coastguard Worker y.__dict__.update(state) 281*cda5da8dSAndroid Build Coastguard Worker if slotstate is not None: 282*cda5da8dSAndroid Build Coastguard Worker for key, value in slotstate.items(): 283*cda5da8dSAndroid Build Coastguard Worker setattr(y, key, value) 284*cda5da8dSAndroid Build Coastguard Worker 285*cda5da8dSAndroid Build Coastguard Worker if listiter is not None: 286*cda5da8dSAndroid Build Coastguard Worker if deep: 287*cda5da8dSAndroid Build Coastguard Worker for item in listiter: 288*cda5da8dSAndroid Build Coastguard Worker item = deepcopy(item, memo) 289*cda5da8dSAndroid Build Coastguard Worker y.append(item) 290*cda5da8dSAndroid Build Coastguard Worker else: 291*cda5da8dSAndroid Build Coastguard Worker for item in listiter: 292*cda5da8dSAndroid Build Coastguard Worker y.append(item) 293*cda5da8dSAndroid Build Coastguard Worker if dictiter is not None: 294*cda5da8dSAndroid Build Coastguard Worker if deep: 295*cda5da8dSAndroid Build Coastguard Worker for key, value in dictiter: 296*cda5da8dSAndroid Build Coastguard Worker key = deepcopy(key, memo) 297*cda5da8dSAndroid Build Coastguard Worker value = deepcopy(value, memo) 298*cda5da8dSAndroid Build Coastguard Worker y[key] = value 299*cda5da8dSAndroid Build Coastguard Worker else: 300*cda5da8dSAndroid Build Coastguard Worker for key, value in dictiter: 301*cda5da8dSAndroid Build Coastguard Worker y[key] = value 302*cda5da8dSAndroid Build Coastguard Worker return y 303*cda5da8dSAndroid Build Coastguard Worker 304*cda5da8dSAndroid Build Coastguard Workerdel types, weakref, PyStringMap 305