mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-07 05:17:10 +03:00
Fixed false positive error with reportUnnecessaryIsInstance diagnostic check with the provided class is dynamic.
This commit is contained in:
parent
df3313c2cd
commit
6da2e0ec81
@ -2496,6 +2496,8 @@ export class Checker extends ParseTreeWalker {
|
||||
];
|
||||
|
||||
const classTypeList: ClassType[] = [];
|
||||
let arg1IncludesSubclasses = false;
|
||||
|
||||
doForEachSubtype(arg1Type, (arg1Subtype) => {
|
||||
if (isClass(arg1Subtype)) {
|
||||
if (TypeBase.isInstantiable(arg1Subtype)) {
|
||||
@ -2506,18 +2508,33 @@ export class Checker extends ParseTreeWalker {
|
||||
) {
|
||||
isValidType = false;
|
||||
}
|
||||
|
||||
if (arg1Subtype.includeSubclasses) {
|
||||
arg1IncludesSubclasses = true;
|
||||
}
|
||||
} else {
|
||||
// The isinstance and issubclass call supports a variation where the second
|
||||
// parameter is a tuple of classes.
|
||||
if (isTupleClass(arg1Subtype) && arg1Subtype.tupleTypeArguments) {
|
||||
arg1Subtype.tupleTypeArguments.forEach((typeArg) => {
|
||||
if (isInstantiableClass(typeArg)) {
|
||||
classTypeList.push(typeArg);
|
||||
} else {
|
||||
isValidType = false;
|
||||
}
|
||||
});
|
||||
if (isTupleClass(arg1Subtype)) {
|
||||
if (arg1Subtype.tupleTypeArguments) {
|
||||
arg1Subtype.tupleTypeArguments.forEach((typeArg) => {
|
||||
if (isInstantiableClass(typeArg)) {
|
||||
classTypeList.push(typeArg);
|
||||
|
||||
if (typeArg.includeSubclasses) {
|
||||
arg1IncludesSubclasses = true;
|
||||
}
|
||||
} else {
|
||||
isValidType = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (arg1Subtype.includeSubclasses) {
|
||||
arg1IncludesSubclasses = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
ClassType.isBuiltIn(arg1Subtype) &&
|
||||
nonstandardClassTypes.some((name) => name === arg1Subtype.details.name)
|
||||
@ -2639,7 +2656,9 @@ export class Checker extends ParseTreeWalker {
|
||||
return combineTypes(objTypeList);
|
||||
};
|
||||
|
||||
if (isTypeSame(filteredType, arg0Type, /* ignorePseudoGeneric */ true)) {
|
||||
// If arg1IncludesSubclasses is true, it contains a Type[X] class rather than X. A Type[X]
|
||||
// could be a subclass of X, so the "unnecessary isinstance check" may be legit.
|
||||
if (!arg1IncludesSubclasses && isTypeSame(filteredType, arg0Type, /* ignorePseudoGeneric */ true)) {
|
||||
this._evaluator.addDiagnostic(
|
||||
this._fileInfo.diagnosticRuleSet.reportUnnecessaryIsInstance,
|
||||
DiagnosticRule.reportUnnecessaryIsInstance,
|
||||
|
@ -201,7 +201,7 @@ test('UnnecessaryIsInstance1', () => {
|
||||
// Turn on errors.
|
||||
configOptions.diagnosticRuleSet.reportUnnecessaryIsInstance = 'error';
|
||||
analysisResults = TestUtils.typeAnalyzeSampleFiles(['unnecessaryIsInstance1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults, 4);
|
||||
TestUtils.validateResults(analysisResults, 5);
|
||||
});
|
||||
|
||||
test('UnnecessaryIsSubclass1', () => {
|
||||
|
@ -1,6 +1,14 @@
|
||||
# This sample tests unnecessary isinstance error reporting.
|
||||
|
||||
from typing import ClassVar, Literal, Protocol, TypedDict, Union, runtime_checkable
|
||||
from typing import (
|
||||
ClassVar,
|
||||
Literal,
|
||||
Protocol,
|
||||
Type,
|
||||
TypedDict,
|
||||
Union,
|
||||
runtime_checkable,
|
||||
)
|
||||
|
||||
from unknown_import import CustomClass1
|
||||
|
||||
@ -67,3 +75,18 @@ def func3(obj: BaseClass):
|
||||
|
||||
if isinstance(obj, (ClassA, ClassB, ClassC)):
|
||||
t_2: Literal["ClassA | ClassB"] = reveal_type(obj)
|
||||
|
||||
|
||||
class A:
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
|
||||
def func4(a: A, cls: Type[A]) -> None:
|
||||
isinstance(a, cls)
|
||||
|
||||
# This should generate an error because it's always true.
|
||||
isinstance(a, A)
|
||||
|
Loading…
Reference in New Issue
Block a user