-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[pylint] Detect global declarations in module scope (PLE0118)
#17411
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
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1503,24 +1503,28 @@ impl<'a> SemanticModel<'a> { | |
|
|
||
| /// Set the [`Globals`] for the current [`Scope`]. | ||
| pub fn set_globals(&mut self, globals: Globals<'a>) { | ||
| // If any global bindings don't already exist in the global scope, add them. | ||
| for (name, range) in globals.iter() { | ||
| if self | ||
| .global_scope() | ||
| .get(name) | ||
| .is_none_or(|binding_id| self.bindings[binding_id].is_unbound()) | ||
| { | ||
| let id = self.bindings.push(Binding { | ||
| kind: BindingKind::Assignment, | ||
| range: *range, | ||
| references: Vec::new(), | ||
| scope: ScopeId::global(), | ||
| source: self.node_id, | ||
| context: self.execution_context(), | ||
| exceptions: self.exceptions(), | ||
| flags: BindingFlags::empty(), | ||
| }); | ||
| self.global_scope_mut().add(name, id); | ||
| // If any global bindings don't already exist in the global scope, add them, unless we are | ||
| // also in the global scope, where we don't want these to count as definitions for rules | ||
| // like `undefined-name` (F821) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you maybe add an example here of what problem would arise if we did run this code at the global level too? It's not entirely clear to me and I'm wondering if not running it creates different problems at the root level (you could try to comment out this code and see what tests fail for the non-global scope and then decide if this is or isn't a problem for the global scope)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I did try deleting this code entirely before because that actually seemed more natural to me, but I didn't write down the results. This is the tricky F821 ( """Test: annotated global."""
n: int
def f():
print(n) # F821 false positive here
def g():
global n
n = 1
g()
f()This shorter case also gets a false positive with the whole loop commented out: def f(): global foo; import foo
def g(): foo.is_used() # false positive hereI don't think we can run into something similar if the If we run the binding loop in the global scope too, this case, also for F821, fails: global x
def foo():
print(x) # F821 false negativeThe second and third cases here look like nice additions to the docs.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, the more I stare at these examples, the more I think I might have been right to consider deleting this code entirely. It's really the assignment and the import that should be adding the bindings, not the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is easily actionable though. I poked around a bit in |
||
| if !self.at_top_level() { | ||
|
MichaReiser marked this conversation as resolved.
|
||
| for (name, range) in globals.iter() { | ||
| if self | ||
| .global_scope() | ||
| .get(name) | ||
| .is_none_or(|binding_id| self.bindings[binding_id].is_unbound()) | ||
| { | ||
| let id = self.bindings.push(Binding { | ||
| kind: BindingKind::Assignment, | ||
| range: *range, | ||
| references: Vec::new(), | ||
| scope: ScopeId::global(), | ||
| source: self.node_id, | ||
| context: self.execution_context(), | ||
| exceptions: self.exceptions(), | ||
| flags: BindingFlags::empty(), | ||
| }); | ||
| self.global_scope_mut().add(name, id); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.