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 | 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 | 272 | 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 | modules_reloading.clear() | |
|
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 |
|
|
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