diff options
Diffstat (limited to 'Lib/copy.py')
-rw-r--r-- | Lib/copy.py | 115 |
1 files changed, 49 insertions, 66 deletions
diff --git a/Lib/copy.py b/Lib/copy.py index 972b94a..f86040a 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -51,7 +51,6 @@ __getstate__() and __setstate__(). See the documentation for module import types import weakref from copyreg import dispatch_table -import builtins class Error(Exception): pass @@ -102,37 +101,33 @@ def copy(x): else: raise Error("un(shallow)copyable object of type %s" % cls) - return _reconstruct(x, rv, 0) + if isinstance(rv, str): + return x + return _reconstruct(x, None, *rv) _copy_dispatch = d = {} def _copy_immutable(x): return x -for t in (type(None), int, float, bool, str, tuple, - bytes, frozenset, type, range, - types.BuiltinFunctionType, type(Ellipsis), +for t in (type(None), int, float, bool, complex, str, tuple, + bytes, frozenset, type, range, slice, + types.BuiltinFunctionType, type(Ellipsis), type(NotImplemented), types.FunctionType, weakref.ref): d[t] = _copy_immutable t = getattr(types, "CodeType", None) if t is not None: d[t] = _copy_immutable -for name in ("complex", "unicode"): - t = getattr(builtins, name, None) - 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): - return x.copy() + +d[list] = list.copy +d[dict] = dict.copy +d[set] = set.copy +d[bytearray] = bytearray.copy + if PyStringMap is not None: - d[PyStringMap] = _copy_with_copy_method + d[PyStringMap] = PyStringMap.copy -del d +del d, t def deepcopy(x, memo=None, _nil=[]): """Deep copy operation on arbitrary Python objects. @@ -179,7 +174,10 @@ def deepcopy(x, memo=None, _nil=[]): else: raise Error( "un(deep)copyable object of type %s" % cls) - y = _reconstruct(x, rv, 1, memo) + if isinstance(rv, str): + y = x + else: + y = _reconstruct(x, memo, *rv) # If is its own copy, don't memoize. if y is not x: @@ -193,13 +191,11 @@ def _deepcopy_atomic(x, memo): return x d[type(None)] = _deepcopy_atomic d[type(Ellipsis)] = _deepcopy_atomic +d[type(NotImplemented)] = _deepcopy_atomic d[int] = _deepcopy_atomic d[float] = _deepcopy_atomic d[bool] = _deepcopy_atomic -try: - d[complex] = _deepcopy_atomic -except NameError: - pass +d[complex] = _deepcopy_atomic d[bytes] = _deepcopy_atomic d[str] = _deepcopy_atomic try: @@ -211,15 +207,16 @@ d[types.BuiltinFunctionType] = _deepcopy_atomic d[types.FunctionType] = _deepcopy_atomic d[weakref.ref] = _deepcopy_atomic -def _deepcopy_list(x, memo): +def _deepcopy_list(x, memo, deepcopy=deepcopy): y = [] memo[id(x)] = y + append = y.append for a in x: - y.append(deepcopy(a, memo)) + append(deepcopy(a, memo)) return y d[list] = _deepcopy_list -def _deepcopy_tuple(x, memo): +def _deepcopy_tuple(x, memo, deepcopy=deepcopy): y = [deepcopy(a, memo) for a in x] # 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. @@ -236,7 +233,7 @@ def _deepcopy_tuple(x, memo): return y d[tuple] = _deepcopy_tuple -def _deepcopy_dict(x, memo): +def _deepcopy_dict(x, memo, deepcopy=deepcopy): y = {} memo[id(x)] = y for key, value in x.items(): @@ -248,7 +245,9 @@ if PyStringMap is not None: def _deepcopy_method(x, memo): # Copy instance methods return type(x)(x.__func__, deepcopy(x.__self__, memo)) -_deepcopy_dispatch[types.MethodType] = _deepcopy_method +d[types.MethodType] = _deepcopy_method + +del d def _keep_alive(x, memo): """Keeps a reference to the object x in the memo. @@ -266,31 +265,15 @@ def _keep_alive(x, memo): # aha, this is the first one :-) memo[id(memo)]=[x] -def _reconstruct(x, info, deep, memo=None): - if isinstance(info, str): - return x - assert isinstance(info, tuple) - if memo is None: - memo = {} - n = len(info) - assert n in (2, 3, 4, 5) - callable, args = info[:2] - if n > 2: - state = info[2] - else: - state = None - if n > 3: - listiter = info[3] - else: - listiter = None - if n > 4: - dictiter = info[4] - else: - dictiter = None +def _reconstruct(x, memo, func, args, + state=None, listiter=None, dictiter=None, + deepcopy=deepcopy): + deep = memo is not None + if deep and args: + args = (deepcopy(arg, memo) for arg in args) + y = func(*args) if deep: - args = deepcopy(args, memo) - y = callable(*args) - memo[id(x)] = y + memo[id(x)] = y if state is not None: if deep: @@ -309,22 +292,22 @@ def _reconstruct(x, info, deep, memo=None): setattr(y, key, value) if listiter is not None: - for item in listiter: - if deep: + if deep: + for item in listiter: item = deepcopy(item, memo) - y.append(item) + y.append(item) + else: + for item in listiter: + y.append(item) if dictiter is not None: - for key, value in dictiter: - if deep: + if deep: + for key, value in dictiter: key = deepcopy(key, memo) value = deepcopy(value, memo) - y[key] = value + y[key] = value + else: + for key, value in dictiter: + y[key] = value return y -del d - -del types - -# Helper for instance creation without calling __init__ -class _EmptyClass: - pass +del types, weakref, PyStringMap |