Fixed a recent regression that results in a false positive when the fully-qualified form of typing.Request is used in an annotation expression. This addresses #8375. (#8381)

This commit is contained in:
Eric Traut 2024-07-11 17:36:23 -07:00 committed by GitHub
parent 472d86519d
commit 39d76a86e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 16 deletions

View File

@ -21598,7 +21598,7 @@ export function createTypeEvaluator(
const result: EffectiveTypeResult = {
type: declaredType ?? UnknownType.create(),
isIncomplete,
includesVariableDecl: typedDecls.some((decl) => decl.type === DeclarationType.Variable),
includesVariableDecl: includesVariableTypeDecl(typedDecls),
includesIllegalTypeAliasDecl: !typedDecls.every((decl) => isPossibleTypeAliasDeclaration(decl)),
includesSpeculativeResult: false,
isRecursiveDefinition: !declaredType,
@ -21611,6 +21611,24 @@ export function createTypeEvaluator(
return inferTypeOfSymbolForUsage(symbol, usageNode, useLastDecl);
}
// Determines whether the set of declarations includes a variable declaration
// that is not part of a typing.pyi or typingExtensions.pyi file.
function includesVariableTypeDecl(decls: Declaration[]): boolean {
return decls.some((decl) => {
if (decl.type === DeclarationType.Variable) {
// Exempt typing.pyi and typingExtensions.pyi, which use variables to
// define some special forms.
const fileInfo = AnalyzerNodeInfo.getFileInfo(decl.node);
if (!fileInfo.isTypingStubFile && !fileInfo.isTypingExtensionsStubFile) {
return true;
}
}
return false;
});
}
function inferTypeOfSymbolForUsage(symbol: Symbol, usageNode?: NameNode, useLastDecl = false): EffectiveTypeResult {
// Look in the inferred type cache to see if we've computed this already.
let cacheEntries = effectiveTypeCache.get(symbol.id);
@ -21683,14 +21701,9 @@ export function createTypeEvaluator(
includesIllegalTypeAliasDecl = true;
}
if (resolvedDecl.type === DeclarationType.Variable) {
// Exempt typing.pyi, which uses variables to define some
// special forms like Any.
const fileInfo = AnalyzerNodeInfo.getFileInfo(resolvedDecl.node);
if (!fileInfo.isTypingStubFile) {
if (includesVariableTypeDecl([resolvedDecl])) {
includesVariableDecl = true;
}
}
if (declIndexToConsider !== undefined && declIndexToConsider !== index) {
return;

View File

@ -4,17 +4,15 @@
# pyright: reportMissingModuleSource=false
from typing import Literal, TypedDict, Annotated
from typing_extensions import ( # pyright: ignore[reportMissingModuleSource]
NotRequired,
Required,
)
import typing_extensions as te
from typing_extensions import Required, NotRequired
class TD1(TypedDict, total=False):
a: Annotated["Required[int]", ""]
b: Annotated[NotRequired[str], ""]
c: "Required[int | str]"
d: Required[str | None]
a: Annotated["te.Required[int]", ""]
b: Annotated[te.NotRequired[str], ""]
c: "te.Required[int | str]"
d: te.Required[str | None]
e: Required[Literal[1, 2, 3]]
f: Required[None]
g: Required[type[int]]