mirror of https://github.com/astral-sh/ruff
Respect attribute chains when resolving builtin call paths (#9309)
## Summary When resolving `dict.__dict__`, we were discarding the `.__dict__` segment when computing the call path. ## Test Plan `cargo test`
This commit is contained in:
parent
ec88acc291
commit
00f3c7d1d5
|
|
@ -0,0 +1,5 @@
|
||||||
|
"""Test for attribute accesses on builtins."""
|
||||||
|
|
||||||
|
a = type({}).__dict__['fromkeys']
|
||||||
|
b = dict.__dict__['fromkeys']
|
||||||
|
assert a is b
|
||||||
|
|
@ -144,6 +144,7 @@ mod tests {
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_22.ipynb"))]
|
#[test_case(Rule::UndefinedName, Path::new("F821_22.ipynb"))]
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_23.py"))]
|
#[test_case(Rule::UndefinedName, Path::new("F821_23.py"))]
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_24.py"))]
|
#[test_case(Rule::UndefinedName, Path::new("F821_24.py"))]
|
||||||
|
#[test_case(Rule::UndefinedName, Path::new("F821_25.py"))]
|
||||||
#[test_case(Rule::UndefinedExport, Path::new("F822_0.py"))]
|
#[test_case(Rule::UndefinedExport, Path::new("F822_0.py"))]
|
||||||
#[test_case(Rule::UndefinedExport, Path::new("F822_1.py"))]
|
#[test_case(Rule::UndefinedExport, Path::new("F822_1.py"))]
|
||||||
#[test_case(Rule::UndefinedExport, Path::new("F822_2.py"))]
|
#[test_case(Rule::UndefinedExport, Path::new("F822_2.py"))]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
|
||||||
|
---
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::analyze::type_inference::{PythonType, ResolvedPythonType};
|
||||||
use crate::model::SemanticModel;
|
use crate::model::SemanticModel;
|
||||||
use crate::{Binding, BindingKind};
|
use crate::{Binding, BindingKind};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Callable {
|
pub enum Callable {
|
||||||
Bool,
|
Bool,
|
||||||
Cast,
|
Cast,
|
||||||
|
|
@ -26,7 +26,7 @@ pub enum Callable {
|
||||||
MypyExtension,
|
MypyExtension,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum SubscriptKind {
|
pub enum SubscriptKind {
|
||||||
/// A subscript of the form `typing.Literal["foo", "bar"]`, i.e., a literal.
|
/// A subscript of the form `typing.Literal["foo", "bar"]`, i.e., a literal.
|
||||||
Literal,
|
Literal,
|
||||||
|
|
|
||||||
|
|
@ -707,7 +707,20 @@ impl<'a> SemanticModel<'a> {
|
||||||
};
|
};
|
||||||
Some(resolved)
|
Some(resolved)
|
||||||
}
|
}
|
||||||
BindingKind::Builtin => Some(smallvec!["", head.id.as_str()]),
|
BindingKind::Builtin => {
|
||||||
|
if value.is_name_expr() {
|
||||||
|
// Ex) `dict`
|
||||||
|
Some(smallvec!["", head.id.as_str()])
|
||||||
|
} else {
|
||||||
|
// Ex) `dict.__dict__`
|
||||||
|
let value_path = collect_call_path(value)?;
|
||||||
|
Some(
|
||||||
|
std::iter::once("")
|
||||||
|
.chain(value_path.iter().copied())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
BindingKind::ClassDefinition(_) | BindingKind::FunctionDefinition(_) => {
|
BindingKind::ClassDefinition(_) | BindingKind::FunctionDefinition(_) => {
|
||||||
let value_path = collect_call_path(value)?;
|
let value_path = collect_call_path(value)?;
|
||||||
let resolved: CallPath = self
|
let resolved: CallPath = self
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue