Skip to content

Commit

Permalink
[pyflakes] Improve error message for UndefinedName when a builtin…
Browse files Browse the repository at this point in the history
… was added in a newer version than specified in Ruff config (`F821`) (#13293)
  • Loading branch information
AlexWaygood authored Sep 10, 2024
1 parent b7cef6c commit 1d5bd89
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 165 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ruff_diagnostics::Diagnostic;
use ruff_python_semantic::Exceptions;
use ruff_python_stdlib::builtins::version_builtin_was_added;

use crate::checkers::ast::Checker;
use crate::codes::Rule;
Expand Down Expand Up @@ -35,9 +36,12 @@ pub(crate) fn unresolved_references(checker: &mut Checker) {
}
}

let symbol_name = reference.name(checker.locator);

checker.diagnostics.push(Diagnostic::new(
pyflakes::rules::UndefinedName {
name: reference.name(checker.locator).to_string(),
name: symbol_name.to_string(),
minor_version_builtin_added: version_builtin_was_added(symbol_name),
},
reference.range(),
));
Expand Down
12 changes: 12 additions & 0 deletions crates/ruff_linter/src/rules/pyflakes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ mod tests {
Ok(())
}

#[test]
fn f821_with_builtin_added_on_new_py_version_but_old_target_version_specified() {
let diagnostics = test_snippet(
"PythonFinalizationError",
&LinterSettings {
target_version: crate::settings::types::PythonVersion::Py312,
..LinterSettings::for_rule(Rule::UndefinedName)
},
);
assert_messages!(diagnostics);
}

#[test_case(Rule::UnusedVariable, Path::new("F841_4.py"))]
#[test_case(Rule::UnusedImport, Path::new("__init__.py"))]
#[test_case(Rule::UnusedImport, Path::new("F401_24/__init__.py"))]
Expand Down
22 changes: 20 additions & 2 deletions crates/ruff_linter/src/rules/pyflakes/rules/undefined_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,35 @@ use ruff_macros::{derive_message_formats, violation};
/// return n * 2
/// ```
///
/// ## Options
/// - [`target-version`]: Can be used to configure which symbols Ruff will understand
/// as being available in the `builtins` namespace.
///
/// ## References
/// - [Python documentation: Naming and binding](https://docs.python.org/3/reference/executionmodel.html#naming-and-binding)
#[violation]
pub struct UndefinedName {
pub(crate) name: String,
pub(crate) minor_version_builtin_added: Option<u8>,
}

impl Violation for UndefinedName {
#[derive_message_formats]
fn message(&self) -> String {
let UndefinedName { name } = self;
format!("Undefined name `{name}`")
let UndefinedName {
name,
minor_version_builtin_added,
} = self;
let tip = minor_version_builtin_added.map(|version_added| {
format!(
r#"Consider specifying `requires-python = ">= 3.{version_added}"` or `tool.ruff.target-version = "py3{version_added}"` in your `pyproject.toml` file."#
)
});

if let Some(tip) = tip {
format!("Undefined name `{name}`. {tip}")
} else {
format!("Undefined name `{name}`")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
---
<filename>:1:1: F821 Undefined name `PythonFinalizationError`. Consider specifying `requires-python = ">= 3.13"` or `tool.ruff.target-version = "py313"` in your `pyproject.toml` file.
|
1 | PythonFinalizationError
| ^^^^^^^^^^^^^^^^^^^^^^^ F821
|
Loading

0 comments on commit 1d5bd89

Please sign in to comment.