@@ -51,7 +51,6 @@ class instances).
5151import types
5252import weakref
5353from copyreg import dispatch_table
54- import builtins
5554
5655class Error (Exception ):
5756 pass
@@ -102,37 +101,33 @@ def copy(x):
102101 else :
103102 raise Error ("un(shallow)copyable object of type %s" % cls )
104103
105- return _reconstruct (x , rv , 0 )
104+ if isinstance (rv , str ):
105+ return x
106+ return _reconstruct (x , None , * rv )
106107
107108
108109_copy_dispatch = d = {}
109110
110111def _copy_immutable (x ):
111112 return x
112- for t in (type (None ), int , float , bool , str , tuple ,
113- bytes , frozenset , type , range ,
114- types .BuiltinFunctionType , type (Ellipsis ),
113+ for t in (type (None ), int , float , bool , complex , str , tuple ,
114+ bytes , frozenset , type , range , slice ,
115+ types .BuiltinFunctionType , type (Ellipsis ), type ( NotImplemented ),
115116 types .FunctionType , weakref .ref ):
116117 d [t ] = _copy_immutable
117118t = getattr (types , "CodeType" , None )
118119if t is not None :
119120 d [t ] = _copy_immutable
120- for name in ("complex" , "unicode" ):
121- t = getattr (builtins , name , None )
122- if t is not None :
123- d [t ] = _copy_immutable
124-
125- def _copy_with_constructor (x ):
126- return type (x )(x )
127- for t in (list , dict , set ):
128- d [t ] = _copy_with_constructor
129-
130- def _copy_with_copy_method (x ):
131- return x .copy ()
121+
122+ d [list ] = list .copy
123+ d [dict ] = dict .copy
124+ d [set ] = set .copy
125+ d [bytearray ] = bytearray .copy
126+
132127if PyStringMap is not None :
133- d [PyStringMap ] = _copy_with_copy_method
128+ d [PyStringMap ] = PyStringMap . copy
134129
135- del d
130+ del d , t
136131
137132def deepcopy (x , memo = None , _nil = []):
138133 """Deep copy operation on arbitrary Python objects.
@@ -179,7 +174,10 @@ def deepcopy(x, memo=None, _nil=[]):
179174 else :
180175 raise Error (
181176 "un(deep)copyable object of type %s" % cls )
182- y = _reconstruct (x , rv , 1 , memo )
177+ if isinstance (rv , str ):
178+ y = x
179+ else :
180+ y = _reconstruct (x , memo , * rv )
183181
184182 # If is its own copy, don't memoize.
185183 if y is not x :
@@ -193,13 +191,11 @@ def _deepcopy_atomic(x, memo):
193191 return x
194192d [type (None )] = _deepcopy_atomic
195193d [type (Ellipsis )] = _deepcopy_atomic
194+ d [type (NotImplemented )] = _deepcopy_atomic
196195d [int ] = _deepcopy_atomic
197196d [float ] = _deepcopy_atomic
198197d [bool ] = _deepcopy_atomic
199- try :
200- d [complex ] = _deepcopy_atomic
201- except NameError :
202- pass
198+ d [complex ] = _deepcopy_atomic
203199d [bytes ] = _deepcopy_atomic
204200d [str ] = _deepcopy_atomic
205201try :
@@ -211,15 +207,16 @@ def _deepcopy_atomic(x, memo):
211207d [types .FunctionType ] = _deepcopy_atomic
212208d [weakref .ref ] = _deepcopy_atomic
213209
214- def _deepcopy_list (x , memo ):
210+ def _deepcopy_list (x , memo , deepcopy = deepcopy ):
215211 y = []
216212 memo [id (x )] = y
213+ append = y .append
217214 for a in x :
218- y . append (deepcopy (a , memo ))
215+ append (deepcopy (a , memo ))
219216 return y
220217d [list ] = _deepcopy_list
221218
222- def _deepcopy_tuple (x , memo ):
219+ def _deepcopy_tuple (x , memo , deepcopy = deepcopy ):
223220 y = [deepcopy (a , memo ) for a in x ]
224221 # We're not going to put the tuple in the memo, but it's still important we
225222 # check for it, in case the tuple contains recursive mutable structures.
@@ -236,7 +233,7 @@ def _deepcopy_tuple(x, memo):
236233 return y
237234d [tuple ] = _deepcopy_tuple
238235
239- def _deepcopy_dict (x , memo ):
236+ def _deepcopy_dict (x , memo , deepcopy = deepcopy ):
240237 y = {}
241238 memo [id (x )] = y
242239 for key , value in x .items ():
@@ -248,7 +245,9 @@ def _deepcopy_dict(x, memo):
248245
249246def _deepcopy_method (x , memo ): # Copy instance methods
250247 return type (x )(x .__func__ , deepcopy (x .__self__ , memo ))
251- _deepcopy_dispatch [types .MethodType ] = _deepcopy_method
248+ d [types .MethodType ] = _deepcopy_method
249+
250+ del d
252251
253252def _keep_alive (x , memo ):
254253 """Keeps a reference to the object x in the memo.
@@ -266,31 +265,15 @@ def _keep_alive(x, memo):
266265 # aha, this is the first one :-)
267266 memo [id (memo )]= [x ]
268267
269- def _reconstruct (x , info , deep , memo = None ):
270- if isinstance (info , str ):
271- return x
272- assert isinstance (info , tuple )
273- if memo is None :
274- memo = {}
275- n = len (info )
276- assert n in (2 , 3 , 4 , 5 )
277- callable , args = info [:2 ]
278- if n > 2 :
279- state = info [2 ]
280- else :
281- state = None
282- if n > 3 :
283- listiter = info [3 ]
284- else :
285- listiter = None
286- if n > 4 :
287- dictiter = info [4 ]
288- else :
289- dictiter = None
268+ def _reconstruct (x , memo , func , args ,
269+ state = None , listiter = None , dictiter = None ,
270+ deepcopy = deepcopy ):
271+ deep = memo is not None
272+ if deep and args :
273+ args = (deepcopy (arg , memo ) for arg in args )
274+ y = func (* args )
290275 if deep :
291- args = deepcopy (args , memo )
292- y = callable (* args )
293- memo [id (x )] = y
276+ memo [id (x )] = y
294277
295278 if state is not None :
296279 if deep :
@@ -309,22 +292,22 @@ def _reconstruct(x, info, deep, memo=None):
309292 setattr (y , key , value )
310293
311294 if listiter is not None :
312- for item in listiter :
313- if deep :
295+ if deep :
296+ for item in listiter :
314297 item = deepcopy (item , memo )
315- y .append (item )
298+ y .append (item )
299+ else :
300+ for item in listiter :
301+ y .append (item )
316302 if dictiter is not None :
317- for key , value in dictiter :
318- if deep :
303+ if deep :
304+ for key , value in dictiter :
319305 key = deepcopy (key , memo )
320306 value = deepcopy (value , memo )
321- y [key ] = value
307+ y [key ] = value
308+ else :
309+ for key , value in dictiter :
310+ y [key ] = value
322311 return y
323312
324- del d
325-
326- del types
327-
328- # Helper for instance creation without calling __init__
329- class _EmptyClass :
330- pass
313+ del types , weakref , PyStringMap
0 commit comments