88from fastcore .utils import *
99from fastcore .script import call_parse
1010
11- import multiprocessing ,types
11+ import multiprocessing ,types , traceback
1212try :
1313 if sys .platform == 'darwin' : multiprocessing .set_start_method ("fork" )
1414except RuntimeError : pass # if re-running cell
2222from IPython .utils .strdispatch import StrDispatch
2323from IPython .display import display as disp , HTML
2424
25- import traceback
2625from base64 import b64encode
27- from io import StringIO
28- from contextlib import redirect_stdout
26+ from html import escape
27+ try : from matplotlib_inline .backend_inline import set_matplotlib_formats
28+ except ImportError : set_matplotlib_formats = None
2929
3030from .nbio import *
3131from .nbio import _dict2obj
3232
3333# %% auto 0
34- __all__ = ['CaptureShell' , 'format_exc' , 'find_output' , 'out_exec' , 'out_stream' , 'out_error' , 'exec_nb' , 'SmartCompleter' ]
34+ __all__ = ['CaptureShell' , 'format_exc' , 'render_outputs' , 'find_output' , 'out_exec' , 'out_stream' , 'out_error' , 'exec_nb' ,
35+ 'SmartCompleter' ]
3536
3637# %% ../nbs/02_shell.ipynb 5
3738class _CustDisplayHook (DisplayHook ):
@@ -49,13 +50,16 @@ def __repr__(self: ExecutionResult): return f'result: {self.result}; err: {self.
4950class CaptureShell (InteractiveShell ):
5051 displayhook_class = _CustDisplayHook
5152
52- def __init__ (self , path :str | Path = None ):
53+ def __init__ (self , path :str | Path = None , mpl_format = 'retina' ):
5354 super ().__init__ ()
5455 self .result ,self .exc = None ,None
5556 if path : self .set_path (path )
5657 self .display_formatter .active = True
5758 if not IN_NOTEBOOK : InteractiveShell ._instance = self
58- self .run_cell ('%matplotlib inline' )
59+ if set_matplotlib_formats :
60+ self .run_cell ("from matplotlib_inline.backend_inline import set_matplotlib_formats" )
61+ self .run_cell (f"set_matplotlib_formats('{ mpl_format } ')" )
62+ self .run_cell ('%matplotlib inline' )
5963
6064 def run_cell (self , raw_cell , store_history = False , silent = False , shell_futures = True , cell_id = None ,
6165 stdout = True , stderr = True , display = True ):
@@ -119,7 +123,31 @@ def run(self:CaptureShell,
119123 self .exc = res .exception
120124 return _out_nb (res , self .display_formatter )
121125
122- # %% ../nbs/02_shell.ipynb 38
126+ # %% ../nbs/02_shell.ipynb 29
127+ def render_outputs (outputs ):
128+ def render_output (out ):
129+ otype = out ['output_type' ]
130+ if otype == 'stream' :
131+ txt = '' .join (out ['text' ])
132+ return f"<pre>{ txt } </pre>" if out ['name' ]== 'stdout' else f"<pre class='stderr'>{ txt } </pre>"
133+ elif otype in ('display_data' ,'execute_result' ):
134+ data = out ['data' ]
135+ _g = lambda t : '' .join (data [t ]) if t in data else None
136+ if d := _g ('text/html' ): return d
137+ if d := _g ('application/javascript' ): return f'<script>{ d } </script>'
138+ if d := _g ('text/markdown' ): return markdown .markdown (d )
139+ if d := _g ('image/svg+xml' ): return d
140+ if d := _g ('image/jpeg' ): return f'<img src="data:image/jpeg;base64,{ d } "/>'
141+ if d := _g ('image/png' ): return f'<img src="data:image/png;base64,{ d } "/>'
142+ if d := _g ('text/latex' ): return f'<div class="math">${ d } $</div>'
143+ if d := _g ('text/plain' ): return f"<pre>{ escape (d )} </pre>"
144+ elif otype == 'error' :
145+ return f"<pre class='error'>{ out ['ename' ]} : { out ['evalue' ]} \n { '' .join (out ['traceback' ])} </pre>"
146+ return ''
147+
148+ return '\n ' .join (map (render_output , outputs ))
149+
150+ # %% ../nbs/02_shell.ipynb 40
123151@patch
124152def cell (self :CaptureShell , cell , stdout = True , stderr = True ):
125153 "Run `cell`, skipping if not code, and store outputs back in cell"
@@ -131,32 +159,32 @@ def cell(self:CaptureShell, cell, stdout=True, stderr=True):
131159 for o in outs :
132160 if 'execution_count' in o : cell ['execution_count' ] = o ['execution_count' ]
133161
134- # %% ../nbs/02_shell.ipynb 41
162+ # %% ../nbs/02_shell.ipynb 43
135163def find_output (outp , # Output from `run`
136164 ot = 'execute_result' # Output_type to find
137165 ):
138166 "Find first output of type `ot` in `CaptureShell.run` output"
139167 return first (o for o in outp if o ['output_type' ]== ot )
140168
141- # %% ../nbs/02_shell.ipynb 44
169+ # %% ../nbs/02_shell.ipynb 46
142170def out_exec (outp ):
143171 "Get data from execution result in `outp`."
144172 out = find_output (outp )
145173 if out : return '\n ' .join (first (out ['data' ].values ()))
146174
147- # %% ../nbs/02_shell.ipynb 46
175+ # %% ../nbs/02_shell.ipynb 48
148176def out_stream (outp ):
149177 "Get text from stream in `outp`."
150178 out = find_output (outp , 'stream' )
151179 if out : return ('\n ' .join (out ['text' ])).strip ()
152180
153- # %% ../nbs/02_shell.ipynb 48
181+ # %% ../nbs/02_shell.ipynb 50
154182def out_error (outp ):
155183 "Get traceback from error in `outp`."
156184 out = find_output (outp , 'error' )
157185 if out : return '\n ' .join (out ['traceback' ])
158186
159- # %% ../nbs/02_shell.ipynb 50
187+ # %% ../nbs/02_shell.ipynb 52
160188def _false (o ): return False
161189
162190@patch
@@ -176,7 +204,7 @@ def run_all(self:CaptureShell,
176204 postproc (cell )
177205 if self .exc and exc_stop : raise self .exc from None
178206
179- # %% ../nbs/02_shell.ipynb 64
207+ # %% ../nbs/02_shell.ipynb 66
180208@patch
181209def execute (self :CaptureShell ,
182210 src :str | Path , # Notebook path to read from
@@ -197,7 +225,7 @@ def execute(self:CaptureShell,
197225 inject_code = inject_code , inject_idx = inject_idx )
198226 if dest : write_nb (nb , dest )
199227
200- # %% ../nbs/02_shell.ipynb 68
228+ # %% ../nbs/02_shell.ipynb 70
201229@patch
202230def prettytb (self :CaptureShell ,
203231 fname :str | Path = None ): # filename to print alongside the traceback
@@ -209,7 +237,7 @@ def prettytb(self:CaptureShell,
209237 fname_str = f' in { fname } ' if fname else ''
210238 return f"{ type (self .exc ).__name__ } { fname_str } :\n { _fence } \n { cell_str } \n "
211239
212- # %% ../nbs/02_shell.ipynb 87
240+ # %% ../nbs/02_shell.ipynb 89
213241@call_parse
214242def exec_nb (
215243 src :str , # Notebook path to read from
@@ -223,7 +251,7 @@ def exec_nb(
223251 CaptureShell ().execute (src , dest , exc_stop = exc_stop , inject_code = inject_code ,
224252 inject_path = inject_path , inject_idx = inject_idx )
225253
226- # %% ../nbs/02_shell.ipynb 90
254+ # %% ../nbs/02_shell.ipynb 92
227255class SmartCompleter (IPCompleter ):
228256 def __init__ (self , shell , namespace = None , jedi = False ):
229257 if namespace is None : namespace = shell .user_ns
@@ -242,3 +270,9 @@ def __call__(self, c):
242270 return [o .text .rpartition ('.' )[- 1 ]
243271 for o in self .completions (c , len (c ))
244272 if o .type == '<unknown>' ]
273+
274+ # %% ../nbs/02_shell.ipynb 94
275+ @patch
276+ def complete (self :CaptureShell , c ):
277+ if not hasattr (self , '_completer' ): self ._completer = SmartCompleter (self )
278+ return self ._completer (c )
0 commit comments