Coverage for src\zapy\utils\module.py: 61%

50 statements  

« prev     ^ index     » next       coverage.py v7.3.4, created at 2023-12-20 14:17 -0500

1from pathlib import Path 

2import importlib.util 

3from threading import Lock 

4import io, sys, types 

5 

6from zapy.templating.eval import exec_async 

7 

8 

9def load_module(module_path: str | Path): 

10 module_path = Path(module_path) 

11 

12 if module_path.is_dir(): 

13 return load_module_dir(module_path) 

14 elif module_path.suffix == '.ipynb': 

15 raise ValueError('use load_ipynb to load ipynb') 

16 else: 

17 return load_module_python(module_path) 

18 

19 

20def load_module_dir(module_path: str | Path): 

21 module_path = Path(module_path) 

22 module_str = str(module_path) 

23 with Lock(): 

24 sys.path.append(module_str) 

25 try: 

26 return load_module_python(module_path / '__init__.py') 

27 finally: 

28 sys.path.remove(module_str) 

29 

30 

31def load_module_python(module_path: str | Path): 

32 module_path = Path(module_path) 

33 module_spec = importlib.util.spec_from_file_location(module_path.stem, module_path) 

34 module = importlib.util.module_from_spec(module_spec) 

35 module_spec.loader.exec_module(module) 

36 

37 return module 

38 

39 

40async def load_ipynb(module_path: str | Path, variables=None): 

41 ''' from https://jupyter-notebook.readthedocs.io/en/latest/examples/Notebook/Importing%20Notebooks.html ''' 

42 from IPython import get_ipython 

43 from IPython.core.interactiveshell import InteractiveShell 

44 from nbformat import read 

45 

46 module_path = Path(module_path) 

47 shell = InteractiveShell.instance() 

48 fullname = module_path.stem 

49 

50 variables = variables or dict() 

51 

52 # load the notebook object 

53 with io.open(module_path, 'r', encoding='utf-8') as f: 

54 nb = read(f, 4) 

55 

56 # create the module and add it to sys.modules if name in sys.modules: 

57 # return sys.modules[name] 

58 mod = types.ModuleType(fullname) 

59 mod.__file__ = module_path 

60 mod.__dict__['get_ipython'] = get_ipython 

61 # apply parameters 

62 for k, v in variables.items(): 

63 mod.__dict__[k] = v 

64 

65 # extra work to ensure that magics that would affect the user_ns 

66 # actually affect the notebook module's ns 

67 save_user_ns = shell.user_ns 

68 shell.user_ns = mod.__dict__ 

69 

70 try: 

71 for cell in nb.cells: 

72 if cell.cell_type == 'code': 72 ↛ 71line 72 didn't jump to line 71, because the condition on line 72 was never false

73 # transform the input to executable Python 

74 code = shell.input_transformer_manager.transform_cell(cell.source) 

75 # run the code in themodule 

76 await exec_async(code, mod.__dict__) 

77 finally: 

78 shell.user_ns = save_user_ns 

79 return mod