This commit is contained in:
Charlie Marsh 2025-12-22 21:44:36 -05:00 committed by GitHub
commit bd52343a34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 9 deletions

View file

@ -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(

View file

@ -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 -->

View file

@ -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