Skip to content

ast.alias._attributes in Python 3.9 and "stdlib/ast.pyi" don't match #14102

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

Closed
hunterhogan opened this issue May 19, 2025 · 0 comments · Fixed by #14103
Closed

ast.alias._attributes in Python 3.9 and "stdlib/ast.pyi" don't match #14102

hunterhogan opened this issue May 19, 2025 · 0 comments · Fixed by #14103

Comments

@hunterhogan
Copy link
Contributor

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.

typeshed/stdlib/ast.pyi

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant