mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-21 19:05:09 +00:00
Support classes that implement __call__
(#13580)
## Summary This looked straightforward and removes some TODOs.
This commit is contained in:
parent
043fba7a57
commit
edba60106b
2 changed files with 45 additions and 2 deletions
|
@ -609,8 +609,20 @@ impl<'db> Type<'db> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle classes which implement the `__call__` protocol
|
Type::Instance(class) => {
|
||||||
Type::Instance(_instance_ty) => CallOutcome::callable(Type::Todo),
|
// Since `__call__` is a dunder, we need to access it as an attribute on the class
|
||||||
|
// rather than the instance (matching runtime semantics).
|
||||||
|
let meta_ty = Type::Class(class);
|
||||||
|
let dunder_call_method = meta_ty.member(db, "__call__");
|
||||||
|
if dunder_call_method.is_unbound() {
|
||||||
|
CallOutcome::not_callable(self)
|
||||||
|
} else {
|
||||||
|
let args = std::iter::once(self)
|
||||||
|
.chain(arg_types.iter().copied())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
dunder_call_method.call(db, &args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// `Any` is callable, and its return type is also `Any`.
|
// `Any` is callable, and its return type is also `Any`.
|
||||||
Type::Any => CallOutcome::callable(Type::Any),
|
Type::Any => CallOutcome::callable(Type::Any),
|
||||||
|
|
|
@ -6723,6 +6723,37 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dunder_call() -> anyhow::Result<()> {
|
||||||
|
let mut db = setup_db();
|
||||||
|
|
||||||
|
db.write_dedented(
|
||||||
|
"/src/a.py",
|
||||||
|
"
|
||||||
|
class Multiplier:
|
||||||
|
def __init__(self, factor: float):
|
||||||
|
self.factor = factor
|
||||||
|
|
||||||
|
def __call__(self, number: float) -> float:
|
||||||
|
return number * self.factor
|
||||||
|
|
||||||
|
a = Multiplier(2.0)(3.0)
|
||||||
|
|
||||||
|
class Unit:
|
||||||
|
...
|
||||||
|
|
||||||
|
b = Unit()(3.0)
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_public_ty(&db, "/src/a.py", "a", "float");
|
||||||
|
assert_public_ty(&db, "/src/a.py", "b", "Unknown");
|
||||||
|
|
||||||
|
assert_file_diagnostics(&db, "src/a.py", &["Object of type 'Unit' is not callable."]);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn boolean_or_expression() -> anyhow::Result<()> {
|
fn boolean_or_expression() -> anyhow::Result<()> {
|
||||||
let mut db = setup_db();
|
let mut db = setup_db();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue