##// END OF EJS Templates
Port `deepreload` to `importlib`...
Nikita Kniazev -
Show More
@@ -28,7 +28,7 b' re-implementation of hierarchical module import.'
28 28
29 29 import builtins as builtin_mod
30 30 from contextlib import contextmanager
31 import imp
31 import importlib
32 32 import sys
33 33
34 34 from types import ModuleType
@@ -174,33 +174,17 b' def import_submodule(mod, subname, fullname):'
174 174 print('Reloading', fullname)
175 175 found_now[fullname] = 1
176 176 oldm = sys.modules.get(fullname, None)
177
178 if mod is None:
179 path = None
180 elif hasattr(mod, '__path__'):
181 path = mod.__path__
182 else:
183 return None
184
185 try:
186 # This appears to be necessary on Python 3, because imp.find_module()
187 # tries to import standard libraries (like io) itself, and we don't
188 # want them to be processed by our deep_import_hook.
189 with replace_import_hook(original_import):
190 fp, filename, stuff = imp.find_module(subname, path)
191 except ImportError:
192 return None
193
194 177 try:
195 m = imp.load_module(fullname, fp, filename, stuff)
178 if oldm is not None:
179 m = importlib.reload(oldm)
180 else:
181 m = importlib.import_module(subname, mod)
196 182 except:
197 183 # load_module probably removed name from modules because of
198 184 # the error. Put back the original module object.
199 185 if oldm:
200 186 sys.modules[fullname] = oldm
201 187 raise
202 finally:
203 if fp: fp.close()
204 188
205 189 add_submodule(mod, m, fullname, subname)
206 190
@@ -285,43 +269,17 b' def deep_reload_hook(m):'
285 269 except:
286 270 modules_reloading[name] = m
287 271
288 dot = name.rfind('.')
289 if dot < 0:
290 subname = name
291 path = None
292 else:
293 272 try:
294 parent = sys.modules[name[:dot]]
295 except KeyError as e:
296 modules_reloading.clear()
297 raise ImportError("reload(): parent %.200s not in sys.modules" % name[:dot]) from e
298 subname = name[dot+1:]
299 path = getattr(parent, "__path__", None)
300
301 try:
302 # This appears to be necessary on Python 3, because imp.find_module()
303 # tries to import standard libraries (like io) itself, and we don't
304 # want them to be processed by our deep_import_hook.
305 with replace_import_hook(original_import):
306 fp, filename, stuff = imp.find_module(subname, path)
307 finally:
308 modules_reloading.clear()
309
310 try:
311 newm = imp.load_module(name, fp, filename, stuff)
273 newm = importlib.reload(m)
312 274 except:
313 # load_module probably removed name from modules because of
314 # the error. Put back the original module object.
315 275 sys.modules[name] = m
316 276 raise
317 277 finally:
318 if fp: fp.close()
319
320 278 modules_reloading.clear()
321 279 return newm
322 280
323 281 # Save the original hooks
324 original_reload = imp.reload
282 original_reload = importlib.reload
325 283
326 284 # Replacement for reload()
327 285 def reload(module, exclude=('sys', 'os.path', 'builtins', '__main__',
@@ -4,11 +4,14 b''
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 import pytest
8 import types
9
7 10 from pathlib import Path
8 11
9 12 from IPython.utils.syspathcontext import prepended_to_syspath
10 13 from IPython.utils.tempdir import TemporaryDirectory
11 from IPython.lib.deepreload import reload as dreload
14 from IPython.lib.deepreload import reload as dreload, modules_reloading
12 15
13 16
14 17 def test_deepreload():
@@ -17,9 +20,9 b' def test_deepreload():'
17 20 with prepended_to_syspath(tmpdir):
18 21 tmpdirpath = Path(tmpdir)
19 22 with open(tmpdirpath / "A.py", "w") as f:
20 f.write("class Object(object):\n pass\n")
23 f.write("class Object:\n pass\nok = True\n")
21 24 with open(tmpdirpath / "B.py", "w") as f:
22 f.write("import A\n")
25 f.write("import A\nassert A.ok, 'we are fine'\n")
23 26 import A
24 27 import B
25 28
@@ -28,7 +31,26 b' def test_deepreload():'
28 31 dreload(B, exclude=["A"])
29 32 assert isinstance(obj, A.Object) is True
30 33
34 # Test that an import failure will not blow-up us.
35 A.ok = False
36 with pytest.raises(AssertionError, match="we are fine"):
37 dreload(B, exclude=["A"])
38 assert len(modules_reloading) == 0
39 assert not A.ok
40
31 41 # Test that A is reloaded.
32 42 obj = A.Object()
43 A.ok = False
33 44 dreload(B)
45 assert A.ok
34 46 assert isinstance(obj, A.Object) is False
47
48
49 def test_not_module():
50 pytest.raises(TypeError, dreload, "modulename")
51
52
53 def test_not_in_sys_modules():
54 fake_module = types.ModuleType("fake_module")
55 with pytest.raises(ImportError, match="not in sys.modules"):
56 dreload(fake_module)
General Comments 0
You need to be logged in to leave comments. Login now