Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions execnb/_modidx.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
'execnb.shell.CaptureShell.prettytb': ('shell.html#captureshell.prettytb', 'execnb/shell.py'),
'execnb.shell.CaptureShell.run': ('shell.html#captureshell.run', 'execnb/shell.py'),
'execnb.shell.CaptureShell.run_all': ('shell.html#captureshell.run_all', 'execnb/shell.py'),
'execnb.shell.CaptureShell.run_async': ('shell.html#captureshell.run_async', 'execnb/shell.py'),
'execnb.shell.CaptureShell.run_cell': ('shell.html#captureshell.run_cell', 'execnb/shell.py'),
'execnb.shell.CaptureShell.set_path': ('shell.html#captureshell.set_path', 'execnb/shell.py'),
'execnb.shell.ExecutionInfo.__repr__': ('shell.html#executioninfo.__repr__', 'execnb/shell.py'),
Expand Down
18 changes: 14 additions & 4 deletions execnb/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __repr__(self: ExecutionResult): return f'result: {self.result}; err: {self.
class CaptureShell(InteractiveShell):
displayhook_class = _CustDisplayHook

def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout=None):
def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout:Optional[int]=None):
super().__init__()
self.history_manager.enabled = history
self.timeout = timeout
Expand All @@ -67,7 +67,7 @@ def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeo
self.run_cell(f"set_matplotlib_formats('{mpl_format}')")

def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True, cell_id=None,
stdout=True, stderr=True, display=True, timeout=None):
stdout=True, stderr=True, display=True, timeout:Optional[int]=None):
if not timeout: timeout = self.timeout
# TODO what if there's a comment?
semic = raw_cell.rstrip().endswith(';')
Expand Down Expand Up @@ -129,13 +129,23 @@ def _out_nb(o, fmt):
def run(self:CaptureShell,
code:str, # Python/IPython code to run
stdout=True, # Capture stdout and save as output?
stderr=True): # Capture stderr and save as output?
stderr=True, # Capture stderr and save as output?
timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds
"Run `code`, returning a list of all outputs in Jupyter notebook format"
res = self.run_cell(code, stdout=stdout, stderr=stderr)
res = self.run_cell(code, stdout=stdout, stderr=stderr, timeout=timeout)
self.result = res.result.result
self.exc = res.exception
return _out_nb(res, self.display_formatter)

# %% ../nbs/02_shell.ipynb
@patch
async def run_async(self:CaptureShell,
code: str, # Python/IPython code to run
stdout=True, # Capture stdout and save as output?
stderr=True, # Capture stderr and save as output?
timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds
return self.run(code, stdout=stdout, stderr=stderr, timeout=timeout)

# %% ../nbs/02_shell.ipynb
def _pre(s, xtra=''): return f"<pre {xtra}><code>{escape(s)}</code></pre>"
def _strip(s): return strip_ansi(escape(s))
Expand Down
135 changes: 129 additions & 6 deletions nbs/02_shell.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"class CaptureShell(InteractiveShell):\n",
" displayhook_class = _CustDisplayHook\n",
"\n",
" def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout=None):\n",
" def __init__(self, path:str|Path=None, mpl_format='retina', history=False, timeout:Optional[int]=None):\n",
" super().__init__()\n",
" self.history_manager.enabled = history\n",
" self.timeout = timeout\n",
Expand All @@ -119,7 +119,7 @@
" self.run_cell(f\"set_matplotlib_formats('{mpl_format}')\")\n",
"\n",
" def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True, cell_id=None,\n",
" stdout=True, stderr=True, display=True, timeout=None):\n",
" stdout=True, stderr=True, display=True, timeout:Optional[int]=None):\n",
" if not timeout: timeout = self.timeout\n",
" # TODO what if there's a comment?\n",
" semic = raw_cell.rstrip().endswith(';')\n",
Expand Down Expand Up @@ -706,9 +706,10 @@
"def run(self:CaptureShell,\n",
" code:str, # Python/IPython code to run\n",
" stdout=True, # Capture stdout and save as output?\n",
" stderr=True): # Capture stderr and save as output?\n",
" stderr=True, # Capture stderr and save as output?\n",
" timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds\n",
" \"Run `code`, returning a list of all outputs in Jupyter notebook format\"\n",
" res = self.run_cell(code, stdout=stdout, stderr=stderr)\n",
" res = self.run_cell(code, stdout=stdout, stderr=stderr, timeout=timeout)\n",
" self.result = res.result.result\n",
" self.exc = res.exception\n",
" return _out_nb(res, self.display_formatter)"
Expand Down Expand Up @@ -863,6 +864,128 @@
"o"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'name': 'stdout', 'output_type': 'stream', 'text': ['no timeout\\n']}]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.run(\"import time; time.sleep(0.1); print('no timeout')\", timeout=1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['\\x1b[0;31m---------------------------------------------------------------------------\\x1b[0m\\n',\n",
" '\\x1b[0;31mTimeoutError\\x1b[0m Traceback (most recent call last)\\n']"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"o = s.run(\"import time; time.sleep(1.1)\", timeout=1)\n",
"o[0]['text'][:2]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"@patch\n",
"async def run_async(self:CaptureShell,\n",
" code: str, # Python/IPython code to run\n",
" stdout=True, # Capture stdout and save as output?\n",
" stderr=True, # Capture stderr and save as output?\n",
" timeout:Optional[int]=None): # Shell command will time out after {timeout} seconds\n",
" return self.run(code, stdout=stdout, stderr=stderr, timeout=timeout)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'data': {'text/plain': ['2']},\n",
" 'metadata': {},\n",
" 'output_type': 'execute_result'}]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await s.run_async(\"1+1\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'name': 'stdout', 'output_type': 'stream', 'text': ['no timeout\\n']}]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await s.run_async(\"import time; time.sleep(0.1); print('no timeout')\", timeout=1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['\\x1b[0;31m---------------------------------------------------------------------------\\x1b[0m\\n',\n",
" '\\x1b[0;31mTimeoutError\\x1b[0m Traceback (most recent call last)\\n']"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await s.run_async(\"import time; time.sleep(1.1);\", timeout=1)\n",
"o[0]['text'][:2]"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -2010,9 +2133,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "python3",
"display_name": "env",
"language": "python",
"name": "python3"
"name": "env"
}
},
"nbformat": 4,
Expand Down