execnb 0.1.6__tar.gz → 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {execnb-0.1.6/execnb.egg-info → execnb-0.1.7}/PKG-INFO +2 -1
- execnb-0.1.7/execnb/__init__.py +1 -0
- {execnb-0.1.6 → execnb-0.1.7}/execnb/_modidx.py +19 -15
- {execnb-0.1.6 → execnb-0.1.7}/execnb/nbio.py +12 -10
- execnb-0.1.7/execnb/shell.py +289 -0
- {execnb-0.1.6 → execnb-0.1.7/execnb.egg-info}/PKG-INFO +2 -1
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/SOURCES.txt +1 -1
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/requires.txt +1 -0
- execnb-0.1.7/pyproject.toml +3 -0
- {execnb-0.1.6 → execnb-0.1.7}/settings.ini +7 -5
- execnb-0.1.6/execnb/__init__.py +0 -1
- execnb-0.1.6/execnb/fastshell.py +0 -124
- execnb-0.1.6/execnb/shell.py +0 -248
- {execnb-0.1.6 → execnb-0.1.7}/LICENSE +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/MANIFEST.in +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/README.md +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/dependency_links.txt +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/entry_points.txt +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/not-zip-safe +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/execnb.egg-info/top_level.txt +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/setup.cfg +0 -0
- {execnb-0.1.6 → execnb-0.1.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: execnb
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.7
|
4
4
|
Summary: A description of your project
|
5
5
|
Home-page: https://github.com/fastai/execnb/
|
6
6
|
Author: Jeremy Howard
|
@@ -18,6 +18,7 @@ Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
19
19
|
Requires-Dist: fastcore>=1.5.5
|
20
20
|
Requires-Dist: ipython
|
21
|
+
Requires-Dist: mistletoe
|
21
22
|
Provides-Extra: dev
|
22
23
|
Requires-Dist: matplotlib; extra == "dev"
|
23
24
|
Requires-Dist: Pillow; extra == "dev"
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.7"
|
@@ -5,8 +5,7 @@ d = { 'settings': { 'branch': 'master',
|
|
5
5
|
'doc_host': 'https://fastai.github.io',
|
6
6
|
'git_url': 'https://github.com/fastai/execnb/',
|
7
7
|
'lib_path': 'execnb'},
|
8
|
-
'syms': { 'execnb.
|
9
|
-
'execnb.nbio': { 'execnb.nbio.NbCell': ('nbio.html#nbcell', 'execnb/nbio.py'),
|
8
|
+
'syms': { 'execnb.nbio': { 'execnb.nbio.NbCell': ('nbio.html#nbcell', 'execnb/nbio.py'),
|
10
9
|
'execnb.nbio.NbCell.__eq__': ('nbio.html#nbcell.__eq__', 'execnb/nbio.py'),
|
11
10
|
'execnb.nbio.NbCell.__hash__': ('nbio.html#nbcell.__hash__', 'execnb/nbio.py'),
|
12
11
|
'execnb.nbio.NbCell.__init__': ('nbio.html#nbcell.__init__', 'execnb/nbio.py'),
|
@@ -23,31 +22,36 @@ d = { 'settings': { 'branch': 'master',
|
|
23
22
|
'execnb.nbio.write_nb': ('nbio.html#write_nb', 'execnb/nbio.py')},
|
24
23
|
'execnb.shell': { 'execnb.shell.CaptureShell': ('shell.html#captureshell', 'execnb/shell.py'),
|
25
24
|
'execnb.shell.CaptureShell.__init__': ('shell.html#captureshell.__init__', 'execnb/shell.py'),
|
26
|
-
'execnb.shell.CaptureShell._add_exec': ('shell.html#captureshell._add_exec', 'execnb/shell.py'),
|
27
|
-
'execnb.shell.CaptureShell._add_out': ('shell.html#captureshell._add_out', 'execnb/shell.py'),
|
28
|
-
'execnb.shell.CaptureShell._result': ('shell.html#captureshell._result', 'execnb/shell.py'),
|
29
|
-
'execnb.shell.CaptureShell._showtraceback': ('shell.html#captureshell._showtraceback', 'execnb/shell.py'),
|
30
|
-
'execnb.shell.CaptureShell._stream': ('shell.html#captureshell._stream', 'execnb/shell.py'),
|
31
25
|
'execnb.shell.CaptureShell.cell': ('shell.html#captureshell.cell', 'execnb/shell.py'),
|
26
|
+
'execnb.shell.CaptureShell.complete': ('shell.html#captureshell.complete', 'execnb/shell.py'),
|
32
27
|
'execnb.shell.CaptureShell.enable_gui': ('shell.html#captureshell.enable_gui', 'execnb/shell.py'),
|
33
|
-
'execnb.shell.CaptureShell.enable_matplotlib': ( 'shell.html#captureshell.enable_matplotlib',
|
34
|
-
'execnb/shell.py'),
|
35
28
|
'execnb.shell.CaptureShell.execute': ('shell.html#captureshell.execute', 'execnb/shell.py'),
|
36
29
|
'execnb.shell.CaptureShell.prettytb': ('shell.html#captureshell.prettytb', 'execnb/shell.py'),
|
37
30
|
'execnb.shell.CaptureShell.run': ('shell.html#captureshell.run', 'execnb/shell.py'),
|
38
31
|
'execnb.shell.CaptureShell.run_all': ('shell.html#captureshell.run_all', 'execnb/shell.py'),
|
32
|
+
'execnb.shell.CaptureShell.run_cell': ('shell.html#captureshell.run_cell', 'execnb/shell.py'),
|
39
33
|
'execnb.shell.CaptureShell.set_path': ('shell.html#captureshell.set_path', 'execnb/shell.py'),
|
40
|
-
'execnb.shell.
|
41
|
-
'execnb.shell.
|
42
|
-
'execnb.shell.
|
43
|
-
'execnb.shell.
|
44
|
-
'execnb.shell.
|
34
|
+
'execnb.shell.ExecutionInfo.__repr__': ('shell.html#executioninfo.__repr__', 'execnb/shell.py'),
|
35
|
+
'execnb.shell.ExecutionResult.__repr__': ('shell.html#executionresult.__repr__', 'execnb/shell.py'),
|
36
|
+
'execnb.shell.SmartCompleter': ('shell.html#smartcompleter', 'execnb/shell.py'),
|
37
|
+
'execnb.shell.SmartCompleter.__call__': ('shell.html#smartcompleter.__call__', 'execnb/shell.py'),
|
38
|
+
'execnb.shell.SmartCompleter.__init__': ('shell.html#smartcompleter.__init__', 'execnb/shell.py'),
|
39
|
+
'execnb.shell._CustDisplayHook': ('shell.html#_custdisplayhook', 'execnb/shell.py'),
|
40
|
+
'execnb.shell._CustDisplayHook.log_output': ('shell.html#_custdisplayhook.log_output', 'execnb/shell.py'),
|
41
|
+
'execnb.shell._CustDisplayHook.write_format_data': ( 'shell.html#_custdisplayhook.write_format_data',
|
42
|
+
'execnb/shell.py'),
|
43
|
+
'execnb.shell._CustDisplayHook.write_output_prompt': ( 'shell.html#_custdisplayhook.write_output_prompt',
|
44
|
+
'execnb/shell.py'),
|
45
45
|
'execnb.shell._false': ('shell.html#_false', 'execnb/shell.py'),
|
46
46
|
'execnb.shell._format_mimedata': ('shell.html#_format_mimedata', 'execnb/shell.py'),
|
47
|
+
'execnb.shell._mk_out': ('shell.html#_mk_out', 'execnb/shell.py'),
|
47
48
|
'execnb.shell._out_exc': ('shell.html#_out_exc', 'execnb/shell.py'),
|
49
|
+
'execnb.shell._out_nb': ('shell.html#_out_nb', 'execnb/shell.py'),
|
48
50
|
'execnb.shell._out_stream': ('shell.html#_out_stream', 'execnb/shell.py'),
|
49
51
|
'execnb.shell.exec_nb': ('shell.html#exec_nb', 'execnb/shell.py'),
|
50
52
|
'execnb.shell.find_output': ('shell.html#find_output', 'execnb/shell.py'),
|
53
|
+
'execnb.shell.format_exc': ('shell.html#format_exc', 'execnb/shell.py'),
|
51
54
|
'execnb.shell.out_error': ('shell.html#out_error', 'execnb/shell.py'),
|
52
55
|
'execnb.shell.out_exec': ('shell.html#out_exec', 'execnb/shell.py'),
|
53
|
-
'execnb.shell.out_stream': ('shell.html#out_stream', 'execnb/shell.py')
|
56
|
+
'execnb.shell.out_stream': ('shell.html#out_stream', 'execnb/shell.py'),
|
57
|
+
'execnb.shell.render_outputs': ('shell.html#render_outputs', 'execnb/shell.py')}}}
|
@@ -1,9 +1,11 @@
|
|
1
|
+
"""Reading and writing Jupyter notebooks"""
|
2
|
+
|
1
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_nbio.ipynb.
|
2
4
|
|
3
5
|
# %% auto 0
|
4
6
|
__all__ = ['NbCell', 'dict2nb', 'read_nb', 'new_nb', 'mk_cell', 'nb2dict', 'nb2str', 'write_nb']
|
5
7
|
|
6
|
-
# %% ../nbs/01_nbio.ipynb
|
8
|
+
# %% ../nbs/01_nbio.ipynb
|
7
9
|
from fastcore.basics import *
|
8
10
|
from fastcore.imports import *
|
9
11
|
|
@@ -11,11 +13,11 @@ import ast,functools
|
|
11
13
|
from pprint import pformat,pprint
|
12
14
|
from json import loads,dumps
|
13
15
|
|
14
|
-
# %% ../nbs/01_nbio.ipynb
|
16
|
+
# %% ../nbs/01_nbio.ipynb
|
15
17
|
def _read_json(self, encoding=None, errors=None):
|
16
18
|
return loads(Path(self).read_text(encoding=encoding, errors=errors))
|
17
19
|
|
18
|
-
# %% ../nbs/01_nbio.ipynb
|
20
|
+
# %% ../nbs/01_nbio.ipynb
|
19
21
|
class NbCell(AttrDict):
|
20
22
|
def __init__(self, idx, cell):
|
21
23
|
super().__init__(cell)
|
@@ -38,7 +40,7 @@ class NbCell(AttrDict):
|
|
38
40
|
def __hash__(self): return hash(self.source) + hash(self.cell_type)
|
39
41
|
def __eq__(self,o): return self.source==o.source and self.cell_type==o.cell_type
|
40
42
|
|
41
|
-
# %% ../nbs/01_nbio.ipynb
|
43
|
+
# %% ../nbs/01_nbio.ipynb
|
42
44
|
def _dict2obj(d, list_func=list, dict_func=AttrDict):
|
43
45
|
"Convert (possibly nested) dicts (or lists of dicts) to `AttrDict`"
|
44
46
|
if isinstance(d, list): return list(map(_dict2obj, d))
|
@@ -51,19 +53,19 @@ def dict2nb(js=None, **kwargs):
|
|
51
53
|
nb.cells = [NbCell(*o) for o in enumerate(nb.cells)]
|
52
54
|
return nb
|
53
55
|
|
54
|
-
# %% ../nbs/01_nbio.ipynb
|
56
|
+
# %% ../nbs/01_nbio.ipynb
|
55
57
|
def read_nb(path):
|
56
58
|
"Return notebook at `path`"
|
57
59
|
res = dict2nb(_read_json(path, encoding='utf-8'))
|
58
60
|
res['path_'] = str(path)
|
59
61
|
return res
|
60
62
|
|
61
|
-
# %% ../nbs/01_nbio.ipynb
|
63
|
+
# %% ../nbs/01_nbio.ipynb
|
62
64
|
def new_nb(cells=None, meta=None, nbformat=4, nbformat_minor=5):
|
63
65
|
"Returns an empty new notebook"
|
64
66
|
return dict2nb(cells=cells or [],metadata=meta or {},nbformat=nbformat,nbformat_minor=nbformat_minor)
|
65
67
|
|
66
|
-
# %% ../nbs/01_nbio.ipynb
|
68
|
+
# %% ../nbs/01_nbio.ipynb
|
67
69
|
def mk_cell(text, # `source` attr in cell
|
68
70
|
cell_type='code', # `cell_type` attr in cell
|
69
71
|
**kwargs): # any other attrs to add to cell
|
@@ -75,7 +77,7 @@ def mk_cell(text, # `source` attr in cell
|
|
75
77
|
kwargs['execution_count']=0
|
76
78
|
return NbCell(0, dict(cell_type=cell_type, source=text, directives_={}, **kwargs))
|
77
79
|
|
78
|
-
# %% ../nbs/01_nbio.ipynb
|
80
|
+
# %% ../nbs/01_nbio.ipynb
|
79
81
|
def nb2dict(d, k=None):
|
80
82
|
"Convert parsed notebook to `dict`"
|
81
83
|
if k=='source': return d.splitlines(keepends=True)
|
@@ -83,13 +85,13 @@ def nb2dict(d, k=None):
|
|
83
85
|
if not isinstance(d, dict): return d
|
84
86
|
return dict(**{k:nb2dict(v,k) for k,v in d.items() if k[-1] != '_'})
|
85
87
|
|
86
|
-
# %% ../nbs/01_nbio.ipynb
|
88
|
+
# %% ../nbs/01_nbio.ipynb
|
87
89
|
def nb2str(nb):
|
88
90
|
"Convert `nb` to a `str`"
|
89
91
|
if isinstance(nb, (AttrDict,list)): nb = nb2dict(nb)
|
90
92
|
return dumps(nb, sort_keys=True, indent=1, ensure_ascii=False) + "\n"
|
91
93
|
|
92
|
-
# %% ../nbs/01_nbio.ipynb
|
94
|
+
# %% ../nbs/01_nbio.ipynb
|
93
95
|
def write_nb(nb, path):
|
94
96
|
"Write `nb` to `path`"
|
95
97
|
new = nb2str(nb)
|
@@ -0,0 +1,289 @@
|
|
1
|
+
"""A shell for running notebook code without a notebook server"""
|
2
|
+
|
3
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_shell.ipynb.
|
4
|
+
|
5
|
+
# %% ../nbs/02_shell.ipynb 2
|
6
|
+
from __future__ import annotations
|
7
|
+
|
8
|
+
from fastcore.utils import *
|
9
|
+
from fastcore.script import call_parse
|
10
|
+
from fastcore.ansi import ansi2html
|
11
|
+
|
12
|
+
import mistletoe,multiprocessing,types,traceback,signal
|
13
|
+
try:
|
14
|
+
if sys.platform == 'darwin': multiprocessing.set_start_method("fork")
|
15
|
+
except RuntimeError: pass # if re-running cell
|
16
|
+
|
17
|
+
from IPython.core.interactiveshell import InteractiveShell, ExecutionInfo, ExecutionResult
|
18
|
+
from IPython.core.displayhook import DisplayHook
|
19
|
+
from IPython.utils.capture import capture_output
|
20
|
+
from IPython.utils.text import strip_ansi
|
21
|
+
from IPython.core.completer import IPCompleter,provisionalcompleter
|
22
|
+
from IPython.core.hooks import CommandChainDispatcher
|
23
|
+
from IPython.core.completerlib import module_completer
|
24
|
+
from IPython.utils.strdispatch import StrDispatch
|
25
|
+
from IPython.display import display as disp, HTML
|
26
|
+
|
27
|
+
from base64 import b64encode
|
28
|
+
from html import escape
|
29
|
+
try: from matplotlib_inline.backend_inline import set_matplotlib_formats
|
30
|
+
except ImportError: set_matplotlib_formats = None
|
31
|
+
|
32
|
+
|
33
|
+
from .nbio import *
|
34
|
+
from .nbio import _dict2obj
|
35
|
+
|
36
|
+
# %% auto 0
|
37
|
+
__all__ = ['CaptureShell', 'format_exc', 'render_outputs', 'find_output', 'out_exec', 'out_stream', 'out_error', 'exec_nb',
|
38
|
+
'SmartCompleter']
|
39
|
+
|
40
|
+
# %% ../nbs/02_shell.ipynb
|
41
|
+
class _CustDisplayHook(DisplayHook):
|
42
|
+
def write_output_prompt(self): pass
|
43
|
+
def write_format_data(self, data, md_dict): pass
|
44
|
+
def log_output(self, format_dict): pass
|
45
|
+
|
46
|
+
@patch
|
47
|
+
def __repr__(self: ExecutionInfo): return f'cell: {self.raw_cell}; id: {self.cell_id}'
|
48
|
+
|
49
|
+
@patch
|
50
|
+
def __repr__(self: ExecutionResult): return f'result: {self.result}; err: {self.error_in_exec}; info: <{self.info}>'
|
51
|
+
|
52
|
+
# %% ../nbs/02_shell.ipynb
|
53
|
+
class CaptureShell(InteractiveShell):
|
54
|
+
displayhook_class = _CustDisplayHook
|
55
|
+
|
56
|
+
def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout=None):
|
57
|
+
super().__init__()
|
58
|
+
self.history_manager.enabled = history
|
59
|
+
self.timeout = timeout
|
60
|
+
self.result,self.exc = None,None
|
61
|
+
if path: self.set_path(path)
|
62
|
+
self.display_formatter.active = True
|
63
|
+
if not IN_NOTEBOOK: InteractiveShell._instance = self
|
64
|
+
if set_matplotlib_formats:
|
65
|
+
self.enable_matplotlib("inline")
|
66
|
+
self.run_cell("from matplotlib_inline.backend_inline import set_matplotlib_formats")
|
67
|
+
self.run_cell(f"set_matplotlib_formats('{mpl_format}')")
|
68
|
+
|
69
|
+
def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True, cell_id=None,
|
70
|
+
stdout=True, stderr=True, display=True, timeout=None):
|
71
|
+
if not timeout: timeout = self.timeout
|
72
|
+
# TODO what if there's a comment?
|
73
|
+
semic = raw_cell.rstrip().endswith(';')
|
74
|
+
if timeout:
|
75
|
+
def handler(*args): raise TimeoutError()
|
76
|
+
signal.signal(signal.SIGALRM, handler)
|
77
|
+
signal.alarm(timeout)
|
78
|
+
with capture_output(display=display, stdout=stdout, stderr=stderr) as c:
|
79
|
+
result = super().run_cell(raw_cell, store_history, silent, shell_futures=shell_futures, cell_id=cell_id)
|
80
|
+
if timeout: signal.alarm(0)
|
81
|
+
return AttrDict(result=result, stdout='' if semic else c.stdout, stderr=c.stderr,
|
82
|
+
display_objects=c.outputs, exception=result.error_in_exec, quiet=semic)
|
83
|
+
|
84
|
+
def set_path(self, path):
|
85
|
+
"Add `path` to python path, or `path.parent` if it's a file"
|
86
|
+
path = Path(path)
|
87
|
+
if path.is_file(): path = path.parent
|
88
|
+
self.run_cell(f"import sys; sys.path.insert(0, '{path.as_posix()}')")
|
89
|
+
|
90
|
+
def enable_gui(self, gui=None): pass
|
91
|
+
|
92
|
+
# %% ../nbs/02_shell.ipynb
|
93
|
+
def format_exc(e):
|
94
|
+
"Format exception `e` as a string"
|
95
|
+
return ''.join(traceback.format_exception(type(e), e, e.__traceback__))
|
96
|
+
|
97
|
+
# %% ../nbs/02_shell.ipynb
|
98
|
+
def _out_stream(text, name): return dict(name=name, output_type='stream', text=text.splitlines(True))
|
99
|
+
def _out_exc(e):
|
100
|
+
ename = type(e).__name__
|
101
|
+
tb = traceback.extract_tb(e.__traceback__)#.format()
|
102
|
+
return dict(ename=str(ename), evalue=str(e), output_type='error', traceback=format_exc(e))
|
103
|
+
|
104
|
+
def _format_mimedata(k, v):
|
105
|
+
"Format mime-type keyed data consistently with Jupyter"
|
106
|
+
if k.startswith('text/'): return v.splitlines(True)
|
107
|
+
if k.startswith('image/') and isinstance(v, bytes):
|
108
|
+
v = b64encode(v).decode()
|
109
|
+
return v+'\n' if not v.endswith('\n') else v
|
110
|
+
return v
|
111
|
+
|
112
|
+
def _mk_out(data, meta, output_type='display_data'):
|
113
|
+
fd = {k:_format_mimedata(k,v) for k,v in data.items()}
|
114
|
+
return dict(data=fd, metadata=meta, output_type=output_type)
|
115
|
+
|
116
|
+
def _out_nb(o, fmt):
|
117
|
+
res = []
|
118
|
+
if o.stdout: res.append(_out_stream(o.stdout, 'stdout'))
|
119
|
+
if o.stderr: res.append(_out_stream(o.stderr, 'stderr'))
|
120
|
+
if o.exception: res.append(_out_exc(o.exception))
|
121
|
+
r = o.result.result
|
122
|
+
for x in o.display_objects: res.append(_mk_out(x.data, x.metadata))
|
123
|
+
if r is not None and not o.quiet:
|
124
|
+
res.append(_mk_out(*fmt.format(r), 'execute_result'))
|
125
|
+
return res
|
126
|
+
|
127
|
+
# %% ../nbs/02_shell.ipynb
|
128
|
+
@patch
|
129
|
+
def run(self:CaptureShell,
|
130
|
+
code:str, # Python/IPython code to run
|
131
|
+
stdout=True, # Capture stdout and save as output?
|
132
|
+
stderr=True): # Capture stderr and save as output?
|
133
|
+
"Run `code`, returning a list of all outputs in Jupyter notebook format"
|
134
|
+
res = self.run_cell(code, stdout=stdout, stderr=stderr)
|
135
|
+
self.result = res.result.result
|
136
|
+
self.exc = res.exception
|
137
|
+
return _out_nb(res, self.display_formatter)
|
138
|
+
|
139
|
+
# %% ../nbs/02_shell.ipynb
|
140
|
+
def render_outputs(outputs, ansi_renderer=strip_ansi):
|
141
|
+
def render_output(out):
|
142
|
+
otype = out['output_type']
|
143
|
+
if otype == 'stream':
|
144
|
+
txt = ansi_renderer(''.join(out['text']))
|
145
|
+
return f"<pre>{txt}</pre>" if out['name']=='stdout' else f"<pre class='stderr'>{txt}</pre>"
|
146
|
+
elif otype in ('display_data','execute_result'):
|
147
|
+
data = out['data']
|
148
|
+
_g = lambda t: ''.join(data[t]) if t in data else None
|
149
|
+
if d := _g('text/html'): return d
|
150
|
+
if d := _g('application/javascript'): return f'<script>{d}</script>'
|
151
|
+
if d := _g('text/markdown'): return mistletoe.markdown(d)
|
152
|
+
if d := _g('image/svg+xml'): return d
|
153
|
+
if d := _g('image/jpeg'): return f'<img src="data:image/jpeg;base64,{d}"/>'
|
154
|
+
if d := _g('image/png'): return f'<img src="data:image/png;base64,{d}"/>'
|
155
|
+
if d := _g('text/latex'): return f'<div class="math">${d}$</div>'
|
156
|
+
if d := _g('text/plain'): return f"<pre>{escape(d)}</pre>"
|
157
|
+
return ''
|
158
|
+
|
159
|
+
return '\n'.join(map(render_output, outputs))
|
160
|
+
|
161
|
+
# %% ../nbs/02_shell.ipynb
|
162
|
+
@patch
|
163
|
+
def cell(self:CaptureShell, cell, stdout=True, stderr=True):
|
164
|
+
"Run `cell`, skipping if not code, and store outputs back in cell"
|
165
|
+
if cell.cell_type!='code': return
|
166
|
+
self._cell_idx = cell.idx_ + 1
|
167
|
+
outs = self.run(cell.source)
|
168
|
+
if outs:
|
169
|
+
cell.outputs = _dict2obj(outs)
|
170
|
+
for o in outs:
|
171
|
+
if 'execution_count' in o: cell['execution_count'] = o['execution_count']
|
172
|
+
|
173
|
+
# %% ../nbs/02_shell.ipynb
|
174
|
+
def find_output(outp, # Output from `run`
|
175
|
+
ot='execute_result' # Output_type to find
|
176
|
+
):
|
177
|
+
"Find first output of type `ot` in `CaptureShell.run` output"
|
178
|
+
return first(o for o in outp if o['output_type']==ot)
|
179
|
+
|
180
|
+
# %% ../nbs/02_shell.ipynb
|
181
|
+
def out_exec(outp):
|
182
|
+
"Get data from execution result in `outp`."
|
183
|
+
out = find_output(outp)
|
184
|
+
if out: return '\n'.join(first(out['data'].values()))
|
185
|
+
|
186
|
+
# %% ../nbs/02_shell.ipynb
|
187
|
+
def out_stream(outp):
|
188
|
+
"Get text from stream in `outp`."
|
189
|
+
out = find_output(outp, 'stream')
|
190
|
+
if out: return ('\n'.join(out['text'])).strip()
|
191
|
+
|
192
|
+
# %% ../nbs/02_shell.ipynb
|
193
|
+
def out_error(outp):
|
194
|
+
"Get traceback from error in `outp`."
|
195
|
+
out = find_output(outp, 'error')
|
196
|
+
if out: return '\n'.join(out['traceback'])
|
197
|
+
|
198
|
+
# %% ../nbs/02_shell.ipynb
|
199
|
+
def _false(o): return False
|
200
|
+
|
201
|
+
@patch
|
202
|
+
def run_all(self:CaptureShell,
|
203
|
+
nb, # A notebook read with `nbclient` or `read_nb`
|
204
|
+
exc_stop:bool=False, # Stop on exceptions?
|
205
|
+
preproc:callable=_false, # Called before each cell is executed
|
206
|
+
postproc:callable=_false, # Called after each cell is executed
|
207
|
+
inject_code:str|None=None, # Code to inject into a cell
|
208
|
+
inject_idx:int=0 # Cell to replace with `inject_code`
|
209
|
+
):
|
210
|
+
"Run all cells in `nb`, stopping at first exception if `exc_stop`"
|
211
|
+
if inject_code is not None: nb.cells[inject_idx].source = inject_code
|
212
|
+
for cell in nb.cells:
|
213
|
+
if not preproc(cell):
|
214
|
+
self.cell(cell)
|
215
|
+
postproc(cell)
|
216
|
+
if self.exc and exc_stop: raise self.exc from None
|
217
|
+
|
218
|
+
# %% ../nbs/02_shell.ipynb
|
219
|
+
@patch
|
220
|
+
def execute(self:CaptureShell,
|
221
|
+
src:str|Path, # Notebook path to read from
|
222
|
+
dest:str|None=None, # Notebook path to write to
|
223
|
+
exc_stop:bool=False, # Stop on exceptions?
|
224
|
+
preproc:callable=_false, # Called before each cell is executed
|
225
|
+
postproc:callable=_false, # Called after each cell is executed
|
226
|
+
inject_code:str|None=None, # Code to inject into a cell
|
227
|
+
inject_path:str|Path|None=None, # Path to file containing code to inject into a cell
|
228
|
+
inject_idx:int=0 # Cell to replace with `inject_code`
|
229
|
+
):
|
230
|
+
"Execute notebook from `src` and save with outputs to `dest"
|
231
|
+
nb = read_nb(src)
|
232
|
+
self._fname = src
|
233
|
+
self.set_path(Path(src).parent.resolve())
|
234
|
+
if inject_path is not None: inject_code = Path(inject_path).read_text()
|
235
|
+
self.run_all(nb, exc_stop=exc_stop, preproc=preproc, postproc=postproc,
|
236
|
+
inject_code=inject_code, inject_idx=inject_idx)
|
237
|
+
if dest: write_nb(nb, dest)
|
238
|
+
|
239
|
+
# %% ../nbs/02_shell.ipynb
|
240
|
+
@patch
|
241
|
+
def prettytb(self:CaptureShell,
|
242
|
+
fname:str|Path=None): # filename to print alongside the traceback
|
243
|
+
"Show a pretty traceback for notebooks, optionally printing `fname`."
|
244
|
+
fname = fname if fname else self._fname
|
245
|
+
_fence = '='*75
|
246
|
+
cell_intro_str = f"While Executing Cell #{self._cell_idx}:" if self._cell_idx else "While Executing:"
|
247
|
+
cell_str = f"\n{cell_intro_str}\n{format_exc(self.exc)}"
|
248
|
+
fname_str = f' in {fname}' if fname else ''
|
249
|
+
return f"{type(self.exc).__name__}{fname_str}:\n{_fence}\n{cell_str}\n"
|
250
|
+
|
251
|
+
# %% ../nbs/02_shell.ipynb
|
252
|
+
@call_parse
|
253
|
+
def exec_nb(
|
254
|
+
src:str, # Notebook path to read from
|
255
|
+
dest:str='', # Notebook path to write to
|
256
|
+
exc_stop:bool=False, # Stop on exceptions?
|
257
|
+
inject_code:str=None, # Code to inject into a cell
|
258
|
+
inject_path:str=None, # Path to file containing code to inject into a cell
|
259
|
+
inject_idx:int=0 # Cell to replace with `inject_code`
|
260
|
+
):
|
261
|
+
"Execute notebook from `src` and save with outputs to `dest`"
|
262
|
+
CaptureShell().execute(src, dest, exc_stop=exc_stop, inject_code=inject_code,
|
263
|
+
inject_path=inject_path, inject_idx=inject_idx)
|
264
|
+
|
265
|
+
# %% ../nbs/02_shell.ipynb
|
266
|
+
class SmartCompleter(IPCompleter):
|
267
|
+
def __init__(self, shell, namespace=None, jedi=False):
|
268
|
+
if namespace is None: namespace = shell.user_ns
|
269
|
+
super().__init__(shell, namespace)
|
270
|
+
self.use_jedi = jedi
|
271
|
+
sdisp = StrDispatch()
|
272
|
+
self.custom_completers = sdisp
|
273
|
+
import_disp = CommandChainDispatcher()
|
274
|
+
import_disp.add(types.MethodType(module_completer, shell))
|
275
|
+
sdisp.add_s('import', import_disp)
|
276
|
+
sdisp.add_s('from', import_disp)
|
277
|
+
|
278
|
+
def __call__(self, c):
|
279
|
+
if not c: return []
|
280
|
+
with provisionalcompleter():
|
281
|
+
return [o.text.rpartition('.')[-1]
|
282
|
+
for o in self.completions(c, len(c))
|
283
|
+
if o.type not in ('magic', 'path')]
|
284
|
+
|
285
|
+
# %% ../nbs/02_shell.ipynb
|
286
|
+
@patch
|
287
|
+
def complete(self:CaptureShell, c):
|
288
|
+
if not hasattr(self, '_completer'): self._completer = SmartCompleter(self)
|
289
|
+
return self._completer(c)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: execnb
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.7
|
4
4
|
Summary: A description of your project
|
5
5
|
Home-page: https://github.com/fastai/execnb/
|
6
6
|
Author: Jeremy Howard
|
@@ -18,6 +18,7 @@ Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
19
19
|
Requires-Dist: fastcore>=1.5.5
|
20
20
|
Requires-Dist: ipython
|
21
|
+
Requires-Dist: mistletoe
|
21
22
|
Provides-Extra: dev
|
22
23
|
Requires-Dist: matplotlib; extra == "dev"
|
23
24
|
Requires-Dist: Pillow; extra == "dev"
|
@@ -9,9 +9,9 @@ user = fastai
|
|
9
9
|
author = Jeremy Howard
|
10
10
|
author_email = j@fast.ai
|
11
11
|
branch = master
|
12
|
-
version = 0.1.
|
12
|
+
version = 0.1.7
|
13
13
|
min_python = 3.7
|
14
|
-
requirements = fastcore>=1.5.5 ipython
|
14
|
+
requirements = fastcore>=1.5.5 ipython mistletoe
|
15
15
|
dev_requirements = matplotlib Pillow
|
16
16
|
console_scripts = exec_nb=execnb.shell:exec_nb
|
17
17
|
audience = Developers
|
@@ -25,13 +25,13 @@ recursive = False
|
|
25
25
|
tst_flags = notest
|
26
26
|
doc_host = https://fastai.github.io
|
27
27
|
doc_baseurl = /execnb/
|
28
|
-
git_url = https://github.com
|
28
|
+
git_url = https://github.com/fastai/execnb/
|
29
29
|
lib_path = execnb
|
30
30
|
title = execnb
|
31
31
|
black_formatting = False
|
32
32
|
readme_nb = index.ipynb
|
33
|
-
allowed_metadata_keys =
|
34
|
-
allowed_cell_metadata_keys =
|
33
|
+
allowed_metadata_keys =
|
34
|
+
allowed_cell_metadata_keys =
|
35
35
|
conda_user = fastai
|
36
36
|
preview_port = 3000
|
37
37
|
preview_host = localhost
|
@@ -39,4 +39,6 @@ jupyter_hooks = True
|
|
39
39
|
clean_ids = True
|
40
40
|
clear_all = False
|
41
41
|
put_version_in_init = True
|
42
|
+
cell_number = False
|
43
|
+
skip_procs =
|
42
44
|
|
execnb-0.1.6/execnb/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.1.6"
|
execnb-0.1.6/execnb/fastshell.py
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
# Copyright (c) IPython Development Team.
|
2
|
-
# Modifications by Jeremy Howard
|
3
|
-
# Distributed under the terms of the Modified BSD License.
|
4
|
-
|
5
|
-
import os, sys, warnings
|
6
|
-
from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
|
7
|
-
from IPython.core.history import HistoryAccessorBase
|
8
|
-
from IPython.core.autocall import ZMQExitAutocall
|
9
|
-
from IPython.core.magic import magics_class, line_magic, Magics
|
10
|
-
from IPython.utils.process import system
|
11
|
-
from traitlets import Instance, Type, Any, default, observe
|
12
|
-
|
13
|
-
@magics_class
|
14
|
-
class KernelMagics(Magics):
|
15
|
-
@line_magic
|
16
|
-
def edit(self, parameter_s='', last_call=['','']): pass
|
17
|
-
|
18
|
-
@line_magic
|
19
|
-
def clear(self, arg_s): pass
|
20
|
-
|
21
|
-
@line_magic
|
22
|
-
def less(self, arg_s): pass
|
23
|
-
|
24
|
-
more = line_magic('more')(less)
|
25
|
-
|
26
|
-
# Man calls a pager, so we also need to redefine it
|
27
|
-
if os.name == 'posix':
|
28
|
-
@line_magic
|
29
|
-
def man(self, arg_s): pass
|
30
|
-
|
31
|
-
@line_magic
|
32
|
-
def autosave(self, arg_s): pass
|
33
|
-
|
34
|
-
def noop(*args, **kwargs): return args
|
35
|
-
|
36
|
-
class DummyHistory(HistoryAccessorBase):
|
37
|
-
def __init__(self, *args, **kw): self.enabled=False
|
38
|
-
def __getattr__(self, k): return noop
|
39
|
-
_log_validate = False
|
40
|
-
|
41
|
-
class FastInteractiveShell(InteractiveShell):
|
42
|
-
data_pub_class = Any()
|
43
|
-
parent_header = Any()
|
44
|
-
exiter = Instance(ZMQExitAutocall)
|
45
|
-
|
46
|
-
def init_history(self): self.history_manager=DummyHistory()
|
47
|
-
def atexit_operations(self, *args, **kwargs): pass
|
48
|
-
|
49
|
-
@default('exiter')
|
50
|
-
def _default_exiter(self): return ZMQExitAutocall(self)
|
51
|
-
|
52
|
-
@observe('exit_now')
|
53
|
-
def _update_exit_now(self, change): pass
|
54
|
-
|
55
|
-
keepkernel_on_exit = None
|
56
|
-
|
57
|
-
def init_environment(self):
|
58
|
-
"Configure the user's environment."
|
59
|
-
env = os.environ
|
60
|
-
env['TERM'] = 'xterm-color'
|
61
|
-
env['CLICOLOR'] = '1'
|
62
|
-
env['PAGER'] = 'cat'
|
63
|
-
env['GIT_PAGER'] = 'cat'
|
64
|
-
|
65
|
-
def init_data_pub(self): pass
|
66
|
-
|
67
|
-
@property
|
68
|
-
def data_pub(self):
|
69
|
-
if not hasattr(self, '_data_pub'):
|
70
|
-
warnings.warn("InteractiveShell.data_pub is deprecated outside IPython parallel.", DeprecationWarning, stacklevel=2)
|
71
|
-
self._data_pub = self.data_pub_class(parent=self)
|
72
|
-
self._data_pub.session = self.display_pub.session
|
73
|
-
self._data_pub.pub_socket = self.display_pub.pub_socket
|
74
|
-
return self._data_pub
|
75
|
-
|
76
|
-
@data_pub.setter
|
77
|
-
def data_pub(self, pub): self._data_pub = pub
|
78
|
-
|
79
|
-
def ask_exit(self):
|
80
|
-
"Engage the exit actions."
|
81
|
-
self.exit_now = (not self.keepkernel_on_exit)
|
82
|
-
payload = dict( source='ask_exit', keepkernel=self.keepkernel_on_exit,)
|
83
|
-
self.payload_manager.write_payload(payload)
|
84
|
-
|
85
|
-
def set_next_input(self, text, replace=False):
|
86
|
-
"Send the specified text to the frontend to be presented at the next input cell."
|
87
|
-
payload = dict( source='set_next_input', text=text, replace=replace,)
|
88
|
-
self.payload_manager.write_payload(payload)
|
89
|
-
|
90
|
-
def set_parent(self, parent):
|
91
|
-
"Set the parent header for associating output with its triggering input"
|
92
|
-
self.parent_header = parent
|
93
|
-
self.displayhook.set_parent(parent)
|
94
|
-
self.display_pub.set_parent(parent)
|
95
|
-
if hasattr(self, '_data_pub'): self.data_pub.set_parent(parent)
|
96
|
-
try: sys.stdout.set_parent(parent)
|
97
|
-
except AttributeError: pass
|
98
|
-
try: sys.stderr.set_parent(parent)
|
99
|
-
except AttributeError: pass
|
100
|
-
|
101
|
-
def get_parent(self): return self.parent_header
|
102
|
-
|
103
|
-
def init_magics(self):
|
104
|
-
super().init_magics()
|
105
|
-
self.register_magics(KernelMagics)
|
106
|
-
self.magics_manager.register_alias('ed', 'edit')
|
107
|
-
|
108
|
-
def init_virtualenv(self): pass
|
109
|
-
|
110
|
-
def system_piped(self, cmd):
|
111
|
-
"Call the given cmd in a subprocess, piping stdout/err "
|
112
|
-
if cmd.rstrip().endswith('&'): raise OSError("Background processes not supported.")
|
113
|
-
if sys.platform == 'win32':
|
114
|
-
cmd = self.var_expand(cmd, depth=1)
|
115
|
-
from IPython.utils._process_win32 import AvoidUNCPath
|
116
|
-
with AvoidUNCPath() as path:
|
117
|
-
if path is not None: cmd = 'pushd %s &&%s' % (path, cmd)
|
118
|
-
self.user_ns['_exit_code'] = system(cmd)
|
119
|
-
else: self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
|
120
|
-
|
121
|
-
system = system_piped
|
122
|
-
|
123
|
-
InteractiveShellABC.register(FastInteractiveShell)
|
124
|
-
|
execnb-0.1.6/execnb/shell.py
DELETED
@@ -1,248 +0,0 @@
|
|
1
|
-
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_shell.ipynb.
|
2
|
-
|
3
|
-
# %% ../nbs/02_shell.ipynb 2
|
4
|
-
from __future__ import annotations
|
5
|
-
|
6
|
-
import os
|
7
|
-
os.environ['MPLBACKEND'] = 'module://matplotlib_inline.backend_inline'
|
8
|
-
|
9
|
-
from fastcore.imports import *
|
10
|
-
from fastcore.basics import *
|
11
|
-
from fastcore.script import call_parse
|
12
|
-
|
13
|
-
import multiprocessing
|
14
|
-
try:
|
15
|
-
if sys.platform == 'darwin': multiprocessing.set_start_method("fork")
|
16
|
-
except RuntimeError: pass # if re-running cell
|
17
|
-
|
18
|
-
import tokenize
|
19
|
-
from IPython.core.interactiveshell import InteractiveShell
|
20
|
-
from IPython.core.displayhook import DisplayHook
|
21
|
-
from IPython.core.displaypub import DisplayPublisher
|
22
|
-
from base64 import b64encode
|
23
|
-
from io import StringIO
|
24
|
-
|
25
|
-
from .fastshell import FastInteractiveShell
|
26
|
-
from .nbio import *
|
27
|
-
from .nbio import _dict2obj
|
28
|
-
|
29
|
-
from collections.abc import Callable
|
30
|
-
|
31
|
-
# %% auto 0
|
32
|
-
__all__ = ['CaptureShell', 'find_output', 'out_exec', 'out_stream', 'out_error', 'exec_nb']
|
33
|
-
|
34
|
-
# %% ../nbs/02_shell.ipynb 4
|
35
|
-
# IPython requires a DisplayHook and DisplayPublisher
|
36
|
-
# We override `__call__` and `publish` to save outputs instead of printing them
|
37
|
-
class _CaptureHook(DisplayHook):
|
38
|
-
"Called when displaying a result"
|
39
|
-
|
40
|
-
def quiet(self):
|
41
|
-
"Should we silence because of ';'?"
|
42
|
-
sio = StringIO(self.shell._code)
|
43
|
-
tokens = list(tokenize.generate_tokens(sio.readline))
|
44
|
-
for t in reversed(tokens):
|
45
|
-
if t.type in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): continue
|
46
|
-
return t.type == tokenize.OP and t.string == ';'
|
47
|
-
|
48
|
-
def __call__(self, result=None):
|
49
|
-
if result is None or self.quiet(): return
|
50
|
-
self.fill_exec_result(result)
|
51
|
-
self.shell._result(result)
|
52
|
-
|
53
|
-
class _CapturePub(DisplayPublisher):
|
54
|
-
"Called when adding an output"
|
55
|
-
def publish(self, data, metadata=None, **kwargs): self.shell._add_out(data, metadata, typ='display_data')
|
56
|
-
|
57
|
-
# %% ../nbs/02_shell.ipynb 5
|
58
|
-
# These are the standard notebook formats for exception and stream data (e.g stdout)
|
59
|
-
def _out_exc(ename, evalue, traceback): return dict(ename=str(ename), evalue=str(evalue), output_type='error', traceback=traceback)
|
60
|
-
def _out_stream(text, name): return dict(name=name, output_type='stream', text=text.splitlines(True))
|
61
|
-
|
62
|
-
# %% ../nbs/02_shell.ipynb 6
|
63
|
-
def _format_mimedata(k, v):
|
64
|
-
"Format mime-type keyed data consistently with Jupyter"
|
65
|
-
if k.startswith('text/'): return v.splitlines(True)
|
66
|
-
if k.startswith('image/') and isinstance(v, bytes):
|
67
|
-
v = b64encode(v).decode()
|
68
|
-
return v+'\n' if not v.endswith('\n') else v
|
69
|
-
return v
|
70
|
-
|
71
|
-
# %% ../nbs/02_shell.ipynb 8
|
72
|
-
class CaptureShell(FastInteractiveShell):
|
73
|
-
"Execute the IPython/Jupyter source code"
|
74
|
-
def __init__(self,
|
75
|
-
path:str|Path=None): # Add `path` to python path
|
76
|
-
super().__init__(displayhook_class=_CaptureHook, display_pub_class=_CapturePub)
|
77
|
-
InteractiveShell._instance = self
|
78
|
-
self.out,self.count = [],1
|
79
|
-
self.exc = self.result = self._fname = self._cell_idx = self._stdout = self._stderr = None
|
80
|
-
if IN_NOTEBOOK:
|
81
|
-
try: self.enable_matplotlib('inline')
|
82
|
-
except ModuleNotFoundError: pass
|
83
|
-
if path: self.set_path(path)
|
84
|
-
|
85
|
-
def enable_matplotlib(self, gui=None):
|
86
|
-
"Enable `matplotlib` in a nested shell"
|
87
|
-
from matplotlib_inline.backend_inline import configure_inline_support
|
88
|
-
configure_inline_support.current_backend = 'unset'
|
89
|
-
return super().enable_matplotlib(gui)
|
90
|
-
|
91
|
-
def set_path(self, path):
|
92
|
-
"Add `path` to python path, or `path.parent` if it's a file"
|
93
|
-
path = Path(path)
|
94
|
-
if path.is_file(): path = path.parent
|
95
|
-
self.run_cell(f"import sys; sys.path.insert(0, '{path.as_posix()}')")
|
96
|
-
|
97
|
-
def enable_gui(self, gui=None):
|
98
|
-
"Disable GUI (over-ridden; called by IPython)"
|
99
|
-
pass
|
100
|
-
|
101
|
-
def _showtraceback(self, etype, evalue, stb: str):
|
102
|
-
self.out.append(_out_exc(etype, evalue, stb))
|
103
|
-
self.exc = (etype, evalue, '\n'.join(stb))
|
104
|
-
|
105
|
-
def _add_out(self, data, meta, typ='execute_result', **kwargs):
|
106
|
-
self._stream()
|
107
|
-
fd = {k:_format_mimedata(k,v) for k,v in data.items()}
|
108
|
-
self.out.append(dict(data=fd, metadata=meta, output_type=typ, **kwargs))
|
109
|
-
|
110
|
-
def _add_exec(self, result, meta, typ='execute_result'):
|
111
|
-
self._add_out(result, meta, execution_count=self.count)
|
112
|
-
self.count += 1
|
113
|
-
|
114
|
-
def _result(self, result):
|
115
|
-
self.result = result
|
116
|
-
self._add_exec(*self.display_formatter.format(result))
|
117
|
-
|
118
|
-
def _stream(self):
|
119
|
-
for nm in ('stdout','stderr'):
|
120
|
-
attr = '_'+nm
|
121
|
-
std = getattr(self, attr)
|
122
|
-
if std is not None:
|
123
|
-
text = std.getvalue()
|
124
|
-
if text:
|
125
|
-
self.out.append(_out_stream(text, nm))
|
126
|
-
setattr(self, attr, StringIO())
|
127
|
-
|
128
|
-
# %% ../nbs/02_shell.ipynb 11
|
129
|
-
@patch
|
130
|
-
def run(self:CaptureShell,
|
131
|
-
code:str, # Python/IPython code to run
|
132
|
-
stdout=True, # Capture stdout and save as output?
|
133
|
-
stderr=True): # Capture stderr and save as output?
|
134
|
-
"Run `code`, returning a list of all outputs in Jupyter notebook format"
|
135
|
-
self._code = code
|
136
|
-
self.exc = False
|
137
|
-
self.out.clear()
|
138
|
-
sys_stdout,sys_stderr = sys.stdout,sys.stderr
|
139
|
-
if stdout: self._stdout = sys.stdout = StringIO()
|
140
|
-
if stderr: self._stderr = sys.stderr = StringIO()
|
141
|
-
try: self.run_cell(code)
|
142
|
-
finally: sys.stdout,sys.stderr = sys_stdout,sys_stderr
|
143
|
-
self._stream()
|
144
|
-
return [*self.out]
|
145
|
-
|
146
|
-
# %% ../nbs/02_shell.ipynb 24
|
147
|
-
@patch
|
148
|
-
def cell(self:CaptureShell, cell, stdout=True, stderr=True):
|
149
|
-
"Run `cell`, skipping if not code, and store outputs back in cell"
|
150
|
-
if cell.cell_type!='code': return
|
151
|
-
self._cell_idx = cell.idx_ + 1
|
152
|
-
outs = self.run(cell.source)
|
153
|
-
if outs:
|
154
|
-
cell.outputs = _dict2obj(outs)
|
155
|
-
for o in outs:
|
156
|
-
if 'execution_count' in o: cell['execution_count'] = o['execution_count']
|
157
|
-
|
158
|
-
# %% ../nbs/02_shell.ipynb 27
|
159
|
-
def find_output(outp, # Output from `run`
|
160
|
-
ot='execute_result' # Output_type to find
|
161
|
-
):
|
162
|
-
"Find first output of type `ot` in `CaptureShell.run` output"
|
163
|
-
return first(o for o in outp if o['output_type']==ot)
|
164
|
-
|
165
|
-
# %% ../nbs/02_shell.ipynb 30
|
166
|
-
def out_exec(outp):
|
167
|
-
"Get data from execution result in `outp`."
|
168
|
-
out = find_output(outp)
|
169
|
-
if out: return '\n'.join(first(out['data'].values()))
|
170
|
-
|
171
|
-
# %% ../nbs/02_shell.ipynb 32
|
172
|
-
def out_stream(outp):
|
173
|
-
"Get text from stream in `outp`."
|
174
|
-
out = find_output(outp, 'stream')
|
175
|
-
if out: return ('\n'.join(out['text'])).strip()
|
176
|
-
|
177
|
-
# %% ../nbs/02_shell.ipynb 34
|
178
|
-
def out_error(outp):
|
179
|
-
"Get traceback from error in `outp`."
|
180
|
-
out = find_output(outp, 'error')
|
181
|
-
if out: return '\n'.join(out['traceback'])
|
182
|
-
|
183
|
-
# %% ../nbs/02_shell.ipynb 37
|
184
|
-
def _false(o): return False
|
185
|
-
|
186
|
-
@patch
|
187
|
-
def run_all(self:CaptureShell,
|
188
|
-
nb, # A notebook read with `nbclient` or `read_nb`
|
189
|
-
exc_stop:bool=False, # Stop on exceptions?
|
190
|
-
preproc:Callable=_false, # Called before each cell is executed
|
191
|
-
postproc:Callable=_false, # Called after each cell is executed
|
192
|
-
inject_code:str|None=None, # Code to inject into a cell
|
193
|
-
inject_idx:int=0 # Cell to replace with `inject_code`
|
194
|
-
):
|
195
|
-
"Run all cells in `nb`, stopping at first exception if `exc_stop`"
|
196
|
-
if inject_code is not None: nb.cells[inject_idx].source = inject_code
|
197
|
-
for cell in nb.cells:
|
198
|
-
if not preproc(cell):
|
199
|
-
self.cell(cell)
|
200
|
-
postproc(cell)
|
201
|
-
if self.exc and exc_stop: raise self.exc[1] from None
|
202
|
-
|
203
|
-
# %% ../nbs/02_shell.ipynb 51
|
204
|
-
@patch
|
205
|
-
def execute(self:CaptureShell,
|
206
|
-
src:str|Path, # Notebook path to read from
|
207
|
-
dest:str|None=None, # Notebook path to write to
|
208
|
-
exc_stop:bool=False, # Stop on exceptions?
|
209
|
-
preproc:Callable=_false, # Called before each cell is executed
|
210
|
-
postproc:Callable=_false, # Called after each cell is executed
|
211
|
-
inject_code:str|None=None, # Code to inject into a cell
|
212
|
-
inject_path:str|Path|None=None, # Path to file containing code to inject into a cell
|
213
|
-
inject_idx:int=0 # Cell to replace with `inject_code`
|
214
|
-
):
|
215
|
-
"Execute notebook from `src` and save with outputs to `dest"
|
216
|
-
nb = read_nb(src)
|
217
|
-
self._fname = src
|
218
|
-
self.set_path(Path(src).parent.resolve())
|
219
|
-
if inject_path is not None: inject_code = Path(inject_path).read_text()
|
220
|
-
self.run_all(nb, exc_stop=exc_stop, preproc=preproc, postproc=postproc,
|
221
|
-
inject_code=inject_code, inject_idx=inject_idx)
|
222
|
-
if dest: write_nb(nb, dest)
|
223
|
-
|
224
|
-
# %% ../nbs/02_shell.ipynb 55
|
225
|
-
@patch
|
226
|
-
def prettytb(self:CaptureShell,
|
227
|
-
fname:str|Path=None): # filename to print alongside the traceback
|
228
|
-
"Show a pretty traceback for notebooks, optionally printing `fname`."
|
229
|
-
fname = fname if fname else self._fname
|
230
|
-
_fence = '='*75
|
231
|
-
cell_intro_str = f"While Executing Cell #{self._cell_idx}:" if self._cell_idx else "While Executing:"
|
232
|
-
cell_str = f"\n{cell_intro_str}\n{self.exc[-1]}"
|
233
|
-
fname_str = f' in {fname}' if fname else ''
|
234
|
-
return f"{type(self.exc[1]).__name__}{fname_str}:\n{_fence}\n{cell_str}\n"
|
235
|
-
|
236
|
-
# %% ../nbs/02_shell.ipynb 74
|
237
|
-
@call_parse
|
238
|
-
def exec_nb(
|
239
|
-
src:str, # Notebook path to read from
|
240
|
-
dest:str='', # Notebook path to write to
|
241
|
-
exc_stop:bool=False, # Stop on exceptions?
|
242
|
-
inject_code:str=None, # Code to inject into a cell
|
243
|
-
inject_path:str=None, # Path to file containing code to inject into a cell
|
244
|
-
inject_idx:int=0 # Cell to replace with `inject_code`
|
245
|
-
):
|
246
|
-
"Execute notebook from `src` and save with outputs to `dest`"
|
247
|
-
CaptureShell().execute(src, dest, exc_stop=exc_stop, inject_code=inject_code,
|
248
|
-
inject_path=inject_path, inject_idx=inject_idx)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|