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
« 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
6from zapy.templating.eval import exec_async
9def load_module(module_path: str | Path):
10 module_path = Path(module_path)
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)
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)
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)
37 return module
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
46 module_path = Path(module_path)
47 shell = InteractiveShell.instance()
48 fullname = module_path.stem
50 variables = variables or dict()
52 # load the notebook object
53 with io.open(module_path, 'r', encoding='utf-8') as f:
54 nb = read(f, 4)
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
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__
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