##// END OF EJS Templates
Merge pull request #12440 from Carreau/intputt
Matthias Bussonnier -
r25922:8c3dc03f merge
parent child Browse files
Show More
@@ -0,0 +1,5 b''
1 Input transformers are now called only once in the execution path of `InteractiveShell`, allowing to register
2 transformer that potentially have side effects (note that this is not recommended). `should_run_async`, and
3 `run_cell_async` now take a recommended optional `transformed_cell`, and `preprocessing_exc_tuple` parameters that will
4 become mandatory at some point in the future; that is to say cells need to be explicitly transformed to be valid Python
5 syntax ahead of trying to run them. :ghpull:`12440`
@@ -81,7 +81,7 b' from warnings import warn'
81 from logging import error
81 from logging import error
82 import IPython.core.hooks
82 import IPython.core.hooks
83
83
84 from typing import List as ListType, Tuple
84 from typing import List as ListType, Tuple, Optional
85 from ast import AST
85 from ast import AST
86
86
87 # NoOpContext is deprecated, but ipykernel imports it from here.
87 # NoOpContext is deprecated, but ipykernel imports it from here.
@@ -2877,11 +2877,24 b' class InteractiveShell(SingletonConfigurable):'
2877
2877
2878 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool) -> ExecutionResult:
2878 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool) -> ExecutionResult:
2879 """Internal method to run a complete IPython cell."""
2879 """Internal method to run a complete IPython cell."""
2880
2881 # we need to avoid calling self.transform_cell multiple time on the same thing
2882 # so we need to store some results:
2883 preprocessing_exc_tuple = None
2884 try:
2885 transformed_cell = self.transform_cell(raw_cell)
2886 except Exception:
2887 transformed_cell = raw_cell
2888 preprocessing_exc_tuple = sys.exc_info()
2889
2890 assert transformed_cell is not None
2880 coro = self.run_cell_async(
2891 coro = self.run_cell_async(
2881 raw_cell,
2892 raw_cell,
2882 store_history=store_history,
2893 store_history=store_history,
2883 silent=silent,
2894 silent=silent,
2884 shell_futures=shell_futures,
2895 shell_futures=shell_futures,
2896 transformed_cell=transformed_cell,
2897 preprocessing_exc_tuple=preprocessing_exc_tuple,
2885 )
2898 )
2886
2899
2887 # run_cell_async is async, but may not actually need an eventloop.
2900 # run_cell_async is async, but may not actually need an eventloop.
@@ -2890,7 +2903,11 b' class InteractiveShell(SingletonConfigurable):'
2890 # `%paste` magic.
2903 # `%paste` magic.
2891 if self.trio_runner:
2904 if self.trio_runner:
2892 runner = self.trio_runner
2905 runner = self.trio_runner
2893 elif self.should_run_async(raw_cell):
2906 elif self.should_run_async(
2907 raw_cell,
2908 transformed_cell=transformed_cell,
2909 preprocessing_exc_tuple=preprocessing_exc_tuple,
2910 ):
2894 runner = self.loop_runner
2911 runner = self.loop_runner
2895 else:
2912 else:
2896 runner = _pseudo_sync_runner
2913 runner = _pseudo_sync_runner
@@ -2904,7 +2921,9 b' class InteractiveShell(SingletonConfigurable):'
2904 self.showtraceback(running_compiled_code=True)
2921 self.showtraceback(running_compiled_code=True)
2905 return result
2922 return result
2906
2923
2907 def should_run_async(self, raw_cell: str) -> bool:
2924 def should_run_async(
2925 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
2926 ) -> bool:
2908 """Return whether a cell should be run asynchronously via a coroutine runner
2927 """Return whether a cell should be run asynchronously via a coroutine runner
2909
2928
2910 Parameters
2929 Parameters
@@ -2921,15 +2940,40 b' class InteractiveShell(SingletonConfigurable):'
2921 """
2940 """
2922 if not self.autoawait:
2941 if not self.autoawait:
2923 return False
2942 return False
2924 try:
2943 if preprocessing_exc_tuple is not None:
2925 cell = self.transform_cell(raw_cell)
2926 except Exception:
2927 # any exception during transform will be raised
2928 # prior to execution
2929 return False
2944 return False
2945 assert preprocessing_exc_tuple is None
2946 if transformed_cell is None:
2947 warnings.warn(
2948 "`should_run_async` will not call `transform_cell`"
2949 " automatically in the future. Please pass the result to"
2950 " `transformed_cell` argument and any exception that happen"
2951 " during the"
2952 "transform in `preprocessing_exc_tuple` in"
2953 " IPython 7.17 and above.",
2954 DeprecationWarning,
2955 stacklevel=2,
2956 )
2957 try:
2958 cell = self.transform_cell(raw_cell)
2959 except Exception:
2960 # any exception during transform will be raised
2961 # prior to execution
2962 return False
2963 else:
2964 cell = transformed_cell
2930 return _should_be_async(cell)
2965 return _should_be_async(cell)
2931
2966
2932 async def run_cell_async(self, raw_cell: str, store_history=False, silent=False, shell_futures=True) -> ExecutionResult:
2967 async def run_cell_async(
2968 self,
2969 raw_cell: str,
2970 store_history=False,
2971 silent=False,
2972 shell_futures=True,
2973 *,
2974 transformed_cell: Optional[str] = None,
2975 preprocessing_exc_tuple: Optional[Any] = None
2976 ) -> ExecutionResult:
2933 """Run a complete IPython cell asynchronously.
2977 """Run a complete IPython cell asynchronously.
2934
2978
2935 Parameters
2979 Parameters
@@ -2948,6 +2992,10 b' class InteractiveShell(SingletonConfigurable):'
2948 shell. It will both be affected by previous __future__ imports, and
2992 shell. It will both be affected by previous __future__ imports, and
2949 any __future__ imports in the code will affect the shell. If False,
2993 any __future__ imports in the code will affect the shell. If False,
2950 __future__ imports are not shared in either direction.
2994 __future__ imports are not shared in either direction.
2995 transformed_cell: str
2996 cell that was passed through transformers
2997 preprocessing_exc_tuple:
2998 trace if the transformation failed.
2951
2999
2952 Returns
3000 Returns
2953 -------
3001 -------
@@ -2982,17 +3030,33 b' class InteractiveShell(SingletonConfigurable):'
2982 if not silent:
3030 if not silent:
2983 self.events.trigger('pre_run_cell', info)
3031 self.events.trigger('pre_run_cell', info)
2984
3032
2985 # If any of our input transformation (input_transformer_manager or
3033 if transformed_cell is None:
2986 # prefilter_manager) raises an exception, we store it in this variable
3034 warnings.warn(
2987 # so that we can display the error after logging the input and storing
3035 "`run_cell_async` will not call `transform_cell`"
2988 # it in the history.
3036 " automatically in the future. Please pass the result to"
2989 try:
3037 " `transformed_cell` argument and any exception that happen"
2990 cell = self.transform_cell(raw_cell)
3038 " during the"
2991 except Exception:
3039 "transform in `preprocessing_exc_tuple` in"
2992 preprocessing_exc_tuple = sys.exc_info()
3040 " IPython 7.17 and above.",
2993 cell = raw_cell # cell has to exist so it can be stored/logged
3041 DeprecationWarning,
3042 stacklevel=2,
3043 )
3044 # If any of our input transformation (input_transformer_manager or
3045 # prefilter_manager) raises an exception, we store it in this variable
3046 # so that we can display the error after logging the input and storing
3047 # it in the history.
3048 try:
3049 cell = self.transform_cell(raw_cell)
3050 except Exception:
3051 preprocessing_exc_tuple = sys.exc_info()
3052 cell = raw_cell # cell has to exist so it can be stored/logged
3053 else:
3054 preprocessing_exc_tuple = None
2994 else:
3055 else:
2995 preprocessing_exc_tuple = None
3056 if preprocessing_exc_tuple is None:
3057 cell = transformed_cell
3058 else:
3059 cell = raw_cell
2996
3060
2997 # Store raw and processed history
3061 # Store raw and processed history
2998 if store_history:
3062 if store_history:
General Comments 0
You need to be logged in to leave comments. Login now