Skip to content
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

nonlocal in locals #2617

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft

nonlocal in locals #2617

wants to merge 4 commits into from

Conversation

yueyinqiu
Copy link

@yueyinqiu yueyinqiu commented Oct 19, 2024

Type of Changes

Type
🐛 Bug fix

Description

Closes #2616

I did this by adding a _nonlocal_names property in TreeRebuilder to store those nonlocal names, like what _global_names does. However it stores FunctionDefs where the variables are created, instead of Nonlocal nodes. (The saved Global nodes in _global_names is not used for as well, but I didn't touch it, in case we may need that one day.)

The items of _nonlocal_names are added in visit_nonlocal, which go through the tree and find the nearest FunctionDef whose locals contains that name.

And it is used in _save_assignment. If node.name is in self._nonlocal_names[-1], then it will be put into self._nonlocal_names[-1][node.name] (the found FunctionDef) rather than into node.parent.

I have also added a unit test test_locals_with_global_and_nonlocal in test_builder.py, but I'm not really sure if I put it in the correct place.

There might be some other problems since it's my first PR for this project. Really need someone to check it before merging.

@yueyinqiu yueyinqiu marked this pull request as ready for review October 19, 2024 07:10
@Pierre-Sassoulas Pierre-Sassoulas added this to the 3.3.6 milestone Oct 19, 2024
@yueyinqiu
Copy link
Author

yueyinqiu commented Oct 20, 2024

Hmmm... Why pylint consider scope as Nonlocal since it's inside if isinstance(scope, nodes.FunctionDef)... Should I add # type: ignore here to suppress the warning?

Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't understand the pylint issue. Pinging @jacobtylerwalls to see if this sounds familiar, they have a very good grasp of recurring pylint issues

@@ -61,6 +61,11 @@ def __init__(
self._manager = manager
self._data = data.split("\n") if data else None
self._global_names: list[dict[str, list[nodes.Global]]] = []
# In _nonlocal_names,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is formatted a bit strange. Does it fit on two lines?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified it to

# In _nonlocal_names saves the FunctionDef where the variable is created,
# rather than Nonlocal, since we don't really need the Nonlocal statement.

astroid/rebuilder.py Show resolved Hide resolved
astroid/rebuilder.py Show resolved Hide resolved
Copy link
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working up the PR, but if you don't mind I'd like to pause to consider this in a little more detail first. My first impression is to wonder if we need to make a change here at all, see comment on issue.

@yueyinqiu yueyinqiu marked this pull request as draft October 21, 2024 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

nonlocal variables are included in locals while global variables not
4 participants