@@ -107,32 +107,35 @@ def __deepcopy__(self, memo):
107
107
# we need to override __deepcopy__ for both Component and
108
108
# ComponentData.
109
109
#
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
120
113
tmp = self .parent_block ()
121
- tmpId = id (tmp )
122
114
# Note: normally we would need to check that tmp does not
123
115
# end up being None. However, since clone() inserts
124
116
# 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 ) )
127
119
tmp = tmp .parent_block ()
128
- tmpId = id (tmp )
120
+ _in_scope = _scope [ id (tmp )]
129
121
130
122
# Remember whether all newly-encountered blocks are in or
131
123
# 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 :
136
139
# component is out-of-scope. shallow copy only
137
140
memo [id (self )] = self
138
141
return self
@@ -258,7 +261,7 @@ def _create_objects_for_deepcopy(self, memo, component_list):
258
261
def _deepcopy_field (self , memo , slot_name , value ):
259
262
saved_memo = len (memo )
260
263
try :
261
- return deepcopy (value , memo )
264
+ return fast_deepcopy (value , memo )
262
265
except CloneError :
263
266
raise
264
267
except :
0 commit comments