execnb 0.1.5__py3-none-any.whl → 0.1.7__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 +24 -16
- execnb/nbio.py +16 -11
- execnb/shell.py +187 -121
- {execnb-0.1.5.dist-info → execnb-0.1.7.dist-info}/METADATA +6 -5
- execnb-0.1.7.dist-info/RECORD +10 -0
- {execnb-0.1.5.dist-info → execnb-0.1.7.dist-info}/WHEEL +1 -1
- execnb/fastshell.py +0 -124
- execnb-0.1.5.dist-info/RECORD +0 -11
- {execnb-0.1.5.dist-info → execnb-0.1.7.dist-info}/LICENSE +0 -0
- {execnb-0.1.5.dist-info → execnb-0.1.7.dist-info}/entry_points.txt +0 -0
- {execnb-0.1.5.dist-info → execnb-0.1.7.dist-info}/top_level.txt +0 -0
execnb/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.7"
|
execnb/_modidx.py
CHANGED
@@ -3,10 +3,9 @@
|
|
3
3
|
d = { 'settings': { 'branch': 'master',
|
4
4
|
'doc_baseurl': '/execnb/',
|
5
5
|
'doc_host': 'https://fastai.github.io',
|
6
|
-
'git_url': 'https://github.com/fastai/execnb/
|
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,27 +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
|
-
'execnb.shell.exec_nb': ('shell.html#exec_nb', 'execnb/shell.py')
|
51
|
+
'execnb.shell.exec_nb': ('shell.html#exec_nb', 'execnb/shell.py'),
|
52
|
+
'execnb.shell.find_output': ('shell.html#find_output', 'execnb/shell.py'),
|
53
|
+
'execnb.shell.format_exc': ('shell.html#format_exc', 'execnb/shell.py'),
|
54
|
+
'execnb.shell.out_error': ('shell.html#out_error', 'execnb/shell.py'),
|
55
|
+
'execnb.shell.out_exec': ('shell.html#out_exec', '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')}}}
|
execnb/nbio.py
CHANGED
@@ -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)
|
@@ -28,7 +30,7 @@ class NbCell(AttrDict):
|
|
28
30
|
|
29
31
|
def parsed_(self):
|
30
32
|
if self.cell_type!='code' or self.source.strip()[:1] in ['%', '!']: return
|
31
|
-
if '_parsed_' not in self:
|
33
|
+
if '_parsed_' not in self:
|
32
34
|
try: self._parsed_ = ast.parse(self.source).body
|
33
35
|
# you can assign the result of ! to a variable in a notebook cell
|
34
36
|
# which will result in a syntax error if parsed with the ast module.
|
@@ -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,28 +53,31 @@ 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
|
70
72
|
"Create an `NbCell` containing `text`"
|
71
73
|
assert cell_type in {'code', 'markdown', 'raw'}
|
72
74
|
if 'metadata' not in kwargs: kwargs['metadata']={}
|
75
|
+
if cell_type == 'code':
|
76
|
+
kwargs['outputs']=[]
|
77
|
+
kwargs['execution_count']=0
|
73
78
|
return NbCell(0, dict(cell_type=cell_type, source=text, directives_={}, **kwargs))
|
74
79
|
|
75
|
-
# %% ../nbs/01_nbio.ipynb
|
80
|
+
# %% ../nbs/01_nbio.ipynb
|
76
81
|
def nb2dict(d, k=None):
|
77
82
|
"Convert parsed notebook to `dict`"
|
78
83
|
if k=='source': return d.splitlines(keepends=True)
|
@@ -80,13 +85,13 @@ def nb2dict(d, k=None):
|
|
80
85
|
if not isinstance(d, dict): return d
|
81
86
|
return dict(**{k:nb2dict(v,k) for k,v in d.items() if k[-1] != '_'})
|
82
87
|
|
83
|
-
# %% ../nbs/01_nbio.ipynb
|
88
|
+
# %% ../nbs/01_nbio.ipynb
|
84
89
|
def nb2str(nb):
|
85
90
|
"Convert `nb` to a `str`"
|
86
91
|
if isinstance(nb, (AttrDict,list)): nb = nb2dict(nb)
|
87
92
|
return dumps(nb, sort_keys=True, indent=1, ensure_ascii=False) + "\n"
|
88
93
|
|
89
|
-
# %% ../nbs/01_nbio.ipynb
|
94
|
+
# %% ../nbs/01_nbio.ipynb
|
90
95
|
def write_nb(nb, path):
|
91
96
|
"Write `nb` to `path`"
|
92
97
|
new = nb2str(nb)
|
execnb/shell.py
CHANGED
@@ -1,65 +1,106 @@
|
|
1
|
+
"""A shell for running notebook code without a notebook server"""
|
2
|
+
|
1
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_shell.ipynb.
|
2
4
|
|
3
5
|
# %% ../nbs/02_shell.ipynb 2
|
4
6
|
from __future__ import annotations
|
5
7
|
|
6
|
-
import
|
7
|
-
os.environ['MPLBACKEND'] = 'module://matplotlib_inline.backend_inline'
|
8
|
-
|
9
|
-
from fastcore.imports import *
|
10
|
-
from fastcore.basics import *
|
8
|
+
from fastcore.utils import *
|
11
9
|
from fastcore.script import call_parse
|
10
|
+
from fastcore.ansi import ansi2html
|
12
11
|
|
13
|
-
import multiprocessing
|
12
|
+
import mistletoe,multiprocessing,types,traceback,signal
|
14
13
|
try:
|
15
14
|
if sys.platform == 'darwin': multiprocessing.set_start_method("fork")
|
16
15
|
except RuntimeError: pass # if re-running cell
|
17
16
|
|
18
|
-
import
|
19
|
-
from IPython.core.interactiveshell import InteractiveShell
|
17
|
+
from IPython.core.interactiveshell import InteractiveShell, ExecutionInfo, ExecutionResult
|
20
18
|
from IPython.core.displayhook import DisplayHook
|
21
|
-
from IPython.
|
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
|
+
|
22
27
|
from base64 import b64encode
|
23
|
-
from
|
28
|
+
from html import escape
|
29
|
+
try: from matplotlib_inline.backend_inline import set_matplotlib_formats
|
30
|
+
except ImportError: set_matplotlib_formats = None
|
31
|
+
|
24
32
|
|
25
|
-
from .fastshell import FastInteractiveShell
|
26
33
|
from .nbio import *
|
27
34
|
from .nbio import _dict2obj
|
28
35
|
|
29
|
-
from collections.abc import Callable
|
30
|
-
|
31
36
|
# %% auto 0
|
32
|
-
__all__ = ['CaptureShell', 'exec_nb'
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
60
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))
|
61
103
|
|
62
|
-
# %% ../nbs/02_shell.ipynb 6
|
63
104
|
def _format_mimedata(k, v):
|
64
105
|
"Format mime-type keyed data consistently with Jupyter"
|
65
106
|
if k.startswith('text/'): return v.splitlines(True)
|
@@ -68,82 +109,56 @@ def _format_mimedata(k, v):
|
|
68
109
|
return v+'\n' if not v.endswith('\n') else v
|
69
110
|
return v
|
70
111
|
|
71
|
-
|
72
|
-
|
73
|
-
|
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)
|
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)
|
84
115
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
self.run_cell(f"import sys; sys.path.insert(0, '{path.as_posix()}')")
|
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
|
96
126
|
|
97
|
-
|
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
|
127
|
+
# %% ../nbs/02_shell.ipynb
|
129
128
|
@patch
|
130
129
|
def run(self:CaptureShell,
|
131
130
|
code:str, # Python/IPython code to run
|
132
131
|
stdout=True, # Capture stdout and save as output?
|
133
132
|
stderr=True): # Capture stderr and save as output?
|
134
133
|
"Run `code`, returning a list of all outputs in Jupyter notebook format"
|
135
|
-
self.
|
136
|
-
self.
|
137
|
-
self.
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
147
162
|
@patch
|
148
163
|
def cell(self:CaptureShell, cell, stdout=True, stderr=True):
|
149
164
|
"Run `cell`, skipping if not code, and store outputs back in cell"
|
@@ -155,15 +170,40 @@ def cell(self:CaptureShell, cell, stdout=True, stderr=True):
|
|
155
170
|
for o in outs:
|
156
171
|
if 'execution_count' in o: cell['execution_count'] = o['execution_count']
|
157
172
|
|
158
|
-
# %% ../nbs/02_shell.ipynb
|
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
|
159
199
|
def _false(o): return False
|
160
200
|
|
161
201
|
@patch
|
162
202
|
def run_all(self:CaptureShell,
|
163
203
|
nb, # A notebook read with `nbclient` or `read_nb`
|
164
204
|
exc_stop:bool=False, # Stop on exceptions?
|
165
|
-
preproc:
|
166
|
-
postproc:
|
205
|
+
preproc:callable=_false, # Called before each cell is executed
|
206
|
+
postproc:callable=_false, # Called after each cell is executed
|
167
207
|
inject_code:str|None=None, # Code to inject into a cell
|
168
208
|
inject_idx:int=0 # Cell to replace with `inject_code`
|
169
209
|
):
|
@@ -173,16 +213,16 @@ def run_all(self:CaptureShell,
|
|
173
213
|
if not preproc(cell):
|
174
214
|
self.cell(cell)
|
175
215
|
postproc(cell)
|
176
|
-
if self.exc and exc_stop: raise self.exc
|
216
|
+
if self.exc and exc_stop: raise self.exc from None
|
177
217
|
|
178
|
-
# %% ../nbs/02_shell.ipynb
|
218
|
+
# %% ../nbs/02_shell.ipynb
|
179
219
|
@patch
|
180
220
|
def execute(self:CaptureShell,
|
181
221
|
src:str|Path, # Notebook path to read from
|
182
222
|
dest:str|None=None, # Notebook path to write to
|
183
223
|
exc_stop:bool=False, # Stop on exceptions?
|
184
|
-
preproc:
|
185
|
-
postproc:
|
224
|
+
preproc:callable=_false, # Called before each cell is executed
|
225
|
+
postproc:callable=_false, # Called after each cell is executed
|
186
226
|
inject_code:str|None=None, # Code to inject into a cell
|
187
227
|
inject_path:str|Path|None=None, # Path to file containing code to inject into a cell
|
188
228
|
inject_idx:int=0 # Cell to replace with `inject_code`
|
@@ -196,7 +236,7 @@ def execute(self:CaptureShell,
|
|
196
236
|
inject_code=inject_code, inject_idx=inject_idx)
|
197
237
|
if dest: write_nb(nb, dest)
|
198
238
|
|
199
|
-
# %% ../nbs/02_shell.ipynb
|
239
|
+
# %% ../nbs/02_shell.ipynb
|
200
240
|
@patch
|
201
241
|
def prettytb(self:CaptureShell,
|
202
242
|
fname:str|Path=None): # filename to print alongside the traceback
|
@@ -204,11 +244,11 @@ def prettytb(self:CaptureShell,
|
|
204
244
|
fname = fname if fname else self._fname
|
205
245
|
_fence = '='*75
|
206
246
|
cell_intro_str = f"While Executing Cell #{self._cell_idx}:" if self._cell_idx else "While Executing:"
|
207
|
-
cell_str = f"\n{cell_intro_str}\n{self.exc
|
247
|
+
cell_str = f"\n{cell_intro_str}\n{format_exc(self.exc)}"
|
208
248
|
fname_str = f' in {fname}' if fname else ''
|
209
|
-
return f"{type(self.exc
|
249
|
+
return f"{type(self.exc).__name__}{fname_str}:\n{_fence}\n{cell_str}\n"
|
210
250
|
|
211
|
-
# %% ../nbs/02_shell.ipynb
|
251
|
+
# %% ../nbs/02_shell.ipynb
|
212
252
|
@call_parse
|
213
253
|
def exec_nb(
|
214
254
|
src:str, # Notebook path to read from
|
@@ -221,3 +261,29 @@ def exec_nb(
|
|
221
261
|
"Execute notebook from `src` and save with outputs to `dest`"
|
222
262
|
CaptureShell().execute(src, dest, exc_stop=exc_stop, inject_code=inject_code,
|
223
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,8 +1,8 @@
|
|
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
|
-
Home-page: https://github.com/fastai/execnb/
|
5
|
+
Home-page: https://github.com/fastai/execnb/
|
6
6
|
Author: Jeremy Howard
|
7
7
|
Author-email: j@fast.ai
|
8
8
|
License: Apache Software License 2.0
|
@@ -16,14 +16,15 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
16
16
|
Requires-Python: >=3.7
|
17
17
|
Description-Content-Type: text/markdown
|
18
18
|
License-File: LICENSE
|
19
|
-
Requires-Dist: fastcore
|
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'
|
24
25
|
|
25
|
-
execnb
|
26
|
-
|
26
|
+
# execnb
|
27
|
+
|
27
28
|
|
28
29
|
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
|
29
30
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
execnb/__init__.py,sha256=YpKDcdV7CqL8n45u267wKtyloM13FSVbOdrqgNZnSLM,22
|
2
|
+
execnb/_modidx.py,sha256=3wJwFT95tiaCPmj7VMQEIim5qLTcOatC2od-ze5WJcc,5771
|
3
|
+
execnb/nbio.py,sha256=gs3EGN0sP2j47XUH31rTn2KT57b3wWnBZsn9AoZm2JQ,3677
|
4
|
+
execnb/shell.py,sha256=4wuuyphJ0M0NCvjQ2RbJlstDHUXFmnWNJExRdveiLew,11958
|
5
|
+
execnb-0.1.7.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
6
|
+
execnb-0.1.7.dist-info/METADATA,sha256=BqAfeem0tFfd_BxveYlY1_kxWuW35KGZc4AHAaSOSSw,3275
|
7
|
+
execnb-0.1.7.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
8
|
+
execnb-0.1.7.dist-info/entry_points.txt,sha256=jZ8LPZCqnu4hXN_AgQpm05hVnTE-C25YK_4aiVX4i78,84
|
9
|
+
execnb-0.1.7.dist-info/top_level.txt,sha256=VGWmzsw8FOlT1r5TdOxaTWIAyRdclcxNdJ2r1hojf5U,7
|
10
|
+
execnb-0.1.7.dist-info/RECORD,,
|
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.5.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
execnb/__init__.py,sha256=rPSfWgIeq2YWVPyESOAwCBt8vftsTpIkuLAGDEzyRQc,22
|
2
|
-
execnb/_modidx.py,sha256=gpQj6i1HkFABwB73tBR5iaLqNDZNUY3wilOxlO7P5FQ,4833
|
3
|
-
execnb/fastshell.py,sha256=ODng8r7-b74lRiCR2nENHuIMubxnkfArh0Su2VMHMSs,4285
|
4
|
-
execnb/nbio.py,sha256=9k15675BTHIWDNVbbN_B93g6pCDECBDX4g7HgxHvyys,3568
|
5
|
-
execnb/shell.py,sha256=se6sLSEql-zTbHWOH0P_fQ8Qg1WJCEv4s2HCfoaaOfE,8911
|
6
|
-
execnb-0.1.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
7
|
-
execnb-0.1.5.dist-info/METADATA,sha256=t5lJC6cUeocujmRxcvQ0nSnMUo4L3VJ8IfbB6lsyfxc,3278
|
8
|
-
execnb-0.1.5.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
9
|
-
execnb-0.1.5.dist-info/entry_points.txt,sha256=jZ8LPZCqnu4hXN_AgQpm05hVnTE-C25YK_4aiVX4i78,84
|
10
|
-
execnb-0.1.5.dist-info/top_level.txt,sha256=VGWmzsw8FOlT1r5TdOxaTWIAyRdclcxNdJ2r1hojf5U,7
|
11
|
-
execnb-0.1.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|