diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-08-29 06:30:23 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-29 06:30:23 (GMT) |
commit | e64f948e762a6b9fd02e2902ccf42438df6fcb61 (patch) | |
tree | 833c88bf7abd2b0ded10bd61468c0d238dedf514 /Lib/ast.py | |
parent | b235a1b47394eedc5f8ea4cf214f56c4c6932e59 (diff) | |
download | cpython-e64f948e762a6b9fd02e2902ccf42438df6fcb61.zip cpython-e64f948e762a6b9fd02e2902ccf42438df6fcb61.tar.gz cpython-e64f948e762a6b9fd02e2902ccf42438df6fcb61.tar.bz2 |
bpo-37950: Fix ast.dump() when call with incompletely initialized node. (GH-15510)
Diffstat (limited to 'Lib/ast.py')
-rw-r--r-- | Lib/ast.py | 39 |
1 files changed, 24 insertions, 15 deletions
@@ -98,26 +98,35 @@ def literal_eval(node_or_string): def dump(node, annotate_fields=True, include_attributes=False): """ - Return a formatted dump of the tree in *node*. This is mainly useful for - debugging purposes. The returned string will show the names and the values - for fields. This makes the code impossible to evaluate, so if evaluation is - wanted *annotate_fields* must be set to False. Attributes such as line + Return a formatted dump of the tree in node. This is mainly useful for + debugging purposes. If annotate_fields is true (by default), + the returned string will show the names and the values for fields. + If annotate_fields is false, the result string will be more compact by + omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, - *include_attributes* can be set to True. + include_attributes can be set to true. """ def _format(node): if isinstance(node, AST): - fields = [(a, _format(b)) for a, b in iter_fields(node)] - rv = '%s(%s' % (node.__class__.__name__, ', '.join( - ('%s=%s' % field for field in fields) - if annotate_fields else - (b for a, b in fields) - )) + args = [] + keywords = annotate_fields + for field in node._fields: + try: + value = getattr(node, field) + except AttributeError: + keywords = True + else: + if keywords: + args.append('%s=%s' % (field, _format(value))) + else: + args.append(_format(value)) if include_attributes and node._attributes: - rv += fields and ', ' or ' ' - rv += ', '.join('%s=%s' % (a, _format(getattr(node, a))) - for a in node._attributes) - return rv + ')' + for a in node._attributes: + try: + args.append('%s=%s' % (a, _format(getattr(node, a)))) + except AttributeError: + pass + return '%s(%s)' % (node.__class__.__name__, ', '.join(args)) elif isinstance(node, list): return '[%s]' % ', '.join(_format(x) for x in node) return repr(node) |