Skip to content

Commit

Permalink
Merge pull request #12440 from Carreau/intputt
Browse files Browse the repository at this point in the history
  • Loading branch information
Carreau committed Jul 23, 2020
2 parents 3554706 + 65d8e78 commit 8c3dc03
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 19 deletions.
102 changes: 83 additions & 19 deletions IPython/core/interactiveshell.py
Expand Up @@ -81,7 +81,7 @@
from logging import error
import IPython.core.hooks

from typing import List as ListType, Tuple
from typing import List as ListType, Tuple, Optional
from ast import AST

# NoOpContext is deprecated, but ipykernel imports it from here.
Expand Down Expand Up @@ -2877,11 +2877,24 @@ def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=Tr

def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool) -> ExecutionResult:
"""Internal method to run a complete IPython cell."""

# we need to avoid calling self.transform_cell multiple time on the same thing
# so we need to store some results:
preprocessing_exc_tuple = None
try:
transformed_cell = self.transform_cell(raw_cell)
except Exception:
transformed_cell = raw_cell
preprocessing_exc_tuple = sys.exc_info()

assert transformed_cell is not None
coro = self.run_cell_async(
raw_cell,
store_history=store_history,
silent=silent,
shell_futures=shell_futures,
transformed_cell=transformed_cell,
preprocessing_exc_tuple=preprocessing_exc_tuple,
)

# run_cell_async is async, but may not actually need an eventloop.
Expand All @@ -2890,7 +2903,11 @@ def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures
# `%paste` magic.
if self.trio_runner:
runner = self.trio_runner
elif self.should_run_async(raw_cell):
elif self.should_run_async(
raw_cell,
transformed_cell=transformed_cell,
preprocessing_exc_tuple=preprocessing_exc_tuple,
):
runner = self.loop_runner
else:
runner = _pseudo_sync_runner
Expand All @@ -2904,7 +2921,9 @@ def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures
self.showtraceback(running_compiled_code=True)
return result

def should_run_async(self, raw_cell: str) -> bool:
def should_run_async(
self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
) -> bool:
"""Return whether a cell should be run asynchronously via a coroutine runner
Parameters
Expand All @@ -2921,15 +2940,40 @@ def should_run_async(self, raw_cell: str) -> bool:
"""
if not self.autoawait:
return False
try:
cell = self.transform_cell(raw_cell)
except Exception:
# any exception during transform will be raised
# prior to execution
if preprocessing_exc_tuple is not None:
return False
assert preprocessing_exc_tuple is None
if transformed_cell is None:
warnings.warn(
"`should_run_async` will not call `transform_cell`"
" automatically in the future. Please pass the result to"
" `transformed_cell` argument and any exception that happen"
" during the"
"transform in `preprocessing_exc_tuple` in"
" IPython 7.17 and above.",
DeprecationWarning,
stacklevel=2,
)
try:
cell = self.transform_cell(raw_cell)
except Exception:
# any exception during transform will be raised
# prior to execution
return False
else:
cell = transformed_cell
return _should_be_async(cell)

async def run_cell_async(self, raw_cell: str, store_history=False, silent=False, shell_futures=True) -> ExecutionResult:
async def run_cell_async(
self,
raw_cell: str,
store_history=False,
silent=False,
shell_futures=True,
*,
transformed_cell: Optional[str] = None,
preprocessing_exc_tuple: Optional[Any] = None
) -> ExecutionResult:
"""Run a complete IPython cell asynchronously.
Parameters
Expand All @@ -2948,6 +2992,10 @@ async def run_cell_async(self, raw_cell: str, store_history=False, silent=False,
shell. It will both be affected by previous __future__ imports, and
any __future__ imports in the code will affect the shell. If False,
__future__ imports are not shared in either direction.
transformed_cell: str
cell that was passed through transformers
preprocessing_exc_tuple:
trace if the transformation failed.
Returns
-------
Expand Down Expand Up @@ -2982,17 +3030,33 @@ def error_before_exec(value):
if not silent:
self.events.trigger('pre_run_cell', info)

# If any of our input transformation (input_transformer_manager or
# prefilter_manager) raises an exception, we store it in this variable
# so that we can display the error after logging the input and storing
# it in the history.
try:
cell = self.transform_cell(raw_cell)
except Exception:
preprocessing_exc_tuple = sys.exc_info()
cell = raw_cell # cell has to exist so it can be stored/logged
if transformed_cell is None:
warnings.warn(
"`run_cell_async` will not call `transform_cell`"
" automatically in the future. Please pass the result to"
" `transformed_cell` argument and any exception that happen"
" during the"
"transform in `preprocessing_exc_tuple` in"
" IPython 7.17 and above.",
DeprecationWarning,
stacklevel=2,
)
# If any of our input transformation (input_transformer_manager or
# prefilter_manager) raises an exception, we store it in this variable
# so that we can display the error after logging the input and storing
# it in the history.
try:
cell = self.transform_cell(raw_cell)
except Exception:
preprocessing_exc_tuple = sys.exc_info()
cell = raw_cell # cell has to exist so it can be stored/logged
else:
preprocessing_exc_tuple = None
else:
preprocessing_exc_tuple = None
if preprocessing_exc_tuple is None:
cell = transformed_cell
else:
cell = raw_cell

# Store raw and processed history
if store_history:
Expand Down
5 changes: 5 additions & 0 deletions docs/source/whatsnew/pr/transformer-call.rst
@@ -0,0 +1,5 @@
Input transformers are now called only once in the execution path of `InteractiveShell`, allowing to register
transformer that potentially have side effects (note that this is not recommended). `should_run_async`, and
`run_cell_async` now take a recommended optional `transformed_cell`, and `preprocessing_exc_tuple` parameters that will
become mandatory at some point in the future; that is to say cells need to be explicitly transformed to be valid Python
syntax ahead of trying to run them. :ghpull:`12440`

0 comments on commit 8c3dc03

Please sign in to comment.