copy.py 8.75 KB
Newer Older
1
"""Generic (shallow and deep) copying operations.
2

3 4
Interface summary:

Tim Peters's avatar
Tim Peters committed
5
        import copy
6

Tim Peters's avatar
Tim Peters committed
7 8
        x = copy.copy(y)        # make a shallow copy of y
        x = copy.deepcopy(y)    # make a deep copy of y
9

10
For module specific errors, copy.Error is raised.
11 12 13 14 15 16

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

- A shallow copy constructs a new compound object and then (to the
17
  extent possible) inserts *the same objects* into it that the
18 19 20 21 22 23 24 25
  original contains.

- A deep copy constructs a new compound object and then, recursively,
  inserts *copies* into it of the objects found in the original.

Two problems often exist with deep copy operations that don't exist
with shallow copy operations:

26
 a) recursive objects (compound objects that, directly or indirectly,
27 28
    contain a reference to themselves) may cause a recursive loop

29
 b) because deep copy copies *everything* it may copy too much, e.g.
30 31 32 33 34
    administrative data structures that should be shared even between
    copies

Python's deep copy operation avoids these problems by:

35 36
 a) keeping a table of objects already copied during the current
    copying pass
37

38
 b) letting user-defined classes override the copying operation or the
39 40 41 42 43 44 45 46
    set of components copied

This version does not copy types like module, class, function, method,
nor stack trace, stack frame, nor file, socket, window, nor array, nor
any similar types.

Classes can use the same interfaces to control copying that they use
to control pickling: they can define methods called __getinitargs__(),
47
__getstate__() and __setstate__().  See the documentation for module
48 49
"pickle" for information on these methods.
"""
50 51

import types
52
import weakref
53
from copyreg import dispatch_table
54
import builtins
55

56
class Error(Exception):
Tim Peters's avatar
Tim Peters committed
57 58
    pass
error = Error   # backward compatibility
59

60 61 62 63 64
try:
    from org.python.core import PyStringMap
except ImportError:
    PyStringMap = None

65
__all__ = ["Error", "copy", "deepcopy"]
66

67
def copy(x):
Tim Peters's avatar
Tim Peters committed
68 69 70 71 72
    """Shallow copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """

73 74 75 76 77 78
    cls = type(x)

    copier = _copy_dispatch.get(cls)
    if copier:
        return copier(x)

79 80 81 82 83 84 85 86
    try:
        issc = issubclass(cls, type)
    except TypeError: # cls is not a class
        issc = False
    if issc:
        # treat it as a regular class:
        return _copy_immutable(x)

87 88 89 90 91
    copier = getattr(cls, "__copy__", None)
    if copier:
        return copier(x)

    reductor = dispatch_table.get(cls)
92 93 94 95 96
    if reductor:
        rv = reductor(x)
    else:
        reductor = getattr(x, "__reduce_ex__", None)
        if reductor:
97
            rv = reductor(4)
98 99 100 101 102 103 104 105
        else:
            reductor = getattr(x, "__reduce__", None)
            if reductor:
                rv = reductor()
            else:
                raise Error("un(shallow)copyable object of type %s" % cls)

    return _reconstruct(x, rv, 0)
Tim Peters's avatar
Tim Peters committed
106

107

108 109
_copy_dispatch = d = {}

110
def _copy_immutable(x):
Tim Peters's avatar
Tim Peters committed
111
    return x
112
for t in (type(None), int, float, bool, str, tuple,
113
          bytes, frozenset, type, range,
Christian Heimes's avatar
Christian Heimes committed
114
          types.BuiltinFunctionType, type(Ellipsis),
115
          types.FunctionType, weakref.ref):
116
    d[t] = _copy_immutable
117 118 119 120
t = getattr(types, "CodeType", None)
if t is not None:
    d[t] = _copy_immutable
for name in ("complex", "unicode"):
121
    t = getattr(builtins, name, None)
122 123 124 125 126 127 128 129 130
    if t is not None:
        d[t] = _copy_immutable

def _copy_with_constructor(x):
    return type(x)(x)
for t in (list, dict, set):
    d[t] = _copy_with_constructor

def _copy_with_copy_method(x):
Tim Peters's avatar
Tim Peters committed
131
    return x.copy()
132
if PyStringMap is not None:
133
    d[PyStringMap] = _copy_with_copy_method
134 135 136

del d

137
def deepcopy(x, memo=None, _nil=[]):
Tim Peters's avatar
Tim Peters committed
138 139 140 141 142 143 144
    """Deep copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """

    if memo is None:
        memo = {}
145

Tim Peters's avatar
Tim Peters committed
146
    d = id(x)
147 148 149 150 151 152 153 154 155 156
    y = memo.get(d, _nil)
    if y is not _nil:
        return y

    cls = type(x)

    copier = _deepcopy_dispatch.get(cls)
    if copier:
        y = copier(x, memo)
    else:
Tim Peters's avatar
Tim Peters committed
157
        try:
158 159
            issc = issubclass(cls, type)
        except TypeError: # cls is not a class (old Boost; see SF #502085)
160 161
            issc = 0
        if issc:
162
            y = _deepcopy_atomic(x, memo)
163
        else:
164 165 166 167 168 169 170 171 172 173
            copier = getattr(x, "__deepcopy__", None)
            if copier:
                y = copier(memo)
            else:
                reductor = dispatch_table.get(cls)
                if reductor:
                    rv = reductor(x)
                else:
                    reductor = getattr(x, "__reduce_ex__", None)
                    if reductor:
174
                        rv = reductor(4)
175 176 177 178 179 180 181 182
                    else:
                        reductor = getattr(x, "__reduce__", None)
                        if reductor:
                            rv = reductor()
                        else:
                            raise Error(
                                "un(deep)copyable object of type %s" % cls)
                y = _reconstruct(x, rv, 1, memo)
183

184 185 186 187
    # If is its own copy, don't memoize.
    if y is not x:
        memo[d] = y
        _keep_alive(x, memo) # Make sure x lives at least as long as d
Tim Peters's avatar
Tim Peters committed
188
    return y
189 190 191 192

_deepcopy_dispatch = d = {}

def _deepcopy_atomic(x, memo):
Tim Peters's avatar
Tim Peters committed
193
    return x
194
d[type(None)] = _deepcopy_atomic
Christian Heimes's avatar
Christian Heimes committed
195
d[type(Ellipsis)] = _deepcopy_atomic
196 197 198
d[int] = _deepcopy_atomic
d[float] = _deepcopy_atomic
d[bool] = _deepcopy_atomic
199
try:
200
    d[complex] = _deepcopy_atomic
201
except NameError:
202
    pass
203
d[bytes] = _deepcopy_atomic
204
d[str] = _deepcopy_atomic
205 206 207 208
try:
    d[types.CodeType] = _deepcopy_atomic
except AttributeError:
    pass
209
d[type] = _deepcopy_atomic
210
d[range] = _deepcopy_atomic
211
d[types.BuiltinFunctionType] = _deepcopy_atomic
Guido van Rossum's avatar
Guido van Rossum committed
212
d[types.FunctionType] = _deepcopy_atomic
213
d[weakref.ref] = _deepcopy_atomic
214 215

def _deepcopy_list(x, memo):
Tim Peters's avatar
Tim Peters committed
216 217 218 219 220
    y = []
    memo[id(x)] = y
    for a in x:
        y.append(deepcopy(a, memo))
    return y
221
d[list] = _deepcopy_list
222 223

def _deepcopy_tuple(x, memo):
224
    y = [deepcopy(a, memo) for a in x]
225 226
    # We're not going to put the tuple in the memo, but it's still important we
    # check for it, in case the tuple contains recursive mutable structures.
Tim Peters's avatar
Tim Peters committed
227
    try:
228
        return memo[id(x)]
Tim Peters's avatar
Tim Peters committed
229 230
    except KeyError:
        pass
231 232
    for k, j in zip(x, y):
        if k is not j:
Tim Peters's avatar
Tim Peters committed
233 234 235 236 237
            y = tuple(y)
            break
    else:
        y = x
    return y
238
d[tuple] = _deepcopy_tuple
239 240

def _deepcopy_dict(x, memo):
Tim Peters's avatar
Tim Peters committed
241 242
    y = {}
    memo[id(x)] = y
243
    for key, value in x.items():
244
        y[deepcopy(key, memo)] = deepcopy(value, memo)
Tim Peters's avatar
Tim Peters committed
245
    return y
246
d[dict] = _deepcopy_dict
247 248
if PyStringMap is not None:
    d[PyStringMap] = _deepcopy_dict
249

250 251 252 253
def _deepcopy_method(x, memo): # Copy instance methods
    return type(x)(x.__func__, deepcopy(x.__self__, memo))
_deepcopy_dispatch[types.MethodType] = _deepcopy_method

254
def _keep_alive(x, memo):
Tim Peters's avatar
Tim Peters committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268
    """Keeps a reference to the object x in the memo.

    Because we remember objects by their id, we have
    to assure that possibly temporary objects are kept
    alive by referencing them.
    We store a reference at the id of the memo, which should
    normally not be used unless someone tries to deepcopy
    the memo itself...
    """
    try:
        memo[id(memo)].append(x)
    except KeyError:
        # aha, this is the first one :-)
        memo[id(memo)]=[x]
269

270
def _reconstruct(x, info, deep, memo=None):
271 272 273
    if isinstance(info, str):
        return x
    assert isinstance(info, tuple)
274 275
    if memo is None:
        memo = {}
276
    n = len(info)
277
    assert n in (2, 3, 4, 5)
278 279 280 281 282
    callable, args = info[:2]
    if n > 2:
        state = info[2]
    else:
        state = {}
283 284 285 286 287 288 289 290
    if n > 3:
        listiter = info[3]
    else:
        listiter = None
    if n > 4:
        dictiter = info[4]
    else:
        dictiter = None
291
    if deep:
292
        args = deepcopy(args, memo)
293
    y = callable(*args)
294
    memo[id(x)] = y
295

296 297
    if state:
        if deep:
298
            state = deepcopy(state, memo)
299 300 301
        if hasattr(y, '__setstate__'):
            y.__setstate__(state)
        else:
302 303 304 305 306 307 308
            if isinstance(state, tuple) and len(state) == 2:
                state, slotstate = state
            else:
                slotstate = None
            if state is not None:
                y.__dict__.update(state)
            if slotstate is not None:
309
                for key, value in slotstate.items():
310
                    setattr(y, key, value)
311 312 313 314 315 316 317 318 319 320 321 322

    if listiter is not None:
        for item in listiter:
            if deep:
                item = deepcopy(item, memo)
            y.append(item)
    if dictiter is not None:
        for key, value in dictiter:
            if deep:
                key = deepcopy(key, memo)
                value = deepcopy(value, memo)
            y[key] = value
323 324
    return y

325 326 327 328
del d

del types

329 330 331
# Helper for instance creation without calling __init__
class _EmptyClass:
    pass