3434from watchdog .utils .event_debouncer import EventDebouncer
3535
3636__author__ = "EcmaXp"
37- __version__ = "0.15.0 "
37+ __version__ = "0.15.1 "
3838__license__ = "MIT"
3939__url__ = "https://pypi.org/project/reloader.py/"
4040__all__ = [
@@ -182,15 +182,19 @@ def patch(self, module_globals: dict):
182182 try :
183183 yield
184184 finally :
185- self .patch_module (old_globals , module_globals )
185+ self .patch_module (old_globals , module_globals , visited = set () )
186186
187- def patch_module (self , old_globals : dict , new_globals : dict ):
187+ def patch_module (self , old_globals : dict , new_globals : dict , * , visited : set [ int ] ):
188188 for key , new_value in new_globals .items ():
189189 old_value = old_globals .get (key )
190190 if old_value is not new_value :
191- new_globals [key ] = self .patch_object (old_value , new_value )
191+ new_globals [key ] = self .patch_object (
192+ old_value ,
193+ new_value ,
194+ visited = visited ,
195+ )
192196
193- def patch_object (self , old_value : Any , new_value : Any ):
197+ def patch_object (self , old_value : Any , new_value : Any , * , visited : set [ int ] ):
194198 if isinstance (new_value , MemberDescriptorType ):
195199 warnings .warn (
196200 "MemberDescriptor is not supported" ,
@@ -200,9 +204,9 @@ def patch_object(self, old_value: Any, new_value: Any):
200204 elif not self .check_object (old_value , new_value ):
201205 return new_value
202206 elif isinstance (old_value , type ) and isinstance (new_value , type ):
203- return self .patch_class (old_value , new_value )
207+ return self .patch_class (old_value , new_value , visited = visited )
204208 elif callable (old_value ) and callable (new_value ):
205- return self .patch_callable (old_value , new_value )
209+ return self .patch_callable (old_value , new_value , visited = visited )
206210 else :
207211 return new_value
208212
@@ -212,12 +216,14 @@ def check_object(old_value: Any, new_value: Any):
212216 new_module = getattr (new_value , "__module__" , None )
213217 return old_module == new_module
214218
215- def patch_class (self , old_class : type , new_class : type ):
216- self .patch_vars (old_class , new_class )
219+ def patch_class (self , old_class : type , new_class : type , * , visited : set [ int ] ):
220+ self .patch_vars (old_class , new_class , visited = visited )
217221 return old_class
218222
219- def patch_callable (self , old_callable : Callable , new_callable : Callable ):
220- self .patch_vars (old_callable , new_callable )
223+ def patch_callable (
224+ self , old_callable : Callable , new_callable : Callable , * , visited : set [int ]
225+ ):
226+ self .patch_vars (old_callable , new_callable , visited = visited )
221227
222228 old_func = inspect .unwrap (old_callable )
223229 new_func = inspect .unwrap (new_callable )
@@ -246,14 +252,22 @@ def patch_callable(self, old_callable: Callable, new_callable: Callable):
246252
247253 return old_callable
248254
249- def patch_vars (self , old_obj , new_obj ):
255+ def patch_vars (self , old_obj , new_obj , * , visited : set [int ]):
256+ if id (old_obj ) in visited :
257+ return
258+
259+ visited .add (id (old_obj ))
250260 old_vars = vars (old_obj )
251261 for key , new_value in vars (new_obj ).items ():
252262 old_value = old_vars .get (key )
253263 if key == "__dict__" :
254264 continue
255265
256- setattr (old_obj , key , self .patch_object (old_value , new_value ))
266+ setattr (
267+ old_obj ,
268+ key ,
269+ self .patch_object (old_value , new_value , visited = visited ),
270+ )
257271
258272
259273class CodeModule :
0 commit comments