MCPcopy Index your code
hub / github.com/ipython/ipython / DeduperReloader

Class DeduperReloader

IPython/extensions/deduperreload/deduperreload.py:174–640  ·  view source on GitHub ↗

This version of autoreload detects when we can leverage targeted recompilation of a subset of a module and patching existing function/method objects to reflect these changes. Detects what functions/methods can be reloaded by recursively comparing the old/new AST of module-level classes

Source from the content-addressed store, hash-verified

172
173
174class DeduperReloader(DeduperReloaderPatchingMixin):
175 """
176 This version of autoreload detects when we can leverage targeted recompilation of a subset of a module and patching
177 existing function/method objects to reflect these changes.
178
179 Detects what functions/methods can be reloaded by recursively comparing the old/new AST of module-level classes,
180 module-level classes' methods, recursing through nested classes' methods. If other changes are made, original
181 autoreload algorithm is called directly.
182 """
183
184 def __init__(self) -> None:
185 self._to_autoreload: AutoreloadTree = AutoreloadTree()
186 self.source_by_modname: dict[str, str] = {}
187 self.dependency_graph: dict[tuple[str, ...], list[DependencyNode]] = {}
188 self._enabled = True
189
190 @property
191 def enabled(self) -> bool:
192 return self._enabled and platform.python_implementation() == "CPython"
193
194 @enabled.setter
195 def enabled(self, value: bool) -> None:
196 self._enabled = value
197
198 def update_sources(self) -> None:
199 """
200 Update dictionary source_by_modname with current modules' source codes.
201 """
202 if not self.enabled:
203 return
204 for new_modname in sys.modules.keys() - self.source_by_modname.keys():
205 new_module = sys.modules[new_modname]
206 if (
207 (fname := get_module_file_name(new_module)) is None
208 or "site-packages" in fname
209 or "dist-packages" in fname
210 or not os.access(fname, os.R_OK)
211 ):
212 self.source_by_modname[new_modname] = ""
213 continue
214 # Skip binary files (e.g., .so, .pyd, .pyo)
215 if not fname.endswith(".py"):
216 self.source_by_modname[new_modname] = ""
217 continue
218 try:
219 # tokenize.open honors PEP 263 coding cookies and defaults
220 # to utf-8, like the import system does.
221 with tokenize.open(fname) as f:
222 self.source_by_modname[new_modname] = f.read()
223 except Exception as e:
224 logger = logging.getLogger("autoreload")
225 logger.exception(
226 f"Failed to read module file '{fname}' for module '{new_modname}': {type(e).__name__}"
227 )
228 self.source_by_modname[new_modname] = ""
229
230 constexpr_detector = ConstexprDetector()
231

Callers 1

__init__Method · 0.90

Calls 1

ConstexprDetectorClass · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…