diff --git a/spyder_kernels/console/kernel.py b/spyder_kernels/console/kernel.py index 91776378..dac088f7 100644 --- a/spyder_kernels/console/kernel.py +++ b/spyder_kernels/console/kernel.py @@ -234,8 +234,7 @@ def filter_stack(self, stack, is_main): return stack @comm_handler - def get_current_frames(self, ignore_internal_threads=True, - capture_locals=False): + def get_current_frames(self, ignore_internal_threads=True): """Get the current frames.""" ignore_list = self.get_system_threads_id() main_id = threading.main_thread().ident @@ -246,9 +245,6 @@ def get_current_frames(self, ignore_internal_threads=True, for thread_id, frame in sys._current_frames().items(): stack = traceback.StackSummary.extract( traceback.walk_stack(frame)) - if capture_locals: - for f_summary, f in zip(stack, traceback.walk_stack(frame)): - f_summary.locals = self.get_namespace_view(frame=f[0]) stack.reverse() if ignore_internal_threads: if thread_id in ignore_list: diff --git a/spyder_kernels/console/shell.py b/spyder_kernels/console/shell.py index c641feb8..49cde462 100644 --- a/spyder_kernels/console/shell.py +++ b/spyder_kernels/console/shell.py @@ -263,10 +263,6 @@ def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None, try: etype, value, tb = self._get_exc_info(exc_tuple) stack = traceback.extract_tb(tb.tb_next) - for f_summary, f in zip( - stack, traceback.walk_tb(tb.tb_next)): - f_summary.locals = self.kernel.get_namespace_view( - frame=f[0]) self.kernel.frontend_call(blocking=False).show_traceback( etype, value, stack) except Exception: diff --git a/spyder_kernels/console/tests/test_console_kernel.py b/spyder_kernels/console/tests/test_console_kernel.py index e69eb79b..f97f5d90 100644 --- a/spyder_kernels/console/tests/test_console_kernel.py +++ b/spyder_kernels/console/tests/test_console_kernel.py @@ -226,7 +226,8 @@ def kernel(request): 'False_', 'True_' ], - 'minmax': False + 'minmax': False, + 'filter_on':True } # Teardown @@ -287,6 +288,31 @@ def test_get_namespace_view(kernel): assert "'python_type': 'int'" in nsview +@pytest.mark.parametrize("filter_on", [True, False]) +def test_get_namespace_view_filter_on(kernel, filter_on): + """ + Test the namespace view of the kernel with filters on and off. + """ + execute = asyncio.run(kernel.do_execute('a = 1', True)) + asyncio.run(kernel.do_execute('TestFilterOff = 1', True)) + + settings = kernel.namespace_view_settings + settings['filter_on'] = filter_on + settings['exclude_capitalized'] = True + nsview = kernel.get_namespace_view() + + if not filter_on: + assert 'a' in nsview + assert 'TestFilterOff' in nsview + else: + assert 'TestFilterOff' not in nsview + assert 'a' in nsview + + # Restore settings for other tests + settings['filter_on'] = True + settings['exclude_capitalized'] = False + + def test_get_var_properties(kernel): """ Test the properties fo the variables in the namespace. diff --git a/spyder_kernels/customize/spyderpdb.py b/spyder_kernels/customize/spyderpdb.py index ec505368..b9d76f63 100755 --- a/spyder_kernels/customize/spyderpdb.py +++ b/spyder_kernels/customize/spyderpdb.py @@ -17,6 +17,7 @@ import traceback import threading from collections import namedtuple +from functools import lru_cache from IPython.core.autocall import ZMQExitAutocall from IPython.core.debugger import Pdb as ipyPdb @@ -678,6 +679,21 @@ def _cmdloop(self): "For copying text while debugging, use Ctrl+Shift+C", file=self.stdout) + @lru_cache + def canonic(self, filename): + """Return canonical form of filename.""" + return super().canonic(filename) + + def do_exitdb(self, arg): + """Exit the debugger""" + self._set_stopinfo(self.botframe, None, -1) + sys.settrace(None) + frame = sys._getframe().f_back + while frame and frame is not self.botframe: + del frame.f_trace + frame = frame.f_back + return 1 + def cmdloop(self, intro=None): """ Repeatedly issue a prompt, accept input, parse an initial prefix diff --git a/spyder_kernels/utils/nsview.py b/spyder_kernels/utils/nsview.py index c19927f8..d7e0ce5a 100644 --- a/spyder_kernels/utils/nsview.py +++ b/spyder_kernels/utils/nsview.py @@ -589,7 +589,8 @@ def is_callable_or_module(value): def globalsfilter(input_dict, check_all=False, filters=None, exclude_private=None, exclude_capitalized=None, exclude_uppercase=None, exclude_unsupported=None, - excluded_names=None, exclude_callables_and_modules=None): + excluded_names=None, exclude_callables_and_modules=None, + filter_on=True): """Keep objects in namespace view according to different criteria.""" output_dict = {} def _is_string(obj): @@ -605,7 +606,7 @@ def _is_string(obj): (exclude_callables_and_modules and is_callable_or_module(value)) or (exclude_unsupported and not is_supported(value, check_all=check_all, filters=filters)) - ) + ) and filter_on if not excluded: output_dict[key] = value return output_dict @@ -617,7 +618,8 @@ def _is_string(obj): REMOTE_SETTINGS = ('check_all', 'exclude_private', 'exclude_uppercase', 'exclude_capitalized', 'exclude_unsupported', 'excluded_names', 'minmax', 'show_callable_attributes', - 'show_special_attributes', 'exclude_callables_and_modules') + 'show_special_attributes', 'exclude_callables_and_modules', + 'filter_on') def get_supported_types(): @@ -673,7 +675,7 @@ def get_remote_data(data, settings, mode, more_excluded_names=None): exclude_capitalized=settings['exclude_capitalized'], exclude_unsupported=settings['exclude_unsupported'], exclude_callables_and_modules=settings['exclude_callables_and_modules'], - excluded_names=excluded_names) + excluded_names=excluded_names, filter_on=settings['filter_on']) def make_remote_view(data, settings, more_excluded_names=None):