13257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""Generic (shallow and deep) copying operations. 23257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 33257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielInterface summary: 43257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 53257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import copy 63257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 73257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel x = copy.copy(y) # make a shallow copy of y 83257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel x = copy.deepcopy(y) # make a deep copy of y 93257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielFor module specific errors, copy.Error is raised. 113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielThe difference between shallow and deep copying is only relevant for 133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcompound objects (objects that contain other objects, like lists or 143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass instances). 153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel- A shallow copy constructs a new compound object and then (to the 173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel extent possible) inserts *the same objects* into it that the 183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel original contains. 193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel- A deep copy constructs a new compound object and then, recursively, 213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel inserts *copies* into it of the objects found in the original. 223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielTwo problems often exist with deep copy operations that don't exist 243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielwith shallow copy operations: 253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel a) recursive objects (compound objects that, directly or indirectly, 273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel contain a reference to themselves) may cause a recursive loop 283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel b) because deep copy copies *everything* it may copy too much, e.g. 303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel administrative data structures that should be shared even between 313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copies 323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielPython's deep copy operation avoids these problems by: 343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel a) keeping a table of objects already copied during the current 363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copying pass 373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel b) letting user-defined classes override the copying operation or the 393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel set of components copied 403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielThis version does not copy types like module, class, function, method, 423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielnor stack trace, stack frame, nor file, socket, window, nor array, nor 433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielany similar types. 443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielClasses can use the same interfaces to control copying that they use 463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielto control pickling: they can define methods called __getinitargs__(), 473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__getstate__() and __setstate__(). See the documentation for module 483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"pickle" for information on these methods. 493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel""" 503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport types 523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport weakref 533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfrom copy_reg import dispatch_table 543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass Error(Exception): 563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielerror = Error # backward compatibility 583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltry: 603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel from org.python.core import PyStringMap 613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexcept ImportError: 623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel PyStringMap = None 633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__all__ = ["Error", "copy", "deepcopy"] 653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef copy(x): 673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Shallow copy operation on arbitrary Python objects. 683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel See the module's __doc__ string for more info. 703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel cls = type(x) 733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copier = _copy_dispatch.get(cls) 753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if copier: 763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return copier(x) 773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copier = getattr(cls, "__copy__", None) 793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if copier: 803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return copier(x) 813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = dispatch_table.get(cls) 833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor(x) 853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = getattr(x, "__reduce_ex__", None) 873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor(2) 893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = getattr(x, "__reduce__", None) 913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor() 933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise Error("un(shallow)copyable object of type %s" % cls) 953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return _reconstruct(x, rv, 0) 973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_copy_dispatch = d = {} 1003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _copy_immutable(x): 1023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x 1033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfor t in (type(None), int, long, float, bool, str, tuple, 1043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel frozenset, type, xrange, types.ClassType, 1053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel types.BuiltinFunctionType, type(Ellipsis), 1063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel types.FunctionType, weakref.ref): 1073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[t] = _copy_immutable 1083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfor name in ("ComplexType", "UnicodeType", "CodeType"): 1093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel t = getattr(types, name, None) 1103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if t is not None: 1113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[t] = _copy_immutable 1123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _copy_with_constructor(x): 1143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return type(x)(x) 1153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfor t in (list, dict, set): 1163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[t] = _copy_with_constructor 1173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _copy_with_copy_method(x): 1193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x.copy() 1203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif PyStringMap is not None: 1213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[PyStringMap] = _copy_with_copy_method 1223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _copy_inst(x): 1243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__copy__'): 1253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x.__copy__() 1263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__getinitargs__'): 1273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel args = x.__getinitargs__() 1283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = x.__class__(*args) 1293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = _EmptyClass() 1313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__class__ = x.__class__ 1323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__getstate__'): 1333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = x.__getstate__() 1343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = x.__dict__ 1363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(y, '__setstate__'): 1373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__setstate__(state) 1383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__dict__.update(state) 1403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 1413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[types.InstanceType] = _copy_inst 1423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldel d 1443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef deepcopy(x, memo=None, _nil=[]): 1463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Deep copy operation on arbitrary Python objects. 1473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel See the module's __doc__ string for more info. 1493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 1503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if memo is None: 1523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo = {} 1533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d = id(x) 1553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = memo.get(d, _nil) 1563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if y is not _nil: 1573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 1583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel cls = type(x) 1603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copier = _deepcopy_dispatch.get(cls) 1623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if copier: 1633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = copier(x, memo) 1643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 1663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel issc = issubclass(cls, type) 1673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except TypeError: # cls is not a class (old Boost; see SF #502085) 1683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel issc = 0 1693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if issc: 1703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = _deepcopy_atomic(x, memo) 1713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel copier = getattr(x, "__deepcopy__", None) 1733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if copier: 1743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = copier(memo) 1753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = dispatch_table.get(cls) 1773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 1783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor(x) 1793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = getattr(x, "__reduce_ex__", None) 1813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 1823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor(2) 1833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel reductor = getattr(x, "__reduce__", None) 1853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if reductor: 1863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel rv = reductor() 1873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel raise Error( 1893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel "un(deep)copyable object of type %s" % cls) 1903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = _reconstruct(x, rv, 1, memo) 1913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[d] = y 1933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel _keep_alive(x, memo) # Make sure x lives at least as long as d 1943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 1953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_deepcopy_dispatch = d = {} 1973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_atomic(x, memo): 1993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x 2003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[type(None)] = _deepcopy_atomic 2013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[type(Ellipsis)] = _deepcopy_atomic 2023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[int] = _deepcopy_atomic 2033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[long] = _deepcopy_atomic 2043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[float] = _deepcopy_atomic 2053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[bool] = _deepcopy_atomic 2063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltry: 2073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[complex] = _deepcopy_atomic 2083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexcept NameError: 2093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 2103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[str] = _deepcopy_atomic 2113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltry: 2123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[unicode] = _deepcopy_atomic 2133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexcept NameError: 2143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 2153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltry: 2163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[types.CodeType] = _deepcopy_atomic 2173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexcept AttributeError: 2183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 2193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[type] = _deepcopy_atomic 2203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[xrange] = _deepcopy_atomic 2213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[types.ClassType] = _deepcopy_atomic 2223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[types.BuiltinFunctionType] = _deepcopy_atomic 2233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[types.FunctionType] = _deepcopy_atomic 2243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[weakref.ref] = _deepcopy_atomic 2253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_list(x, memo): 2273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = [] 2283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(x)] = y 2293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for a in x: 2303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.append(deepcopy(a, memo)) 2313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 2323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[list] = _deepcopy_list 2333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_tuple(x, memo): 2353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = [] 2363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for a in x: 2373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.append(deepcopy(a, memo)) 2383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d = id(x) 2393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return memo[d] 2413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except KeyError: 2423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 2433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for i in range(len(x)): 2443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if x[i] is not y[i]: 2453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = tuple(y) 2463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel break 2473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = x 2493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[d] = y 2503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 2513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[tuple] = _deepcopy_tuple 2523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_dict(x, memo): 2543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = {} 2553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(x)] = y 2563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for key, value in x.iteritems(): 2573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y[deepcopy(key, memo)] = deepcopy(value, memo) 2583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 2593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[dict] = _deepcopy_dict 2603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif PyStringMap is not None: 2613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel d[PyStringMap] = _deepcopy_dict 2623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_method(x, memo): # Copy instance methods 2643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return type(x)(x.im_func, deepcopy(x.im_self, memo), x.im_class) 2653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel_deepcopy_dispatch[types.MethodType] = _deepcopy_method 2663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _keep_alive(x, memo): 2683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Keeps a reference to the object x in the memo. 2693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Because we remember objects by their id, we have 2713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel to assure that possibly temporary objects are kept 2723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel alive by referencing them. 2733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel We store a reference at the id of the memo, which should 2743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel normally not be used unless someone tries to deepcopy 2753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel the memo itself... 2763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 2773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel try: 2783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(memo)].append(x) 2793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel except KeyError: 2803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # aha, this is the first one :-) 2813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(memo)]=[x] 2823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _deepcopy_inst(x, memo): 2843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__deepcopy__'): 2853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x.__deepcopy__(memo) 2863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__getinitargs__'): 2873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel args = x.__getinitargs__() 2883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel args = deepcopy(args, memo) 2893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = x.__class__(*args) 2903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = _EmptyClass() 2923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__class__ = x.__class__ 2933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(x)] = y 2943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(x, '__getstate__'): 2953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = x.__getstate__() 2963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = x.__dict__ 2983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = deepcopy(state, memo) 2993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(y, '__setstate__'): 3003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__setstate__(state) 3013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__dict__.update(state) 3033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 3043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanield[types.InstanceType] = _deepcopy_inst 3053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _reconstruct(x, info, deep, memo=None): 3073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if isinstance(info, str): 3083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return x 3093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel assert isinstance(info, tuple) 3103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if memo is None: 3113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo = {} 3123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel n = len(info) 3133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel assert n in (2, 3, 4, 5) 3143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel callable, args = info[:2] 3153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if n > 2: 3163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = info[2] 3173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = {} 3193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if n > 3: 3203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel listiter = info[3] 3213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel listiter = None 3233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if n > 4: 3243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel dictiter = info[4] 3253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel dictiter = None 3273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if deep: 3283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel args = deepcopy(args, memo) 3293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y = callable(*args) 3303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel memo[id(x)] = y 3313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if state: 3333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if deep: 3343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state = deepcopy(state, memo) 3353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if hasattr(y, '__setstate__'): 3363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__setstate__(state) 3373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if isinstance(state, tuple) and len(state) == 2: 3393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel state, slotstate = state 3403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel slotstate = None 3423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if state is not None: 3433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.__dict__.update(state) 3443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if slotstate is not None: 3453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for key, value in slotstate.iteritems(): 3463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel setattr(y, key, value) 3473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if listiter is not None: 3493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for item in listiter: 3503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if deep: 3513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel item = deepcopy(item, memo) 3523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y.append(item) 3533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if dictiter is not None: 3543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for key, value in dictiter: 3553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if deep: 3563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel key = deepcopy(key, memo) 3573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel value = deepcopy(value, memo) 3583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel y[key] = value 3593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return y 3603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldel d 3623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldel types 3643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel# Helper for instance creation without calling __init__ 3663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass _EmptyClass: 3673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel pass 3683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef _test(): 3703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l = [None, 1, 2L, 3.14, 'xyzzy', (1, 2L), [3.14, 'abc'], 3713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel {'abc': 'ABC'}, (), [], {}] 3723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l1 = copy(l) 3733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l1==l 3743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l1 = map(copy, l) 3753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l1==l 3763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l1 = deepcopy(l) 3773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l1==l 3783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel class C: 3793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, arg=None): 3803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.a = 1 3813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.arg = arg 3823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if __name__ == '__main__': 3833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import sys 3843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel file = sys.argv[0] 3853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 3863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel file = __file__ 3873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.fp = open(file) 3883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.fp.close() 3893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __getstate__(self): 3903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return {'a': self.a, 'arg': self.arg} 3913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __setstate__(self, state): 3923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for key, value in state.iteritems(): 3933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel setattr(self, key, value) 3943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __deepcopy__(self, memo=None): 3953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel new = self.__class__(deepcopy(self.arg, memo)) 3963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel new.a = self.a 3973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return new 3983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel c = C('argument sketch') 3993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l.append(c) 4003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l2 = copy(l) 4013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l == l2 4023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l 4033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l2 4043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l2 = deepcopy(l) 4053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l == l2 4063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l 4073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print l2 4083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l.append({l[1]: l, 'xyz': l[2]}) 4093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l3 = copy(l) 4103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import repr 4113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l) 4123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l1) 4133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l2) 4143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l3) 4153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel l3 = deepcopy(l) 4163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel import repr 4173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l) 4183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l1) 4193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l2) 4203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print map(repr.repr, l3) 4213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel class odict(dict): 4223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, d = {}): 4233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.a = 99 4243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel dict.__init__(self, d) 4253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __setitem__(self, k, i): 4263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel dict.__setitem__(self, k, i) 4273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.a 4283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel o = odict({"A" : "B"}) 4293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel x = deepcopy(o) 4303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print(o, x) 4313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif __name__ == '__main__': 4333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel _test() 434