mirror of
https://github.com/microsoft/pyright.git
synced 2024-08-16 19:30:26 +03:00
Fixed a bug that results in a false negative when a class explicitly inherits from a protocol that defines an instance variable but the child re-declares as a ClassVar
without an explicit type. This addresses #7455. (#7463)
This commit is contained in:
parent
06bc912e38
commit
3ccd7b87b5
@ -6132,9 +6132,11 @@ export class Checker extends ParseTreeWalker {
|
||||
}
|
||||
|
||||
// If the symbol has no declaration, and the type is inferred,
|
||||
// skip this check.
|
||||
if (!symbol.hasTypedDeclarations() && !this._evaluator.isFinalVariable(symbol)) {
|
||||
return;
|
||||
// skip the type validation but still check for other issues like
|
||||
// Final overrides and class/instance variable mismatches.
|
||||
let validateType = true;
|
||||
if (!symbol.hasTypedDeclarations()) {
|
||||
validateType = false;
|
||||
}
|
||||
|
||||
// Get the symbol type defined in this class.
|
||||
@ -6169,7 +6171,13 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
firstOverride = firstOverride ?? baseClassAndSymbol;
|
||||
|
||||
this._validateBaseClassOverride(baseClassAndSymbol, symbol, typeOfSymbol, classType, name);
|
||||
this._validateBaseClassOverride(
|
||||
baseClassAndSymbol,
|
||||
symbol,
|
||||
validateType ? typeOfSymbol : AnyType.create(),
|
||||
classType,
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
if (!firstOverride) {
|
||||
|
@ -110,14 +110,12 @@ _Self = TypeVar("_Self")
|
||||
|
||||
class Class5:
|
||||
@property
|
||||
def real(self: _Self) -> _Self:
|
||||
...
|
||||
def real(self: _Self) -> _Self: ...
|
||||
|
||||
|
||||
class MockClass5(Protocol[_T_co]):
|
||||
@property
|
||||
def real(self) -> _T_co:
|
||||
...
|
||||
def real(self) -> _T_co: ...
|
||||
|
||||
|
||||
foo5 = Class5()
|
||||
@ -130,14 +128,12 @@ C6 = TypeVar("C6", bound="Class6")
|
||||
|
||||
class MockClass6(Protocol):
|
||||
@property
|
||||
def bar(self: P6) -> ContextManager[P6]:
|
||||
...
|
||||
def bar(self: P6) -> ContextManager[P6]: ...
|
||||
|
||||
|
||||
class Class6:
|
||||
@property
|
||||
def bar(self: C6) -> ContextManager[C6]:
|
||||
...
|
||||
def bar(self: C6) -> ContextManager[C6]: ...
|
||||
|
||||
|
||||
i: MockClass6 = Class6()
|
||||
@ -158,8 +154,7 @@ a: Proto7 = Class7("")
|
||||
|
||||
class Proto8(Protocol):
|
||||
@property
|
||||
def x(self) -> str:
|
||||
...
|
||||
def x(self) -> str: ...
|
||||
|
||||
|
||||
class Class8(NamedTuple):
|
||||
@ -171,12 +166,10 @@ b: Proto8 = Class8("")
|
||||
|
||||
class Proto9(Protocol):
|
||||
@property
|
||||
def x(self) -> str:
|
||||
...
|
||||
def x(self) -> str: ...
|
||||
|
||||
@x.setter
|
||||
def x(self, n: str) -> None:
|
||||
...
|
||||
def x(self, n: str) -> None: ...
|
||||
|
||||
|
||||
class Proto10(Protocol):
|
||||
@ -231,11 +224,11 @@ p11_1: Proto11 = Concrete11()
|
||||
|
||||
|
||||
class Proto12(Protocol):
|
||||
val1: Sequence[int]
|
||||
val1: list[int]
|
||||
|
||||
|
||||
class Concrete12:
|
||||
val1: ClassVar[Sequence[int]]
|
||||
val1: ClassVar = [1, 2, 3]
|
||||
|
||||
|
||||
# This should generate an error because of a ClassVar mismatch.
|
||||
@ -255,12 +248,10 @@ T13 = TypeVar("T13", covariant=True)
|
||||
|
||||
class Proto13(Protocol[T13]):
|
||||
@property
|
||||
def prop1(self) -> T13:
|
||||
...
|
||||
def prop1(self) -> T13: ...
|
||||
|
||||
|
||||
class Proto14(Proto13[T13], Protocol):
|
||||
...
|
||||
class Proto14(Proto13[T13], Protocol): ...
|
||||
|
||||
|
||||
class Concrete14(Generic[T13]):
|
||||
@ -268,8 +259,7 @@ class Concrete14(Generic[T13]):
|
||||
self.prop1 = val
|
||||
|
||||
|
||||
def func14(val: Proto14[T13]):
|
||||
...
|
||||
def func14(val: Proto14[T13]): ...
|
||||
|
||||
|
||||
func14(Concrete14(1))
|
||||
|
@ -26,8 +26,7 @@ class Protocol3(Protocol2, Protocol):
|
||||
cm11: int
|
||||
|
||||
|
||||
class Concrete1(Protocol1):
|
||||
...
|
||||
class Concrete1(Protocol1): ...
|
||||
|
||||
|
||||
# This should generate an error because some attributes are not implemented.
|
||||
@ -67,8 +66,7 @@ Concrete4()
|
||||
|
||||
|
||||
class Protocol5(Protocol):
|
||||
def method1(self) -> int:
|
||||
...
|
||||
def method1(self) -> int: ...
|
||||
|
||||
|
||||
# This should generate an error because "method1" is
|
||||
@ -93,8 +91,7 @@ class Concrete6(Mixin, Protocol6):
|
||||
|
||||
class Protocol7(Protocol):
|
||||
@abstractmethod
|
||||
def method1(self):
|
||||
...
|
||||
def method1(self): ...
|
||||
|
||||
|
||||
class Mixin7(Protocol7, ABC):
|
||||
@ -112,3 +109,12 @@ class Concrete7A(Protocol7):
|
||||
@final
|
||||
class Concrete7B(Mixin7, Protocol7):
|
||||
pass
|
||||
|
||||
|
||||
class Protocol8(Protocol):
|
||||
x: int
|
||||
|
||||
|
||||
class Concrete8(Protocol8):
|
||||
# This should generate an error because x is a ClassVar.
|
||||
x: ClassVar = 1
|
||||
|
@ -1414,7 +1414,7 @@ test('Protocol48', () => {
|
||||
test('ProtocolExplicit1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocolExplicit1.py']);
|
||||
|
||||
TestUtils.validateResults(analysisResults, 4);
|
||||
TestUtils.validateResults(analysisResults, 5);
|
||||
});
|
||||
|
||||
test('ProtocolExplicit3', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user