Skip to content

Commit 275a6e7

Browse files
committed
Only replace importers not from six (fixes bpython#874)
This avoids the breakage seen in bpython#874. Changes to six won't trigger a reload, however not breaking six is more important. The code now also only provides some functions of the underling finder/importer also does.
1 parent e38c478 commit 275a6e7

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

bpython/curtsiesfrontend/repl.py

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -212,50 +212,51 @@ def __init__(self, watcher, loader):
212212
self.watcher = watcher
213213
self.loader = loader
214214

215-
def load_module(self, name):
215+
def __getattr__(self, name):
216+
if name == "create_module" and hasattr(self.loader, name):
217+
return self._create_module
218+
if name == "load_module" and hasattr(self.loader, name):
219+
return self._load_module
220+
return getattr(self.loader, name)
221+
222+
def _create_module(self, spec):
223+
spec = self.loader.create_module(spec)
224+
if getattr(spec, "origin", None) is not None and spec.origin != "builtin":
225+
self.watcher.track_module(spec.origin)
226+
return spec
227+
228+
def _load_module(self, name):
216229
module = self.loader.load_module(name)
217230
if hasattr(module, "__file__"):
218231
self.watcher.track_module(module.__file__)
219232
return module
220233

221234

222235
class ImportFinder:
223-
def __init__(self, watcher, old_meta_path):
236+
def __init__(self, finder, watcher):
224237
self.watcher = watcher
225-
self.old_meta_path = old_meta_path
226-
227-
def find_distributions(self, context):
228-
for finder in self.old_meta_path:
229-
distribution_finder = getattr(finder, "find_distributions", None)
230-
if distribution_finder is not None:
231-
loader = finder.find_distributions(context)
232-
if loader is not None:
233-
return loader
234-
235-
return None
236-
237-
def find_spec(self, fullname, path, target=None):
238-
for finder in self.old_meta_path:
239-
# Consider the finder only if it implements find_spec
240-
if getattr(finder, "find_spec", None) is None:
241-
continue
242-
# Attempt to find the spec
243-
spec = finder.find_spec(fullname, path, target)
244-
if spec is not None:
245-
if getattr(spec, "__loader__", None) is not None:
246-
# Patch the loader to enable reloading
247-
spec.__loader__ = ImportLoader(
248-
self.watcher, spec.__loader__
249-
)
250-
return spec
251-
252-
def find_module(self, fullname, path=None):
253-
for finder in self.old_meta_path:
254-
loader = finder.find_module(fullname, path)
255-
if loader is not None:
256-
return ImportLoader(self.watcher, loader)
257-
258-
return None
238+
self.finder = finder
239+
240+
def __getattr__(self, name):
241+
if name == "find_spec" and hasattr(self.finder, name):
242+
return self._find_spec
243+
if name == "find_module" and hasattr(self.finder, name):
244+
return self._find_module
245+
return getattr(self.finder, name)
246+
247+
def _find_spec(self, fullname, path, target=None):
248+
# Attempt to find the spec
249+
spec = self.finder.find_spec(fullname, path, target)
250+
if spec is not None:
251+
if getattr(spec, "__loader__", None) is not None:
252+
# Patch the loader to enable reloading
253+
spec.__loader__ = ImportLoader(self.watcher, spec.__loader__)
254+
return spec
255+
256+
def _find_module(self, fullname, path=None):
257+
loader = self.finder.find_module(fullname, path)
258+
if loader is not None:
259+
return ImportLoader(self.watcher, loader)
259260

260261

261262
class BaseRepl(BpythonRepl):
@@ -531,7 +532,17 @@ def __enter__(self):
531532

532533
self.orig_meta_path = sys.meta_path
533534
if self.watcher:
534-
sys.meta_path = [ImportFinder(self.watcher, self.orig_meta_path)]
535+
meta_path = []
536+
for finder in sys.meta_path:
537+
# All elements get wrapped in ImportFinder instances execepted for instances of
538+
# _SixMetaPathImporter (from six). When importing six, it will check if the importer
539+
# is already part of sys.meta_path and will remove instances. We do not want to
540+
# break this feature (see also #874).
541+
if type(finder).__name__ == "_SixMetaPathImporter":
542+
meta_path.append(finder)
543+
else:
544+
meta_path.append(ImportFinder(finder, self.watcher))
545+
sys.meta_path = meta_path
535546

536547
sitefix.monkeypatch_quit()
537548
return self

0 commit comments

Comments
 (0)