mirror of
https://github.com/astral-sh/ruff.git
synced 2025-12-23 09:19:39 +00:00
Merge da4d195b74 into 4745d15fff
This commit is contained in:
commit
bd52343a34
3 changed files with 56 additions and 9 deletions
|
|
@ -194,7 +194,7 @@ static SYMPY: Benchmark = Benchmark::new(
|
|||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
13100,
|
||||
13105,
|
||||
);
|
||||
|
||||
static TANJUN: Benchmark = Benchmark::new(
|
||||
|
|
|
|||
|
|
@ -525,6 +525,42 @@ c.name = None
|
|||
c.name = 42
|
||||
```
|
||||
|
||||
### Overriding properties in subclasses
|
||||
|
||||
When a subclass overrides a property, accessing other inherited properties from within the
|
||||
overriding property methods should still work correctly.
|
||||
|
||||
```py
|
||||
class Base:
|
||||
_value: float = 0.0
|
||||
|
||||
@property
|
||||
def value(self) -> float:
|
||||
return self._value
|
||||
|
||||
@value.setter
|
||||
def value(self, v: float) -> None:
|
||||
self._value = v
|
||||
|
||||
@property
|
||||
def other(self) -> float:
|
||||
return self.value
|
||||
|
||||
@other.setter
|
||||
def other(self, v: float) -> None:
|
||||
self.value = v
|
||||
|
||||
class Derived(Base):
|
||||
@property
|
||||
def other(self) -> float:
|
||||
return self.value
|
||||
|
||||
@other.setter
|
||||
def other(self, v: float) -> None:
|
||||
reveal_type(self.value) # revealed: int | float
|
||||
self.value = v
|
||||
```
|
||||
|
||||
### Properties with no setters
|
||||
|
||||
<!-- snapshot-diagnostics -->
|
||||
|
|
|
|||
|
|
@ -3386,16 +3386,27 @@ impl<'db> ClassLiteral<'db> {
|
|||
let is_valid_scope = |method_scope: &Scope| {
|
||||
if let Some(method_def) = method_scope.node().as_function() {
|
||||
let method_name = method_def.node(&module).name.as_str();
|
||||
if let Some(Type::FunctionLiteral(method_type)) =
|
||||
class_member(db, class_body_scope, method_name)
|
||||
.inner
|
||||
.place
|
||||
.ignore_possibly_undefined()
|
||||
match class_member(db, class_body_scope, method_name)
|
||||
.inner
|
||||
.place
|
||||
.ignore_possibly_undefined()
|
||||
{
|
||||
let method_decorator = MethodDecorator::try_from_fn_type(db, method_type);
|
||||
if method_decorator != Ok(target_method_decorator) {
|
||||
return false;
|
||||
Some(Type::FunctionLiteral(method_type)) => {
|
||||
let method_decorator = MethodDecorator::try_from_fn_type(db, method_type);
|
||||
if method_decorator != Ok(target_method_decorator) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Some(Type::PropertyInstance(_)) => {
|
||||
// Property getters and setters have their own scopes. They take `self`
|
||||
// as the first parameter (like regular instance methods), so they're
|
||||
// included when looking for `MethodDecorator::None`. However, they're
|
||||
// not classmethods or staticmethods, so exclude them for those cases.
|
||||
if target_method_decorator != MethodDecorator::None {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue