diff --git a/resources/test/fixtures/F821_3.py b/resources/test/fixtures/F821_3.py index 9dd6bfd5a5..0dc8399b5c 100644 --- a/resources/test/fixtures/F821_3.py +++ b/resources/test/fixtures/F821_3.py @@ -12,3 +12,13 @@ x: dict["key", "value"] # OK x: dict[str, str] + +# OK +def unimportant(name): + pass + + +def dang(dict, set, list): + unimportant(name=dict["name"]) + unimportant(name=set["name"]) + unimportant(name=list["name"]) diff --git a/src/check_ast.rs b/src/check_ast.rs index 2edc0e7a88..de270814d4 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -177,6 +177,15 @@ impl<'a> Checker<'a> { || (typing::in_extensions(target) && match_call_path(call_path, "typing_extensions", target, &self.from_imports)) } + + /// Return `true` if `member` is bound as a builtin. + pub fn is_builtin(&self, member: &str) -> bool { + self.current_scopes() + .find_map(|scope| scope.values.get(member)) + .map_or(false, |binding| { + matches!(binding.kind, BindingKind::Builtin) + }) + } } impl<'a, 'b> Visitor<'b> for Checker<'a> @@ -1964,6 +1973,7 @@ where value, &self.from_imports, &self.import_aliases, + |member| self.is_builtin(member), ) { Some(subscript) => { match subscript { diff --git a/src/python/typing.rs b/src/python/typing.rs index 2db9aead31..36c9df3c88 100644 --- a/src/python/typing.rs +++ b/src/python/typing.rs @@ -209,15 +209,21 @@ pub enum SubscriptKind { PEP593AnnotatedSubscript, } -pub fn match_annotated_subscript( +pub fn match_annotated_subscript( expr: &Expr, from_imports: &FxHashMap<&str, FxHashSet<&str>>, import_aliases: &FxHashMap<&str, &str>, -) -> Option { + is_builtin: F, +) -> Option +where + F: Fn(&str) -> bool, +{ let call_path = dealias_call_path(collect_call_paths(expr), import_aliases); if !call_path.is_empty() { for (module, member) in SUBSCRIPTS { - if match_call_path(&call_path, module, member, from_imports) { + if match_call_path(&call_path, module, member, from_imports) + && (!module.is_empty() || is_builtin(member)) + { return Some(SubscriptKind::AnnotatedSubscript); } } diff --git a/src/rules/plugins/convert_exit_to_sys_exit.rs b/src/rules/plugins/convert_exit_to_sys_exit.rs index e8c6d8f8c5..d660e424c4 100644 --- a/src/rules/plugins/convert_exit_to_sys_exit.rs +++ b/src/rules/plugins/convert_exit_to_sys_exit.rs @@ -21,12 +21,7 @@ fn is_module_star_imported(checker: &Checker, module: &str) -> bool { /// Return `true` if `exit` is (still) bound as a built-in in the current scope. fn has_builtin_exit_in_scope(checker: &Checker) -> bool { - !is_module_star_imported(checker, "sys") - && checker - .current_scopes() - .find_map(|scope| scope.values.get("exit")) - .map(|binding| matches!(binding.kind, BindingKind::Builtin)) - .unwrap_or_default() + !is_module_star_imported(checker, "sys") && checker.is_builtin("exit") } /// Return the appropriate `sys.exit` reference based on the current set of