Treat re-exported annotations as used-at-runtime (#2689)

This commit is contained in:
Charlie Marsh 2023-02-09 11:22:15 -05:00 committed by GitHub
parent 54d1719424
commit 8a98cfc4b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 35 deletions

View file

@ -0,0 +1,6 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import List
__all__ = ("List",)

View file

@ -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;
}

View file

@ -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<()> {

View file

@ -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: ~

View file

@ -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))
}

View file

@ -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))
}