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