Skip to content

Conversation

@bzoracler
Copy link
Contributor

@bzoracler bzoracler commented May 9, 2024

Fixes #8378

  • ast.AST no longer owns attributes which may not exist on all subclasses (node locations, type_comment). These are all shifted to subclasses which actually own the attributes (d5e0838, 75a2e8e, f9a2cb9)
  • ast.AST no longer has the constructor __init__(self, *args: Any, **kwargs: Any).
  • All subclasses of ast.AST which have a non-empty _fields: ClassVar[tuple[str, ...]] or _attributes: ClassVar[tuple[str, ...]] now have their own __init__ constructor (d886a45). The constructor has:
    • Positional-or-keyword arguments in the order in which they appear in _fields, and
    • Non-mandatory keyword-only arguments from _attributes. These are expressed using a combination of typing.TypedDict and typing_extensions.Unpack.
      • These are non-mandatory because I expect most users won't pass explicit locations, but rather use something like ast.fix_missing_locations.

Updates:

  • Arguments of type ast.expr_context are not required to be passed to the constructor, but they will not exist on node instances for Python < 3.13.
  • Arguments of type list are not required to be passed to the constructor for Python >= 3.13.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@JelleZijlstra
Copy link
Member

Thanks for this, I had been thinking of adding it but hadn't gotten around to it.

stdlib/_ast.pyi Outdated
__match_args__ = ("body", "type_ignores")
body: list[stmt]
type_ignores: list[TypeIgnore]
def __init__(self, body: list[stmt], type_ignores: list[TypeIgnore]) -> None: ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These list fields should default to the empty list on 3.13+.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c82a5fa

decorator_list: list[expr],
returns: expr | None = None,
*,
type_comment: str | None = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think type_comment needs to be keyword-only on this overload.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9655775

@github-actions

This comment has been minimized.

@bzoracler
Copy link
Contributor Author

bzoracler commented May 10, 2024

I didn't add these other changes from Python 3.13 runtime to this PR:

  1. AST._field_types - not sure what the intention is for the values of these dictionaries; are they meant to be for runtime introspection, or can they be anything?
  2. The default_value parameter for ast.TypeVar, ast.ParamSpec, ast.TypeVarTuple - the runtime suggests that this defaults to None if not passed, but the grammar does not mark this field as optional. (I misread the grammar, they're definitely optional)

@github-actions

This comment has been minimized.

@JelleZijlstra
Copy link
Member

  1. AST._field_types - not sure what the intention is for the values of these dictionaries; are they meant to be for runtime introspection, or can they be anything?

It's used by the constructor of AST nodes to figure out what defaults to use. I did document it, so I think we should add it to the ast.AST class as ClassVar[dict[str, Any]].

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

pyp (https://github.com/hauntsaninja/pyp)
+ pyp.py:585: error: "AST" has no attribute "lineno"  [attr-defined]
+ pyp.py:586: error: "AST" has no attribute "end_lineno"  [attr-defined]

sphinx (https://github.com/sphinx-doc/sphinx)
+ sphinx/ext/autodoc/preserve_defaults.py: note: In function "get_default_value":
+ sphinx/ext/autodoc/preserve_defaults.py:114:12: error: "AST" has no attribute "lineno"  [attr-defined]
+ sphinx/ext/autodoc/preserve_defaults.py:114:31: error: "AST" has no attribute "end_lineno"  [attr-defined]
+ sphinx/ext/autodoc/preserve_defaults.py:115:26: error: "AST" has no attribute "lineno"  [attr-defined]
+ sphinx/ext/autodoc/preserve_defaults.py:116:25: error: "AST" has no attribute "col_offset"  [attr-defined]
+ sphinx/ext/autodoc/preserve_defaults.py:116:45: error: "AST" has no attribute "end_col_offset"  [attr-defined]

mypy (https://github.com/python/mypy)
+ mypy/fastparse.py:1998: error: "Index" has no attribute "col_offset"  [attr-defined]
+ mypy/fastparse.py:2001: error: "Slice" has no attribute "col_offset"  [attr-defined]
+ mypy/fastparse.py:2002: error: Argument 1 to "Tuple" has incompatible type "List[slice]"; expected "List[expr]"  [arg-type]

pytest (https://github.com/pytest-dev/pytest)
+ src/_pytest/assertion/rewrite.py:839: error: Argument 1 to "Dict" has incompatible type "list[Constant]"; expected "list[expr | None]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:839: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:839: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:932: error: Argument 3 to "If" has incompatible type "list[If]"; expected "list[stmt]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:932: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:932: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:938: error: Argument 1 to "Assign" has incompatible type "list[Name]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:938: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:938: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:963: error: Argument 1 to "Assign" has incompatible type "list[Name]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:963: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:963: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:1145: error: Argument 1 to "Tuple" has incompatible type "list[Constant]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:1145: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:1145: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:1146: error: Argument 1 to "Tuple" has incompatible type "list[Name]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:1146: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:1146: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:1147: error: Argument 1 to "Tuple" has incompatible type "list[Constant]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:1147: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:1147: note: Consider using "Sequence" instead, which is covariant
+ src/_pytest/assertion/rewrite.py:1151: error: Argument 2 to "BoolOp" has incompatible type "list[Name]"; expected "list[expr]"  [arg-type]
+ src/_pytest/assertion/rewrite.py:1151: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
+ src/_pytest/assertion/rewrite.py:1151: note: Consider using "Sequence" instead, which is covariant
+ testing/test_assertrewrite.py:133: error: "AST" has no attribute "lineno"  [attr-defined]
+ testing/test_assertrewrite.py:134: error: "AST" has no attribute "col_offset"  [attr-defined]
+ testing/test_assertrewrite.py:135: error: "AST" has no attribute "end_lineno"  [attr-defined]
+ testing/test_assertrewrite.py:136: error: "AST" has no attribute "end_col_offset"  [attr-defined]

werkzeug (https://github.com/pallets/werkzeug)
+ src/werkzeug/routing/rules.py:785: error: Argument 1 to "JoinedStr" has incompatible type "list[AST]"; expected "list[expr]"  [arg-type]
+ src/werkzeug/routing/rules.py:788: error: List item 0 has incompatible type "AST"; expected "expr"  [list-item]
+ src/werkzeug/routing/rules.py:788: error: List item 1 has incompatible type "AST"; expected "expr"  [list-item]
+ src/werkzeug/routing/rules.py:818: error: "AST" has no attribute "lineno"  [attr-defined]
+ src/werkzeug/routing/rules.py:820: error: "AST" has no attribute "end_lineno"  [attr-defined]
+ src/werkzeug/routing/rules.py:820: error: "AST" has no attribute "lineno"  [attr-defined]
+ src/werkzeug/routing/rules.py:822: error: "AST" has no attribute "col_offset"  [attr-defined]
+ src/werkzeug/routing/rules.py:824: error: "AST" has no attribute "end_col_offset"  [attr-defined]
+ src/werkzeug/routing/rules.py:824: error: "AST" has no attribute "col_offset"  [attr-defined]

ibis (https://github.com/ibis-project/ibis)
+ ibis/backends/bigquery/udf/core.py:66: error: Missing positional arguments "args", "keywords" in call to "Call"  [call-arg]
+ ibis/backends/bigquery/udf/core.py:79: error: Missing positional arguments "args", "keywords" in call to "Call"  [call-arg]
+ ibis/backends/bigquery/udf/core.py:85: error: Missing positional arguments "args", "keywords" in call to "Call"  [call-arg]
+ ibis/backends/bigquery/udf/core.py:85: error: Missing positional argument "value" in call to "Attribute"  [call-arg]
+ ibis/backends/bigquery/udf/core.py:95: error: Missing positional arguments "args", "keywords" in call to "Call"  [call-arg]

flake8-pyi (https://github.com/PyCQA/flake8-pyi)
+ pyi.py:2249: error: "AST" has no attribute "lineno"  [attr-defined]
+ pyi.py:2249: error: "AST" has no attribute "col_offset"  [attr-defined]

streamlit (https://github.com/streamlit/streamlit)
+ lib/streamlit/runtime/scriptrunner/magic.py: note: In function "_build_st_write_call":
+ lib/streamlit/runtime/scriptrunner/magic.py:166:12: error: Unexpected keyword argument "kwargs" for "Call"; did you mean "args"?  [call-arg]
+ note: "Call" defined here
+ lib/streamlit/runtime/scriptrunner/magic.py:166:12: error: Unexpected keyword argument "starargs" for "Call"  [call-arg]
+ note: "Call" defined here

Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@JelleZijlstra JelleZijlstra merged commit 5bd7150 into python:main May 18, 2024
JelleZijlstra added a commit to PyCQA/flake8-pyi that referenced this pull request May 18, 2024
python/typeshed#11880 correctly points out that not all AST nodes have a line and column number.
JelleZijlstra added a commit to JelleZijlstra/pytest that referenced this pull request May 18, 2024
python/typeshed#11880 adds more precise types for AST nodes. I'm submitting some changes to adapt pytest to these changes.
AlexWaygood pushed a commit to PyCQA/flake8-pyi that referenced this pull request May 18, 2024
python/typeshed#11880 correctly points out that not all AST nodes have a
line and column number.
JelleZijlstra added a commit to JelleZijlstra/werkzeug that referenced this pull request May 18, 2024
Adapting to changes in python/typeshed#11880. This mostly adds
more precise types for individual pieces of AST.
JelleZijlstra added a commit to JelleZijlstra/sphinx that referenced this pull request May 18, 2024
Followup from python/typeshed#11880. Not all AST nodes have a lineno; in this file only parameter defaults are passed to this function, which are always ast.expr.
bluetech pushed a commit to pytest-dev/pytest that referenced this pull request May 18, 2024
python/typeshed#11880 adds more precise types for AST nodes. I'm submitting some changes to adapt pytest to these changes.
@bzoracler bzoracler deleted the ast-subclass-constructors branch May 18, 2024 20:12
JelleZijlstra added a commit to JelleZijlstra/streamlit that referenced this pull request May 18, 2024
See https://docs.python.org/3.10/library/ast.html#abstract-grammar for a reference on the attributes `ast.Call` takes.

A future version of mypy will give a type error for this code (python/typeshed#11880).
vdonato added a commit to streamlit/streamlit that referenced this pull request May 21, 2024
See https://docs.python.org/3.10/library/ast.html#abstract-grammar for a
reference on the attributes `ast.Call` takes.

A future version of mypy will give a type error for this code
(python/typeshed#11880).

Co-authored-by: Vincent Donato <[email protected]>
davidism pushed a commit to JelleZijlstra/werkzeug that referenced this pull request Aug 20, 2024
Adapting to changes in python/typeshed#11880. This mostly adds
more precise types for individual pieces of AST.
benjamin-awd pushed a commit to benjamin-awd/streamlit that referenced this pull request Sep 29, 2024
See https://docs.python.org/3.10/library/ast.html#abstract-grammar for a
reference on the attributes `ast.Call` takes.

A future version of mypy will give a type error for this code
(python/typeshed#11880).

Co-authored-by: Vincent Donato <[email protected]>
asmeralt pushed a commit to asmeralt/streamlit that referenced this pull request Sep 29, 2025
See https://docs.python.org/3.10/library/ast.html#abstract-grammar for a
reference on the attributes `ast.Call` takes.

A future version of mypy will give a type error for this code
(python/typeshed#11880).

Co-authored-by: Vincent Donato <[email protected]>
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 this pull request may close these issues.

Typing the ast.AST subclass constructors

3 participants