You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Misbehavior of f.__code__.co_firstlineno for decorated functions #139838
In the last example, the line continuation after @ is not handled correctly and the first line for f.__code__ then becomes the line at dummy. Because of that, the values returned by inspect.findsource(f) will not be consistent and inspect.getsourcelines will not use the correct source (it will only start at "dummy" and will not contain the "@" part).
@serhiy-storchaka suggested that this is an issue in the AST parser. I however don't know how we should actually fix this.
Consequences to inspect.getsource and other introspection functions:
This is a complex issue. The range of FunctionDef starts with the def line, it does not include decorators. The decorator_list attribute is a list of decorator expressions. Expression does not include @, so its range does not include the line with a single @\. co_firstlineno is calculated as minimum of lineno of the function and all decorator expressions.
Decorated functions and classes are the only nodes whose range do not include ranges of all its subnodes. We can change this by making their range including decorators (with @), this is relatively easy. This can only be done in a new release. We will lost information about the line containing def or class. I do not know what will be an impact of this.
Other option -- change AST even more. Instead of the decorator_list attribute of function and class nodes containing the list of decorators, introduce a Decorated node that wraps the function or class node and contains the list of decorators. Then we will have the position of def or class as well as the position of the first @, and the ranges will children will be always included in the range of the parent. But this will require changes in the code generator and some other code.
Expression does not include @, so its range does not include the line with a single @. co_firstlineno is calculated as minimum of lineno of the function and all decorator expressions.
Yes that's what I observed.
We will lost information about the line containing def or class
I think it will have an impact for analysis tools. Especially, static ones that could only rely on reading the file. An alternative to keep the current behavior could be to have an additional attribute that includes the entire range. That way we know the effective location of def and its surrounding.
Actually, it may not necessarily be that bad. In codegen_function:
firstlineno=s->lineno;
if (asdl_seq_LEN(decos)) {
firstlineno= ((expr_ty)asdl_seq_GET(decos, 0))->lineno;
}
So, we're already considering firstlineno to be the lineno of the first decorator. The decorators are arbitrary nodes but we could add where the decorator really started. And here, firstlineno wouldn't be lineno but atsymbol_lineno for instance.
I am trying to modify the parser but I never touched the grammar file and thus I'm not sure how I can make @ as part of the line being parsed. AFAIK, this is the only case where we have a non-keyword word which produces an AST node.
changed the title [-]Misbehavior of `f.__code__.co_firstlineno` for `@\`-decorated functions[/-][+]Misbehavior of `f.__code__.co_firstlineno` for decorated functions[/+]on Oct 29, 2025
Activity
serhiy-storchaka commentedon Oct 9, 2025
This is a complex issue. The range of
FunctionDefstarts with thedefline, it does not include decorators. Thedecorator_listattribute is a list of decorator expressions. Expression does not include@, so its range does not include the line with a single@\.co_firstlinenois calculated as minimum oflinenoof the function and all decorator expressions.Decorated functions and classes are the only nodes whose range do not include ranges of all its subnodes. We can change this by making their range including decorators (with
@), this is relatively easy. This can only be done in a new release. We will lost information about the line containingdeforclass. I do not know what will be an impact of this.Other option -- change AST even more. Instead of the
decorator_listattribute of function and class nodes containing the list of decorators, introduce aDecoratednode that wraps the function or class node and contains the list of decorators. Then we will have the position ofdeforclassas well as the position of the first@, and the ranges will children will be always included in the range of the parent. But this will require changes in the code generator and some other code.There may be old issues for this problem.
picnixz commentedon Oct 9, 2025
Yes that's what I observed.
I think it will have an impact for analysis tools. Especially, static ones that could only rely on reading the file. An alternative to keep the current behavior could be to have an additional attribute that includes the entire range. That way we know the effective location of
defand its surrounding.picnixz commentedon Oct 9, 2025
Actually, it may not necessarily be that bad. In
codegen_function:So, we're already considering firstlineno to be the lineno of the first decorator. The decorators are arbitrary nodes but we could add where the decorator really started. And here, firstlineno wouldn't be
linenobutatsymbol_linenofor instance.picnixz commentedon Oct 9, 2025
I am trying to modify the parser but I never touched the grammar file and thus I'm not sure how I can make
@as part of the line being parsed. AFAIK, this is the only case where we have a non-keyword word which produces an AST node.serhiy-storchaka commentedon Oct 9, 2025
See also #77392 and #9731. So the first idea would return the old behavior which had its own issues.
picnixz commentedon Oct 10, 2025
Arf, I see. I don't have much time today but I'll try to have a look tomorrow.
inspect.getsourcelinesbroken on commented decorators in 3.13.8 #140268 as a duplicate of this issuedmadisetti commentedon Oct 17, 2025
inspect.getsourceregressions for functions decorated with multi-line@(...)decorators. #140731 as a duplicate of this issue[-]Misbehavior of `f.__code__.co_firstlineno` for `@\`-decorated functions[/-][+]Misbehavior of `f.__code__.co_firstlineno` for decorated functions[/+]