33# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/13_nbio.ipynb.
44
55# %% auto #0
6- __all__ = ['NbCell' , 'dict2nb' , 'read_nb' , 'mk_cell' , 'new_nb' , 'nb2dict' , 'nb2str' , 'write_nb' , 'cell2xml' , 'cells2xml ' ,
7- 'Notebook ' , 'preferred_out ' , 'apply_controls ' , 'mk_stream ' , 'concat_streams' , 'render_output' ,
8- 'render_outputs' ]
6+ __all__ = ['NbCell' , 'dict2nb' , 'read_nb' , 'mk_cell' , 'new_nb' , 'nb2dict' , 'nb2str' , 'write_nb' , 'preferred_out ' ,
7+ 'apply_controls ' , 'mk_stream ' , 'mk_result ' , 'mk_display' , 'mk_error ' , 'concat_streams' , 'render_output' ,
8+ 'render_outputs' , 'render_text' , 'cell2xml' , 'cells2xml' , 'Notebook' ]
99
1010# %% ../nbs/13_nbio.ipynb #954ca1aa
1111from .basics import *
@@ -106,8 +106,117 @@ def write_nb(nb, path):
106106 if new != old :
107107 with open (path , 'w' , encoding = 'utf-8' ) as f : f .write (new )
108108
109- # %% ../nbs/13_nbio.ipynb #102e32c6
110- from .xml import Code ,Markdown ,Raw ,NB ,Source ,Out ,to_xml
109+ # %% ../nbs/13_nbio.ipynb #530b9cd1
110+ from .xml import Code ,Markdown ,Raw ,NB ,Source ,Out ,to_xml ,ft
111+
112+ # %% ../nbs/13_nbio.ipynb #9f22b923
113+ def preferred_out (data , html1st = True , include_imgs = False ):
114+ preftyps = ('application/javascript' , 'text/latex' )
115+ preftyps = (('text/html' , 'text/markdown' ) if html1st else ('text/markdown' , 'text/html' )) + preftyps
116+ if include_imgs : preftyps += 'image/jpeg' ,'image/png' ,'image/svg+xml'
117+ preftyps += ('text/plain' ,)
118+ for mt in preftyps :
119+ if (text := data .get (mt )): return mt ,text
120+ return 'text/plain' ,''
121+
122+ # %% ../nbs/13_nbio.ipynb #efec6078
123+ def apply_controls (text ):
124+ r"Apply \r and \b to text, returning processed result"
125+ lines = text .split ('\n ' )
126+ for i , line in enumerate (lines ):
127+ if 0 < (rpos := line .rfind ('\r ' ))< len (line )- 1 : lines [i ] = line [rpos + 1 :]
128+ text = '\n ' .join (lines )
129+ while (pos := text .find ('\b ' )) >= 0 : text = text [:max (0 , pos - 1 )] + text [pos + 1 :]
130+ return text
131+
132+ # %% ../nbs/13_nbio.ipynb #24a47a87
133+ def _join (d ): return '' .join (d ) if isinstance (d , list ) else d
134+
135+ # %% ../nbs/13_nbio.ipynb #51fcbb01
136+ def mk_stream (name , text ):
137+ "Helper to create an output stream dict"
138+ return {'output_type' : 'stream' , 'name' : name , 'text' : text }
139+
140+ def _mkout (typ , metadata = None , ** data ):
141+ return dict (output_type = typ , data = {k .replace ('_' ,'/' ):v for k ,v in data .items ()}, metadata = metadata or {})
142+
143+ def mk_result (metadata = None , ** data ):
144+ "Helper to create an execute_result output dict"
145+ return _mkout ('execute_result' , metadata , ** data )
146+
147+ def mk_display (metadata = None , ** data ):
148+ "Helper to create a display_data output dict"
149+ return _mkout ('display_data' , metadata , ** data )
150+
151+ def mk_error (traceback , ename = '' , evalue = '' ):
152+ "Helper to create an error output dict"
153+ return dict (output_type = 'error' , ename = ename , evalue = evalue , traceback = listify (traceback ))
154+
155+ # %% ../nbs/13_nbio.ipynb #493e36b0
156+ def concat_streams (outputs ):
157+ "Concatenate stream outputs by name (stdout/stderr), preserving execute_result at end"
158+ streams , res , execute_results = {}, [], []
159+ for out in outputs :
160+ if out ['output_type' ] == 'stream' :
161+ name , text = out ['name' ], _join (out ['text' ])
162+ streams [name ] = apply_controls (streams .get (name , '' ) + text )
163+ elif out ['output_type' ] in ('error' ,'execute_result' ): execute_results .append (out )
164+ else : res .append (out )
165+ if 'stdout' in streams : res .append (mk_stream ('stdout' , streams ['stdout' ]))
166+ if 'stderr' in streams : res .append (mk_stream ('stderr' , streams ['stderr' ]))
167+ res .extend (execute_results )
168+ return res
169+
170+ # %% ../nbs/13_nbio.ipynb #a3deacac
171+ def _preferred_msg_out (out , ** kwargs ):
172+ typ = out ['output_type' ]
173+ if typ == 'stream' : return 'text/plain' , _join (out .get ('text' , "" ))
174+ elif typ == 'error' : return 'text/plain' , '\n ' .join (out .get ('traceback' , []))
175+ elif typ in ('execute_result' , 'display_data' ): return preferred_out (out .get ('data' , {}), ** kwargs )
176+ return 'text/plain' ,f'Error: Failed to parse unknown output - { out } '
177+
178+ # %% ../nbs/13_nbio.ipynb #4daf81fd
179+ def render_output (out ):
180+ "Convert a single output dict to an HTML string"
181+ def _fmt (text ):
182+ res = ansi2html (str (text ))
183+ return f'<pre class="!border-0 !rounded-none !my-0 !p-0"><code class="nohighlight">{ res } </code></pre>'
184+ ptyp ,d = _preferred_msg_out (out , html1st = True , include_imgs = True )
185+ d = _join (d )
186+ if ptyp == 'text/plain' : return _fmt (d )
187+ elif ptyp == 'text/html' : return d
188+ elif ptyp == 'application/javascript' : return f'<script>{ d } </script>'
189+ elif ptyp == 'text/markdown' : return d
190+ elif ptyp == 'text/latex' : return f'<div>{ d } </div>'
191+ elif ptyp == 'image/jpeg' : return f'<img src="data:image/jpeg;base64,{ d } "/>'
192+ elif ptyp == 'image/png' : return f'<img src="data:image/png;base64,{ d } "/>'
193+ elif ptyp == 'image/svg+xml' : return d
194+ return ''
195+
196+ # %% ../nbs/13_nbio.ipynb #e59b5289
197+ def render_outputs (outputs ):
198+ "Render a full list of outputs, concatenating streams first."
199+ if (not isinstance (outputs , (list ,tuple ))) or (outputs and not isinstance (outputs [0 ],dict )): return ''
200+ return '\n ' .join (render_output (o ) for o in concat_streams (outputs ))
201+
202+ # %% ../nbs/13_nbio.ipynb #88b0018a
203+ def _render_text (out , html1st = False ):
204+ typ = out ['output_type' ]
205+ mime ,d = _preferred_msg_out (out , html1st = html1st , include_imgs = False )
206+ d = _join (d )
207+ if not d : return None
208+ attrs = {}
209+ if typ == 'stream' : typ = out .get ('name' )
210+ elif typ in ('execute_result' ,'display_data' ) and mime != 'text/plain' : attrs ['mime' ] = mime
211+ body = f'\n { d } ' if d .endswith ('\n ' ) else f'\n { d } \n '
212+ return d , to_xml (ft (typ , body , ** attrs ), do_escape = False , indent = False )
213+
214+ def render_text (outputs , html1st = False ):
215+ "Render notebook outputs to concise text, using XML-ish tags when multiple outputs are present."
216+ if (not isinstance (outputs , (list ,tuple ))) or (outputs and not isinstance (outputs [0 ],dict )): return ''
217+ items = [o for out in concat_streams (outputs ) if (o := _render_text (out , html1st = html1st ))]
218+ if not items : return ''
219+ return items [0 ][0 ] if len (items )== 1 else '\n ' .join (o [1 ] for o in items )
111220
112221# %% ../nbs/13_nbio.ipynb #ca73be1c
113222_ctfuns_nb = dict (code = Code , markdown = Markdown , raw = Raw )
@@ -118,7 +227,7 @@ def cell2xml(cell, ids=True, incl_out=True):
118227 kw = dict (id = cell .id ) if ids else {}
119228 output = getattr (cell , 'outputs' , None ) if incl_out else None
120229 if not output : return f (cell .source , ** kw )
121- return f (Source (cell .source ), Out (str (output )), ** kw )
230+ return f (Source (cell .source ), Out (render_text (output )), ** kw )
122231
123232def cells2xml (cells , wrap = NB , ids = True , incl_out = True , ** kw ):
124233 "Convert notebook cells to XML format"
@@ -202,78 +311,3 @@ def view(self:Notebook, id, nums=True):
202311 lines = self [id ].source .splitlines ()
203312 if nums : lines = [f'{ i + 1 :6d} │ { l } ' for i ,l in enumerate (lines )]
204313 return '\n ' .join (lines )
205-
206- # %% ../nbs/13_nbio.ipynb #e9e2dd49
207- def preferred_out (data , html1st = True , include_imgs = False ):
208- preftyps = ('application/javascript' , 'text/latex' )
209- preftyps = (('text/html' , 'text/markdown' ) if html1st else ('text/markdown' , 'text/html' )) + preftyps
210- if include_imgs : preftyps += 'image/jpeg' ,'image/png' ,'image/svg+xml'
211- preftyps += ('text/plain' ,)
212- for mt in preftyps :
213- if (text := data .get (mt )): return mt ,text
214- return 'text/plain' ,''
215-
216- # %% ../nbs/13_nbio.ipynb #7ca5835e
217- def apply_controls (text ):
218- r"Apply \r and \b to text, returning processed result"
219- lines = text .split ('\n ' )
220- for i , line in enumerate (lines ):
221- if 0 < (rpos := line .rfind ('\r ' ))< len (line )- 1 : lines [i ] = line [rpos + 1 :]
222- text = '\n ' .join (lines )
223- while (pos := text .find ('\b ' )) >= 0 : text = text [:max (0 , pos - 1 )] + text [pos + 1 :]
224- return text
225-
226- # %% ../nbs/13_nbio.ipynb #b2078b30
227- def _join (d ): return '' .join (d ) if isinstance (d , list ) else d
228-
229- # %% ../nbs/13_nbio.ipynb #19700480
230- def mk_stream (name , text ):
231- "Helper to create an output stream dict"
232- return {'output_type' : 'stream' , 'name' : name , 'text' : text }
233-
234- # %% ../nbs/13_nbio.ipynb #4af14ed7
235- def concat_streams (outputs ):
236- "Concatenate stream outputs by name (stdout/stderr), preserving execute_result at end"
237- streams , res , execute_results = {}, [], []
238- for out in outputs :
239- if out ['output_type' ] == 'stream' :
240- name , text = out ['name' ], _join (out ['text' ])
241- streams [name ] = apply_controls (streams .get (name , '' ) + text )
242- elif out ['output_type' ] in ('error' ,'execute_result' ): execute_results .append (out )
243- else : res .append (out )
244- if 'stdout' in streams : res .append (mk_stream ('stdout' , streams ['stdout' ]))
245- if 'stderr' in streams : res .append (mk_stream ('stderr' , streams ['stderr' ]))
246- res .extend (execute_results )
247- return res
248-
249- # %% ../nbs/13_nbio.ipynb #12560bc9
250- def _preferred_msg_out (out , ** kwargs ):
251- typ = out ['output_type' ]
252- if typ == 'stream' : return 'text/plain' , _join (out .get ('text' , "" ))
253- elif typ == 'error' : return 'text/plain' , '\n ' .join (out .get ('traceback' , []))
254- elif typ in ('execute_result' , 'display_data' ): return preferred_out (out .get ('data' , {}), ** kwargs )
255- return 'text/plain' ,f'Error: Failed to parse unknown output - { out } '
256-
257- # %% ../nbs/13_nbio.ipynb #7d321a24
258- def render_output (out ):
259- "Convert a single output dict to an HTML string"
260- def _fmt (text ):
261- res = ansi2html (str (text ))
262- return f'<pre class="!border-0 !rounded-none !my-0 !p-0"><code class="nohighlight">{ res } </code></pre>'
263- ptyp ,d = _preferred_msg_out (out , html1st = True , include_imgs = True )
264- d = _join (d )
265- if ptyp == 'text/plain' : return _fmt (d )
266- elif ptyp == 'text/html' : return d
267- elif ptyp == 'application/javascript' : return f'<script>{ d } </script>'
268- elif ptyp == 'text/markdown' : return d
269- elif ptyp == 'text/latex' : return f'<div>{ d } </div>'
270- elif ptyp == 'image/jpeg' : return f'<img src="data:image/jpeg;base64,{ d } "/>'
271- elif ptyp == 'image/png' : return f'<img src="data:image/png;base64,{ d } "/>'
272- elif ptyp == 'image/svg+xml' : return d
273- return ''
274-
275- # %% ../nbs/13_nbio.ipynb #5ff35ad7
276- def render_outputs (outputs ):
277- "Render a full list of outputs, concatenating streams first."
278- if (not isinstance (outputs , (list ,tuple ))) or (outputs and not isinstance (outputs [0 ],dict )): return ''
279- return '\n ' .join (render_output (o ) for o in concat_streams (outputs ))
0 commit comments