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
The inspect getsource method fails to return the full source code of a target function if it has been decorated with a decorator that has been passed an argument with its own argument of a lambda function. This only happens if the decorator argument with the lambda is not the first argument of the decorator and there is an argument before it with a bracket e.g. a class or tuple.
The issue is caused by the inspect class BlockFinder wrongly setting self.indecorator to False when the token ")" is passed in the stream to tokeneater. This results in the lambda being able to incorrectly raise an EndOfBlock.
Potential Solution
By tracking if a "(" token has been ran whilst self.indecorator is True and preventing self.indecorator from going False until a ")" token is passed the issue is avoided.
The updated BlockFinder class which prevents this issue:
classBlockFinder:
"""Provide a tokeneater() method to detect the end of a code block."""def__init__(self):
self.indent=0self.islambda=Falseself.started=Falseself.passline=Falseself.indecorator=Falseself.decoratorhasargs=Falseself.last=1self.body_col0=Noneself.decorator_open_bracket=Falseself.decorator_args_open_bracket=0deftokeneater(self, type, token, srowcol, erowcol, line):
ifnotself.startedandnotself.indecorator:
iftoken=="@":
self.indecorator=Trueeliftokenin ("def", "class", "lambda"):
iftoken=="lambda":
self.islambda=Trueself.started=Trueself.passline=Trueeliftoken=="(":
ifself.indecorator:
self.decoratorhasargs=Trueifself.decorator_open_bracket:
self.decorator_args_open_bracket+=1else:
self.decorator_open_bracket=Trueeliftoken==")":
ifself.indecoratorandself.decorator_args_open_bracket:
self.decorator_args_open_bracket-=1elifself.indecorator:
self.indecorator=Falseself.decorator_open_bracket=Falseself.decoratorhasargs=Falseeliftype==tokenize.NEWLINE:
self.passline=Falseself.last=srowcol[0]
ifself.islambda:
raiseEndOfBlockifself.indecoratorandnotself.decoratorhasargs:
self.indecorator=Falseelifself.passline:
passeliftype==tokenize.INDENT:
ifself.body_col0isNoneandself.started:
self.body_col0=erowcol[1]
self.indent=self.indent+1self.passline=Trueeliftype==tokenize.DEDENT:
self.indent=self.indent-1ifself.indent<=0:
raiseEndOfBlockeliftype==tokenize.COMMENT:
ifself.body_col0isnotNoneandsrowcol[1] >=self.body_col0:
self.last=srowcol[0]
elifself.indent==0andtypenotin (tokenize.COMMENT, tokenize.NL):
raiseEndOfBlock
Your environment
CPython versions tested on: 3.10.8
Operating system and architecture: Windows / Linux
The text was updated successfully, but these errors were encountered:
Thanks for the careful debugging and the report. This was already fixed in #99654 and backported to 3.10 in fe7c309 -- if you upgrade to Python 3.10.10, it should contain the fix.
Bug report
The inspect getsource method fails to return the full source code of a target function if it has been decorated with a decorator that has been passed an argument with its own argument of a lambda function. This only happens if the decorator argument with the lambda is not the first argument of the decorator and there is an argument before it with a bracket e.g. a class or tuple.
The first three examples above will print the correct source code however the final three examples will print only:
The issue is caused by the inspect class BlockFinder wrongly setting self.indecorator to False when the token ")" is passed in the stream to tokeneater. This results in the lambda being able to incorrectly raise an EndOfBlock.
Potential Solution
By tracking if a "(" token has been ran whilst self.indecorator is True and preventing self.indecorator from going False until a ")" token is passed the issue is avoided.
The updated BlockFinder class which prevents this issue:
Your environment
The text was updated successfully, but these errors were encountered: