I am posting this as a single place to put information about all the various ways that a value in Locals or Watch can have children, and the rules or issues involved with each.
This is my understanding of the rules. Anyone please feel free to edit this text directly to make corrections.
An attribute of
is any name that appears in
. It includes properties. The value for
PTVS excludes certain attributes:
- Anything of the form
- Anything where
val.name.__call__ exists. This includes all user-defined methods defined at the class level for an instance, but it also excludes any other callable objects.
Proposal, please come up with some criterion to show more of these objects without cluttering up the space. If names that are found only in the class tree are grouped separately, then I would suppose that all callable children could be shown
without too much clutter.
is iterable if it behaves like some sort of sequence or mapping. It yields a sequence of values, and in the case of a mapping, (key, value) pairs.
Children are listed in iteration order. For a sequence, the names are
and the values are the iterated values. For a mapping, the names are
of the key) and
from the iterated pairs.
Sequence and mapping types are supposed to provide
. But not all of these are required to successfully enumerate the children.
Issues for discussion are:
- Distinguishing mapping types and what are the keys and values.
A mapping type is an object that can generate (key, value) pairs in one of various ways. A
val.items/iteritems/viewitems() method should be used if it exists. Otherwise, a
val.keys/iterkeys/viewkeys() method should be used if it exists. Otherwise,
iter(val) should be used to get the keys.
In the latter two cases,
val[key] is evaluated for each key generated and should succeed.
len(val) is used, if it exists, to limit the iterations, except for
val.keys(), which produce lists. If
len(val) does not exist, then the number of iterations can be limited, as it is currently to 10,000.
I like the idea of having a special child node for "items", which will show (key, value) tuples in the same order. This will allow the user to examine the keys by their children or adding to a Watch window.
PTVS currently only treates types derived from
dict as mapping types.
Proposal: to do this for all mapping types as defined here.
- Distinguishing sequence types and what are the values.
A sequence type is an object that can generate a sequence of values. It could have an
iter(val). The length of the iteration can be limited to 10,000 if
len(val) is not available, just as for mapping types. If there is no
iter(val) then there must be a
val[n] must succeed for all
0 <= n < len(val).
An object with
iter(val) might be either a mapping type or a sequence type. The difference is in how the values coincide with
- Values that should not iterate the children.
val should not iterate children if it has an
iter(val) is val. Enumerating values from this object is destructive to the object and makes it an iterator. At present the only types of iterator that do not iterate children are generators.
Proposal: to do this for all iterators.
- Being able to correctly expand descendants of the children.
I believe all these problems will be solved by a possible change in PTVS in which the actual Python object being shown in the window is remembered, and later reused if expanded or added to a Watch window. See Issue #2074, comment by pminaev Jan 17 1:17 a.m.
Even though the objects won't later be reevaluated, it's still nice to have an equivalent Python expression which will show up in the Watch window. The user can copy/paste or edit the expression text at her own risk, if it has side effects or an expansion
(direct or indirect) has side effects.
Special child nodes and top level Locals nodes
As a way of making the screen less cluttered, certain categories of children or top level items might be grouped under special nodes. An example mentioned above would be
for mapping types. I don't know if you all would prefer
or some other spelling; however I suggest
that a consistent convention be adopted and that it
. In C++, you see
nodes for some objects, but that's OK because the brackets for sequences only contain numbers. Not the case with Python mapping types.
Some possibilities for categories are: (1) global variables at the top level, (2) imported modules (if not included with globals), (3) the class of an instance, (4) the base classes of a class, or perhaps each base class separately, (5) all attributes for an
instance, wherever they are found, (6) all attributes for an instance that are found somewhere in the class tree, (7) special names (that is,
), and so on. I invite specific proposals of this nature.