copy.py (9056B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\copy.py 2 import types 3 import weakref 4 from copy_reg import dispatch_table 5 6 class Error(Exception): 7 pass 8 9 10 error = Error 11 try: 12 from org.python.core import PyStringMap 13 except ImportError: 14 PyStringMap = None 15 16 __all__ = ['Error', 'copy', 'deepcopy'] 17 18 def copy(x): 19 cls = type(x) 20 copier = _copy_dispatch.get(cls) 21 if copier: 22 return copier(x) 23 copier = getattr(cls, '__copy__', None) 24 if copier: 25 return copier(x) 26 reductor = dispatch_table.get(cls) 27 if reductor: 28 rv = reductor(x) 29 else: 30 reductor = getattr(x, '__reduce_ex__', None) 31 if reductor: 32 rv = reductor(2) 33 else: 34 reductor = getattr(x, '__reduce__', None) 35 if reductor: 36 rv = reductor() 37 else: 38 raise Error('un(shallow)copyable object of type %s' % cls) 39 return _reconstruct(x, rv, 0) 40 41 42 _copy_dispatch = d = {} 43 44 def _copy_immutable(x): 45 return x 46 47 48 for t in (type(None), 49 int, 50 long, 51 float, 52 bool, 53 str, 54 tuple, 55 frozenset, 56 type, 57 xrange, 58 types.ClassType, 59 types.BuiltinFunctionType, 60 type(Ellipsis), 61 types.FunctionType, 62 weakref.ref): 63 d[t] = _copy_immutable 64 65 for name in ('ComplexType', 'UnicodeType', 'CodeType'): 66 t = getattr(types, name, None) 67 if t is not None: 68 d[t] = _copy_immutable 69 70 def _copy_with_constructor(x): 71 return type(x)(x) 72 73 74 for t in (list, dict, set): 75 d[t] = _copy_with_constructor 76 77 def _copy_with_copy_method(x): 78 return x.copy() 79 80 81 if PyStringMap is not None: 82 d[PyStringMap] = _copy_with_copy_method 83 84 def _copy_inst(x): 85 if hasattr(x, '__copy__'): 86 return x.__copy__() 87 if hasattr(x, '__getinitargs__'): 88 args = x.__getinitargs__() 89 y = x.__class__(*args) 90 else: 91 y = _EmptyClass() 92 y.__class__ = x.__class__ 93 if hasattr(x, '__getstate__'): 94 state = x.__getstate__() 95 else: 96 state = x.__dict__ 97 if hasattr(y, '__setstate__'): 98 y.__setstate__(state) 99 else: 100 y.__dict__.update(state) 101 return y 102 103 104 d[types.InstanceType] = _copy_inst 105 del d 106 107 def deepcopy(x, memo = None, _nil = []): 108 if memo is None: 109 memo = {} 110 d = id(x) 111 y = memo.get(d, _nil) 112 if y is not _nil: 113 return y 114 cls = type(x) 115 copier = _deepcopy_dispatch.get(cls) 116 if copier: 117 y = copier(x, memo) 118 else: 119 try: 120 issc = issubclass(cls, type) 121 except TypeError: 122 issc = 0 123 124 if issc: 125 y = _deepcopy_atomic(x, memo) 126 else: 127 copier = getattr(x, '__deepcopy__', None) 128 if copier: 129 y = copier(memo) 130 else: 131 reductor = dispatch_table.get(cls) 132 if reductor: 133 rv = reductor(x) 134 else: 135 reductor = getattr(x, '__reduce_ex__', None) 136 if reductor: 137 rv = reductor(2) 138 else: 139 reductor = getattr(x, '__reduce__', None) 140 if reductor: 141 rv = reductor() 142 else: 143 raise Error('un(deep)copyable object of type %s' % cls) 144 y = _reconstruct(x, rv, 1, memo) 145 memo[d] = y 146 _keep_alive(x, memo) 147 return y 148 149 150 _deepcopy_dispatch = d = {} 151 152 def _deepcopy_atomic(x, memo): 153 return x 154 155 156 d[type(None)] = _deepcopy_atomic 157 d[type(Ellipsis)] = _deepcopy_atomic 158 d[int] = _deepcopy_atomic 159 d[long] = _deepcopy_atomic 160 d[float] = _deepcopy_atomic 161 d[bool] = _deepcopy_atomic 162 try: 163 d[complex] = _deepcopy_atomic 164 except NameError: 165 pass 166 167 d[str] = _deepcopy_atomic 168 try: 169 d[unicode] = _deepcopy_atomic 170 except NameError: 171 pass 172 173 try: 174 d[types.CodeType] = _deepcopy_atomic 175 except AttributeError: 176 pass 177 178 d[type] = _deepcopy_atomic 179 d[xrange] = _deepcopy_atomic 180 d[types.ClassType] = _deepcopy_atomic 181 d[types.BuiltinFunctionType] = _deepcopy_atomic 182 d[types.FunctionType] = _deepcopy_atomic 183 d[weakref.ref] = _deepcopy_atomic 184 185 def _deepcopy_list(x, memo): 186 y = [] 187 memo[id(x)] = y 188 for a in x: 189 y.append(deepcopy(a, memo)) 190 191 return y 192 193 194 d[list] = _deepcopy_list 195 196 def _deepcopy_tuple(x, memo): 197 y = [] 198 for a in x: 199 y.append(deepcopy(a, memo)) 200 201 d = id(x) 202 try: 203 return memo[d] 204 except KeyError: 205 pass 206 207 for i in range(len(x)): 208 if x[i] is not y[i]: 209 y = tuple(y) 210 break 211 else: 212 y = x 213 214 memo[d] = y 215 return y 216 217 218 d[tuple] = _deepcopy_tuple 219 220 def _deepcopy_dict(x, memo): 221 y = {} 222 memo[id(x)] = y 223 for key, value in x.iteritems(): 224 y[deepcopy(key, memo)] = deepcopy(value, memo) 225 226 return y 227 228 229 d[dict] = _deepcopy_dict 230 if PyStringMap is not None: 231 d[PyStringMap] = _deepcopy_dict 232 233 def _deepcopy_method(x, memo): 234 return type(x)(x.im_func, deepcopy(x.im_self, memo), x.im_class) 235 236 237 _deepcopy_dispatch[types.MethodType] = _deepcopy_method 238 239 def _keep_alive(x, memo): 240 try: 241 memo[id(memo)].append(x) 242 except KeyError: 243 memo[id(memo)] = [x] 244 245 246 def _deepcopy_inst(x, memo): 247 if hasattr(x, '__deepcopy__'): 248 return x.__deepcopy__(memo) 249 if hasattr(x, '__getinitargs__'): 250 args = x.__getinitargs__() 251 args = deepcopy(args, memo) 252 y = x.__class__(*args) 253 else: 254 y = _EmptyClass() 255 y.__class__ = x.__class__ 256 memo[id(x)] = y 257 if hasattr(x, '__getstate__'): 258 state = x.__getstate__() 259 else: 260 state = x.__dict__ 261 state = deepcopy(state, memo) 262 if hasattr(y, '__setstate__'): 263 y.__setstate__(state) 264 else: 265 y.__dict__.update(state) 266 return y 267 268 269 d[types.InstanceType] = _deepcopy_inst 270 271 def _reconstruct(x, info, deep, memo = None): 272 if isinstance(info, str): 273 return x 274 if memo is None: 275 memo = {} 276 n = len(info) 277 callable, args = info[:2] 278 if n > 2: 279 state = info[2] 280 else: 281 state = {} 282 if n > 3: 283 listiter = info[3] 284 else: 285 listiter = None 286 if n > 4: 287 dictiter = info[4] 288 else: 289 dictiter = None 290 if deep: 291 args = deepcopy(args, memo) 292 y = callable(*args) 293 memo[id(x)] = y 294 if state: 295 if deep: 296 state = deepcopy(state, memo) 297 if hasattr(y, '__setstate__'): 298 y.__setstate__(state) 299 else: 300 if isinstance(state, tuple) and len(state) == 2: 301 state, slotstate = state 302 else: 303 slotstate = None 304 if state is not None: 305 y.__dict__.update(state) 306 if slotstate is not None: 307 for key, value in slotstate.iteritems(): 308 setattr(y, key, value) 309 310 if listiter is not None: 311 for item in listiter: 312 if deep: 313 item = deepcopy(item, memo) 314 y.append(item) 315 316 if dictiter is not None: 317 for key, value in dictiter: 318 if deep: 319 key = deepcopy(key, memo) 320 value = deepcopy(value, memo) 321 y[key] = value 322 323 return y 324 325 326 del d 327 del types 328 329 class _EmptyClass: 330 pass 331 332 333 def _test(): 334 l = [None, 335 1, 336 2L, 337 3.14, 338 'xyzzy', 339 (1, 2L), 340 [3.14, 'abc'], 341 {'abc': 'ABC'}, 342 (), 343 [], 344 {}] 345 l1 = copy(l) 346 print l1 == l 347 l1 = map(copy, l) 348 print l1 == l 349 l1 = deepcopy(l) 350 print l1 == l 351 352 class C: 353 354 def __init__(self, arg = None): 355 self.a = 1 356 self.arg = arg 357 if __name__ == '__main__': 358 import sys 359 file = sys.argv[0] 360 else: 361 file = __file__ 362 self.fp = open(file) 363 self.fp.close() 364 365 def __getstate__(self): 366 return {'a': self.a, 367 'arg': self.arg} 368 369 def __setstate__(self, state): 370 for key, value in state.iteritems(): 371 setattr(self, key, value) 372 373 def __deepcopy__(self, memo = None): 374 new = self.__class__(deepcopy(self.arg, memo)) 375 new.a = self.a 376 return new 377 378 c = C('argument sketch') 379 l.append(c) 380 l2 = copy(l) 381 print l == l2 382 print l 383 print l2 384 l2 = deepcopy(l) 385 print l == l2 386 print l 387 print l2 388 l.append({l[1]: l, 389 'xyz': l[2]}) 390 l3 = copy(l) 391 import repr 392 print map(repr.repr, l) 393 print map(repr.repr, l1) 394 print map(repr.repr, l2) 395 print map(repr.repr, l3) 396 l3 = deepcopy(l) 397 import repr 398 print map(repr.repr, l) 399 print map(repr.repr, l1) 400 print map(repr.repr, l2) 401 print map(repr.repr, l3) 402 403 class odict(dict): 404 405 def __init__(self, d = {}): 406 self.a = 99 407 dict.__init__(self, d) 408 409 def __setitem__(self, k, i): 410 dict.__setitem__(self, k, i) 411 self.a 412 413 o = odict({'A': 'B'}) 414 x = deepcopy(o) 415 print (o, x) 416 417 418 if __name__ == '__main__': 419 _test()