@@ -48,10 +48,8 @@ class instances).
4848"pickle" for information on these methods.
4949"""
5050
51- # XXX need to support copy_reg here too...
52-
5351import types
54- from copy_reg import _better_reduce
52+ from copy_reg import _better_reduce , dispatch_table
5553
5654class Error (Exception ):
5755 pass
@@ -70,25 +68,25 @@ def copy(x):
7068 See the module's __doc__ string for more info.
7169 """
7270
73- try :
74- copierfunction = _copy_dispatch [ type ( x )]
75- except KeyError :
76- try :
77- copier = x . __copy__
78- except AttributeError :
79- try :
80- reductor = x . __class__ . __reduce__
81- if reductor == object . __reduce__ :
82- reductor = _better_reduce
83- except AttributeError :
84- raise Error ( "un(shallow)copyable object of type %s" % type ( x ))
85- else :
86- y = _reconstruct ( x , reductor ( x ), 0 )
87- else :
88- y = copier ()
89- else :
90- y = copierfunction ( x )
91- return y
71+ cls = type ( x )
72+
73+ copier = _copy_dispatch . get ( cls )
74+ if copier :
75+ return copier ( x )
76+
77+ copier = getattr ( cls , "__copy__" , None )
78+ if copier :
79+ return copier ( x )
80+
81+ reductor = dispatch_table . get ( cls )
82+ if not reductor :
83+ reductor = getattr ( cls , "__reduce__" , None )
84+ if reductor == object . __reduce__ :
85+ reductor = _better_reduce
86+ elif not reductor :
87+ raise Error ( "un(shallow)copyable object of type %s" % cls )
88+
89+ return _reconstruct ( x , reductor ( x ), 0 )
9290
9391
9492_copy_dispatch = d = {}
@@ -153,43 +151,47 @@ def _copy_inst(x):
153151
154152del d
155153
156- def deepcopy (x , memo = None ):
154+ def deepcopy (x , memo = None , _nil = [] ):
157155 """Deep copy operation on arbitrary Python objects.
158156
159157 See the module's __doc__ string for more info.
160158 """
161159
162160 if memo is None :
163161 memo = {}
162+
164163 d = id (x )
165- if d in memo :
166- return memo [d ]
167- try :
168- copierfunction = _deepcopy_dispatch [type (x )]
169- except KeyError :
164+ y = memo .get (d , _nil )
165+ if y is not _nil :
166+ return y
167+
168+ cls = type (x )
169+
170+ copier = _deepcopy_dispatch .get (cls )
171+ if copier :
172+ y = copier (x , memo )
173+ else :
170174 try :
171- issc = issubclass (type ( x ) , type )
172- except TypeError :
175+ issc = issubclass (cls , type )
176+ except TypeError : # cls is not a class (old Boost; see SF #502085)
173177 issc = 0
174178 if issc :
175- y = _deepcopy_dispatch [ type ]( x , memo )
179+ copier = _deepcopy_atomic
176180 else :
177- try :
178- copier = x .__deepcopy__
179- except AttributeError :
180- try :
181- reductor = x .__class__ .__reduce__
182- if reductor == object .__reduce__ :
183- reductor = _better_reduce
184- except AttributeError :
185- raise Error ("un(shallow)copyable object of type %s" %
186- type (x ))
187- else :
188- y = _reconstruct (x , reductor (x ), 1 , memo )
189- else :
190- y = copier (memo )
191- else :
192- y = copierfunction (x , memo )
181+ copier = getattr (cls , "__deepcopy__" , None )
182+
183+ if copier :
184+ y = copier (x , memo )
185+ else :
186+ reductor = dispatch_table .get (cls )
187+ if not reductor :
188+ reductor = getattr (cls , "__reduce__" , None )
189+ if reductor == object .__reduce__ :
190+ reductor = _better_reduce
191+ elif not reductor :
192+ raise Error ("un(deep)copyable object of type %s" % cls )
193+ y = _reconstruct (x , reductor (x ), 1 , memo )
194+
193195 memo [d ] = y
194196 _keep_alive (x , memo ) # Make sure x lives at least as long as d
195197 return y
@@ -380,7 +382,7 @@ def __getstate__(self):
380382 def __setstate__ (self , state ):
381383 for key , value in state .iteritems ():
382384 setattr (self , key , value )
383- def __deepcopy__ (self , memo = None ):
385+ def __deepcopy__ (self , memo = None ):
384386 new = self .__class__ (deepcopy (self .arg , memo ))
385387 new .a = self .a
386388 return new
0 commit comments