fabioz / PyDev.Debugger

Sources for the debugger used in PyDev, PyCharm and VSCode Python
Eclipse Public License 1.0
425 stars 122 forks source link

Functions starting with underscore are not grouped with function variables #246

Open jasongrout opened 1 year ago

jasongrout commented 1 year ago

Over in https://github.com/ipython/ipykernel/issues/1072, we noticed that sometimes getting the variables in a frame lists a function starting with a underscore as a normal variable, instead of grouping it with the function variables.

Here's a self-contained example illustrating the issue if run in ipython.

  1. Install ipython and debugpy: pip install ipython debugpy
  2. Create the repro.py file below:
repro.py ```python # This is example reproduces code from https://github.com/ipython/ipykernel/blob/main/ipykernel/debugger.py # This import is required to have the next ones working... from debugpy.server import api # noqa from _pydevd_bundle import pydevd_frame_utils # isort: skip from _pydevd_bundle.pydevd_suspended_frames import ( # isort: skip SuspendedFramesManager, _FramesTracker, ) class _FakeCode: def __init__(self, co_filename, co_name): self.co_filename = co_filename self.co_name = co_name class _FakeFrame: def __init__(self, f_code, f_globals, f_locals): self.f_code = f_code self.f_globals = f_globals self.f_locals = f_locals self.f_back = None class _DummyPyDB: def __init__(self): from _pydevd_bundle.pydevd_api import PyDevdAPI self.variable_presentation = PyDevdAPI.VariablePresentation() class VariableExplorer: def __init__(self): self.suspended_frame_manager = SuspendedFramesManager() self.py_db = _DummyPyDB() self.tracker = _FramesTracker(self.suspended_frame_manager, self.py_db) self.frame = None def track(self): var = get_ipython().user_ns self.frame = _FakeFrame(_FakeCode("", 'filename'), var, var) self.tracker.track("thread1", pydevd_frame_utils.create_frames_list_from_frame(self.frame)) def untrack_all(self): self.tracker.untrack_all() def get_children_variables(self, variable_ref=None): var_ref = variable_ref if not var_ref: var_ref = id(self.frame) variables = self.suspended_frame_manager.get_variable(var_ref) return [x.get_var_data() for x in variables.get_children_variables()] # Create a variable explorer v = VariableExplorer() v.track() # Define two functions, one starting with an underscore def abc(): ... def _abc(): ... # Note that `abc` does not appear in the results, but `_abc` does appear in the results. import pprint pprint.pprint([v for v in v.get_children_variables() if 'abc' in v["name"]]) ```
  1. Run ipython repro.py. Notice that _abc is listed in the output, but abc is not listed in the output.

My confusion is: it appears that abc is grouped with function variables, which is why it doesn't appear in the output. Why is _abc not grouped with the function variables, i.e., why does it appear in the output?