10000 Implemented PEP 698 (@override) support for methods decorated with `@… · sourcegraph/scip-python@e7f418a · GitHub
[go: up one dir, main page]

Skip to content

Commit e7f418a

Browse files
committed
Implemented PEP 698 (@OverRide) support for methods decorated with @property decorator. This addresses microsoft/pyright#4877.
1 parent 1a0731e commit e7f418a

File tree

4 files changed

+36
-7
lines changed

4 files changed

+36
-7
lines changed

packages/pyright-internal/src/analyzer/checker.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5332,6 +5332,15 @@ export class Checker extends ParseTreeWalker {
53325332
overrideFunction = overrideType;
53335333
} else if (isOverloadedFunction(overrideType)) {
53345334
overrideFunction = OverloadedFunctionType.getImplementation(overrideType);
5335+
} else if (isClassInstance(overrideType) && ClassType.isPropertyClass(overrideType)) {
5336+
const fgetSymbol = overrideType.details.fields.get('fget');
5337+
5338+
if (fgetSymbol) {
5339+
const fgetType = this._evaluator.getDeclaredTypeOfSymbol(fgetSymbol)?.type;
5340+
if (fgetType && isFunction(fgetType)) {
5341+
overrideFunction = fgetType;
5342+
}
5343+
}
53355344
}
53365345

53375346
if (!overrideFunction?.details.declaration || FunctionType.isOverridden(overrideFunction)) {
@@ -5365,6 +5374,15 @@ export class Checker extends ParseTreeWalker {
53655374
overrideFunction = overrideType;
53665375
} else if (isOverloadedFunction(overrideType)) {
53675376
overrideFunction = OverloadedFunctionType.getImplementation(overrideType);
5377+
} else if (isClassInstance(overrideType) && ClassType.isPropertyClass(overrideType)) {
5378+
const fgetSymbol = overrideType.details.fields.get('fget');
5379+
5380+
if (fgetSymbol) {
5381+
const fgetType = this._evaluator.getDeclaredTypeOfSymbol(fgetSymbol)?.type;
5382+
if (fgetType && isFunction(fgetType)) {
5383+
overrideFunction = fgetType;
5384+
}
5385+
}
53685386
}
53695387

53705388
if (!overrideFunction?.details.declaration || !FunctionType.isOverridden(overrideFunction)) {

packages/pyright-internal/src/tests/samples/override1.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ def method5(self, x: int | str) -> int | str:
2020

2121

2222
class ClassC(ClassA, ClassB):
23+
@property
24+
@override
25+
# This should generate an error because prop_a doesn't
26+
# override anything in its base class.
27+
def prop_a(self) -> int:
28+
raise NotImplementedError
29+
2330
@override
2431
def method1(self) -> None:
2532
pass

packages/pyright-internal/src/tests/samples/override2.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ def __init__(self):
1212
def method1(self):
1313
pass
1414

15+
@property
16+
def prop_c(self) -> int:
17+
return 0
18+
1519

1620
class Child(Base):
1721
def __init__(self):
@@ -20,3 +24,8 @@ def __init__(self):
2024
# This should generate an error if reportImplicitOverride is enabled.
2125
def method1(self):
2226
pass
27+
28+
@property
29+
# This should generate an error if reportImplicitOverride is enabled.
30+
def prop_c(self) -> int:
31+
return 0

packages/pyright-internal/src/tests/typeEvaluator5.test.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,7 @@ test('Hashability1', () => {
147147

148148
test('Override1', () => {
149149
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['override1.py']);
150-
TestUtils.validateResults(analysisResults, 2);
151-
});
152-
153-
test('Override1', () => {
154-
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['override1.py']);
155-
TestUtils.validateResults(analysisResults, 2);
150+
TestUtils.validateResults(analysisResults, 3);
156151
});
157152

158153
test('Override2', () => {
@@ -163,7 +158,7 @@ test('Override2', () => {
163158

164159
configOptions.diagnosticRuleSet.reportImplicitOverride = 'error';
165160
const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['override2.py'], configOptions);
166-
TestUtils.validateResults(analysisResults2, 1);
161+
TestUtils.validateResults(analysisResults2, 2);
167162
});
168163

169164
test('TypeVarDefault1', () => {

0 commit comments

Comments
 (0)
0