Repository navigation
Typing the ast.AST subclass constructors #8378
Description
Activity
I'd be in favour of adding
__init__stubs to each subclass. PR welcome!Reacted by Alex WaygoodThoughts on the
dataclass_transformidea?I would prefer explicit
__init__s, since typically typeshed prefers to mirror closely what's happening at the runtime, rather than getting fancy and lying. Also not sure how well supported PEP 681 currently is by type checkers — last I checked mypy doesn't yet support it.
(Note dataclass_transform would have to be applied to a base class to work, not to the class itself. You'd also want to be careful to get all the params right, e.g. we shouldn't synthesise comparison methods and stuff)Reacted by Michael and Alex WaygoodInvoking the constructors seems fragile to me. For example, if you instantiate
ast.Module, it's easy to forget passing in a second argument and end up with aModulethat doesn't have atype_ignoresattribute:>>> ast.dump(ast.parse('f()')) "Module(body=[Expr(value=Call(func=Name(id='f', ctx=Load()), args=[], keywords=[]))], type_ignores=[])" >>> ast.parse('f()').type_ignores [] >>> ast.Module(body=[]).type_ignores Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Module' object has no attribute 'type_ignores'You can even make an empty module that doesn't have any attributes:
>>> ast.dump(ast.Module()) 'Module()' >>> ast.dump(ast.Module([])) 'Module(body=[])' >>> ast.dump(ast.Module([], [])) 'Module(body=[], type_ignores=[])'So code that instantiates AST nodes will break every time a new attribute is added. Maybe it means that you shouldn't do this and the type checker should error if you do this, or maybe it just means that type checking is unusually important here.
@Akuli I interpret it as type checking being particularly important for this module, which is why I raised this issue. imo ideally the actual constructor would validate the arguments too, but it doesn't seem to do that, and I don't want to touch the C code that provides the constructor, so I'm instead aiming at a type annotated constructor.
Reacted by Akuli, Jelle Zijlstra and Alex Waygood- addedstubs: improvementImprove/refactor existing annotations, other stubs issuesImprove/refactor existing annotations, other stubs issues
on Jul 24, 2022 - addedhelp wantedAn actionable problem of low to medium complexity where a PR would be very welcomeAn actionable problem of low to medium complexity where a PR would be very welcome
on Nov 1, 2023
We currently have static types for the fields of most (all?)
astclasses, but none of these have typed constructors, e.g.:typeshed/stdlib/_ast.pyi
Lines 79 to 86 in 62cde01
I think technically this might be because none of these subclasses actually have a unique constructor, but that shouldn't stop us from typing each of the constructors, since in practise the constructor arguments must correspond to the class fields.
Before I do this, though, I'm firstly wondering if an easy solution here would be to apply the
dataclass_transformdecorator (note: not the same as thedataclassdecorator). This would simply tell the type checker that all the class fields can and should be provided in the constructor, which is broadly correct. However I don't have a deep understanding of how theast.ASTconstructor works, so this might not be the correct behaviour. ForClassDefthis might look like:If this isn't sufficient, I propose that we simply add an
__init__()stub to each subclass. For instance, for theClassDefabove, this might look like: