ipynb_importer.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import io
  2. import os
  3. import sys
  4. import types
  5. from IPython import get_ipython
  6. from nbformat import read
  7. from IPython.core.interactiveshell import InteractiveShell
  8. class NotebookFinder(object):
  9. """Module finder that locates Jupyter Notebooks"""
  10. def __init__(self):
  11. self.loaders = {}
  12. def find_module(self, fullname, path=None):
  13. nb_path = find_notebook(fullname, path)
  14. if not nb_path:
  15. return
  16. key = path
  17. if path:
  18. # lists aren't hashable
  19. key = os.path.sep.join(path)
  20. if key not in self.loaders:
  21. self.loaders[key] = NotebookLoader(path)
  22. return self.loaders[key]
  23. def find_notebook(fullname, path=None):
  24. """find a notebook, given its fully qualified name and an optional path
  25. This turns "foo.bar" into "foo/bar.ipynb"
  26. and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
  27. does not exist.
  28. """
  29. name = fullname.rsplit('.', 1)[-1]
  30. if not path:
  31. path = ['']
  32. for d in path:
  33. nb_path = os.path.join(d, name + ".ipynb")
  34. if os.path.isfile(nb_path):
  35. return nb_path
  36. # let import Notebook_Name find "Notebook Name.ipynb"
  37. nb_path = nb_path.replace("_", " ")
  38. if os.path.isfile(nb_path):
  39. return nb_path
  40. class NotebookLoader(object):
  41. """Module Loader for Jupyter Notebooks"""
  42. def __init__(self, path=None):
  43. self.shell = InteractiveShell.instance()
  44. self.path = path
  45. def load_module(self, fullname):
  46. """import a notebook as a module"""
  47. path = find_notebook(fullname, self.path)
  48. print("importing Jupyter notebook from %s" % path)
  49. # load the notebook object
  50. with io.open(path, 'r', encoding='utf-8') as f:
  51. nb = read(f, 4)
  52. # create the module and add it to sys.modules
  53. # if name in sys.modules:
  54. # return sys.modules[name]
  55. mod = types.ModuleType(fullname)
  56. mod.__file__ = path
  57. mod.__loader__ = self
  58. mod.__dict__['get_ipython'] = get_ipython
  59. sys.modules[fullname] = mod
  60. # extra work to ensure that magics that would affect the user_ns
  61. # actually affect the notebook module's ns
  62. save_user_ns = self.shell.user_ns
  63. self.shell.user_ns = mod.__dict__
  64. try:
  65. for cell in nb.cells:
  66. if cell.cell_type == 'code':
  67. # transform the input to executable Python
  68. code = self.shell.input_transformer_manager.transform_cell(
  69. cell.source)
  70. # run the code in themodule
  71. exec(code, mod.__dict__)
  72. finally:
  73. self.shell.user_ns = save_user_ns
  74. return mod
  75. sys.meta_path.append(NotebookFinder())