-
-
Notifications
You must be signed in to change notification settings - Fork 30k
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
ast.NodeTransformer doc bug #47780
Comments
I am testing python 2.6 from SVN version: 40110 I tried the following, based on the documentation Python 2.6b2+ (unknown, Aug 6 2008, 18:05:08)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ast
>>> a = ast.parse('foo', mode='eval')
>>> x = compile(a, '<unknown>', mode='eval')
>>> class RewriteName(ast.NodeTransformer):
... def visit_Name(self, node):
... return ast.copy_location(ast.Subscript(
... value=ast.Name(id='data', ctx=ast.Load()),
... slice=ast.Index(value=ast.Str(s=node.id)),
... ctx=node.ctx
... ), node)
...
>>> a2 = RewriteName().visit(a)
>>> x2 = compile(a2, '<unknown>', mode='eval')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: required field "lineno" missing from expr
>>> |
This is actually not a bug. copy_location does not work recursively. import ast
a = ast.parse('foo', mode='eval')
x = compile(a, '<unknown>', mode='eval')
class RewriteName(ast.NodeTransformer):
def visit_Name(self, node):
return ast.Subscript(
value=ast.Name(id='data', ctx=ast.Load()),
slice=ast.Index(value=ast.Str(s=node.id)),
ctx=node.ctx
)
a2 = ast.fix_missing_locations(RewriteName().visit(a)) |
I am reopening this as a doc bug because RewriteName is a copy (with 'ast.' prefixes added) of a buggy example in the doc. The bug is that the new .value Name and Str attributes do not get the required 'lineno' and 'col_offset' attributes. As Armin said, copy_location is not recursive and does not fix children of the node it fixes. Also, the recursive .visit method does not recurse into children of replacement nodes (and if it did, the new Str node would still not be fixed). The fix could be to reuse the Name node and add another copy_location call: the following works. def visit_Name(self, node):
return ast.copy_location(
ast.Subscript(
value=node,
slice=ast.Index(value=ast.copy_location(
ast.Str(s=node.id), node)),
ctx=node.ctx),
node) but I think this illustrates that comment in the fix_missing_locations() entry that locations are "tedious to fill in for generated nodes". So I think the doc fix should use Armin's version of RewriteName and say to call fix_missing_locations on the result of .visit if new nodes are added. (I checked that his code still works in 3.5). The entry for NodeTransformer might mention that .visit does not recurse into replacement nodes. The missing lineno error came up in this python-list thread: |
I re-verified the problem, its presence in the doc, and the fix with 3.9. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: