Importnb

    %reload_ext tonyfast
    __import__('requests_cache').install_cache('importnb'); import inspect, sys, IPython, nbformat, nbconvert, pathlib, json, pytest

Why importnb?

  • Teaches good reproducible habits. Restart and run all
  • Promotes less complex notebooks.
  • Notebooks can be used as applications.
  • Notebooks seed tests.
    import importnb

Make notebook

    pathlib.Path('demo.ipynb').write_text(json.dumps(
        nbformat.v4.new_notebook(cells=[nbformat.v4.new_code_cell("""
    foo = 10
    print(F"🥇 {foo}")""".splitlines(True))])))
208

import a notebook

    with importnb.Notebook():
        import demo
        
    F"{demo.__file__}"
'demo.ipynb'

Are the notebooks reload-able?

    with pytest.raises(ModuleNotFoundError):
        importnb.reload(demo)

🤝 change the notebook

    pathlib.Path('demo.ipynb').write_text(json.dumps(
        nbformat.v4.new_notebook(cells=[nbformat.v4.new_code_cell("""
    foo = "What"
    print(F"⓶ {foo}")""".splitlines(True))])))
208
    with importnb.Notebook():
        importnb.reload(demo)
⓶ What

https://github.com/deathbeds/importnb

Relative imports.

Import notebooks in "__init__.py" and "__main__.py" files.

    IPython.display.display(
        IPython.display.Code("https://gist.githubusercontent.com/tonyfast/fee98e31e3da90c3606c5dc14a703f0c/raw/780b50a6708b40c56274e4c66c82eeb48bee50e6/__init__.py".text()))
__all__ = 'jschema',
with __import__('importnb').Notebook(lazy=True):
  from .jschema import *

Notebooks that make extensions

    IPython.display.display(
        IPython.display.Code("https://raw.githubusercontent.com/tonyfast/gists/master/tonyfast/__init__.py".text()))
def load_ipython_extension(shell):
    with __import__('importnb').Notebook(): from . import jschema, ainteractive
    jschema.load_ipython_extension(shell)
    ainteractive.load_ipython_extension(shell)
def unload_ipython_extension(shell):
    with __import__('importnb').Notebook(): from . import jschema, ainteractive
    jschema.unload_ipython_extension(shell)
    ainteractive.unload_ipython_extension(shell)

__name__ == '__main__' is important

In notebooks, we are working in the application. It hasn’t been named yet.

What does importnb do?

... temporarily modifies the sys.path_hooks used to discover typical python files.

Before

    inspect.getclosurevars(sys.path_hooks[1]).nonlocals['loader_details']
((_frozen_importlib_external.ExtensionFileLoader,
  ['.cpython-37m-darwin.so', '.abi3.so', '.so']),
 (_frozen_importlib_external.SourceFileLoader, ['.py']),
 (_frozen_importlib_external.SourcelessFileLoader, ['.pyc']))

After

    with importnb.Notebook(): print(inspect.getclosurevars(sys.path_hooks[1]).nonlocals['loader_details'])
((functools.partial(<class 'importnb.loader.Notebook'>, lazy=False, fuzzy=True, markdown_docstring=True, position=0, main=False), ('.ipynb',)), (<class '_frozen_importlib_external.ExtensionFileLoader'>, ['.cpython-37m-darwin.so', '.abi3.so', '.so']), (<class '_frozen_importlib_external.SourceFileLoader'>, ['.py']), (<class '_frozen_importlib_external.SourcelessFileLoader'>, ['.pyc']))

Parameterized notebooks

    %%capture
    f = importnb.Parameterize.load('demo.ipynb')
    f(foo=' 🙏')
⓶  🙏





<module 'demo' from 'demo.ipynb'>
    def _(l:(0, 100)): f(foo=l)
    _
<function _ at 0x113dd4d90>



interactive(children=(IntSlider(value=50, description='l'), Output()), _dom_classes=('widget-interact',))

😫 CLI looks busted.

Written on September 24, 2019