Feature request: Locals window should not indicate an expandable node when it has no children


When a node appears in the Locals (or Watch, etc.) window, it has a + sign unless it is one of several specific type such as int, or it is indexable but has no items (such as an empty list or dict).
However, if the node has no displayable children, then clicking on the + sign makes the + sign go away, because the debugger script reports back an empty set of children.

What I would like to see is that when any object is reported back to VS as a node in one of these windows, the debugger script will determine if it is expandable using the same logic that will later be used to report on the expansion.

By "displayable," I am referring to the fact that certain children (like methods or with something names) are deliberately filtered out of the children that are displayed.


Zooba wrote Jan 3 at 4:26 PM

There are two reasons we do it this way, and they are likely to mean that we can't change it.

The first reason is side-effects. Because we're actually executing Python code in the background, we run the risk that enumerating an object may actually change it. To avoid this, we enumerate it once, and only when requested by the user (who presumably knows whether their object will change).

The second reason is performance. We already have many complaints about the speed of the debugger both when running (which is largely unavoidable at this stage) and when stepping. Checking the members and types of every object for each step will severely affect stepping performance, especially when there are many locals but likely even with only a few.

A far more realistic "fix" for your issue is to ensure that every object has children - perhaps we add a [type] child. I realize that this doesn't particularly make the window easier to use, but without a reliable and fast method of introspection (that doesn't require us to write large amounts of code for every version of Python we support) there isn't really a good alternative.

mrolle wrote Jan 4 at 8:03 AM

OK I understand about not enumerating a property when it is first presented to the IDE, because of possible side effects.
However, you can sometimes tell if expansion will be empty, I think. without risking modifying any state. You can do the dir() to see what attributes you will be displaying. And if it is an iterable object, you can see if it will give you a len(). In the latter case, I'm not sure if the len() function is "supposed" to be non-modifying.

So if the value is not iterable, you can at least see if it has any displayable attributes and then report as expandable or not, accordingly.

By the way, I've also thought about expanding generator objects. I know that a some generators are infinite. However, the IDE doesn't ever ask for all of the children. Rather, it asks for an interface which will then be used to get any requested subset of the children. There is the possible issue that a generator can only be used once, as well as possibly having side effects. But as you said above, caveat emptor.

pminaev wrote Jan 8 at 10:07 PM

For generators, we should do the same as what C# does for generic IEnumerables - don't show values, but show it as a method with a the deferred evaluation refresh icon, and when you click on refresh, eval and fetch results.

pminaev wrote Jan 15 at 8:00 PM

A separate bug to track generator expansion feature: