Title: AttributeError in ast.unparse
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.11, Python 3.10, Python 3.9
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: BTaskaya, Mark.Shannon, benjamin.peterson, brett.cannon, pablogsal, xiaket, yselivanov
Priority: normal Keywords: patch

Created on 2021-08-12 01:26 by xiaket, last changed 2021-08-16 08:04 by lukasz.langa.

Pull Requests
URL Status Linked Edit
PR 27770 open BTaskaya, 2021-08-14 17:54
Messages (2)
msg399427 - (view) Author: Kai Xia (xiaket) * Date: 2021-08-12 01:26
I was trying to construct an ast object dynamically and I think I can identify some potential issue.

With the following snippet:

#!/usr/bin/env python3
import ast
import sys


good = ast.Assign(
    targets=[ast.Name(id="hello", ctx=ast.Store())],

bad = ast.Assign(
    targets=[ast.Name(id="hello", ctx=ast.Store())],

On my box the output looks like:

3.9.6 (default, Jun 29 2021, 05:25:02)
[Clang 12.0.5 (clang-1205.0.22.9)]
hello = 'world'
Traceback (most recent call last):
  File "/Users/xiaket/", line 19, in <module>
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 1572, in unparse
    return unparser.visit(ast_obj)
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 801, in visit
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 795, in traverse
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 407, in visit
    return visitor(node)
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 858, in visit_Assign
    if type_comment := self.get_type_comment(node):
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/", line 786, in get_type_comment
    comment = self._type_ignores.get(node.lineno) or node.type_comment
AttributeError: 'Assign' object has no attribute 'lineno'

As I can understand, when we need to construct the Assign object, we'll need to provide two keyword arguments, targets and value. We don't need to provide the `lineno` as it should be an attribute of the statement node. Also, if we don't run `unparse` against the object, apparently it works fine.

I think in the `get_type_comment` method, we are making the assumption that the lineno is set automatically, this is true when we are parsing python source code as string. But when we are creating the object from scratch, we don't have that `lineno` attribute and it will fail.
msg399593 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python committer) Date: 2021-08-14 14:42
I don't think this is really an issue considering some other functionalities that consumes AST code (e.g `compile`) will expect it to be annotated with location metadata. This is why the `ast` module already comes bundled with a utility function called `fix_missing_locations` which in your example would work;

> print(ast.unparse(bad))
> print(ast.unparse(ast.fix_missing_locations(bad)))

Though I recall seeing this error once before, and since there also some counter examples (e.g ast.increment_lineno) that assume an AST node might lack of these attributes even though the nodes declare them makes it worth to fix.
Date User Action Args
2021-08-16 08:04:15lukasz.langasetversions: + Python 3.10, Python 3.11
2021-08-14 17:54:18BTaskayasetkeywords: + patch
stage: patch review
pull_requests: + pull_request26245
2021-08-14 14:42:22BTaskayasetmessages: + msg399593
2021-08-13 23:05:25terry.reedysettitle: Issue with unparse in ast module -> AttributeError in ast.unparse
2021-08-13 23:04:23terry.reedysetnosy: + brett.cannon, benjamin.peterson, Mark.Shannon, yselivanov, pablogsal, BTaskaya
2021-08-12 01:26:20xiaketcreate