-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
I'm 51% sure this belongs in typeshed, 49% sure this belongs in cpython, and 106.88% surely confused.
The 3.9 interpreter says ast.alias._attributes = (), however, the stub says **kwargs: Unpack[_Attributes], therefore, at the very least, there is conflicting information.
Lines 1431 to 1444 in a7ae4ec
| class alias(AST): | |
| lineno: int | |
| col_offset: int | |
| end_lineno: int | None | |
| end_col_offset: int | None | |
| if sys.version_info >= (3, 10): | |
| __match_args__ = ("name", "asname") | |
| name: str | |
| asname: str | None | |
| def __init__(self, name: str, asname: str | None = None, **kwargs: Unpack[_Attributes]) -> None: ... | |
| if sys.version_info >= (3, 14): | |
| def __replace__(self, *, name: str = ..., asname: str | None = ..., **kwargs: Unpack[_Attributes]) -> Self: ... | |
Evidence the stub file should change I am confused about what should change
I checked whether ast.alias.lineno exists in Python 3.9.
Python 3.9
(.309) C:\clones\typeshed>py
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ast
>>> source = 'from pathlib import Path'
>>> astModule = ast.parse(source)
>>> for node in ast.walk(astModule):
... if isinstance(node, ast.alias):
... print(node.lineno)
...
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
AttributeError: 'alias' object has no attribute 'lineno'
Python 3.12
I compared to Python 3.12 just to make sure.
(.venv) C:\clones\typeshed>py
Python 3.12.10 (tags/v3.12.10:0cc8128, Apr 8 2025, 12:21:36) [MSC v.1943 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ast
>>> source = 'from pathlib import Path'
>>> astModule = ast.parse(source)
>>> for node in ast.walk(astModule):
... if isinstance(node, ast.alias):
... print(node.lineno)
...
1
Obviously, the stub file is off
I compared the actual interpreter behaviors to the stub file, so the situation is clear, right?
But, just to be thorough...
Just in case, I wrote some code to look at the "_attributes" from a few different angles. I thought it would reinforce what I had found. Instead, I am unsure which source is reporting inaccurate information, and I don't know what one should investigate next.
import ast
import sys
print(f"\n{sys.version = }")
print(f"\n{ast.alias._attributes = }")
print(f'\n{(source := """from pathlib import Path""") = }')
astModule = ast.parse(source)
for node in ast.walk(astModule):
if isinstance(node, ast.alias):
try:
print(node.lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(ast.unparse(ast.Module([node], type_ignores=[])))
except AttributeError as ERRORmessage:
print(ERRORmessage)
print(f"\n{(ast_alias := ast.alias(name='Donald_Glover', asname='Childish_Gambino', lineno=0, col_offset=0, end_lineno=None, end_col_offset=None, OVER=9000)) = }")
node = ast_alias
if isinstance(node, ast.alias):
try:
print(node.lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.OVER)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(ast.unparse(ast.Module([node], type_ignores=[])))
except AttributeError as ERRORmessage:
print(ERRORmessage)
else:
print(type(node))
print(f"\n{(ast_alias := ast.alias(name='Temujin', asname='Genghis_Khan')) = }")
node = ast_alias
if isinstance(node, ast.alias):
try:
print(node.lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_lineno)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.end_col_offset)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(node.OVER)
except AttributeError as ERRORmessage:
print(ERRORmessage)
try:
print(ast.unparse(ast.Module([node], type_ignores=[])))
except AttributeError as ERRORmessage:
print(ERRORmessage)
else:
print(type(node))The full output
(.309) C:\clones\typeshed>alias309.py
sys.version = '3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)]'
ast.alias._attributes = ()
(source := """from pathlib import Path""") = 'from pathlib import Path'
'alias' object has no attribute 'lineno'
'alias' object has no attribute 'col_offset'
'alias' object has no attribute 'end_lineno'
'alias' object has no attribute 'end_col_offset'
Path
(ast_alias := ast.alias(name='Donald_Glover', asname='Childish_Gambino', lineno=0, col_offset=0, end_lineno=None, end_col_offset=None, OVER=9000)) = <ast.alias object at 0x000002A40DF58D90>
0
0
None
None
9000
Donald_Glover as Childish_Gambino
(ast_alias := ast.alias(name='Temujin', asname='Genghis_Khan')) = <ast.alias object at 0x000002A40DF58D00>
'alias' object has no attribute 'lineno'
'alias' object has no attribute 'col_offset'
'alias' object has no attribute 'end_lineno'
'alias' object has no attribute 'end_col_offset'
'alias' object has no attribute 'OVER'
Temujin as Genghis_Khan