Add future argument to all NodeNG.statement() calls#1235
Add future argument to all NodeNG.statement() calls#1235Pierre-Sassoulas merged 12 commits intopylint-dev:mainfrom
future argument to all NodeNG.statement() calls#1235Conversation
astroid/nodes/node_classes.py
Outdated
| try: | ||
| mystmt = self.statement(future=True) | ||
| except StatementMissing: | ||
| mystmt = self |
There was a problem hiding this comment.
@cdce8p These are the lines I referred to. Both calls to self.statement() will raise a StatementMissing exception when called on a nodes.Module. By adding a check for self.parent, which nodes.Module don't have, and a try ... except we can catch this.
However, similar to the actual change in #1217 I wonder if mystmt should actually become a nodes.Module in the first place (as it would still be with this change). You probably have a better idea if this is the way to go about fixing this.
Note that nodes.Module can't be imported due to circular imports so we can't do isinstance() here.
There was a problem hiding this comment.
I had some time to think about it. Did I make made a mistake by suggesting to raise an error if statement() is called on Module?
Some points to consider
statement()is often used together withframe()and thus doesn't quite represent an actualast.Statement. It's rather used to compare if thestatement()of a node is also equal to theframe(). Thus returningModulemade sense in that context.- During a normal
pylintrun you didn't encounter anAttributeErroras a parent had always been defined or it was aModulewhich returned itself. To updatepylint, we would need to add exception handling in at least some / most (?) cases. - Just from looking at the changes here, I'm not sure it's an actual improvement.
@DanielNoord What do you think?
There was a problem hiding this comment.
@DanielNoord Sorry to ping you again so soon. If we follow though and revert the change, I think if would be good to do so before pylint 2.12.0 is released. Reverting it would also address #1239.
/CC: @Pierre-Sassoulas
There was a problem hiding this comment.
If we need to revert that we might as well do it quick as the deprecation warning exists in 2.8.5 that has been released, it's better if it's reverted fast. I did not follow this close enough to have an opinion about it, so I trust your decision on this. Re-releasing astroid with a revert is cheap.
There was a problem hiding this comment.
I would recommend doing that. Would like to know what @DanielNoord thinks first as he also spend considerable time with the original change. One or two days more doesn't really matter too much, just the issue with the 2.12 release.
There was a problem hiding this comment.
I haven't gotten the time to look at this sufficiently. Should be able to do so tomorrow.
My initial feeling is that we should probably try and find a way to allow the precious behaviour but not in statement. statement returning Modules is completely unexpected based on the methods name and that confusion is what caused this in the first place. I think it is valuable to avoid such unlogical behaviour.
I haven't looked into why we need to return modules exactly in the first place, @cdce8p already mentioned it but haven't fully read the initial comment. But if this is indeed a valid use case, perhaps we need a module_and_statement()?
There was a problem hiding this comment.
I do agree. The name statement isn't ideal.
However as for changing it, I don't think it's worth it. We don't gain anything and just break code in the process. If there were a clear advantage, maybe. But even then there is a point to be made that the function should stay the same and we should instead add a new one that only returns actual Statement nodes. That would be backwards compatible.
There was a problem hiding this comment.
Just as this PR my response is WIP. But;
I have looked at _filter_stmts, which is the only function causing problems in astroid with future=True.
https://github.com/PyCQA/astroid/blob/30711bc012592844a902d1d5912b3b2b6f2dce0f/astroid/nodes/node_classes.py#L401
mystmt is used on some occasions, which I will discuss to show what happens when mystmt is in fact a nodes.Module.
https://github.com/PyCQA/astroid/blob/30711bc012592844a902d1d5912b3b2b6f2dce0f/astroid/nodes/node_classes.py#L448
nodes.Module.fromlineno is always 0. Therefore, this check will never be True.
stmt will never be a nodes.Module since _filter_stmts is only called with self.locals[name]. This will never include a nodes.Module so this check will never be True.
_get_filtered_stmts is not defined on nodes.Module. All three definitions of _get_filtered_stmts rely on comparing the self of _get_filtered_stmts to mystmt or calling self.statement() and comparing to mystmt. Since self is never nodes.Module this will never return True and done will never be True.
Since nodes.Module doesn't have a parent this will never be True.
So, to me it seems that the return of self for nodes.Module is done to avoid the AttributeError but is not meaningful in any way. Initialising mystmt as None and only reassigning if self.parent as I do in the commit I just added seems fine for astroid.
I tested these changes locally with pylint and all tests pass.
Then there is the issue of whether the behaviour of future is compatible with pylint. I am going to investigate this now and see whether we really need statement() to return nodes.Module. I agree that adding try ... except everywhere would not be good, but seeing as the change to astroid is relatively simple I think we might get away with it.
There was a problem hiding this comment.
I think pylint-dev/pylint#5310 shows that the effect of no longer returning nodes.Module for pylint is minimal as well.
That PR adds one isinstance(nodes.Module) (related to nodes.Module.fromlineno), one if XXX.parent and changes one except AttributeError to except StatementMissing. I tested that PR against the latest commit of astroid in this branch and all tests passed.
Based on this I think we do not need to revert the earlier change.
We never need statement() to return nodes.Module, both in pylint and in astroid. There is no if statement in any of the projects that evaluates to True whenever the method does return a nodes.Module. I think the return self was added to avoid creating crashes when AttributeError was raised or might have served a purpose it no longer does.
Pierre-Sassoulas
left a comment
There was a problem hiding this comment.
Very nice ! I just realized that we should have done that before releasing 2.8.5 as we already had this issue signaled to us previousely
cdce8p
left a comment
There was a problem hiding this comment.
I don't have the bandwidth at the moment to think about this further. It looks like you have done the research and it'll work out. So let's finish it then.
Could you also add quotes around NoReturn in the two places linked below? That would fix #1239 https://github.com/PyCQA/astroid/blob/30711bc012592844a902d1d5912b3b2b6f2dce0f/astroid/nodes/node_ng.py#L278
https://github.com/PyCQA/astroid/blob/30711bc012592844a902d1d5912b3b2b6f2dce0f/astroid/nodes/scoped_nodes.py#L665
cdce8p
left a comment
There was a problem hiding this comment.
Overall this looks good. Could you add a one line regarding the NoReturn fix? Either here or, as mentioned in the comment, in a new PR.
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
for more information, see https://pre-commit.ci
|
@Pierre-Sassoulas Should we do this before the primer? Or do you want to wait? |
|
@Pierre-Sassoulas Now that |
…ev#1235) * Add ``future`` argument to all ``NodeNG.statement()`` calls * Add typing from ``statement()`` Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Steps
Description
Follow up to #1217
This makes all calls to
NodeNG.statementuse thefuturekeyword argument added in #1217.There is one case where this is not as straightforward because the code depends on
nodes.Module.statement()returning itself. This is why I have marked this as a draft. I will comment on the relevant line.Closes #1239
Type of Changes
Related Issue