Files
dcalc/PublicReference/utils/copy.py
T
2024-11-04 14:45:20 +08:00

162 lines
3.9 KiB
Python

import types
import weakref
from copyreg import dispatch_table
def copy(x):
cls = type(x)
copier = _copy_dispatch.get(cls)
if copier:
return copier(x)
if issubclass(cls, type):
return _copy_immutable(x)
copier = getattr(cls, "__copy__", None)
if copier is not None:
return copier(x)
reductor = dispatch_table.get(cls)
if reductor is not None:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor is not None:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
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, complex, str, tuple, bytes, frozenset,
type, range, slice, property, 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
d[list] = list.copy
d[dict] = dict.copy
d[set] = set.copy
d[bytearray] = bytearray.copy
def deepcopy(x):
cls = type(x)
copier = _deepcopy_dispatch.get(cls)
if copier is not None:
y = copier(x)
else:
if issubclass(cls, type):
y = _deepcopy_atomic(x)
else:
copier = getattr(x, "__deepcopy__", None)
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor is not None:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
if isinstance(rv, str):
y = x
else:
y = _reconstruct(x, *rv)
return y
_deepcopy_dispatch = d = {}
def _deepcopy_atomic(x):
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
d[complex] = _deepcopy_atomic
d[bytes] = _deepcopy_atomic
d[str] = _deepcopy_atomic
d[types.CodeType] = _deepcopy_atomic
d[type] = _deepcopy_atomic
d[range] = _deepcopy_atomic
d[types.BuiltinFunctionType] = _deepcopy_atomic
d[types.FunctionType] = _deepcopy_atomic
d[weakref.ref] = _deepcopy_atomic
d[property] = _deepcopy_atomic
def _deepcopy_list(x, deepcopy=deepcopy):
y = []
append = y.append
for a in x:
append(deepcopy(a))
return y
d[list] = _deepcopy_list
def _deepcopy_dict(x, deepcopy=deepcopy):
y = {}
for key, value in x.items():
y[deepcopy(key)] = deepcopy(value)
return y
d[dict] = _deepcopy_dict
def _reconstruct(x,
func,
args,
state=None,
listiter=None,
dictiter=None,
deepcopy=deepcopy):
y = func(*args)
if state is not None:
state = deepcopy(state)
if hasattr(y, '__setstate__'):
y.__setstate__(state)
else:
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:
for key, value in slotstate.items():
setattr(y, key, value)
if listiter is not None:
for item in listiter:
item = deepcopy(item)
y.append(item)
if dictiter is not None:
for key, value in dictiter:
key = deepcopy(key)
value = deepcopy(value)
y[key] = value
return y