```python
    %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.


```python
    import importnb
```

### Make notebook


```python
    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


```python
    with importnb.Notebook():
        import demo
        
    F"{demo.__file__}"
```




    'demo.ipynb'



### Are the notebooks reload-able?


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

# 🤝 change the notebook


```python
    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




```python
    with importnb.Notebook():
        importnb.reload(demo)
```

    ⓶ What


https://github.com/deathbeds/importnb

## Relative imports.

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


```python
    IPython.display.display(
        IPython.display.Code("https://gist.githubusercontent.com/tonyfast/fee98e31e3da90c3606c5dc14a703f0c/raw/780b50a6708b40c56274e4c66c82eeb48bee50e6/__init__.py".text()))
```


<style>.output_html .hll { background-color: #ffffcc }
.output_html  { background: #f8f8f8; }
.output_html .c { color: #408080; font-style: italic } /* Comment */
.output_html .err { border: 1px solid #FF0000 } /* Error */
.output_html .k { color: #008000; font-weight: bold } /* Keyword */
.output_html .o { color: #666666 } /* Operator */
.output_html .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.output_html .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.output_html .cp { color: #BC7A00 } /* Comment.Preproc */
.output_html .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.output_html .c1 { color: #408080; font-style: italic } /* Comment.Single */
.output_html .cs { color: #408080; font-style: italic } /* Comment.Special */
.output_html .gd { color: #A00000 } /* Generic.Deleted */
.output_html .ge { font-style: italic } /* Generic.Emph */
.output_html .gr { color: #FF0000 } /* Generic.Error */
.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.output_html .gi { color: #00A000 } /* Generic.Inserted */
.output_html .go { color: #888888 } /* Generic.Output */
.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.output_html .gs { font-weight: bold } /* Generic.Strong */
.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.output_html .gt { color: #0044DD } /* Generic.Traceback */
.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.output_html .kp { color: #008000 } /* Keyword.Pseudo */
.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.output_html .kt { color: #B00040 } /* Keyword.Type */
.output_html .m { color: #666666 } /* Literal.Number */
.output_html .s { color: #BA2121 } /* Literal.String */
.output_html .na { color: #7D9029 } /* Name.Attribute */
.output_html .nb { color: #008000 } /* Name.Builtin */
.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.output_html .no { color: #880000 } /* Name.Constant */
.output_html .nd { color: #AA22FF } /* Name.Decorator */
.output_html .ni { color: #999999; font-weight: bold } /* Name.Entity */
.output_html .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.output_html .nf { color: #0000FF } /* Name.Function */
.output_html .nl { color: #A0A000 } /* Name.Label */
.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */
.output_html .nv { color: #19177C } /* Name.Variable */
.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.output_html .w { color: #bbbbbb } /* Text.Whitespace */
.output_html .mb { color: #666666 } /* Literal.Number.Bin */
.output_html .mf { color: #666666 } /* Literal.Number.Float */
.output_html .mh { color: #666666 } /* Literal.Number.Hex */
.output_html .mi { color: #666666 } /* Literal.Number.Integer */
.output_html .mo { color: #666666 } /* Literal.Number.Oct */
.output_html .sa { color: #BA2121 } /* Literal.String.Affix */
.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */
.output_html .sc { color: #BA2121 } /* Literal.String.Char */
.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */
.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.output_html .s2 { color: #BA2121 } /* Literal.String.Double */
.output_html .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */
.output_html .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.output_html .sx { color: #008000 } /* Literal.String.Other */
.output_html .sr { color: #BB6688 } /* Literal.String.Regex */
.output_html .s1 { color: #BA2121 } /* Literal.String.Single */
.output_html .ss { color: #19177C } /* Literal.String.Symbol */
.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */
.output_html .fm { color: #0000FF } /* Name.Function.Magic */
.output_html .vc { color: #19177C } /* Name.Variable.Class */
.output_html .vg { color: #19177C } /* Name.Variable.Global */
.output_html .vi { color: #19177C } /* Name.Variable.Instance */
.output_html .vm { color: #19177C } /* Name.Variable.Magic */
.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="n">__all__</span> <span class="o">=</span> <span class="s1">&#39;jschema&#39;</span><span class="p">,</span>
<span class="k">with</span> <span class="nb">__import__</span><span class="p">(</span><span class="s1">&#39;importnb&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">Notebook</span><span class="p">(</span><span class="n">lazy</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
  <span class="kn">from</span> <span class="nn">.jschema</span> <span class="kn">import</span> <span class="o">*</span>
</pre></div>



Notebooks that make extensions


```python
    IPython.display.display(
        IPython.display.Code("https://raw.githubusercontent.com/tonyfast/gists/master/tonyfast/__init__.py".text()))
```


<style>.output_html .hll { background-color: #ffffcc }
.output_html  { background: #f8f8f8; }
.output_html .c { color: #408080; font-style: italic } /* Comment */
.output_html .err { border: 1px solid #FF0000 } /* Error */
.output_html .k { color: #008000; font-weight: bold } /* Keyword */
.output_html .o { color: #666666 } /* Operator */
.output_html .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.output_html .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.output_html .cp { color: #BC7A00 } /* Comment.Preproc */
.output_html .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.output_html .c1 { color: #408080; font-style: italic } /* Comment.Single */
.output_html .cs { color: #408080; font-style: italic } /* Comment.Special */
.output_html .gd { color: #A00000 } /* Generic.Deleted */
.output_html .ge { font-style: italic } /* Generic.Emph */
.output_html .gr { color: #FF0000 } /* Generic.Error */
.output_html .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.output_html .gi { color: #00A000 } /* Generic.Inserted */
.output_html .go { color: #888888 } /* Generic.Output */
.output_html .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.output_html .gs { font-weight: bold } /* Generic.Strong */
.output_html .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.output_html .gt { color: #0044DD } /* Generic.Traceback */
.output_html .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.output_html .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.output_html .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.output_html .kp { color: #008000 } /* Keyword.Pseudo */
.output_html .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.output_html .kt { color: #B00040 } /* Keyword.Type */
.output_html .m { color: #666666 } /* Literal.Number */
.output_html .s { color: #BA2121 } /* Literal.String */
.output_html .na { color: #7D9029 } /* Name.Attribute */
.output_html .nb { color: #008000 } /* Name.Builtin */
.output_html .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.output_html .no { color: #880000 } /* Name.Constant */
.output_html .nd { color: #AA22FF } /* Name.Decorator */
.output_html .ni { color: #999999; font-weight: bold } /* Name.Entity */
.output_html .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.output_html .nf { color: #0000FF } /* Name.Function */
.output_html .nl { color: #A0A000 } /* Name.Label */
.output_html .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.output_html .nt { color: #008000; font-weight: bold } /* Name.Tag */
.output_html .nv { color: #19177C } /* Name.Variable */
.output_html .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.output_html .w { color: #bbbbbb } /* Text.Whitespace */
.output_html .mb { color: #666666 } /* Literal.Number.Bin */
.output_html .mf { color: #666666 } /* Literal.Number.Float */
.output_html .mh { color: #666666 } /* Literal.Number.Hex */
.output_html .mi { color: #666666 } /* Literal.Number.Integer */
.output_html .mo { color: #666666 } /* Literal.Number.Oct */
.output_html .sa { color: #BA2121 } /* Literal.String.Affix */
.output_html .sb { color: #BA2121 } /* Literal.String.Backtick */
.output_html .sc { color: #BA2121 } /* Literal.String.Char */
.output_html .dl { color: #BA2121 } /* Literal.String.Delimiter */
.output_html .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.output_html .s2 { color: #BA2121 } /* Literal.String.Double */
.output_html .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.output_html .sh { color: #BA2121 } /* Literal.String.Heredoc */
.output_html .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.output_html .sx { color: #008000 } /* Literal.String.Other */
.output_html .sr { color: #BB6688 } /* Literal.String.Regex */
.output_html .s1 { color: #BA2121 } /* Literal.String.Single */
.output_html .ss { color: #19177C } /* Literal.String.Symbol */
.output_html .bp { color: #008000 } /* Name.Builtin.Pseudo */
.output_html .fm { color: #0000FF } /* Name.Function.Magic */
.output_html .vc { color: #19177C } /* Name.Variable.Class */
.output_html .vg { color: #19177C } /* Name.Variable.Global */
.output_html .vi { color: #19177C } /* Name.Variable.Instance */
.output_html .vm { color: #19177C } /* Name.Variable.Magic */
.output_html .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">):</span>
    <span class="k">with</span> <span class="nb">__import__</span><span class="p">(</span><span class="s1">&#39;importnb&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">Notebook</span><span class="p">():</span> <span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">jschema</span><span class="p">,</span> <span class="n">ainteractive</span>
    <span class="n">jschema</span><span class="o">.</span><span class="n">load_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">)</span>
    <span class="n">ainteractive</span><span class="o">.</span><span class="n">load_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">unload_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">):</span>
    <span class="k">with</span> <span class="nb">__import__</span><span class="p">(</span><span class="s1">&#39;importnb&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">Notebook</span><span class="p">():</span> <span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">jschema</span><span class="p">,</span> <span class="n">ainteractive</span>
    <span class="n">jschema</span><span class="o">.</span><span class="n">unload_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">)</span>
    <span class="n">ainteractive</span><span class="o">.</span><span class="n">unload_ipython_extension</span><span class="p">(</span><span class="n">shell</span><span class="p">)</span>

</pre></div>



# [`__name__ == '__main__'` is important](https://nbviewer.jupyter.org/github/deathbeds/deathbeds.github.io/blob/master/deathbeds/2018-07-09-name-is-main.ipynb)

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


```python
    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


```python
    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




```python
    %%capture
    f = importnb.Parameterize.load('demo.ipynb')
```


```python
    f(foo=' 🙏')
```

    ⓶  🙏





    <module 'demo' from 'demo.ipynb'>




```python
    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.
