mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
Treat re-exported annotations as used-at-runtime (#2689)
This commit is contained in:
parent
54d1719424
commit
8a98cfc4b8
6 changed files with 58 additions and 35 deletions
6
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_11.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_11.py
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import List
|
||||
|
||||
__all__ = ("List",)
|
|
@ -4312,17 +4312,33 @@ impl<'a> Checker<'a> {
|
|||
_ => false,
|
||||
} {
|
||||
let (all_names, all_names_flags) = extract_all_names(self, parent, current);
|
||||
let all_bindings: Vec<usize> = all_names
|
||||
.iter()
|
||||
.filter_map(|name| current.bindings.get(name.as_str()))
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
if self.settings.rules.enabled(&Rule::InvalidAllFormat)
|
||||
&& matches!(all_names_flags, AllNamesFlags::INVALID_FORMAT)
|
||||
{
|
||||
pylint::rules::invalid_all_format(self, expr);
|
||||
if self.settings.rules.enabled(&Rule::InvalidAllFormat) {
|
||||
if matches!(all_names_flags, AllNamesFlags::INVALID_FORMAT) {
|
||||
self.diagnostics
|
||||
.push(pylint::rules::invalid_all_format(expr));
|
||||
}
|
||||
}
|
||||
|
||||
if self.settings.rules.enabled(&Rule::InvalidAllObject)
|
||||
&& matches!(all_names_flags, AllNamesFlags::INVALID_OBJECT)
|
||||
{
|
||||
pylint::rules::invalid_all_object(self, expr);
|
||||
if self.settings.rules.enabled(&Rule::InvalidAllObject) {
|
||||
if matches!(all_names_flags, AllNamesFlags::INVALID_OBJECT) {
|
||||
self.diagnostics
|
||||
.push(pylint::rules::invalid_all_object(expr));
|
||||
}
|
||||
}
|
||||
|
||||
// Mark all exported names as used-at-runtime.
|
||||
for index in all_bindings {
|
||||
self.bindings[index].mark_used(
|
||||
GLOBAL_SCOPE_INDEX,
|
||||
Range::from_located(expr),
|
||||
ExecutionContext::Runtime,
|
||||
);
|
||||
}
|
||||
|
||||
self.add_binding(
|
||||
|
@ -4701,13 +4717,7 @@ impl<'a> Checker<'a> {
|
|||
| BindingKind::StarImportation(..)
|
||||
| BindingKind::FutureImportation
|
||||
) {
|
||||
// Skip used exports from `__all__`
|
||||
if binding.used()
|
||||
|| all_names
|
||||
.as_ref()
|
||||
.map(|names| names.contains(name))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
if binding.used() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4829,7 +4839,7 @@ impl<'a> Checker<'a> {
|
|||
let mut ignored: FxHashMap<BindingContext, Vec<UnusedImport>> =
|
||||
FxHashMap::default();
|
||||
|
||||
for (name, index) in &scope.bindings {
|
||||
for index in scope.bindings.values() {
|
||||
let binding = &self.bindings[*index];
|
||||
|
||||
let full_name = match &binding.kind {
|
||||
|
@ -4839,13 +4849,7 @@ impl<'a> Checker<'a> {
|
|||
_ => continue,
|
||||
};
|
||||
|
||||
// Skip used exports from `__all__`
|
||||
if binding.used()
|
||||
|| all_names
|
||||
.as_ref()
|
||||
.map(|names| names.contains(name))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
if binding.used() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ mod tests {
|
|||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_8.py"); "TCH004_8")]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_9.py"); "TCH004_9")]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_10.py"); "TCH004_10")]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_11.py"); "TCH004_11")]
|
||||
#[test_case(Rule::EmptyTypeCheckingBlock, Path::new("TCH005.py"); "TCH005")]
|
||||
#[test_case(Rule::TypingOnlyThirdPartyImport, Path::new("strict.py"); "strict")]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/flake8_type_checking/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
RuntimeImportInTypeCheckingBlock:
|
||||
full_name: typing.List
|
||||
location:
|
||||
row: 4
|
||||
column: 23
|
||||
end_location:
|
||||
row: 4
|
||||
column: 27
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
use ruff_macros::{define_violation, derive_message_formats};
|
||||
use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_macros::{define_violation, derive_message_formats};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violation::Violation;
|
||||
|
||||
|
@ -17,8 +17,6 @@ impl Violation for InvalidAllFormat {
|
|||
}
|
||||
|
||||
/// PLE0605
|
||||
pub fn invalid_all_format(checker: &mut Checker, expr: &Expr) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(InvalidAllFormat, Range::from_located(expr)));
|
||||
pub fn invalid_all_format(expr: &Expr) -> Diagnostic {
|
||||
Diagnostic::new(InvalidAllFormat, Range::from_located(expr))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use ruff_macros::{define_violation, derive_message_formats};
|
||||
use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_macros::{define_violation, derive_message_formats};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violation::Violation;
|
||||
|
||||
|
@ -17,8 +17,6 @@ impl Violation for InvalidAllObject {
|
|||
}
|
||||
|
||||
/// PLE0604
|
||||
pub fn invalid_all_object(checker: &mut Checker, expr: &Expr) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(InvalidAllObject, Range::from_located(expr)));
|
||||
pub fn invalid_all_object(expr: &Expr) -> Diagnostic {
|
||||
Diagnostic::new(InvalidAllObject, Range::from_located(expr))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue