-
-
Notifications
You must be signed in to change notification settings - Fork 276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add future
argument to all NodeNG.statement()
calls
#1235
Add future
argument to all NodeNG.statement()
calls
#1235
Conversation
astroid/nodes/node_classes.py
Outdated
try: | ||
mystmt = self.statement(future=True) | ||
except StatementMissing: | ||
mystmt = self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 returningModule
made sense in that context.- During a normal
pylint
run you didn't encounter anAttributeError
as a parent had always been defined or it was aModule
which 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]>
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 <[email protected]>
Steps
Description
Follow up to #1217
This makes all calls to
NodeNG.statement
use thefuture
keyword 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