execnb 0.1.8__py3-none-any.whl → 0.1.10__py3-none-any.whl
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/__init__.py +1 -1
- execnb/_modidx.py +6 -2
- execnb/shell.py +55 -28
- {execnb-0.1.8.dist-info → execnb-0.1.10.dist-info}/METADATA +5 -5
- execnb-0.1.10.dist-info/RECORD +10 -0
- execnb-0.1.8.dist-info/RECORD +0 -10
- {execnb-0.1.8.dist-info → execnb-0.1.10.dist-info}/LICENSE +0 -0
- {execnb-0.1.8.dist-info → execnb-0.1.10.dist-info}/WHEEL +0 -0
- {execnb-0.1.8.dist-info → execnb-0.1.10.dist-info}/entry_points.txt +0 -0
- {execnb-0.1.8.dist-info → execnb-0.1.10.dist-info}/top_level.txt +0 -0
execnb/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.10"
|
execnb/_modidx.py
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
d = { 'settings': { 'branch': 'master',
|
4
4
|
'doc_baseurl': '/execnb/',
|
5
|
-
'doc_host': 'https://
|
6
|
-
'git_url': 'https://github.com/
|
5
|
+
'doc_host': 'https://AnswerDotAI.github.io',
|
6
|
+
'git_url': 'https://github.com/AnswerDotAI/execnb/',
|
7
7
|
'lib_path': 'execnb'},
|
8
8
|
'syms': { 'execnb.nbio': { 'execnb.nbio.NbCell': ('nbio.html#nbcell', 'execnb/nbio.py'),
|
9
9
|
'execnb.nbio.NbCell.__eq__': ('nbio.html#nbcell.__eq__', 'execnb/nbio.py'),
|
@@ -22,6 +22,7 @@ d = { 'settings': { 'branch': 'master',
|
|
22
22
|
'execnb.nbio.write_nb': ('nbio.html#write_nb', 'execnb/nbio.py')},
|
23
23
|
'execnb.shell': { 'execnb.shell.CaptureShell': ('shell.html#captureshell', 'execnb/shell.py'),
|
24
24
|
'execnb.shell.CaptureShell.__init__': ('shell.html#captureshell.__init__', 'execnb/shell.py'),
|
25
|
+
'execnb.shell.CaptureShell._run': ('shell.html#captureshell._run', 'execnb/shell.py'),
|
25
26
|
'execnb.shell.CaptureShell.cell': ('shell.html#captureshell.cell', 'execnb/shell.py'),
|
26
27
|
'execnb.shell.CaptureShell.complete': ('shell.html#captureshell.complete', 'execnb/shell.py'),
|
27
28
|
'execnb.shell.CaptureShell.enable_gui': ('shell.html#captureshell.enable_gui', 'execnb/shell.py'),
|
@@ -29,6 +30,7 @@ d = { 'settings': { 'branch': 'master',
|
|
29
30
|
'execnb.shell.CaptureShell.prettytb': ('shell.html#captureshell.prettytb', 'execnb/shell.py'),
|
30
31
|
'execnb.shell.CaptureShell.run': ('shell.html#captureshell.run', 'execnb/shell.py'),
|
31
32
|
'execnb.shell.CaptureShell.run_all': ('shell.html#captureshell.run_all', 'execnb/shell.py'),
|
33
|
+
'execnb.shell.CaptureShell.run_async': ('shell.html#captureshell.run_async', 'execnb/shell.py'),
|
32
34
|
'execnb.shell.CaptureShell.run_cell': ('shell.html#captureshell.run_cell', 'execnb/shell.py'),
|
33
35
|
'execnb.shell.CaptureShell.set_path': ('shell.html#captureshell.set_path', 'execnb/shell.py'),
|
34
36
|
'execnb.shell.ExecutionInfo.__repr__': ('shell.html#executioninfo.__repr__', 'execnb/shell.py'),
|
@@ -48,6 +50,8 @@ d = { 'settings': { 'branch': 'master',
|
|
48
50
|
'execnb.shell._out_exc': ('shell.html#_out_exc', 'execnb/shell.py'),
|
49
51
|
'execnb.shell._out_nb': ('shell.html#_out_nb', 'execnb/shell.py'),
|
50
52
|
'execnb.shell._out_stream': ('shell.html#_out_stream', 'execnb/shell.py'),
|
53
|
+
'execnb.shell._pre': ('shell.html#_pre', 'execnb/shell.py'),
|
54
|
+
'execnb.shell._strip': ('shell.html#_strip', 'execnb/shell.py'),
|
51
55
|
'execnb.shell.exec_nb': ('shell.html#exec_nb', 'execnb/shell.py'),
|
52
56
|
'execnb.shell.find_output': ('shell.html#find_output', 'execnb/shell.py'),
|
53
57
|
'execnb.shell.format_exc': ('shell.html#format_exc', 'execnb/shell.py'),
|
execnb/shell.py
CHANGED
@@ -53,7 +53,7 @@ def __repr__(self: ExecutionResult): return f'result: {self.result}; err: {self.
|
|
53
53
|
class CaptureShell(InteractiveShell):
|
54
54
|
displayhook_class = _CustDisplayHook
|
55
55
|
|
56
|
-
def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout=None):
|
56
|
+
def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout:Optional[int]=None):
|
57
57
|
super().__init__()
|
58
58
|
self.history_manager.enabled = history
|
59
59
|
self.timeout = timeout
|
@@ -63,21 +63,15 @@ class CaptureShell(InteractiveShell):
|
|
63
63
|
if not IN_NOTEBOOK: InteractiveShell._instance = self
|
64
64
|
if set_matplotlib_formats:
|
65
65
|
self.enable_matplotlib("inline")
|
66
|
-
self.
|
67
|
-
self.
|
66
|
+
self._run("from matplotlib_inline.backend_inline import set_matplotlib_formats")
|
67
|
+
self._run(f"set_matplotlib_formats('{mpl_format}')")
|
68
68
|
|
69
|
-
def
|
70
|
-
stdout=True, stderr=True, display=True
|
71
|
-
if not timeout: timeout = self.timeout
|
69
|
+
def _run(self, raw_cell, store_history=False, silent=False, shell_futures=True, cell_id=None,
|
70
|
+
stdout=True, stderr=True, display=True):
|
72
71
|
# TODO what if there's a comment?
|
73
72
|
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
73
|
with capture_output(display=display, stdout=stdout, stderr=stderr) as c:
|
79
74
|
result = super().run_cell(raw_cell, store_history, silent, shell_futures=shell_futures, cell_id=cell_id)
|
80
|
-
if timeout: signal.alarm(0)
|
81
75
|
return AttrDict(result=result, stdout='' if semic else c.stdout, stderr=c.stderr,
|
82
76
|
display_objects=c.outputs, exception=result.error_in_exec, quiet=semic)
|
83
77
|
|
@@ -85,14 +79,28 @@ class CaptureShell(InteractiveShell):
|
|
85
79
|
"Add `path` to python path, or `path.parent` if it's a file"
|
86
80
|
path = Path(path)
|
87
81
|
if path.is_file(): path = path.parent
|
88
|
-
self.
|
82
|
+
self._run(f"import sys; sys.path.insert(0, '{path.as_posix()}')")
|
89
83
|
|
90
84
|
def enable_gui(self, gui=None): pass
|
91
85
|
|
86
|
+
# %% ../nbs/02_shell.ipynb
|
87
|
+
@patch
|
88
|
+
def run_cell(self:CaptureShell, raw_cell, store_history=False, silent=False, shell_futures=True, cell_id=None,
|
89
|
+
stdout=True, stderr=True, display=True, timeout=None):
|
90
|
+
if not timeout: timeout = self.timeout
|
91
|
+
if timeout:
|
92
|
+
def handler(*args): raise TimeoutError()
|
93
|
+
signal.signal(signal.SIGALRM, handler)
|
94
|
+
signal.alarm(timeout)
|
95
|
+
try: return self._run(raw_cell, store_history, silent, shell_futures, cell_id=cell_id,
|
96
|
+
stdout=stdout, stderr=stderr, display=display)
|
97
|
+
finally:
|
98
|
+
if timeout: signal.alarm(0)
|
99
|
+
|
92
100
|
# %% ../nbs/02_shell.ipynb
|
93
101
|
def format_exc(e):
|
94
|
-
"Format exception `e` as a string"
|
95
|
-
return
|
102
|
+
"Format exception `e` as a string list"
|
103
|
+
return traceback.format_exception(type(e), e, e.__traceback__)
|
96
104
|
|
97
105
|
# %% ../nbs/02_shell.ipynb
|
98
106
|
def _out_stream(text, name): return dict(name=name, output_type='stream', text=text.splitlines(True))
|
@@ -122,6 +130,9 @@ def _out_nb(o, fmt):
|
|
122
130
|
for x in o.display_objects: res.append(_mk_out(x.data, x.metadata))
|
123
131
|
if r is not None and not o.quiet:
|
124
132
|
res.append(_mk_out(*fmt.format(r), 'execute_result'))
|
133
|
+
if 'execution_count' not in o: o['execution_count']=None
|
134
|
+
for p in res:
|
135
|
+
if p["output_type"]=="execute_result": p['execution_count'] = o['execution_count']
|
125
136
|
return res
|
126
137
|
|
127
138
|
# %% ../nbs/02_shell.ipynb
|
@@ -129,33 +140,52 @@ def _out_nb(o, fmt):
|
|
129
140
|
def run(self:CaptureShell,
|
130
141
|
code:str, # Python/IPython code to run
|
131
142
|
stdout=True, # Capture stdout and save as output?
|
132
|
-
stderr=True
|
143
|
+
stderr=True, # Capture stderr and save as output?
|
144
|
+
timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds
|
133
145
|
"Run `code`, returning a list of all outputs in Jupyter notebook format"
|
134
|
-
res = self.run_cell(code, stdout=stdout, stderr=stderr)
|
146
|
+
res = self.run_cell(code, stdout=stdout, stderr=stderr, timeout=timeout)
|
135
147
|
self.result = res.result.result
|
136
148
|
self.exc = res.exception
|
137
149
|
return _out_nb(res, self.display_formatter)
|
138
150
|
|
139
151
|
# %% ../nbs/02_shell.ipynb
|
140
|
-
|
141
|
-
|
152
|
+
@patch
|
153
|
+
async def run_async(self:CaptureShell,
|
154
|
+
code: str, # Python/IPython code to run
|
155
|
+
stdout=True, # Capture stdout and save as output?
|
156
|
+
stderr=True, # Capture stderr and save as output?
|
157
|
+
timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds
|
158
|
+
return self.run(code, stdout=stdout, stderr=stderr, timeout=timeout)
|
159
|
+
|
160
|
+
# %% ../nbs/02_shell.ipynb
|
161
|
+
def _pre(s, xtra=''): return f"<pre {xtra}><code>{escape(s)}</code></pre>"
|
162
|
+
def _strip(s): return strip_ansi(escape(s))
|
163
|
+
|
164
|
+
def render_outputs(outputs, ansi_renderer=_strip, include_imgs=True, pygments=False):
|
165
|
+
try:
|
166
|
+
from mistletoe import markdown, HTMLRenderer
|
167
|
+
from mistletoe.contrib.pygments_renderer import PygmentsRenderer
|
142
168
|
except ImportError: return print('mistletoe not found -- please install it')
|
169
|
+
renderer = PygmentsRenderer if pygments else HTMLRenderer
|
143
170
|
def render_output(out):
|
144
171
|
otype = out['output_type']
|
145
172
|
if otype == 'stream':
|
146
173
|
txt = ansi_renderer(''.join(out['text']))
|
147
|
-
|
174
|
+
xtra = '' if out['name']=='stdout' else "class='stderr'"
|
175
|
+
return f"<pre {xtra}><code>{txt}</code></pre>"
|
148
176
|
elif otype in ('display_data','execute_result'):
|
149
177
|
data = out['data']
|
150
178
|
_g = lambda t: ''.join(data[t]) if t in data else None
|
151
179
|
if d := _g('text/html'): return d
|
152
180
|
if d := _g('application/javascript'): return f'<script>{d}</script>'
|
153
|
-
if d := _g('text/markdown'): return
|
154
|
-
if d := _g('image/svg+xml'): return d
|
155
|
-
if d := _g('image/jpeg'): return f'<img src="data:image/jpeg;base64,{d}"/>'
|
156
|
-
if d := _g('image/png'): return f'<img src="data:image/png;base64,{d}"/>'
|
181
|
+
if d := _g('text/markdown'): return markdown(d, renderer=renderer)
|
157
182
|
if d := _g('text/latex'): return f'<div class="math">${d}$</div>'
|
158
|
-
if
|
183
|
+
if include_imgs:
|
184
|
+
if d := _g('image/jpeg'): return f'<img src="data:image/jpeg;base64,{d}"/>'
|
185
|
+
if d := _g('image/png'): return f'<img src="data:image/png;base64,{d}"/>'
|
186
|
+
if d := _g('text/plain'): return _pre(d)
|
187
|
+
if d := _g('image/svg+xml'): return d
|
188
|
+
|
159
189
|
return ''
|
160
190
|
|
161
191
|
return '\n'.join(map(render_output, outputs))
|
@@ -167,10 +197,7 @@ def cell(self:CaptureShell, cell, stdout=True, stderr=True):
|
|
167
197
|
if cell.cell_type!='code': return
|
168
198
|
self._cell_idx = cell.idx_ + 1
|
169
199
|
outs = self.run(cell.source)
|
170
|
-
if outs:
|
171
|
-
cell.outputs = _dict2obj(outs)
|
172
|
-
for o in outs:
|
173
|
-
if 'execution_count' in o: cell['execution_count'] = o['execution_count']
|
200
|
+
if outs: cell.outputs = _dict2obj(outs)
|
174
201
|
|
175
202
|
# %% ../nbs/02_shell.ipynb
|
176
203
|
def find_output(outp, # Output from `run`
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: execnb
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.10
|
4
4
|
Summary: A description of your project
|
5
|
-
Home-page: https://github.com/
|
5
|
+
Home-page: https://github.com/AnswerDotAI/execnb/
|
6
6
|
Author: Jeremy Howard
|
7
7
|
Author-email: j@fast.ai
|
8
8
|
License: Apache Software License 2.0
|
@@ -48,7 +48,7 @@ mamba installed.)
|
|
48
48
|
## How to use
|
49
49
|
|
50
50
|
Use
|
51
|
-
[`CaptureShell`](https://
|
51
|
+
[`CaptureShell`](https://AnswerDotAI.github.io/execnb/shell.html#captureshell)
|
52
52
|
to run Jupyter code and capture notebook outputs, without running a
|
53
53
|
Jupyter server (or even having it installed):
|
54
54
|
|
@@ -69,7 +69,7 @@ s.run('1+1')
|
|
69
69
|
'execution_count': 1}]
|
70
70
|
|
71
71
|
To execute a notebook and save it with outputs filled in, use
|
72
|
-
[`CaptureShell.execute`](https://
|
72
|
+
[`CaptureShell.execute`](https://AnswerDotAI.github.io/execnb/shell.html#captureshell.execute):
|
73
73
|
|
74
74
|
``` python
|
75
75
|
try:
|
@@ -81,7 +81,7 @@ finally: Path('tmp.ipynb').unlink()
|
|
81
81
|
[{'name': 'stdout', 'output_type': 'stream', 'text': ['1\n']}, {'data': {'text/plain': ['2']}, 'execution_count': 3, 'metadata': {}, 'output_type': 'execute_result'}]
|
82
82
|
|
83
83
|
You can also execute notebooks from the command line with
|
84
|
-
[`exec_nb`](https://
|
84
|
+
[`exec_nb`](https://AnswerDotAI.github.io/execnb/shell.html#exec_nb):
|
85
85
|
|
86
86
|
``` python
|
87
87
|
!exec_nb --help
|
@@ -0,0 +1,10 @@
|
|
1
|
+
execnb/__init__.py,sha256=z0zCHFTcKSR0tJ6h5qrpNmRVP21QIPP8N0p7quCnnm0,23
|
2
|
+
execnb/_modidx.py,sha256=mGvzO-ucSjMp0NX4t0Ed7XNi2v-gvMPLQUiGQpN1QKU,6211
|
3
|
+
execnb/nbio.py,sha256=gs3EGN0sP2j47XUH31rTn2KT57b3wWnBZsn9AoZm2JQ,3677
|
4
|
+
execnb/shell.py,sha256=Hbn0pF_-Iwr7aENw_Pxo9iwRfPCjP0SHK_jDHZgzIog,13357
|
5
|
+
execnb-0.1.10.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
6
|
+
execnb-0.1.10.dist-info/METADATA,sha256=XRVqx4VzVcDvLjoglJrxijIifOgSW8gP3JaFXqTvtcQ,3313
|
7
|
+
execnb-0.1.10.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
8
|
+
execnb-0.1.10.dist-info/entry_points.txt,sha256=jZ8LPZCqnu4hXN_AgQpm05hVnTE-C25YK_4aiVX4i78,84
|
9
|
+
execnb-0.1.10.dist-info/top_level.txt,sha256=VGWmzsw8FOlT1r5TdOxaTWIAyRdclcxNdJ2r1hojf5U,7
|
10
|
+
execnb-0.1.10.dist-info/RECORD,,
|
execnb-0.1.8.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
execnb/__init__.py,sha256=C69ADlbQREQlR15trneyA2sk8x0-oH4rDAX5fsv19_U,22
|
2
|
-
execnb/_modidx.py,sha256=3wJwFT95tiaCPmj7VMQEIim5qLTcOatC2od-ze5WJcc,5771
|
3
|
-
execnb/nbio.py,sha256=gs3EGN0sP2j47XUH31rTn2KT57b3wWnBZsn9AoZm2JQ,3677
|
4
|
-
execnb/shell.py,sha256=qpCkd1FZsGXyOWjOrfAluGbk7h4D7a3SnCwbyRz0L9s,12055
|
5
|
-
execnb-0.1.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
6
|
-
execnb-0.1.8.dist-info/METADATA,sha256=i3gK5I8cEbHu-pXhkuJy1od601HKmloMhpk40AsYrWw,3292
|
7
|
-
execnb-0.1.8.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
8
|
-
execnb-0.1.8.dist-info/entry_points.txt,sha256=jZ8LPZCqnu4hXN_AgQpm05hVnTE-C25YK_4aiVX4i78,84
|
9
|
-
execnb-0.1.8.dist-info/top_level.txt,sha256=VGWmzsw8FOlT1r5TdOxaTWIAyRdclcxNdJ2r1hojf5U,7
|
10
|
-
execnb-0.1.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|