mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:47 +00:00
Flag PEP 585 and PEP 604 violations in quoted annotations (#3593)
This commit is contained in:
parent
81d0884974
commit
7c0f17279c
17 changed files with 173 additions and 98 deletions
|
@ -2170,9 +2170,8 @@ where
|
||||||
ExprKind::Subscript { value, slice, .. } => {
|
ExprKind::Subscript { value, slice, .. } => {
|
||||||
// Ex) Optional[...], Union[...]
|
// Ex) Optional[...], Union[...]
|
||||||
if self.ctx.in_type_definition
|
if self.ctx.in_type_definition
|
||||||
&& !self.ctx.in_deferred_string_type_definition
|
|
||||||
&& !self.settings.pyupgrade.keep_runtime_typing
|
&& !self.settings.pyupgrade.keep_runtime_typing
|
||||||
&& self.settings.rules.enabled(Rule::TypingUnion)
|
&& self.settings.rules.enabled(Rule::NonPEP604Annotation)
|
||||||
&& (self.settings.target_version >= PythonVersion::Py310
|
&& (self.settings.target_version >= PythonVersion::Py310
|
||||||
|| (self.settings.target_version >= PythonVersion::Py37
|
|| (self.settings.target_version >= PythonVersion::Py37
|
||||||
&& self.ctx.annotations_future_enabled
|
&& self.ctx.annotations_future_enabled
|
||||||
|
@ -2225,16 +2224,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) List[...]
|
// Ex) List[...]
|
||||||
if !self.ctx.in_deferred_string_type_definition
|
if !self.settings.pyupgrade.keep_runtime_typing
|
||||||
&& !self.settings.pyupgrade.keep_runtime_typing
|
&& self.settings.rules.enabled(Rule::NonPEP585Annotation)
|
||||||
&& self.settings.rules.enabled(Rule::DeprecatedCollectionType)
|
|
||||||
&& (self.settings.target_version >= PythonVersion::Py39
|
&& (self.settings.target_version >= PythonVersion::Py39
|
||||||
|| (self.settings.target_version >= PythonVersion::Py37
|
|| (self.settings.target_version >= PythonVersion::Py37
|
||||||
&& self.ctx.annotations_future_enabled
|
&& self.ctx.annotations_future_enabled
|
||||||
&& self.ctx.in_annotation))
|
&& self.ctx.in_annotation))
|
||||||
&& typing::is_pep585_builtin(expr, |expr| {
|
&& typing::is_pep585_builtin(expr, &self.ctx)
|
||||||
self.ctx.resolve_call_path(expr)
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||||
}
|
}
|
||||||
|
@ -2271,14 +2267,13 @@ where
|
||||||
}
|
}
|
||||||
ExprKind::Attribute { attr, value, .. } => {
|
ExprKind::Attribute { attr, value, .. } => {
|
||||||
// Ex) typing.List[...]
|
// Ex) typing.List[...]
|
||||||
if !self.ctx.in_deferred_string_type_definition
|
if !self.settings.pyupgrade.keep_runtime_typing
|
||||||
&& !self.settings.pyupgrade.keep_runtime_typing
|
&& self.settings.rules.enabled(Rule::NonPEP585Annotation)
|
||||||
&& self.settings.rules.enabled(Rule::DeprecatedCollectionType)
|
|
||||||
&& (self.settings.target_version >= PythonVersion::Py39
|
&& (self.settings.target_version >= PythonVersion::Py39
|
||||||
|| (self.settings.target_version >= PythonVersion::Py37
|
|| (self.settings.target_version >= PythonVersion::Py37
|
||||||
&& self.ctx.annotations_future_enabled
|
&& self.ctx.annotations_future_enabled
|
||||||
&& self.ctx.in_annotation))
|
&& self.ctx.in_annotation))
|
||||||
&& typing::is_pep585_builtin(expr, |expr| self.ctx.resolve_call_path(expr))
|
&& typing::is_pep585_builtin(expr, &self.ctx)
|
||||||
{
|
{
|
||||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||||
}
|
}
|
||||||
|
@ -2434,7 +2429,7 @@ where
|
||||||
if self.settings.rules.enabled(Rule::OSErrorAlias) {
|
if self.settings.rules.enabled(Rule::OSErrorAlias) {
|
||||||
pyupgrade::rules::os_error_alias_call(self, func);
|
pyupgrade::rules::os_error_alias_call(self, func);
|
||||||
}
|
}
|
||||||
if self.settings.rules.enabled(Rule::IsinstanceWithTuple)
|
if self.settings.rules.enabled(Rule::NonPEP604Isinstance)
|
||||||
&& self.settings.target_version >= PythonVersion::Py310
|
&& self.settings.target_version >= PythonVersion::Py310
|
||||||
{
|
{
|
||||||
pyupgrade::rules::use_pep604_isinstance(self, expr, func, args);
|
pyupgrade::rules::use_pep604_isinstance(self, expr, func, args);
|
||||||
|
@ -3575,7 +3570,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
match match_annotated_subscript(
|
match match_annotated_subscript(
|
||||||
value,
|
value,
|
||||||
|expr| self.ctx.resolve_call_path(expr),
|
&self.ctx,
|
||||||
self.settings.typing_modules.iter().map(String::as_str),
|
self.settings.typing_modules.iter().map(String::as_str),
|
||||||
) {
|
) {
|
||||||
Some(subscript) => {
|
Some(subscript) => {
|
||||||
|
|
|
@ -355,8 +355,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
|
||||||
(Pyupgrade, "003") => Rule::TypeOfPrimitive,
|
(Pyupgrade, "003") => Rule::TypeOfPrimitive,
|
||||||
(Pyupgrade, "004") => Rule::UselessObjectInheritance,
|
(Pyupgrade, "004") => Rule::UselessObjectInheritance,
|
||||||
(Pyupgrade, "005") => Rule::DeprecatedUnittestAlias,
|
(Pyupgrade, "005") => Rule::DeprecatedUnittestAlias,
|
||||||
(Pyupgrade, "006") => Rule::DeprecatedCollectionType,
|
(Pyupgrade, "006") => Rule::NonPEP585Annotation,
|
||||||
(Pyupgrade, "007") => Rule::TypingUnion,
|
(Pyupgrade, "007") => Rule::NonPEP604Annotation,
|
||||||
(Pyupgrade, "008") => Rule::SuperCallWithParameters,
|
(Pyupgrade, "008") => Rule::SuperCallWithParameters,
|
||||||
(Pyupgrade, "009") => Rule::UTF8EncodingDeclaration,
|
(Pyupgrade, "009") => Rule::UTF8EncodingDeclaration,
|
||||||
(Pyupgrade, "010") => Rule::UnnecessaryFutureImport,
|
(Pyupgrade, "010") => Rule::UnnecessaryFutureImport,
|
||||||
|
@ -386,7 +386,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
|
||||||
(Pyupgrade, "035") => Rule::DeprecatedImport,
|
(Pyupgrade, "035") => Rule::DeprecatedImport,
|
||||||
(Pyupgrade, "036") => Rule::OutdatedVersionBlock,
|
(Pyupgrade, "036") => Rule::OutdatedVersionBlock,
|
||||||
(Pyupgrade, "037") => Rule::QuotedAnnotation,
|
(Pyupgrade, "037") => Rule::QuotedAnnotation,
|
||||||
(Pyupgrade, "038") => Rule::IsinstanceWithTuple,
|
(Pyupgrade, "038") => Rule::NonPEP604Isinstance,
|
||||||
|
|
||||||
// pydocstyle
|
// pydocstyle
|
||||||
(Pydocstyle, "100") => Rule::UndocumentedPublicModule,
|
(Pydocstyle, "100") => Rule::UndocumentedPublicModule,
|
||||||
|
|
|
@ -325,8 +325,8 @@ ruff_macros::register_rules!(
|
||||||
rules::pyupgrade::rules::TypeOfPrimitive,
|
rules::pyupgrade::rules::TypeOfPrimitive,
|
||||||
rules::pyupgrade::rules::UselessObjectInheritance,
|
rules::pyupgrade::rules::UselessObjectInheritance,
|
||||||
rules::pyupgrade::rules::DeprecatedUnittestAlias,
|
rules::pyupgrade::rules::DeprecatedUnittestAlias,
|
||||||
rules::pyupgrade::rules::DeprecatedCollectionType,
|
rules::pyupgrade::rules::NonPEP585Annotation,
|
||||||
rules::pyupgrade::rules::TypingUnion,
|
rules::pyupgrade::rules::NonPEP604Annotation,
|
||||||
rules::pyupgrade::rules::SuperCallWithParameters,
|
rules::pyupgrade::rules::SuperCallWithParameters,
|
||||||
rules::pyupgrade::rules::UTF8EncodingDeclaration,
|
rules::pyupgrade::rules::UTF8EncodingDeclaration,
|
||||||
rules::pyupgrade::rules::UnnecessaryFutureImport,
|
rules::pyupgrade::rules::UnnecessaryFutureImport,
|
||||||
|
@ -356,7 +356,7 @@ ruff_macros::register_rules!(
|
||||||
rules::pyupgrade::rules::DeprecatedImport,
|
rules::pyupgrade::rules::DeprecatedImport,
|
||||||
rules::pyupgrade::rules::OutdatedVersionBlock,
|
rules::pyupgrade::rules::OutdatedVersionBlock,
|
||||||
rules::pyupgrade::rules::QuotedAnnotation,
|
rules::pyupgrade::rules::QuotedAnnotation,
|
||||||
rules::pyupgrade::rules::IsinstanceWithTuple,
|
rules::pyupgrade::rules::NonPEP604Isinstance,
|
||||||
// pydocstyle
|
// pydocstyle
|
||||||
rules::pydocstyle::rules::UndocumentedPublicModule,
|
rules::pydocstyle::rules::UndocumentedPublicModule,
|
||||||
rules::pydocstyle::rules::UndocumentedPublicClass,
|
rules::pydocstyle::rules::UndocumentedPublicClass,
|
||||||
|
|
|
@ -22,8 +22,8 @@ mod tests {
|
||||||
#[test_case(Rule::TypeOfPrimitive, Path::new("UP003.py"); "UP003")]
|
#[test_case(Rule::TypeOfPrimitive, Path::new("UP003.py"); "UP003")]
|
||||||
#[test_case(Rule::UselessObjectInheritance, Path::new("UP004.py"); "UP004")]
|
#[test_case(Rule::UselessObjectInheritance, Path::new("UP004.py"); "UP004")]
|
||||||
#[test_case(Rule::DeprecatedUnittestAlias, Path::new("UP005.py"); "UP005")]
|
#[test_case(Rule::DeprecatedUnittestAlias, Path::new("UP005.py"); "UP005")]
|
||||||
#[test_case(Rule::DeprecatedCollectionType, Path::new("UP006.py"); "UP006")]
|
#[test_case(Rule::NonPEP585Annotation, Path::new("UP006.py"); "UP006")]
|
||||||
#[test_case(Rule::TypingUnion, Path::new("UP007.py"); "UP007")]
|
#[test_case(Rule::NonPEP604Annotation, Path::new("UP007.py"); "UP007")]
|
||||||
#[test_case(Rule::SuperCallWithParameters, Path::new("UP008.py"); "UP008")]
|
#[test_case(Rule::SuperCallWithParameters, Path::new("UP008.py"); "UP008")]
|
||||||
#[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_0.py"); "UP009_0")]
|
#[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_0.py"); "UP009_0")]
|
||||||
#[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_1.py"); "UP009_1")]
|
#[test_case(Rule::UTF8EncodingDeclaration, Path::new("UP009_1.py"); "UP009_1")]
|
||||||
|
@ -67,7 +67,7 @@ mod tests {
|
||||||
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_3.py"); "UP036_3")]
|
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_3.py"); "UP036_3")]
|
||||||
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_4.py"); "UP036_4")]
|
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_4.py"); "UP036_4")]
|
||||||
#[test_case(Rule::QuotedAnnotation, Path::new("UP037.py"); "UP037")]
|
#[test_case(Rule::QuotedAnnotation, Path::new("UP037.py"); "UP037")]
|
||||||
#[test_case(Rule::IsinstanceWithTuple, Path::new("UP038.py"); "UP038")]
|
#[test_case(Rule::NonPEP604Isinstance, Path::new("UP038.py"); "UP038")]
|
||||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
let snapshot = path.to_string_lossy().to_string();
|
let snapshot = path.to_string_lossy().to_string();
|
||||||
let diagnostics = test_path(
|
let diagnostics = test_path(
|
||||||
|
@ -84,7 +84,7 @@ mod tests {
|
||||||
Path::new("pyupgrade/future_annotations.py"),
|
Path::new("pyupgrade/future_annotations.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
target_version: PythonVersion::Py37,
|
target_version: PythonVersion::Py37,
|
||||||
..settings::Settings::for_rule(Rule::DeprecatedCollectionType)
|
..settings::Settings::for_rule(Rule::NonPEP585Annotation)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
assert_yaml_snapshot!(diagnostics);
|
assert_yaml_snapshot!(diagnostics);
|
||||||
|
@ -97,7 +97,7 @@ mod tests {
|
||||||
Path::new("pyupgrade/future_annotations.py"),
|
Path::new("pyupgrade/future_annotations.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
target_version: PythonVersion::Py310,
|
target_version: PythonVersion::Py310,
|
||||||
..settings::Settings::for_rule(Rule::DeprecatedCollectionType)
|
..settings::Settings::for_rule(Rule::NonPEP585Annotation)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
assert_yaml_snapshot!(diagnostics);
|
assert_yaml_snapshot!(diagnostics);
|
||||||
|
@ -110,7 +110,7 @@ mod tests {
|
||||||
Path::new("pyupgrade/future_annotations.py"),
|
Path::new("pyupgrade/future_annotations.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
target_version: PythonVersion::Py37,
|
target_version: PythonVersion::Py37,
|
||||||
..settings::Settings::for_rule(Rule::TypingUnion)
|
..settings::Settings::for_rule(Rule::NonPEP604Annotation)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
assert_yaml_snapshot!(diagnostics);
|
assert_yaml_snapshot!(diagnostics);
|
||||||
|
@ -123,7 +123,7 @@ mod tests {
|
||||||
Path::new("pyupgrade/future_annotations.py"),
|
Path::new("pyupgrade/future_annotations.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
target_version: PythonVersion::Py310,
|
target_version: PythonVersion::Py310,
|
||||||
..settings::Settings::for_rule(Rule::TypingUnion)
|
..settings::Settings::for_rule(Rule::NonPEP604Annotation)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
assert_yaml_snapshot!(diagnostics);
|
assert_yaml_snapshot!(diagnostics);
|
||||||
|
|
|
@ -42,9 +42,9 @@ pub(crate) use unnecessary_future_import::{unnecessary_future_import, Unnecessar
|
||||||
pub(crate) use unpacked_list_comprehension::{
|
pub(crate) use unpacked_list_comprehension::{
|
||||||
unpacked_list_comprehension, UnpackedListComprehension,
|
unpacked_list_comprehension, UnpackedListComprehension,
|
||||||
};
|
};
|
||||||
pub(crate) use use_pep585_annotation::{use_pep585_annotation, DeprecatedCollectionType};
|
pub(crate) use use_pep585_annotation::{use_pep585_annotation, NonPEP585Annotation};
|
||||||
pub(crate) use use_pep604_annotation::{use_pep604_annotation, TypingUnion};
|
pub(crate) use use_pep604_annotation::{use_pep604_annotation, NonPEP604Annotation};
|
||||||
pub(crate) use use_pep604_isinstance::{use_pep604_isinstance, IsinstanceWithTuple};
|
pub(crate) use use_pep604_isinstance::{use_pep604_isinstance, NonPEP604Isinstance};
|
||||||
pub(crate) use useless_metaclass_type::{useless_metaclass_type, UselessMetaclassType};
|
pub(crate) use useless_metaclass_type::{useless_metaclass_type, UselessMetaclassType};
|
||||||
pub(crate) use useless_object_inheritance::{useless_object_inheritance, UselessObjectInheritance};
|
pub(crate) use useless_object_inheritance::{useless_object_inheritance, UselessObjectInheritance};
|
||||||
pub(crate) use yield_in_for_loop::{yield_in_for_loop, YieldInForLoop};
|
pub(crate) use yield_in_for_loop::{yield_in_for_loop, YieldInForLoop};
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
use rustpython_parser::ast::Expr;
|
use rustpython_parser::ast::Expr;
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix};
|
use ruff_diagnostics::{AutofixKind, Availability, Diagnostic, Fix, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
||||||
// TODO: document referencing [PEP 585]: https://peps.python.org/pep-0585/
|
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct DeprecatedCollectionType {
|
pub struct NonPEP585Annotation {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub fixable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AlwaysAutofixableViolation for DeprecatedCollectionType {
|
impl Violation for NonPEP585Annotation {
|
||||||
|
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));
|
||||||
|
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
let DeprecatedCollectionType { name } = self;
|
let NonPEP585Annotation { name, .. } = self;
|
||||||
format!(
|
format!(
|
||||||
"Use `{}` instead of `{}` for type annotations",
|
"Use `{}` instead of `{}` for type annotations",
|
||||||
name.to_lowercase(),
|
name.to_lowercase(),
|
||||||
|
@ -24,9 +26,10 @@ impl AlwaysAutofixableViolation for DeprecatedCollectionType {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {
|
||||||
let DeprecatedCollectionType { name } = self;
|
self.fixable.then_some(|NonPEP585Annotation { name, .. }| {
|
||||||
format!("Replace `{name}` with `{}`", name.to_lowercase())
|
format!("Replace `{name}` with `{}`", name.to_lowercase())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +40,15 @@ pub fn use_pep585_annotation(checker: &mut Checker, expr: &Expr) {
|
||||||
.resolve_call_path(expr)
|
.resolve_call_path(expr)
|
||||||
.and_then(|call_path| call_path.last().copied())
|
.and_then(|call_path| call_path.last().copied())
|
||||||
{
|
{
|
||||||
|
let fixable = !checker.ctx.in_deferred_string_type_definition;
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
DeprecatedCollectionType {
|
NonPEP585Annotation {
|
||||||
name: binding.to_string(),
|
name: binding.to_string(),
|
||||||
|
fixable,
|
||||||
},
|
},
|
||||||
Range::from(expr),
|
Range::from(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if fixable && checker.patch(diagnostic.kind.rule()) {
|
||||||
let binding = binding.to_lowercase();
|
let binding = binding.to_lowercase();
|
||||||
if checker.ctx.is_builtin(&binding) {
|
if checker.ctx.is_builtin(&binding) {
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Operator};
|
use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Operator};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix};
|
use ruff_diagnostics::{AutofixKind, Availability, Diagnostic, Fix, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::unparse_expr;
|
use ruff_python_ast::helpers::unparse_expr;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
@ -8,18 +8,21 @@ use ruff_python_ast::types::Range;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
||||||
// TODO: document referencing [PEP 604]: https://peps.python.org/pep-0604/
|
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct TypingUnion;
|
pub struct NonPEP604Annotation {
|
||||||
|
pub fixable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Violation for NonPEP604Annotation {
|
||||||
|
const AUTOFIX: Option<AutofixKind> = Some(AutofixKind::new(Availability::Sometimes));
|
||||||
|
|
||||||
impl AlwaysAutofixableViolation for TypingUnion {
|
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
format!("Use `X | Y` for type annotations")
|
format!("Use `X | Y` for type annotations")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {
|
||||||
"Convert to `X | Y`".to_string()
|
self.fixable.then_some(|_| format!("Convert to `X | Y`"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +80,6 @@ enum TypingMember {
|
||||||
|
|
||||||
/// UP007
|
/// UP007
|
||||||
pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, slice: &Expr) {
|
pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, slice: &Expr) {
|
||||||
// Avoid rewriting forward annotations.
|
|
||||||
if any_arg_is_str(slice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(typing_member) = checker.ctx.resolve_call_path(value).as_ref().and_then(|call_path| {
|
let Some(typing_member) = checker.ctx.resolve_call_path(value).as_ref().and_then(|call_path| {
|
||||||
if checker.ctx.match_typing_call_path(call_path, "Optional") {
|
if checker.ctx.match_typing_call_path(call_path, "Optional") {
|
||||||
Some(TypingMember::Optional)
|
Some(TypingMember::Optional)
|
||||||
|
@ -94,10 +92,14 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Avoid fixing forward annotations.
|
||||||
|
let fixable = !checker.ctx.in_deferred_string_type_definition && !any_arg_is_str(slice);
|
||||||
|
|
||||||
match typing_member {
|
match typing_member {
|
||||||
TypingMember::Optional => {
|
TypingMember::Optional => {
|
||||||
let mut diagnostic = Diagnostic::new(TypingUnion, Range::from(expr));
|
let mut diagnostic =
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
Diagnostic::new(NonPEP604Annotation { fixable }, Range::from(expr));
|
||||||
|
if fixable && checker.patch(diagnostic.kind.rule()) {
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
unparse_expr(&optional(slice), checker.stylist),
|
unparse_expr(&optional(slice), checker.stylist),
|
||||||
expr.location,
|
expr.location,
|
||||||
|
@ -107,8 +109,9 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
TypingMember::Union => {
|
TypingMember::Union => {
|
||||||
let mut diagnostic = Diagnostic::new(TypingUnion, Range::from(expr));
|
let mut diagnostic =
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
Diagnostic::new(NonPEP604Annotation { fixable }, Range::from(expr));
|
||||||
|
if fixable && checker.patch(diagnostic.kind.rule()) {
|
||||||
match &slice.node {
|
match &slice.node {
|
||||||
ExprKind::Slice { .. } => {
|
ExprKind::Slice { .. } => {
|
||||||
// Invalid type annotation.
|
// Invalid type annotation.
|
||||||
|
|
|
@ -35,13 +35,12 @@ impl CallKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: document referencing [PEP 604]: https://peps.python.org/pep-0604/
|
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct IsinstanceWithTuple {
|
pub struct NonPEP604Isinstance {
|
||||||
pub kind: CallKind,
|
pub kind: CallKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AlwaysAutofixableViolation for IsinstanceWithTuple {
|
impl AlwaysAutofixableViolation for NonPEP604Isinstance {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
format!("Use `X | Y` in `{}` call instead of `(X, Y)`", self.kind)
|
format!("Use `X | Y` in `{}` call instead of `(X, Y)`", self.kind)
|
||||||
|
@ -93,7 +92,7 @@ pub fn use_pep604_isinstance(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diagnostic =
|
let mut diagnostic =
|
||||||
Diagnostic::new(IsinstanceWithTuple { kind }, Range::from(expr));
|
Diagnostic::new(NonPEP604Isinstance { kind }, Range::from(expr));
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
unparse_expr(&union(elts), checker.stylist),
|
unparse_expr(&union(elts), checker.stylist),
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -23,7 +23,7 @@ expression: diagnostics
|
||||||
column: 20
|
column: 20
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -43,7 +43,7 @@ expression: diagnostics
|
||||||
column: 13
|
column: 13
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -63,7 +63,7 @@ expression: diagnostics
|
||||||
column: 15
|
column: 15
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -83,7 +83,20 @@ expression: diagnostics
|
||||||
column: 14
|
column: 14
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 29
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 29
|
||||||
|
column: 20
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -23,7 +23,7 @@ expression: diagnostics
|
||||||
column: 22
|
column: 22
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -43,7 +43,7 @@ expression: diagnostics
|
||||||
column: 29
|
column: 29
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -63,7 +63,7 @@ expression: diagnostics
|
||||||
column: 45
|
column: 45
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -83,7 +83,7 @@ expression: diagnostics
|
||||||
column: 44
|
column: 44
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -103,7 +103,7 @@ expression: diagnostics
|
||||||
column: 31
|
column: 31
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -123,7 +123,7 @@ expression: diagnostics
|
||||||
column: 33
|
column: 33
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -143,7 +143,72 @@ expression: diagnostics
|
||||||
column: 40
|
column: 40
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
|
body: "Use `X | Y` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 30
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 30
|
||||||
|
column: 47
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP604Annotation
|
||||||
|
body: "Use `X | Y` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 30
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 30
|
||||||
|
column: 47
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP604Annotation
|
||||||
|
body: "Use `X | Y` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 34
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 34
|
||||||
|
column: 33
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP604Annotation
|
||||||
|
body: "Use `X | Y` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 38
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 38
|
||||||
|
column: 26
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP604Annotation
|
||||||
|
body: "Use `X | Y` for type annotations"
|
||||||
|
suggestion: ~
|
||||||
|
fixable: false
|
||||||
|
location:
|
||||||
|
row: 42
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 42
|
||||||
|
column: 37
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: IsinstanceWithTuple
|
name: NonPEP604Isinstance
|
||||||
body: "Use `X | Y` in `isinstance` call instead of `(X, Y)`"
|
body: "Use `X | Y` in `isinstance` call instead of `(X, Y)`"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -23,7 +23,7 @@ expression: diagnostics
|
||||||
column: 26
|
column: 26
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: IsinstanceWithTuple
|
name: NonPEP604Isinstance
|
||||||
body: "Use `X | Y` in `issubclass` call instead of `(X, Y)`"
|
body: "Use `X | Y` in `issubclass` call instead of `(X, Y)`"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -23,7 +23,7 @@ expression: diagnostics
|
||||||
column: 21
|
column: 21
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -43,7 +43,7 @@ expression: diagnostics
|
||||||
column: 12
|
column: 12
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -63,7 +63,7 @@ expression: diagnostics
|
||||||
column: 30
|
column: 30
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: DeprecatedCollectionType
|
name: NonPEP585Annotation
|
||||||
body: "Use `list` instead of `List` for type annotations"
|
body: "Use `list` instead of `List` for type annotations"
|
||||||
suggestion: "Replace `List` with `list`"
|
suggestion: "Replace `List` with `list`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -3,7 +3,7 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||||
expression: diagnostics
|
expression: diagnostics
|
||||||
---
|
---
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
@ -23,7 +23,7 @@ expression: diagnostics
|
||||||
column: 16
|
column: 16
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
name: TypingUnion
|
name: NonPEP604Annotation
|
||||||
body: "Use `X | Y` for type annotations"
|
body: "Use `X | Y` for type annotations"
|
||||||
suggestion: "Convert to `X | Y`"
|
suggestion: "Convert to `X | Y`"
|
||||||
fixable: true
|
fixable: true
|
||||||
|
|
|
@ -137,7 +137,7 @@ mod tests {
|
||||||
fn redirects() -> Result<()> {
|
fn redirects() -> Result<()> {
|
||||||
let diagnostics = test_path(
|
let diagnostics = test_path(
|
||||||
Path::new("ruff/redirects.py"),
|
Path::new("ruff/redirects.py"),
|
||||||
&settings::Settings::for_rules(vec![Rule::TypingUnion]),
|
&settings::Settings::for_rules(vec![Rule::NonPEP604Annotation]),
|
||||||
)?;
|
)?;
|
||||||
assert_yaml_snapshot!(diagnostics);
|
assert_yaml_snapshot!(diagnostics);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use ruff_python_stdlib::typing::{PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS, SUBSCRIPTS};
|
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use crate::types::CallPath;
|
use ruff_python_stdlib::typing::{PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS, SUBSCRIPTS};
|
||||||
|
|
||||||
|
use crate::context::Context;
|
||||||
|
|
||||||
pub enum Callable {
|
pub enum Callable {
|
||||||
ForwardRef,
|
ForwardRef,
|
||||||
|
@ -18,14 +19,11 @@ pub enum SubscriptKind {
|
||||||
PEP593AnnotatedSubscript,
|
PEP593AnnotatedSubscript,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_annotated_subscript<'a, F>(
|
pub fn match_annotated_subscript<'a>(
|
||||||
expr: &'a Expr,
|
expr: &Expr,
|
||||||
resolve_call_path: F,
|
context: &Context,
|
||||||
typing_modules: impl Iterator<Item = &'a str>,
|
typing_modules: impl Iterator<Item = &'a str>,
|
||||||
) -> Option<SubscriptKind>
|
) -> Option<SubscriptKind> {
|
||||||
where
|
|
||||||
F: FnOnce(&'a Expr) -> Option<CallPath<'a>>,
|
|
||||||
{
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
expr.node,
|
expr.node,
|
||||||
ExprKind::Name { .. } | ExprKind::Attribute { .. }
|
ExprKind::Name { .. } | ExprKind::Attribute { .. }
|
||||||
|
@ -33,7 +31,7 @@ where
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_call_path(expr).and_then(|call_path| {
|
context.resolve_call_path(expr).and_then(|call_path| {
|
||||||
if SUBSCRIPTS.contains(&call_path.as_slice()) {
|
if SUBSCRIPTS.contains(&call_path.as_slice()) {
|
||||||
return Some(SubscriptKind::AnnotatedSubscript);
|
return Some(SubscriptKind::AnnotatedSubscript);
|
||||||
}
|
}
|
||||||
|
@ -63,11 +61,8 @@ where
|
||||||
|
|
||||||
/// Returns `true` if `Expr` represents a reference to a typing object with a
|
/// Returns `true` if `Expr` represents a reference to a typing object with a
|
||||||
/// PEP 585 built-in.
|
/// PEP 585 built-in.
|
||||||
pub fn is_pep585_builtin<'a, F>(expr: &'a Expr, resolve_call_path: F) -> bool
|
pub fn is_pep585_builtin(expr: &Expr, context: &Context) -> bool {
|
||||||
where
|
context.resolve_call_path(expr).map_or(false, |call_path| {
|
||||||
F: FnOnce(&'a Expr) -> Option<CallPath<'a>>,
|
|
||||||
{
|
|
||||||
resolve_call_path(expr).map_or(false, |call_path| {
|
|
||||||
PEP_585_BUILTINS_ELIGIBLE.contains(&call_path.as_slice())
|
PEP_585_BUILTINS_ELIGIBLE.contains(&call_path.as_slice())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue