-
Notifications
You must be signed in to change notification settings - Fork 944
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements pylint rule [W0603: global-statement](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/global-statement.html). Currently checks for global statement usage in a few StmtKinds (as tested in the `pylint` `global-statement` test case [here](https://github.com/PyCQA/pylint/blob/b70d2abd7fabe9bfd735a30b593b9cd5eaa36194/tests/functional/g/globals.py)): * Assign * AugAssign * ClassDef * FunctionDef | AsyncFunctionDef * Import * ImportFrom * Delete
- Loading branch information
Showing
9 changed files
with
299 additions
and
1 deletion.
There are no files selected for viewing
75 changes: 75 additions & 0 deletions
75
crates/ruff/resources/test/fixtures/pylint/global_statement.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Adapted from: | ||
# https://github.com/PyCQA/pylint/blob/b70d2abd7fabe9bfd735a30b593b9cd5eaa36194/tests/functional/g/globals.py | ||
|
||
CONSTANT = 1 | ||
|
||
|
||
def FUNC(): | ||
pass | ||
|
||
|
||
class CLASS: | ||
pass | ||
|
||
|
||
def fix_constant(value): | ||
"""All this is ok, but try not to use `global` ;)""" | ||
global CONSTANT # [global-statement] | ||
print(CONSTANT) | ||
CONSTANT = value | ||
|
||
|
||
def global_with_import(): | ||
"""Should only warn for global-statement when using `Import` node""" | ||
global sys # [global-statement] | ||
import sys | ||
|
||
|
||
def global_with_import_from(): | ||
"""Should only warn for global-statement when using `ImportFrom` node""" | ||
global namedtuple # [global-statement] | ||
from collections import namedtuple | ||
|
||
|
||
def global_del(): | ||
"""Deleting the global name prevents `global-variable-not-assigned`""" | ||
global CONSTANT # [global-statement] | ||
print(CONSTANT) | ||
del CONSTANT | ||
|
||
|
||
def global_operator_assign(): | ||
"""Operator assigns should only throw a global statement error""" | ||
global CONSTANT # [global-statement] | ||
print(CONSTANT) | ||
CONSTANT += 1 | ||
|
||
|
||
def global_function_assign(): | ||
"""Function assigns should only throw a global statement error""" | ||
global CONSTANT # [global-statement] | ||
|
||
def CONSTANT(): | ||
pass | ||
|
||
CONSTANT() | ||
|
||
|
||
def override_func(): | ||
"""Overriding a function should only throw a global statement error""" | ||
global FUNC # [global-statement] | ||
|
||
def FUNC(): | ||
pass | ||
|
||
FUNC() | ||
|
||
|
||
def override_class(): | ||
"""Overriding a class should only throw a global statement error""" | ||
global CLASS # [global-statement] | ||
|
||
class CLASS: | ||
pass | ||
|
||
CLASS() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
use ruff_macros::{define_violation, derive_message_formats}; | ||
|
||
use crate::checkers::ast::Checker; | ||
use crate::registry::Diagnostic; | ||
use crate::violation::Violation; | ||
use crate::Range; | ||
|
||
define_violation!( | ||
/// ## What it does | ||
/// Checks for the use of `global` statements to update identifiers. | ||
/// | ||
/// ## Why is this bad? | ||
/// Pylint discourages the use of `global` variables as global mutable | ||
/// state is a common source of bugs and confusing behavior. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// var = 1 | ||
/// | ||
/// def foo(): | ||
/// global var # [global-statement] | ||
/// var = 10 | ||
/// print(var) | ||
/// | ||
/// foo() | ||
/// print(var) | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// var = 1 | ||
/// | ||
/// def foo(): | ||
/// print(var) | ||
/// return 10 | ||
/// | ||
/// var = foo() | ||
/// print(var) | ||
/// ``` | ||
pub struct GlobalStatement { | ||
pub name: String, | ||
} | ||
); | ||
impl Violation for GlobalStatement { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
let GlobalStatement { name } = self; | ||
format!("Using the global statement to update `{name}` is discouraged") | ||
} | ||
} | ||
|
||
/// PLW0603 | ||
pub fn global_statement(checker: &mut Checker, name: &str) { | ||
let scope = checker.current_scope(); | ||
if let Some(index) = scope.bindings.get(name) { | ||
let binding = &checker.bindings[*index]; | ||
if binding.kind.is_global() { | ||
let diagnostic = Diagnostic::new( | ||
GlobalStatement { | ||
name: name.to_string(), | ||
}, | ||
// Match Pylint's behavior by reporting on the `global` statement`, rather | ||
// than the variable usage. | ||
Range::from_located( | ||
binding | ||
.source | ||
.as_ref() | ||
.expect("`global` bindings should always have a `source`"), | ||
), | ||
); | ||
checker.diagnostics.push(diagnostic); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
...f/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW0603_global_statement.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
--- | ||
source: crates/ruff/src/rules/pylint/mod.rs | ||
expression: diagnostics | ||
--- | ||
- kind: | ||
GlobalStatement: | ||
name: CONSTANT | ||
location: | ||
row: 17 | ||
column: 4 | ||
end_location: | ||
row: 17 | ||
column: 19 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: sys | ||
location: | ||
row: 24 | ||
column: 4 | ||
end_location: | ||
row: 24 | ||
column: 14 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: namedtuple | ||
location: | ||
row: 30 | ||
column: 4 | ||
end_location: | ||
row: 30 | ||
column: 21 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: CONSTANT | ||
location: | ||
row: 36 | ||
column: 4 | ||
end_location: | ||
row: 36 | ||
column: 19 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: CONSTANT | ||
location: | ||
row: 43 | ||
column: 4 | ||
end_location: | ||
row: 43 | ||
column: 19 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: CONSTANT | ||
location: | ||
row: 50 | ||
column: 4 | ||
end_location: | ||
row: 50 | ||
column: 19 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: FUNC | ||
location: | ||
row: 60 | ||
column: 4 | ||
end_location: | ||
row: 60 | ||
column: 15 | ||
fix: ~ | ||
parent: ~ | ||
- kind: | ||
GlobalStatement: | ||
name: CLASS | ||
location: | ||
row: 70 | ||
column: 4 | ||
end_location: | ||
row: 70 | ||
column: 16 | ||
fix: ~ | ||
parent: ~ | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.