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