##// END OF EJS Templates
Merge pull request #12462 from meeseeksmachine/auto-backport-of-pr-12440-on-7.x...
Matthias Bussonnier -
r25927:0f74b428 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.
@@ -2883,11 +2883,24 b' class InteractiveShell(SingletonConfigurable):'
2883
2883
2884 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool):
2884 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool):
2885 """Internal method to run a complete IPython cell."""
2885 """Internal method to run a complete IPython cell."""
2886
2887 # we need to avoid calling self.transform_cell multiple time on the same thing
2888 # so we need to store some results:
2889 preprocessing_exc_tuple = None
2890 try:
2891 transformed_cell = self.transform_cell(raw_cell)
2892 except Exception:
2893 transformed_cell = raw_cell
2894 preprocessing_exc_tuple = sys.exc_info()
2895
2896 assert transformed_cell is not None
2886 coro = self.run_cell_async(
2897 coro = self.run_cell_async(
2887 raw_cell,
2898 raw_cell,
2888 store_history=store_history,
2899 store_history=store_history,
2889 silent=silent,
2900 silent=silent,
2890 shell_futures=shell_futures,
2901 shell_futures=shell_futures,
2902 transformed_cell=transformed_cell,
2903 preprocessing_exc_tuple=preprocessing_exc_tuple,
2891 )
2904 )
2892
2905
2893 # run_cell_async is async, but may not actually need an eventloop.
2906 # run_cell_async is async, but may not actually need an eventloop.
@@ -2896,7 +2909,11 b' class InteractiveShell(SingletonConfigurable):'
2896 # `%paste` magic.
2909 # `%paste` magic.
2897 if self.trio_runner:
2910 if self.trio_runner:
2898 runner = self.trio_runner
2911 runner = self.trio_runner
2899 elif self.should_run_async(raw_cell):
2912 elif self.should_run_async(
2913 raw_cell,
2914 transformed_cell=transformed_cell,
2915 preprocessing_exc_tuple=preprocessing_exc_tuple,
2916 ):
2900 runner = self.loop_runner
2917 runner = self.loop_runner
2901 else:
2918 else:
2902 runner = _pseudo_sync_runner
2919 runner = _pseudo_sync_runner
@@ -2911,7 +2928,9 b' class InteractiveShell(SingletonConfigurable):'
2911 return result
2928 return result
2912 return
2929 return
2913
2930
2914 def should_run_async(self, raw_cell: str) -> bool:
2931 def should_run_async(
2932 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
2933 ) -> bool:
2915 """Return whether a cell should be run asynchronously via a coroutine runner
2934 """Return whether a cell should be run asynchronously via a coroutine runner
2916
2935
2917 Parameters
2936 Parameters
@@ -2928,15 +2947,40 b' class InteractiveShell(SingletonConfigurable):'
2928 """
2947 """
2929 if not self.autoawait:
2948 if not self.autoawait:
2930 return False
2949 return False
2931 try:
2950 if preprocessing_exc_tuple is not None:
2932 cell = self.transform_cell(raw_cell)
2933 except Exception:
2934 # any exception during transform will be raised
2935 # prior to execution
2936 return False
2951 return False
2952 assert preprocessing_exc_tuple is None
2953 if transformed_cell is None:
2954 warnings.warn(
2955 "`should_run_async` will not call `transform_cell`"
2956 " automatically in the future. Please pass the result to"
2957 " `transformed_cell` argument and any exception that happen"
2958 " during the"
2959 "transform in `preprocessing_exc_tuple` in"
2960 " IPython 7.17 and above.",
2961 DeprecationWarning,
2962 stacklevel=2,
2963 )
2964 try:
2965 cell = self.transform_cell(raw_cell)
2966 except Exception:
2967 # any exception during transform will be raised
2968 # prior to execution
2969 return False
2970 else:
2971 cell = transformed_cell
2937 return _should_be_async(cell)
2972 return _should_be_async(cell)
2938
2973
2939 async def run_cell_async(self, raw_cell: str, store_history=False, silent=False, shell_futures=True) -> ExecutionResult:
2974 async def run_cell_async(
2975 self,
2976 raw_cell: str,
2977 store_history=False,
2978 silent=False,
2979 shell_futures=True,
2980 *,
2981 transformed_cell: Optional[str] = None,
2982 preprocessing_exc_tuple: Optional[Any] = None
2983 ) -> ExecutionResult:
2940 """Run a complete IPython cell asynchronously.
2984 """Run a complete IPython cell asynchronously.
2941
2985
2942 Parameters
2986 Parameters
@@ -2955,6 +2999,10 b' class InteractiveShell(SingletonConfigurable):'
2955 shell. It will both be affected by previous __future__ imports, and
2999 shell. It will both be affected by previous __future__ imports, and
2956 any __future__ imports in the code will affect the shell. If False,
3000 any __future__ imports in the code will affect the shell. If False,
2957 __future__ imports are not shared in either direction.
3001 __future__ imports are not shared in either direction.
3002 transformed_cell: str
3003 cell that was passed through transformers
3004 preprocessing_exc_tuple:
3005 trace if the transformation failed.
2958
3006
2959 Returns
3007 Returns
2960 -------
3008 -------
@@ -2989,17 +3037,33 b' class InteractiveShell(SingletonConfigurable):'
2989 if not silent:
3037 if not silent:
2990 self.events.trigger('pre_run_cell', info)
3038 self.events.trigger('pre_run_cell', info)
2991
3039
2992 # If any of our input transformation (input_transformer_manager or
3040 if transformed_cell is None:
2993 # prefilter_manager) raises an exception, we store it in this variable
3041 warnings.warn(
2994 # so that we can display the error after logging the input and storing
3042 "`run_cell_async` will not call `transform_cell`"
2995 # it in the history.
3043 " automatically in the future. Please pass the result to"
2996 try:
3044 " `transformed_cell` argument and any exception that happen"
2997 cell = self.transform_cell(raw_cell)
3045 " during the"
2998 except Exception:
3046 "transform in `preprocessing_exc_tuple` in"
2999 preprocessing_exc_tuple = sys.exc_info()
3047 " IPython 7.17 and above.",
3000 cell = raw_cell # cell has to exist so it can be stored/logged
3048 DeprecationWarning,
3049 stacklevel=2,
3050 )
3051 # If any of our input transformation (input_transformer_manager or
3052 # prefilter_manager) raises an exception, we store it in this variable
3053 # so that we can display the error after logging the input and storing
3054 # it in the history.
3055 try:
3056 cell = self.transform_cell(raw_cell)
3057 except Exception:
3058 preprocessing_exc_tuple = sys.exc_info()
3059 cell = raw_cell # cell has to exist so it can be stored/logged
3060 else:
3061 preprocessing_exc_tuple = None
3001 else:
3062 else:
3002 preprocessing_exc_tuple = None
3063 if preprocessing_exc_tuple is None:
3064 cell = transformed_cell
3065 else:
3066 cell = raw_cell
3003
3067
3004 # Store raw and processed history
3068 # Store raw and processed history
3005 if store_history:
3069 if store_history:
General Comments 0
You need to be logged in to leave comments. Login now