Skip to content

Commit

Permalink
Merge pull request fastai#10 from seeM/fix-enable-matplotlib
Browse files Browse the repository at this point in the history
  • Loading branch information
jph00 committed Jul 4, 2022
2 parents f347085 + 622ac6f commit 8cf9541
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 32 deletions.
1 change: 1 addition & 0 deletions execnb/_modidx.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
'execnb.shell': { 'execnb.shell.CaptureShell': 'https://fastai.github.io/execnb/shell#CaptureShell',
'execnb.shell.CaptureShell.cell': 'https://fastai.github.io/execnb/shell#CaptureShell.cell',
'execnb.shell.CaptureShell.enable_gui': 'https://fastai.github.io/execnb/shell#CaptureShell.enable_gui',
'execnb.shell.CaptureShell.enable_matplotlib': 'https://fastai.github.io/execnb/shell#CaptureShell.enable_matplotlib',
'execnb.shell.CaptureShell.execute': 'https://fastai.github.io/execnb/shell#CaptureShell.execute',
'execnb.shell.CaptureShell.prettytb': 'https://fastai.github.io/execnb/shell#CaptureShell.prettytb',
'execnb.shell.CaptureShell.run': 'https://fastai.github.io/execnb/shell#CaptureShell.run',
Expand Down
17 changes: 9 additions & 8 deletions execnb/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ def _out_exc(ename, evalue, traceback): return dict(ename=str(ename), evalue=str
def _out_stream(text): return dict(name='stdout', output_type='stream', text=text.splitlines(False))

# %% ../nbs/02_shell.ipynb 7
_CODE_MATPLOTLIB_INLINE = """
from IPython import get_ipython
try: get_ipython().run_line_magic('matplotlib', 'inline')
except ModuleNotFoundError: pass
""".strip()

class CaptureShell(FastInteractiveShell):
"Execute the IPython/Jupyter source code"
def __init__(self,
Expand All @@ -54,7 +48,8 @@ def __init__(self,
InteractiveShell._instance = self
self.out,self.count = [],1
self.exc = self.result = self._fname = self._cell_idx = None
self.run_cell(_CODE_MATPLOTLIB_INLINE)
try: self.enable_matplotlib('inline')
except ModuleNotFoundError: pass
if path: self.set_path(path)

def set_path(self, path):
Expand All @@ -67,6 +62,12 @@ def enable_gui(self, gui=None):
"Disable GUI (over-ridden; called by IPython)"
pass

def enable_matplotlib(self, gui=None):
"Enable `matplotlib` in a nested shell"
from matplotlib_inline.backend_inline import configure_inline_support
configure_inline_support.current_backend = 'unset'
return super().enable_matplotlib(gui)

def _showtraceback(self, etype, evalue, stb: str):
self.out.append(_out_exc(etype, evalue, stb))
self.exc = (etype, evalue, '\n'.join(stb))
Expand Down Expand Up @@ -169,7 +170,7 @@ def prettytb(self:CaptureShell,
fname_str = f' in {fname}' if fname else ''
return f"{type(self.exc[1]).__name__}{fname_str}:\n{_fence}\n{cell_str}\n"

# %% ../nbs/02_shell.ipynb 50
# %% ../nbs/02_shell.ipynb 52
@call_parse
def exec_nb(
src:str, # Notebook path to read from
Expand Down
65 changes: 43 additions & 22 deletions nbs/02_shell.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,6 @@
"outputs": [],
"source": [
"#|export\n",
"_CODE_MATPLOTLIB_INLINE = \"\"\"\n",
"from IPython import get_ipython\n",
"try: get_ipython().run_line_magic('matplotlib', 'inline')\n",
"except ModuleNotFoundError: pass\n",
"\"\"\".strip()\n",
"\n",
"class CaptureShell(FastInteractiveShell):\n",
" \"Execute the IPython/Jupyter source code\"\n",
" def __init__(self,\n",
Expand All @@ -104,7 +98,8 @@
" InteractiveShell._instance = self\n",
" self.out,self.count = [],1\n",
" self.exc = self.result = self._fname = self._cell_idx = None\n",
" self.run_cell(_CODE_MATPLOTLIB_INLINE)\n",
" try: self.enable_matplotlib('inline')\n",
" except ModuleNotFoundError: pass\n",
" if path: self.set_path(path)\n",
" \n",
" def set_path(self, path):\n",
Expand All @@ -117,6 +112,12 @@
" \"Disable GUI (over-ridden; called by IPython)\"\n",
" pass\n",
" \n",
" def enable_matplotlib(self, gui=None):\n",
" \"Enable `matplotlib` in a nested shell\"\n",
" from matplotlib_inline.backend_inline import configure_inline_support\n",
" configure_inline_support.current_backend = 'unset'\n",
" return super().enable_matplotlib(gui)\n",
" \n",
" def _showtraceback(self, etype, evalue, stb: str):\n",
" self.out.append(_out_exc(etype, evalue, stb))\n",
" self.exc = (etype, evalue, '\\n'.join(stb))\n",
Expand Down Expand Up @@ -219,8 +220,8 @@
" 'execution_count': 1},\n",
" {'name': 'stdout',\n",
" 'output_type': 'stream',\n",
" 'text': ['CPU times: user 1e+03 ns, sys: 0 ns, total: 1e+03 ns',\n",
" 'Wall time: 2.62 us']}]"
" 'text': ['CPU times: user 3 us, sys: 1 us, total: 4 us',\n",
" 'Wall time: 6.2 us']}]"
]
},
"execution_count": null,
Expand Down Expand Up @@ -299,9 +300,9 @@
"text": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)\n",
"\u001b[0;32m<ipython-input-1-01648acb07bd>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n",
"\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Oops\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOops\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
"\n",
"\u001b[0;31mException\u001b[0m: Oops\n"
]
}
Expand Down Expand Up @@ -513,7 +514,7 @@
" 'output_type': 'error',\n",
" 'traceback': ['\\x1b[0;31m---------------------------------------------------------------------------\\x1b[0m',\n",
" '\\x1b[0;31mException\\x1b[0m Traceback (most recent call last)',\n",
" '\\x1b[0;32m<ipython-input-1-1c97c1d317ab>\\x1b[0m in \\x1b[0;36m<module>\\x1b[0;34m\\x1b[0m\\n\\x1b[0;32m----> 1\\x1b[0;31m \\x1b[0;32mraise\\x1b[0m \\x1b[0mException\\x1b[0m\\x1b[0;34m(\\x1b[0m\\x1b[0;34m\"Oopsie!\"\\x1b[0m\\x1b[0;34m)\\x1b[0m\\x1b[0;34m\\x1b[0m\\x1b[0;34m\\x1b[0m\\x1b[0m\\n\\x1b[0m',\n",
" 'Input \\x1b[0;32mIn [1]\\x1b[0m, in \\x1b[0;36m<cell line: 1>\\x1b[0;34m()\\x1b[0m\\n\\x1b[0;32m----> 1\\x1b[0m \\x1b[38;5;28;01mraise\\x1b[39;00m \\x1b[38;5;167;01mException\\x1b[39;00m(\\x1b[38;5;124m\"\\x1b[39m\\x1b[38;5;124mOopsie!\\x1b[39m\\x1b[38;5;124m\"\\x1b[39m)\\n',\n",
" '\\x1b[0;31mException\\x1b[0m: Oopsie!']}]"
]
},
Expand Down Expand Up @@ -723,15 +724,15 @@
"While Executing Cell #2:\n",
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n",
"\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)\n",
"\u001b[0;32m<ipython-input-1-b968a57a586e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n",
"\u001b[1;32m 1\u001b[0m \u001b[0;31m# some comments\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'hello'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m----> 3\u001b[0;31m \u001b[0mfoo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\n",
"\u001b[0;32m~/github/execnb/tests/err.py\u001b[0m in \u001b[0;36mfoo\u001b[0;34m()\u001b[0m\n",
"\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfoo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;36m13\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m98\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0m\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 3>\u001b[0;34m()\u001b[0m\n",
"\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# some comments\u001b[39;00m\n",
"\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mhello\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"\u001b[0;32m----> 3\u001b[0m \u001b[43mfoo\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"\n",
"File \u001b[0;32m~/code/execnb/tests/err.py:2\u001b[0m, in \u001b[0;36mfoo\u001b[0;34m()\u001b[0m\n",
"\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfoo\u001b[39m():\n",
"\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;241m13\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m98\u001b[39m\n",
"\n",
"\u001b[0;31mAssertionError\u001b[0m: \n",
"\n"
]
Expand All @@ -745,6 +746,26 @@
" print(s.prettytb())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Tests -"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# matplotlib images are captured when outer shell uses inline backend\n",
"import matplotlib\n",
"matplotlib.use('module://matplotlib_inline.backend_inline')\n",
"res = CaptureShell().run('import matplotlib.pyplot as plt; plt.plot([0,1]);')\n",
"assert any('image/png' in o['data'] for o in res),'Image not captured'"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
4 changes: 2 additions & 2 deletions nbs/sidebar.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
website:
sidebar:
contents:
- index.ipynb
- 01_nbio.ipynb
- 02_shell.ipynb
- index.ipynb
- 02_shell.ipynb

0 comments on commit 8cf9541

Please sign in to comment.