Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jasongrout opened this issue Jan 6, 2023 · 0 comments

Comments

@jasongrout
Copy link

jasongrout commented Jan 6, 2023

Over in ipython/ipykernel#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
# 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("<module>", '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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant