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( |
|
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( |
|
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 |
|
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