Suggestion: make ast constructor types accept sequences

Summary

I suggest changing the current ast constructors from behaving like this:

class List:
    def __init__(self, elts: list[expr]):
        self.elts = elts

To this:

class List:
    def __init__(self, elts: Sequence[expr]):
        self.elts = list(elts)

Explanation

The data structure used for ast sequences of types is currently the list:

>>> import ast
>>> x = ast.parse("[1, 2]", mode="eval")
>>> x.body.elts
[<ast.Constant object at 0x1015bb010>, <ast.Constant object at 0x1015bb0d0>]
>>> type(x.body.elts)
<class 'list'>

Although I don’t see why it needs to be mutable, I won’t suggest changing this for compatibility reasons. I will assume that it is a given that the public interface of something like ast.List must remain as:

class List:
    elts: list[expr]

Instead I will look at the constructor. The ast types currently store the exact value that was passed into their constructor:

>>> ast.List(elts=123).elts
123

This means that a user must currently pass in a list to these constructors, to avoid breaking the interface mentioned above. However, this is not desirable because of list being invariant. Consequently, the following code, which looks sensible and safe, is illegal:

x = [ast.Constant(1), ast.Constant(2)]
ast.List(x)

e.g. pyright complains:

  "list[Constant]" is not assignable to "list[expr]"
    Type parameter "_T@list" is invariant, but "Constant" is not the same as "expr"
    Consider switching from "list" to "Sequence" which is covariant (reportArgumentType)

This issue has been discussed before, e.g. here, but the issue can’t be solved by changing the type signatures only, there needs to be a change in the Python internals to.

To fix this correctly, we just need to make ast types call list() on their list arguments. Then we can also loosen the constructor types to be Sequence, which would solve the above type error:

class List:
    def __init__(self, elts: Sequence[expr]):
        self.elts = list(elts)

Examples above run using Python 3.13.2, pyright 1.1.399.

Note that list(elts) would also work with an elts: Iterable[expr], so I suppose you could go more general than a Sequence.