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