Skip to content

Commit

Permalink
[flake8-pyi] - add autofix for future-annotations-in-stub (`PYI04…
Browse files Browse the repository at this point in the history
…4`) (#12676)

## Summary

add autofix for `PYI044`

## Test Plan

`cargo test`
  • Loading branch information
diceroll123 authored Aug 6, 2024
1 parent 5499821 commit 7b5fd63
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Bad import.
from __future__ import annotations # PYI044.
from __future__ import annotations, with_statement # PYI044.

# Good imports.
from __future__ import Something
from __future__ import with_statement
import sys
from socket import AF_INET
20 changes: 19 additions & 1 deletion crates/ruff_linter/src/rules/flake8_pyi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod tests {
use test_case::test_case;

use crate::registry::Rule;
use crate::settings::types::PythonVersion;
use crate::settings::types::{PreviewMode, PythonVersion};
use crate::test::test_path;
use crate::{assert_messages, settings};

Expand Down Expand Up @@ -149,4 +149,22 @@ mod tests {
assert_messages!(snapshot, diagnostics);
Ok(())
}

#[test_case(Rule::FutureAnnotationsInStub, Path::new("PYI044.pyi"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"preview__{}_{}",
rule_code.noqa_code(),
path.to_string_lossy()
);
let diagnostics = test_path(
Path::new("flake8_pyi").join(path).as_path(),
&settings::LinterSettings {
preview: PreviewMode::Enabled,
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use ruff_python_ast::StmtImportFrom;

use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation};

use crate::checkers::ast::Checker;
use crate::{checkers::ast::Checker, fix};

/// ## What it does
/// Checks for the presence of the `from __future__ import annotations` import
Expand All @@ -21,10 +21,16 @@ use crate::checkers::ast::Checker;
pub struct FutureAnnotationsInStub;

impl Violation for FutureAnnotationsInStub {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;

#[derive_message_formats]
fn message(&self) -> String {
format!("`from __future__ import annotations` has no effect in stub files, since type checkers automatically treat stubs as having those semantics")
}

fn fix_title(&self) -> Option<String> {
Some("Remove `from __future__ import annotations`".to_string())
}
}

/// PYI044
Expand All @@ -37,9 +43,26 @@ pub(crate) fn from_future_import(checker: &mut Checker, target: &StmtImportFrom)
} = target
{
if name == "__future__" && names.iter().any(|alias| &*alias.name == "annotations") {
checker
.diagnostics
.push(Diagnostic::new(FutureAnnotationsInStub, *range));
let mut diagnostic = Diagnostic::new(FutureAnnotationsInStub, *range);

if checker.settings.preview.is_enabled() {
let stmt = checker.semantic().current_statement();

diagnostic.try_set_fix(|| {
let edit = fix::edits::remove_unused_imports(
std::iter::once("annotations"),
stmt,
None,
checker.locator(),
checker.stylist(),
checker.indexer(),
)?;

Ok(Fix::safe_edit(edit))
});
}

checker.diagnostics.push(diagnostic);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ PYI044.pyi:2:1: PYI044 `from __future__ import annotations` has no effect in stu
1 | # Bad import.
2 | from __future__ import annotations # PYI044.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI044
3 |
4 | # Good imports.
3 | from __future__ import annotations, with_statement # PYI044.
|
= help: Remove `from __future__ import annotations`


PYI044.pyi:3:1: PYI044 `from __future__ import annotations` has no effect in stub files, since type checkers automatically treat stubs as having those semantics
|
1 | # Bad import.
2 | from __future__ import annotations # PYI044.
3 | from __future__ import annotations, with_statement # PYI044.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI044
4 |
5 | # Good imports.
|
= help: Remove `from __future__ import annotations`
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI044.pyi:2:1: PYI044 [*] `from __future__ import annotations` has no effect in stub files, since type checkers automatically treat stubs as having those semantics
|
1 | # Bad import.
2 | from __future__ import annotations # PYI044.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI044
3 | from __future__ import annotations, with_statement # PYI044.
|
= help: Remove `from __future__ import annotations`

Safe fix
1 1 | # Bad import.
2 |-from __future__ import annotations # PYI044.
3 2 | from __future__ import annotations, with_statement # PYI044.
4 3 |
5 4 | # Good imports.

PYI044.pyi:3:1: PYI044 [*] `from __future__ import annotations` has no effect in stub files, since type checkers automatically treat stubs as having those semantics
|
1 | # Bad import.
2 | from __future__ import annotations # PYI044.
3 | from __future__ import annotations, with_statement # PYI044.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI044
4 |
5 | # Good imports.
|
= help: Remove `from __future__ import annotations`

Safe fix
1 1 | # Bad import.
2 2 | from __future__ import annotations # PYI044.
3 |-from __future__ import annotations, with_statement # PYI044.
3 |+from __future__ import with_statement # PYI044.
4 4 |
5 5 | # Good imports.
6 6 | from __future__ import with_statement

0 comments on commit 7b5fd63

Please sign in to comment.