@@ -107,32 +107,35 @@ def __deepcopy__(self, memo):
107107 # we need to override __deepcopy__ for both Component and
108108 # ComponentData.
109109 #
110- # Note: there is an edge case when cloning a block: the initial
111- # call to deepcopy (on the target block) has __block_scope__
112- # defined, however, the parent block of self is either None, or
113- # is (by definition) out of scope. So we will check that
114- # id(self) is not in __block_scope__: if it is, then this is the
115- # top-level block and we need to do the normal deepcopy.
116- if '__block_scope__' in memo and \
117- id (self ) not in memo ['__block_scope__' ]:
118- _known = memo ['__block_scope__' ]
119- _new = []
110+ if '__block_scope__' in memo :
111+ _scope = memo ['__block_scope__' ]
112+ _new = None
120113 tmp = self .parent_block ()
121- tmpId = id (tmp )
122114 # Note: normally we would need to check that tmp does not
123115 # end up being None. However, since clone() inserts
124116 # id(None) into the __block_scope__ dictionary, we are safe
125- while tmpId not in _known :
126- _new . append ( tmpId )
117+ while id ( tmp ) not in _scope :
118+ _new = ( _new , id ( tmp ) )
127119 tmp = tmp .parent_block ()
128- tmpId = id (tmp )
120+ _in_scope = _scope [ id (tmp )]
129121
130122 # Remember whether all newly-encountered blocks are in or
131123 # out of scope (prevent duplicate work)
132- for _id in _new :
133- _known [_id ] = _known [tmpId ]
134-
135- if not _known [tmpId ]:
124+ while _new is not None :
125+ _new , _id = _new
126+ _scope [_id ] = _in_scope
127+
128+ # Note: there is an edge case when cloning a block: the
129+ # initial call to deepcopy (on the target block) has
130+ # __block_scope__ defined, however, the parent block of self
131+ # is either None, or is (by definition) out of scope. So we
132+ # will check that id(self) is not in __block_scope__: if it
133+ # is, then this is the top-level block and we need to do the
134+ # normal deepcopy. We defer this check until now for
135+ # efficiency reasons beause we expect that (for sane models)
136+ # the bulk of the ccomponents we will encounter will be *in*
137+ # scope.
138+ if not _in_scope and id (self ) not in _scope :
136139 # component is out-of-scope. shallow copy only
137140 memo [id (self )] = self
138141 return self
@@ -258,7 +261,7 @@ def _create_objects_for_deepcopy(self, memo, component_list):
258261 def _deepcopy_field (self , memo , slot_name , value ):
259262 saved_memo = len (memo )
260263 try :
261- return deepcopy (value , memo )
264+ return fast_deepcopy (value , memo )
262265 except CloneError :
263266 raise
264267 except :
0 commit comments