showemptyattrs option on Node.show()#570
Conversation
| pass | ||
|
|
||
| def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None): | ||
| def show(self, buf=sys.stdout, offset=0, attrnames=False, hideemptyattrs=False, nodenames=False, showcoord=False, _my_node_name=None): |
There was a problem hiding this comment.
In general, I think it's preferable to have positive logic as much as possible, to avoid double-negation in code and reasoning about code.
Can you make it showemptyattrs=True?
There was a problem hiding this comment.
Hmm, yeah showemptyattrs does seem easier to reason about after extracting a helper.
if self.attr_names:
is_empty = lambda v: v is None or (hasattr(v, '__len__') and len(v) == 0)
nvlist = [(n, getattr(self,n)) for n in self.attr_names \
if showemptyattrs or not is_empty(getattr(self,n))]Do you think it is worth also extracting a filter, or just leave it inline?
if self.attr_names:
is_empty = lambda v: v is None or (hasattr(v, '__len__') and len(v) == 0)
attr_filter = lambda v: showemptyattrs or not is_empty(v)
nvlist = [(n, getattr(self,n)) for n in self.attr_names if attr_filter(getattr(self,n))]| buf.write(lead + self.__class__.__name__+ ': ') | ||
|
|
||
| if self.attr_names: | ||
| nvlist = [] |
There was a problem hiding this comment.
If you factor out the emptiness check into a helper function, this loop can become a simple loop comprehension again:
nvlist = [(n, getattr(self, n)) for n in self.attr_names if ...]
Or something similar
|
Ok, new commit pushed. |
|
Thanks for merging! Just to have it indexed by google, I'll drop an example here about how users can patch in their own custom #!/usr/bin/env python3
# Demonstration of patching in an alternative Node.show() method.
import sys
from pycparser import c_parser
from pycparser.c_ast import *
def show(self, buf=sys.stdout, indent=4, showcoord=True, _my_node_name=None, _lead='', _lastcoord=None, _depth=1):
""" Pretty print the Node and all its attributes and
children (recursively) to a buffer.
buf:
Open IO buffer into which the Node is printed.
indent:
The number of spaces to indent at each level.
showcoord:
Do you want the coordinates of each Node to be
displayed.
returns the number of parens which need to be closed by the parent.
"""
# print the node type
s = _lead
if _my_node_name:
s += "%s = " % _my_node_name
s += "%s(" % (self.__class__.__name__)
if showcoord and self.coord:
# only print the line number if it has changed
coord_did_change = _lastcoord is None \
or self.coord.file != _lastcoord.file \
or self.coord.line != _lastcoord.line
if coord_did_change:
s += ' // '
if self.coord.file:
s += '%s ' % self.coord.file
s += 'line %s' % self.coord.line
_lastcoord = self.coord
buf.write(s + '\n')
# use dots to give visual column cues
lead2 = _lead + '.' + (' ' * (indent-1))
# print the attributes
if self.attr_names:
for name, value in [(n, getattr(self,n)) for n in self.attr_names]:
# suppress empty fields
if value is None:
continue
if hasattr(value, '__len__') and len(value) == 0:
continue
buf.write(lead2 + "%s = %s\n" % (name, value))
# print the children.
unclosed_depth = 0
for i, (child_name, child) in enumerate(self.children()):
is_last = i+1 == len(self.children())
unclosed_depth = child.show(
buf,
indent=indent,
_my_node_name=child_name,
_lead=lead2,
_lastcoord=_lastcoord,
_depth=_depth+1
)
if not is_last:
dot_spaces = ('.' + ' '*(indent-1))
spaces_cparen = ')' + ' ' * (indent-1)
buf.write((dot_spaces * _depth) + (spaces_cparen * unclosed_depth) + '\n')
else:
# let the caller close out parens after the last child
pass
if _depth == 1:
# this is the final paren closing
unclosed_depth += 1
spaces_cparen = ')' + ' ' * (indent-1)
buf.write((spaces_cparen * unclosed_depth) + '\n')
else:
# let the caller close out parens after the last child
return unclosed_depth + 1
# patch in our custom show
Node.show = show
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.stderr.write("Error: no filename given.\n")
sys.exit(1)
fname = sys.argv[1]
with open(fname, 'r') as fd:
text = fd.read()
parser = c_parser.CParser()
ast = parser.parse(text)
ast.show()given int main(int argc, char** argv) {
printf("Hello, world!\n");
return 0;
}the above prints the following: |
This PR adds a
hideemptyattrsoption toNode.show(). Let me know what you think!Given
hello.c:Here's a comparison of all of the options.
default
show():with
hideemptyattrs:attrnames=True:with
hideemptyattrs:nodenames=True:with
hideemptyattrs:showcoord=True:with
hideemptyattrs: