4
4
from __future__ import absolute_import
5
5
from __future__ import print_function
6
6
7
- import imp
8
- import threading
7
+ import inspect
9
8
import warnings
10
9
from contextlib import contextmanager
11
10
12
11
from decorator import decorator
13
12
from IPython import get_ipython
14
13
from ipython_genutils .py3compat import iteritems
15
- from ipython_genutils .py3compat import PY3
16
14
from ipython_genutils .py3compat import string_types
17
15
from traitlets import Any
18
16
from traitlets import Bool
@@ -433,6 +431,10 @@ def sync_imports(self, local=True, quiet=False):
433
431
modules = set ()
434
432
results = []
435
433
434
+ # get the calling frame
435
+ # that's two steps up due to `@contextmanager`
436
+ context_frame = inspect .getouterframes (inspect .currentframe ())[2 ].frame
437
+
436
438
@util .interactive
437
439
def remote_import (name , fromlist , level ):
438
440
"""the function to be passed to apply, that actually performs the import
@@ -456,17 +458,17 @@ def view_import(name, globals={}, locals={}, fromlist=[], level=0):
456
458
save_import = builtin_mod .__import__
457
459
builtin_mod .__import__ = local_import
458
460
459
- if imp .lock_held ():
460
- # this is a side-effect import, don't do it remotely, or even
461
- # ignore the local effects
461
+ import_frame = inspect .getouterframes (inspect .currentframe ())[1 ].frame
462
+ if import_frame is not context_frame :
463
+ # only forward imports from the context frame,
464
+ # not secondary imports
465
+ # TODO: does this ever happen, or is the above `__import__` enough?
462
466
return local_import (name , globals , locals , fromlist , level )
463
467
464
- imp .acquire_lock ()
465
468
if local :
466
469
mod = local_import (name , globals , locals , fromlist , level )
467
470
else :
468
471
raise NotImplementedError ("remote-only imports not yet implemented" )
469
- imp .release_lock ()
470
472
471
473
key = name + ':' + ',' .join (fromlist or [])
472
474
if level <= 0 and key not in modules :
0 commit comments