Skip to content

Commit db59873

Browse files
committed
0.15.1
1 parent daa53ca commit db59873

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "reloader.py"
3-
version = "0.15.0"
3+
version = "0.15.1"
44
description = "A simple script reloader"
55
license = "MIT"
66
authors = ["EcmaXp <[email protected]>"]

reloader.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from 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

259273
class CodeModule:

0 commit comments

Comments
 (0)