-
Notifications
You must be signed in to change notification settings - Fork 178
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
Catch usage of undefined name with global statement #324
base: main
Are you sure you want to change the base?
Conversation
a9bdb17
to
869e6c0
Compare
@sigmavirus24 it seems the CI is failing not because of the test. |
ah. sorry, I didn't know that it's error of flake8 |
wait... all flake8 error isn't related with my PR. |
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.
Also please add the test from the original issue to make sure the problem is corrected.
def test(x):
global x
pyflakes/checker.py
Outdated
elif isinstance(node.ctx, ast.Del): | ||
self.handleNodeDelete(node) | ||
if (isinstance(self.scope, FunctionScope) and | ||
node.id in self.scope.global_names): | ||
if not node.id in global_scope: |
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.
This line causing the CI to fail. E713
, should be written if x not in y
instead of if not x in y
.
pyflakes/checker.py
Outdated
else: | ||
name = alias.asname or alias.name | ||
importation = Importation(name, node, alias.name) | ||
importation = Importation(name, node, name) |
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.
Are you sure about this? The 3rd arg of Importation
originally always pass alias.name
(the fullname of import) and now it could have value of alias.asname
. The meaning of code changes.
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.
oh, sorry. it's my mistake
pyflakes/checker.py
Outdated
@@ -430,6 +431,13 @@ def unusedAssignments(self): | |||
and isinstance(binding, Assignment)): | |||
yield name, binding | |||
|
|||
def usedAssignments(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.
Why is this declared but never used?
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.
sorry. my mistake
pyflakes/checker.py
Outdated
@@ -1331,6 +1364,13 @@ def IMPORTFROM(self, node): | |||
module, alias.name) | |||
self.addBinding(node, importation) | |||
|
|||
if isinstance(self.scope, FunctionScope): |
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.
This code block is the same as the block above. It should probably be factored out into a separate function.
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.
yep
@adhikasp, I've already added. check the commit message. |
You mean this one? fdf2353#diff-44d7abf892e78127bd9438c51e1cfd49R340 But this is different compared to the snippet in the original issue. There should be another test when a function have args with same name as a global variable declared inside it. The function in your test above doesn't receive any argument. |
Sorry. I thought it was same code. |
@adhikasp By the way, What error should this test catch? |
The issue is actually different with the given task at gci... |
1bda547
to
4b00b8d
Compare
Yeah, the GCI task I specified is different to #249. The one I specified matches the test case @seeeturtle created. def main():
global x
print(x)
main() So I think @adhikasp's comment about the test doesn't apply. (Actually, #249 would have been easier. I probably should have specified that case for the GCI task.) |
@myint Can you approve the task too? |
Hooray! I didn't thought I can do this task well, but I did :) |
Oh I see, my bad then 😄 |
Just waiting for February now :) See you then |
Hello, @myint, I just found that this PR hasn't merged for a while. |
@seeeturtle One of the other PyCQA members needs to approve this before I can merge it. This is the case for several of the open pull requests. |
Ah, I got it. Thanks
2018. 7. 16. 오전 1:16 Steven Myint <notifications@github.com> 작성:
… @seeeturtle One of the other PyCQA members needs to approve this before I can merge it. This is the case for several of the open pull requests.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
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.
One fix required, and a few restructures.
Also please add a test
def f():
global m
print(m)
def g():
global m
m = 1
g()
f()
That should have no errors, and your patch handles this correctly. The added test will help prevent it breaking in the future, when other changes are made to pyflakes.
pyflakes/checker.py
Outdated
else: | ||
name = alias.asname or alias.name | ||
importation = Importation(name, node, alias.name) | ||
self.addBinding(node, importation) | ||
|
||
self.store_global_scope(name, alias) |
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.
This needs to be self.store_global_scope(importation.name, alias)
, otherwise the following will fail:
self.flakes('''
def f(): global foo; import foo.bar
def g(): foo.is_used()
''')
You can add that test into test_assignedToGlobal
.
Importing foo.bar
is a bit strange -- it imports and binds the module foo
as that name, and then imports foo.bar
but there is no additional binding in the scope for foo.bar
.
The determination of the binding name is done within SubmoduleImportation
.
Note it would be much better if you did the self.store_global_scope(...)
inside addBinding
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.
Sorry for responding too late, @jayvdb.
I was reading the addBinding
and there is something I can't understand.
Where does scope
comes from? I can't find it...
Anyway, Thanks for reviewing :)
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.
self-answering...
the variable in for loop (for controlling the loop) can be used at outside of it.
pyflakes/checker.py
Outdated
if '.' in alias.name and not alias.asname: | ||
importation = SubmoduleImportation(alias.name, node) | ||
importation = SubmoduleImportation(name, node) |
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.
this change can be reverted.
pyflakes/checker.py
Outdated
elif isinstance(node.ctx, ast.Del): | ||
self.handleNodeDelete(node) | ||
if (isinstance(self.scope, FunctionScope) and |
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.
this should go in handleNodeDelete
, where there is already logic regarding globals
pyflakes/checker.py
Outdated
elif isinstance(node.ctx, (ast.Store, ast.AugStore)): | ||
self.handleNodeStore(node) | ||
if (isinstance(self.scope, FunctionScope) and |
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.
this should go in handleNodeStore
, where there is already logic regarding globals
pyflakes/checker.py
Outdated
# Locate the name in locals / function / globals scopes. | ||
if isinstance(node.ctx, (ast.Load, ast.AugLoad)): | ||
self.handleNodeLoad(node) | ||
if (node.id == 'locals' and isinstance(self.scope, FunctionScope) | ||
and isinstance(node.parent, ast.Call)): | ||
# we are doing locals() call in current scope | ||
self.scope.usesLocals = True | ||
if (isinstance(self.scope, FunctionScope) and |
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.
this should probably go in handleNodeLoad
When we use undefined name declared by global statement, pyflakes should catch the error but it doesn't. This will fix pyflakes to catch this error. Note test_undefined_global for example of this.
72f208f
to
6f7f425
Compare
done @jayvdb |
Will this ever get merged? It's been two years! |
Anything I can do to help push this over the finish line? |
Related to #249