Merge branch 'main' into add-azure-devops-release

This commit is contained in:
Bill Schnurr 2024-07-02 11:56:06 -07:00 committed by GitHub
commit ba50f35bb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
572 changed files with 4067 additions and 4145 deletions

View File

@ -35,7 +35,7 @@ jobs:
contents: read
strategy:
matrix:
shard-index: [0, 1]
shard-index: [0, 1, 2, 3, 4, 5, 6, 7]
fail-fast: false
steps:
- uses: actions/checkout@v4
@ -69,7 +69,7 @@ jobs:
--repo pyright_to_test \
--type-checker pyright \
--new $GITHUB_SHA --old base_commit \
--num-shards 2 --shard-index ${{ matrix.shard-index }} \
--num-shards 8 --shard-index ${{ matrix.shard-index }} \
--debug \
--output concise \
| tee diff_${{ matrix.shard-index }}.txt

View File

@ -3092,106 +3092,123 @@ export class Checker extends ParseTreeWalker {
private _reportInvalidOverload(name: string, symbol: Symbol) {
const typedDecls = symbol.getTypedDeclarations();
if (typedDecls.length >= 1) {
const primaryDecl = typedDecls[0];
if (typedDecls.length === 0) {
return;
}
if (primaryDecl.type === DeclarationType.Function) {
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
const overloadedFunctions = isOverloadedFunction(type)
? OverloadedFunctionType.getOverloads(type)
: isFunction(type) && FunctionType.isOverloaded(type)
? [type]
: [];
const primaryDecl = typedDecls[0];
if (overloadedFunctions.length === 1) {
// There should never be a single overload.
this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.singleOverload().format({ name }),
primaryDecl.node.name
);
}
if (primaryDecl.type !== DeclarationType.Function) {
return;
}
// If the file is not a stub and this is the first overload,
// verify that there is an implementation.
if (!this._fileInfo.isStubFile && overloadedFunctions.length > 0) {
let implementationFunction: FunctionType | undefined;
let exemptMissingImplementation = false;
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
const overloadedFunctions = isOverloadedFunction(type)
? OverloadedFunctionType.getOverloads(type)
: isFunction(type) && FunctionType.isOverloaded(type)
? [type]
: [];
if (isOverloadedFunction(type)) {
implementationFunction = OverloadedFunctionType.getImplementation(type);
// If the implementation has no name, it was synthesized probably by a
// decorator that used a callable with a ParamSpec that captured the
// overloaded signature. We'll exempt it from this check.
if (isOverloadedFunction(type)) {
const overloads = OverloadedFunctionType.getOverloads(type);
if (overloads.length > 0 && overloads[0].details.name === '') {
return;
}
} else if (isFunction(type)) {
if (type.details.name === '') {
return;
}
}
// If the implementation has no name, it was synthesized probably by a
// decorator that used a callable with a ParamSpec that captured the
// overloaded signature. We'll exempt it from this check.
const overloads = OverloadedFunctionType.getOverloads(type);
if (overloads.length > 0 && overloads[0].details.name === '') {
exemptMissingImplementation = true;
}
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) {
implementationFunction = type;
if (overloadedFunctions.length === 1) {
// There should never be a single overload.
this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.singleOverload().format({ name }),
primaryDecl.node.name
);
}
// If the file is not a stub and this is the first overload,
// verify that there is an implementation.
if (this._fileInfo.isStubFile || overloadedFunctions.length === 0) {
return;
}
let implementationFunction: FunctionType | undefined;
if (isOverloadedFunction(type)) {
implementationFunction = OverloadedFunctionType.getImplementation(type);
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) {
implementationFunction = type;
}
if (!implementationFunction) {
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node);
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) {
const classType = this._evaluator.getTypeOfClass(containingClassNode);
if (classType) {
if (ClassType.isProtocolClass(classType.classType)) {
return;
}
if (!implementationFunction) {
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node);
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) {
const classType = this._evaluator.getTypeOfClass(containingClassNode);
if (classType) {
if (ClassType.isProtocolClass(classType.classType)) {
exemptMissingImplementation = true;
} else if (ClassType.supportsAbstractMethods(classType.classType)) {
if (
isOverloadedFunction(type) &&
OverloadedFunctionType.getOverloads(type).every((overload) =>
FunctionType.isAbstractMethod(overload)
)
) {
exemptMissingImplementation = true;
}
}
}
if (ClassType.supportsAbstractMethods(classType.classType)) {
if (
isOverloadedFunction(type) &&
OverloadedFunctionType.getOverloads(type).every((overload) =>
FunctionType.isAbstractMethod(overload)
)
) {
return;
}
// If this is a method within a protocol class, don't require that
// there is an implementation.
if (!exemptMissingImplementation) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportNoOverloadImplementation,
LocMessage.overloadWithoutImplementation().format({
name: primaryDecl.node.name.value,
}),
primaryDecl.node.name
);
}
} else if (isOverloadedFunction(type)) {
// Verify that all overload signatures are assignable to implementation signature.
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
const diag = new DiagnosticAddendum();
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
if (implementationFunction!.details.declaration) {
const diagnostic = this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadImplementationMismatch().format({
name,
index: index + 1,
}) + diag.getString(),
implementationFunction!.details.declaration.node.name
);
if (diagnostic && overload.details.declaration) {
diagnostic.addRelatedInfo(
LocAddendum.overloadSignature(),
overload.details.declaration?.uri ?? primaryDecl.uri,
overload.details.declaration?.range ?? primaryDecl.range
);
}
}
}
});
}
}
}
// If this is a method within a protocol class, don't require that
// there is an implementation.
this._evaluator.addDiagnostic(
DiagnosticRule.reportNoOverloadImplementation,
LocMessage.overloadWithoutImplementation().format({
name: primaryDecl.node.name.value,
}),
primaryDecl.node.name
);
return;
}
if (!isOverloadedFunction(type)) {
return;
}
// Verify that all overload signatures are assignable to implementation signature.
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
const diag = new DiagnosticAddendum();
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
if (implementationFunction!.details.declaration) {
const diagnostic = this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadImplementationMismatch().format({
name,
index: index + 1,
}) + diag.getString(),
implementationFunction!.details.declaration.node.name
);
if (diagnostic && overload.details.declaration) {
diagnostic.addRelatedInfo(
LocAddendum.overloadSignature(),
overload.details.declaration?.uri ?? primaryDecl.uri,
overload.details.declaration?.range ?? primaryDecl.range
);
}
}
}
});
}
private _reportMultipleFinalDeclarations(name: string, symbol: Symbol, scopeType: ScopeType) {

View File

@ -134,6 +134,11 @@ export interface IncompleteType {
isRecursionSentinel?: boolean;
}
interface ReachabilityCacheEntry {
isReachable: boolean | undefined;
isReachableFrom: Map<number, boolean>;
}
// Define a user type guard function for IncompleteType.
export function isIncompleteType(cachedType: CachedType): cachedType is IncompleteType {
return !!(cachedType as IncompleteType).isIncompleteType;
@ -164,6 +169,7 @@ export function getCodeFlowEngine(
speculativeTypeTracker: SpeculativeTypeTracker
): CodeFlowEngine {
const isReachableRecursionSet = new Set<number>();
const reachabilityCache = new Map<number, ReachabilityCacheEntry>();
const callIsNoReturnCache = new Map<number, boolean>();
const isExceptionContextManagerCache = new Map<number, boolean>();
let flowIncompleteGeneration = 1;
@ -1182,11 +1188,29 @@ export function getCodeFlowEngine(
printControlFlowGraph(flowNode, /* reference */ undefined, 'isFlowNodeReachable');
}
function isFlowNodeReachableRecursive(
flowNode: FlowNode,
sourceFlowNode: FlowNode | undefined,
recursionCount = 0
): boolean {
function cacheReachabilityResult(isReachable: boolean): boolean {
// If there is a finally gate set, we will not cache the results
// because this can affect the reachability.
if (closedFinallyGateSet.size > 0) {
return isReachable;
}
let cacheEntry = reachabilityCache.get(flowNode.id);
if (!cacheEntry) {
cacheEntry = { isReachable: undefined, isReachableFrom: new Map<number, boolean>() };
reachabilityCache.set(flowNode.id, cacheEntry);
}
if (!sourceFlowNode) {
cacheEntry.isReachable = isReachable;
} else {
cacheEntry.isReachableFrom.set(sourceFlowNode.id, isReachable);
}
return isReachable;
}
function isFlowNodeReachableRecursive(flowNode: FlowNode, recursionCount = 0): boolean {
// Cut off the recursion at some point to prevent a stack overflow.
const maxFlowNodeReachableRecursionCount = 64;
if (recursionCount > maxFlowNodeReachableRecursionCount) {
@ -1197,21 +1221,36 @@ export function getCodeFlowEngine(
let curFlowNode = flowNode;
while (true) {
// See if we've already cached this result.
const cacheEntry = reachabilityCache.get(flowNode.id);
if (cacheEntry !== undefined && closedFinallyGateSet.size === 0) {
if (!sourceFlowNode) {
if (cacheEntry.isReachable !== undefined) {
return cacheEntry.isReachable;
}
} else {
const isReachableFrom = cacheEntry.isReachableFrom.get(sourceFlowNode.id);
if (isReachableFrom !== undefined) {
return isReachableFrom;
}
}
}
// If we've already visited this node, we can assume
// it wasn't reachable.
if (visitedFlowNodeSet.has(curFlowNode.id)) {
return false;
return cacheReachabilityResult(false);
}
// Note that we've been here before.
visitedFlowNodeSet.add(curFlowNode.id);
if (curFlowNode.flags & FlowFlags.Unreachable) {
return false;
return cacheReachabilityResult(false);
}
if (curFlowNode === sourceFlowNode) {
return true;
return cacheReachabilityResult(true);
}
if (
@ -1271,7 +1310,7 @@ export function getCodeFlowEngine(
}
if (isUnreachable) {
return false;
return cacheReachabilityResult(false);
}
}
}
@ -1287,7 +1326,7 @@ export function getCodeFlowEngine(
// it always raises an exception or otherwise doesn't return,
// so we can assume that the code before this is unreachable.
if (!ignoreNoReturn && isCallNoReturn(evaluator, callFlowNode)) {
return false;
return cacheReachabilityResult(false);
}
curFlowNode = callFlowNode.antecedent;
@ -1304,29 +1343,29 @@ export function getCodeFlowEngine(
isExceptionContextManager(evaluator, expr, contextMgrNode.isAsync)
)
) {
return false;
return cacheReachabilityResult(false);
}
}
const labelNode = curFlowNode as FlowLabel;
for (const antecedent of labelNode.antecedents) {
if (isFlowNodeReachableRecursive(antecedent, sourceFlowNode, recursionCount)) {
return true;
if (isFlowNodeReachableRecursive(antecedent, recursionCount)) {
return cacheReachabilityResult(true);
}
}
return false;
return cacheReachabilityResult(false);
}
if (curFlowNode.flags & FlowFlags.Start) {
// If we hit the start but were looking for a particular source flow
// node, return false. Otherwise, the start is what we're looking for.
return sourceFlowNode ? false : true;
return cacheReachabilityResult(sourceFlowNode ? false : true);
}
if (curFlowNode.flags & FlowFlags.PreFinallyGate) {
const preFinallyFlowNode = curFlowNode as FlowPreFinallyGate;
if (closedFinallyGateSet.has(preFinallyFlowNode.id)) {
return false;
return cacheReachabilityResult(false);
}
curFlowNode = preFinallyFlowNode.antecedent;
@ -1339,10 +1378,8 @@ export function getCodeFlowEngine(
try {
closedFinallyGateSet.add(postFinallyFlowNode.preFinallyGate.id);
return isFlowNodeReachableRecursive(
postFinallyFlowNode.antecedent,
sourceFlowNode,
recursionCount
return cacheReachabilityResult(
isFlowNodeReachableRecursive(postFinallyFlowNode.antecedent, recursionCount)
);
} finally {
if (!wasGateClosed) {
@ -1353,7 +1390,7 @@ export function getCodeFlowEngine(
// We shouldn't get here.
fail('Unexpected flow node flags');
return false;
return cacheReachabilityResult(false);
}
}
@ -1364,7 +1401,7 @@ export function getCodeFlowEngine(
isReachableRecursionSet.add(flowNode.id);
try {
return isFlowNodeReachableRecursive(flowNode, sourceFlowNode);
return isFlowNodeReachableRecursive(flowNode);
} finally {
isReachableRecursionSet.delete(flowNode.id);
}

View File

@ -1020,7 +1020,7 @@ function assignTypeToParamSpec(
// performs this reverse mapping of type arguments and populates the type var
// map for the target type. If the type is not assignable to the expected type,
// it returns false.
export function populateTypeVarContextBasedOnExpectedType(
export function addConstraintsForExpectedType(
evaluator: TypeEvaluator,
type: ClassType,
expectedType: Type,

View File

@ -17,7 +17,7 @@ import { DiagnosticAddendum } from '../common/diagnostic';
import { DiagnosticRule } from '../common/diagnosticRules';
import { LocMessage } from '../localization/localize';
import { ArgumentCategory, ExpressionNode, ParameterCategory } from '../parser/parseNodes';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
import { addConstraintsForExpectedType } from './constraintSolver';
import { applyConstructorTransform, hasConstructorTransform } from './constructorTransform';
import { getTypeVarScopesForNode } from './parseTreeUtils';
import { CallResult, FunctionArgument, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
@ -25,14 +25,17 @@ import {
InferenceContext,
MemberAccessFlags,
UniqueSignatureTracker,
addTypeVarsToListIfUnique,
applySolvedTypeVars,
buildTypeVarContextFromSpecializedClass,
convertToInstance,
convertTypeToParamSpecValue,
doForEachSignature,
doForEachSubtype,
ensureFunctionSignaturesAreUnique,
getTypeVarArgumentsRecursive,
getTypeVarScopeId,
getTypeVarScopeIds,
isTupleClass,
lookUpClassMember,
mapSubtypes,
@ -60,6 +63,7 @@ import {
isInstantiableClass,
isNever,
isOverloadedFunction,
isParamSpec,
isTypeVar,
isUnion,
isUnknown,
@ -286,7 +290,7 @@ function validateNewAndInitMethods(
newMethodReturnType = applySolvedTypeVars(
ClassType.cloneAsInstance(type),
new TypeVarContext(getTypeVarScopeId(type)),
{ unknownIfNotFound: true }
{ unknownIfNotFound: true, tupleClassType: evaluator.getTupleClassType() }
) as ClassType;
}
@ -539,7 +543,7 @@ function validateInitMethod(
typeVarContext.addSolveForScope(getTypeVarScopeId(initMethodType));
if (
populateTypeVarContextBasedOnExpectedType(
!addConstraintsForExpectedType(
evaluator,
ClassType.cloneAsInstance(type),
expectedSubType,
@ -548,54 +552,56 @@ function validateInitMethod(
errorNode.start
)
) {
const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext);
let callResult: CallResult | undefined;
callResult = evaluator.useSpeculativeMode(errorNode, () => {
return evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext.clone(),
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
});
if (!callResult.argumentErrors) {
// Call validateCallArguments again, this time without speculative
// mode, so any errors are reported.
callResult = evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext,
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
if (callResult.isTypeIncomplete) {
isTypeIncomplete = true;
}
if (callResult.argumentErrors) {
argumentErrors = true;
}
if (callResult.overloadsUsedForCall) {
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
}
// Note that we've found an expected type that works.
foundWorkingExpectedType = true;
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
}
return undefined;
}
return undefined;
const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext);
let callResult: CallResult | undefined;
callResult = evaluator.useSpeculativeMode(errorNode, () => {
return evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext.clone(),
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
});
if (callResult.argumentErrors) {
return undefined;
}
// Call validateCallArguments again, this time without speculative
// mode, so any errors are reported.
callResult = evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext,
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
if (callResult.isTypeIncomplete) {
isTypeIncomplete = true;
}
if (callResult.argumentErrors) {
argumentErrors = true;
}
if (callResult.overloadsUsedForCall) {
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
}
// Note that we've found an expected type that works.
foundWorkingExpectedType = true;
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
},
/* sortSubtypes */ true
);
@ -704,7 +710,7 @@ function validateFallbackConstructorCall(
}
if (expectedType) {
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluator,
ClassType.cloneAsInstance(type),
expectedType,
@ -818,6 +824,7 @@ function applyExpectedTypeForConstructor(
const specializedType = applySolvedTypeVars(type, typeVarContext, {
unknownIfNotFound: unsolvedTypeVarsAreUnknown,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType;
return ClassType.cloneAsInstance(specializedType);
}
@ -1086,10 +1093,43 @@ function createFunctionFromInitMethod(
}
const convertedInit = FunctionType.clone(boundInit);
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? selfType ?? objectType;
let returnType = selfType;
if (!returnType) {
returnType = objectType;
// If this is a generic type, self-specialize the class (i.e. fill in
// its own type parameters as type arguments).
if (objectType.details.typeParameters.length > 0 && !objectType.typeArguments) {
const typeVarContext = new TypeVarContext(getTypeVarScopeIds(objectType));
// If a TypeVar is not used in any of the parameter types, it should take
// on its default value (typically Unknown) in the resulting specialized type.
const typeVarsInParams: TypeVarType[] = [];
convertedInit.details.parameters.forEach((param, index) => {
const paramType = FunctionType.getEffectiveParameterType(convertedInit, index);
addTypeVarsToListIfUnique(typeVarsInParams, getTypeVarArgumentsRecursive(paramType));
});
typeVarsInParams.forEach((typeVar) => {
if (isParamSpec(typeVar)) {
typeVarContext.setTypeVarType(typeVar, convertTypeToParamSpecValue(typeVar));
} else {
typeVarContext.setTypeVarType(typeVar, typeVar);
}
});
returnType = applySolvedTypeVars(objectType, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType;
}
}
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? returnType;
if (convertedInit.specializedTypes) {
convertedInit.specializedTypes.returnType = selfType ?? objectType;
convertedInit.specializedTypes.returnType = returnType;
}
if (!convertedInit.details.docString && classType.details.docString) {

View File

@ -821,7 +821,10 @@ function getConverterInputType(
const inputTypeVarContext = new TypeVarContext(typeVar.scopeId);
if (evaluator.assignType(targetFunction, signature, diagAddendum, inputTypeVarContext)) {
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, { unknownIfNotFound: true });
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, {
unknownIfNotFound: true,
tupleClassType: evaluator.getTupleClassType(),
});
acceptedTypes.push(overloadSolution);
}
});

View File

@ -109,7 +109,8 @@ export class ImportResolver {
private _cachedFilesForPath = new Map<string, Uri[]>();
private _cachedDirExistenceForRoot = new Map<string, boolean>();
private _stdlibModules: Set<string> | undefined;
protected cachedParentImportResults: ParentDirectoryCache;
protected readonly cachedParentImportResults: ParentDirectoryCache;
constructor(readonly serviceProvider: ServiceProvider, private _configOptions: ConfigOptions, readonly host: Host) {
this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([]));
@ -172,7 +173,7 @@ export class ImportResolver {
return suggestions;
}
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root);
const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
const origin = sourceFileUri.getDirectory();
let current: Uri | undefined = origin;
@ -533,7 +534,7 @@ export class ImportResolver {
execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor
): ImportResult {
const importName = this.formatImportName(moduleDescriptor);
const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = [];
const importResult = this._resolveImportStrict(
importName,
@ -559,7 +560,7 @@ export class ImportResolver {
}
// Check whether the given file is in the parent directory import resolution cache.
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root);
const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
if (!this.cachedParentImportResults.checkValidPath(this.fileSystem, sourceFileUri, root)) {
return importResult;
}
@ -776,74 +777,12 @@ export class ImportResolver {
protected getNativeModuleName(uri: Uri): string | undefined {
const fileExtension = uri.lastExtension.toLowerCase();
if (this._isNativeModuleFileExtension(fileExtension)) {
if (_isNativeModuleFileExtension(fileExtension)) {
return stripFileExtension(uri.fileName, /* multiDotExtension */ true);
}
return undefined;
}
protected getModuleNameFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): string | undefined {
const moduleNameInfo = this.getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
return undefined;
}
return moduleNameInfo.moduleName;
}
protected getModuleNameInfoFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): ModuleNameInfoFromPath | undefined {
let fileUriWithoutExtension = fileUri.stripExtension();
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
if (this._isNativeModuleFileExtension(fileUri.lastExtension)) {
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
}
if (!fileUriWithoutExtension.startsWith(containerPath)) {
return undefined;
}
// Strip off the '/__init__' if it's present.
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
}
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
if (stripTopContainerDir) {
if (parts.length === 0) {
return undefined;
}
parts.shift();
}
if (parts.length === 0) {
return undefined;
}
// Handle the case where the symbol was resolved to a stubs package
// rather than the real package. We'll strip off the "-stubs" suffix
// in this case.
if (parts[0].endsWith(stubsSuffix)) {
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
}
// Check whether parts contains invalid characters.
const containsInvalidCharacters = parts.some((p) => !this._isIdentifier(p));
return {
moduleName: parts.join('.'),
containsInvalidCharacters,
};
}
// Potentially modifies the ImportResult by removing some or all of the
// implicit import entries. Only the imported symbols should be included.
protected filterImplicitImports(
@ -880,22 +819,6 @@ export class ImportResolver {
return newImportResult;
}
protected formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
}
protected getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
if (!this._isDefaultWorkspace(executionRoot)) {
return executionRoot!;
}
return sourceFileUri.getDirectory();
}
private _isDefaultWorkspace(uri: Uri | undefined) {
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
}
private _resolveImportStrict(
importName: string,
sourceFileUri: Uri,
@ -1119,7 +1042,7 @@ export class ImportResolver {
);
if (stdLibTypeshedPath) {
moduleName = this.getModuleNameFromPath(stdLibTypeshedPath, fileUri);
moduleName = getModuleNameFromPath(stdLibTypeshedPath, fileUri);
if (moduleName) {
const moduleDescriptor: ImportedModuleDescriptor = {
leadingDots: 0,
@ -1149,7 +1072,7 @@ export class ImportResolver {
// Look for it in the root directory of the execution environment.
if (execEnv.root) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(execEnv.root, fileUri);
const candidateModuleNameInfo = _getModuleNameInfoFromPath(execEnv.root, fileUri);
if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1163,7 +1086,7 @@ export class ImportResolver {
}
for (const extraPath of execEnv.extraPaths) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(extraPath, fileUri);
const candidateModuleNameInfo = _getModuleNameInfoFromPath(extraPath, fileUri);
if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1182,7 +1105,7 @@ export class ImportResolver {
// Check for a typings file.
if (this._configOptions.stubPath) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri);
const candidateModuleNameInfo = _getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri);
if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1209,7 +1132,7 @@ export class ImportResolver {
);
if (thirdPartyTypeshedPath) {
const candidateModuleName = this.getModuleNameFromPath(
const candidateModuleName = getModuleNameFromPath(
thirdPartyTypeshedPath,
fileUri,
/* stripTopContainerDir */ true
@ -1226,7 +1149,7 @@ export class ImportResolver {
const thirdPartyTypeshedPathEx = this.getTypeshedPathEx(execEnv, importFailureInfo);
if (thirdPartyTypeshedPathEx) {
const candidateModuleName = this.getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri);
const candidateModuleName = getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri);
// Does this candidate look better than the previous best module name?
// We'll always try to use the shortest version.
@ -1241,7 +1164,7 @@ export class ImportResolver {
const pythonSearchPaths = this.getPythonSearchPaths(importFailureInfo);
for (const searchPath of pythonSearchPaths) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(searchPath, fileUri);
const candidateModuleNameInfo = _getModuleNameInfoFromPath(searchPath, fileUri);
if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1260,7 +1183,7 @@ export class ImportResolver {
}
if (detectPyTyped && importType === ImportType.ThirdParty) {
const root = this.getParentImportResolutionRoot(fileUri, execEnv.root);
const root = getParentImportResolutionRoot(fileUri, execEnv.root);
// Go up directories one by one looking for a py.typed file.
let current: Uri | undefined = fileUri.getDirectory();
@ -1552,7 +1475,7 @@ export class ImportResolver {
moduleDescriptor: ImportedModuleDescriptor,
allowPyi: boolean
): ImportResult | undefined {
const importName = this.formatImportName(moduleDescriptor);
const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = [];
// Check for a local stub file using stubPath.
@ -1828,16 +1751,6 @@ export class ImportResolver {
return bestImportSoFar;
}
private _isIdentifier(value: string) {
for (let i = 0; i < value.length; i++) {
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
return false;
}
}
return true;
}
private _findTypeshedPath(
execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor,
@ -2588,7 +2501,7 @@ export class ImportResolver {
// Make sure we don't use parent folder resolution when checking whether the given name is resolvable.
let importResult: ImportResult | undefined;
if (strictOnly) {
const importName = this.formatImportName(moduleDescriptor);
const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = [];
importResult = this._resolveImportStrict(
@ -2653,7 +2566,7 @@ export class ImportResolver {
if (fileExt === '.py' || fileExt === '.pyi') {
strippedFileName = stripFileExtension(filePath.fileName);
} else if (
this._isNativeModuleFileExtension(fileExt) &&
_isNativeModuleFileExtension(fileExt) &&
!this.fileExistsCached(filePath.packageUri) &&
!this.fileExistsCached(filePath.packageStubUri)
) {
@ -2770,15 +2683,10 @@ export class ImportResolver {
const fileExtension = fileUri.lastExtension.toLowerCase();
const withoutExtension = stripFileExtension(fileUri.fileName, /* multiDotExtension */ true);
return (
this._isNativeModuleFileExtension(fileExtension) &&
equateStringsCaseInsensitive(moduleName, withoutExtension)
_isNativeModuleFileExtension(fileExtension) && equateStringsCaseInsensitive(moduleName, withoutExtension)
);
}
private _isNativeModuleFileExtension(fileExtension: string): boolean {
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
}
private _tryWalkUp(current: Uri | undefined): Uri | undefined {
if (!current || current.isEmpty() || current.isRoot()) {
return undefined;
@ -2796,7 +2704,7 @@ export class ImportResolver {
return (
current &&
!current.isEmpty() &&
(current.isChild(root) || (current.equals(root) && this._isDefaultWorkspace(execEnv.root)))
(current.isChild(root) || (current.equals(root) && _isDefaultWorkspace(execEnv.root)))
);
}
}
@ -2806,3 +2714,95 @@ export type ImportResolverFactory = (
options: ConfigOptions,
host: Host
) => ImportResolver;
export function formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
}
export function getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
if (!_isDefaultWorkspace(executionRoot)) {
return executionRoot!;
}
return sourceFileUri.getDirectory();
}
export function getModuleNameFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): string | undefined {
const moduleNameInfo = _getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
return undefined;
}
return moduleNameInfo.moduleName;
}
function _getModuleNameInfoFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): ModuleNameInfoFromPath | undefined {
let fileUriWithoutExtension = fileUri.stripExtension();
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
if (_isNativeModuleFileExtension(fileUri.lastExtension)) {
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
}
if (!fileUriWithoutExtension.startsWith(containerPath)) {
return undefined;
}
// Strip off the '/__init__' if it's present.
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
}
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
if (stripTopContainerDir) {
if (parts.length === 0) {
return undefined;
}
parts.shift();
}
if (parts.length === 0) {
return undefined;
}
// Handle the case where the symbol was resolved to a stubs package
// rather than the real package. We'll strip off the "-stubs" suffix
// in this case.
if (parts[0].endsWith(stubsSuffix)) {
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
}
// Check whether parts contains invalid characters.
const containsInvalidCharacters = parts.some((p) => !_isIdentifier(p));
return {
moduleName: parts.join('.'),
containsInvalidCharacters,
};
}
function _isNativeModuleFileExtension(fileExtension: string): boolean {
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
}
function _isDefaultWorkspace(uri: Uri | undefined) {
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
}
function _isIdentifier(value: string) {
for (let i = 0; i < value.length; i++) {
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
return false;
}
}
return true;
}

View File

@ -703,7 +703,7 @@ export function getTypeOfBinaryOperation(
}
}
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// Exempt "|" because it might be a union operation involving unknowns.
if (node.operator !== OperatorType.BitwiseOr) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.binaryOperationNotAllowed(), node);
@ -950,7 +950,7 @@ export function getTypeOfUnaryOperation(
flags: EvaluatorFlags,
inferenceContext: InferenceContext | undefined
): TypeResult {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.unaryOperationNotAllowed(), node);
return { type: UnknownType.create() };
}
@ -1087,7 +1087,7 @@ export function getTypeOfTernaryOperation(
): TypeResult {
const fileInfo = getFileInfo(node);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.ternaryNotAllowed(), node);
return { type: UnknownType.create() };
}

View File

@ -29,7 +29,7 @@ import {
PatternValueNode,
} from '../parser/parseNodes';
import { CodeFlowReferenceExpressionNode } from './codeFlowTypes';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
import { addConstraintsForExpectedType } from './constraintSolver';
import { getTypeVarScopesForNode, isMatchingExpression } from './parseTreeUtils';
import { EvaluatorFlags, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
import {
@ -685,7 +685,7 @@ function narrowTypeBasedOnClassPattern(
// specialize it with Unknown type arguments.
if (isClass(exprType) && !exprType.typeAliasInfo) {
exprType = ClassType.cloneRemoveTypePromotions(exprType);
exprType = specializeWithUnknownTypeArgs(exprType);
exprType = specializeWithUnknownTypeArgs(exprType, evaluator.getTupleClassType());
}
// Are there any positional arguments? If so, try to get the mappings for
@ -921,7 +921,7 @@ function narrowTypeBasedOnClassPattern(
const matchTypeInstance = ClassType.cloneAsInstance(unspecializedMatchType);
if (
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluator,
matchTypeInstance,
subjectSubtypeExpanded,
@ -932,6 +932,7 @@ function narrowTypeBasedOnClassPattern(
) {
resultType = applySolvedTypeVars(matchTypeInstance, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType;
}
}
@ -1454,7 +1455,7 @@ function getSequencePatternInfo(
if (sequenceType && isInstantiableClass(sequenceType)) {
const sequenceTypeVarContext = new TypeVarContext(getTypeVarScopeId(sequenceType));
if (
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluator,
ClassType.cloneAsInstance(sequenceType),
subtype,

View File

@ -102,7 +102,7 @@ export function assignClassToProtocol(
// If the caller has provided a destination type var context,
// we can't use the cached value unless the dest has no type
// parameters to solve.
if (!destTypeVarContext || destType.details.typeParameters.length === 0) {
if (!destTypeVarContext || !requiresSpecialization(destType)) {
return true;
}
}

View File

@ -643,7 +643,7 @@ export class AnalyzerService {
const configs = this._getExtendedConfigurations(configFilePath ?? pyprojectFilePath);
if (configs) {
if (configs && configs.length > 0) {
for (const config of configs) {
configOptions.initializeFromJson(
config.configFileJsonObj,

View File

@ -97,7 +97,7 @@ import {
isCodeFlowSupportedForReference,
wildcardImportReferenceKey,
} from './codeFlowTypes';
import { assignTypeToTypeVar, populateTypeVarContextBasedOnExpectedType, updateTypeVarType } from './constraintSolver';
import { addConstraintsForExpectedType, assignTypeToTypeVar, updateTypeVarType } from './constraintSolver';
import {
createFunctionFromConstructor,
getBoundInitMethod,
@ -1266,7 +1266,7 @@ export function createTypeEvaluator(
}
case ParseNodeType.AssignmentExpression: {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.walrusNotAllowed(), node);
}
@ -1294,7 +1294,7 @@ export function createTypeEvaluator(
typeResult = getTypeOfExpression(
node.typeAnnotation,
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple |
@ -1337,7 +1337,7 @@ export function createTypeEvaluator(
// If this is a PEP 695 type alias, remove the special form so the type
// printer prints it as its aliased type rather than TypeAliasType.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if (typeResult.type.specialForm && ClassType.isBuiltIn(typeResult.type.specialForm, 'TypeAliasType')) {
typeResult.type = TypeBase.cloneAsSpecialForm(typeResult.type, undefined);
}
@ -1404,7 +1404,7 @@ export function createTypeEvaluator(
}
function getTypeOfAwaitOperator(node: AwaitNode, flags: EvaluatorFlags, inferenceContext?: InferenceContext) {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.awaitNotAllowed(), node);
return { type: UnknownType.create() };
}
@ -1484,7 +1484,7 @@ export function createTypeEvaluator(
ClassType.isBuiltIn(iterType, 'tuple')
) {
typeResult = { type: ClassType.cloneForUnpacked(iterType) };
} else if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
} else if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.unpackInAnnotation(), node, node.starToken);
typeResult = { type: UnknownType.create() };
} else {
@ -1726,7 +1726,7 @@ export function createTypeEvaluator(
let evaluatorFlags =
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.ConvertEllipsisToAny |
EvaluatorFlags.EvaluateStringLiteralAsType;
@ -4411,7 +4411,7 @@ export function createTypeEvaluator(
node,
name,
!allowForwardReferences,
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
);
if (!symbolWithScope) {
@ -4424,7 +4424,7 @@ export function createTypeEvaluator(
alias,
alias.value,
!allowForwardReferences,
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
);
}
}
@ -4517,7 +4517,7 @@ export function createTypeEvaluator(
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
targetSymbolId: symbol.id,
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
});
if (codeFlowTypeResult.type) {
@ -4532,7 +4532,7 @@ export function createTypeEvaluator(
// Detect, report, and fill in missing type arguments if appropriate.
type = reportMissingTypeArguments(node, type, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// Verify that the name does not refer to a (non type alias) variable.
if (effectiveTypeInfo.includesVariableDecl && !type.typeAliasInfo) {
let isAllowedTypeForVariable = isTypeVar(type) || isTypeAliasPlaceholder(type);
@ -4593,7 +4593,7 @@ export function createTypeEvaluator(
type = convertTypeVarToRuntimeInstance(node, type, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
reportUseOfTypeCheckOnly(type, node);
}
@ -4926,7 +4926,10 @@ export function createTypeEvaluator(
let defaultType: Type;
if (param.details.isDefaultExplicit || param.details.isParamSpec) {
defaultType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
defaultType = applySolvedTypeVars(param, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
} else if (param.details.isVariadic && tupleClass && isInstantiableClass(tupleClass)) {
defaultType = makeTupleObject(
[{ type: UnknownType.create(), isUnbounded: true }],
@ -4951,7 +4954,10 @@ export function createTypeEvaluator(
}
type = TypeBase.cloneForTypeAlias(
applySolvedTypeVars(type, typeVarContext, { unknownIfNotFound: true }),
applySolvedTypeVars(type, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
}),
type.typeAliasInfo.name,
type.typeAliasInfo.fullName,
type.typeAliasInfo.moduleName,
@ -5088,7 +5094,7 @@ export function createTypeEvaluator(
let leftExprFlags = EvaluatorFlags.MemberAccessBaseDefaults;
leftExprFlags |=
flags &
(EvaluatorFlags.ExpectingTypeAnnotation |
(EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.VariableTypeAnnotation |
EvaluatorFlags.AllowForwardReferences |
EvaluatorFlags.NotParsedByInterpreter |
@ -5155,7 +5161,7 @@ export function createTypeEvaluator(
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
targetSymbolId: indeterminateSymbolId,
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
});
if (codeFlowTypeResult.type) {
@ -5288,7 +5294,7 @@ export function createTypeEvaluator(
}
// It's illegal to reference a member from a type variable.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if (!isIncomplete) {
addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
@ -5632,7 +5638,7 @@ export function createTypeEvaluator(
type = isFunctionRule ? AnyType.create() : UnknownType.create();
}
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
reportUseOfTypeCheckOnly(type, node.memberName);
}
@ -6515,7 +6521,7 @@ export function createTypeEvaluator(
type: indexTypeResult.type,
isIncomplete: !!baseTypeResult.isIncomplete || !!indexTypeResult.isIncomplete,
},
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0,
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
});
if (codeFlowTypeResult.type) {
@ -6855,7 +6861,10 @@ export function createTypeEvaluator(
if (index < typeArgs.length) {
typeArgType = convertToInstance(typeArgs[index].type);
} else if (param.details.isDefaultExplicit) {
typeArgType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
typeArgType = applySolvedTypeVars(param, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
} else {
typeArgType = UnknownType.create();
}
@ -7018,7 +7027,7 @@ export function createTypeEvaluator(
getIndexAccessMagicMethodName(usage)
);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// If the class doesn't derive from Generic, a type argument should not be allowed.
addDiagnostic(
DiagnosticRule.reportInvalidTypeArguments,
@ -7059,7 +7068,7 @@ export function createTypeEvaluator(
// Special-case InitVar, used in dataclasses.
const typeArgs = getTypeArgs(node, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if ((flags & EvaluatorFlags.VariableTypeAnnotation) === 0) {
addError(LocMessage.initVarNotAllowed(), node.baseExpression);
}
@ -7743,7 +7752,7 @@ export function createTypeEvaluator(
signatureTracker: UniqueSignatureTracker | undefined
): TypeResult {
if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.parent?.nodeType !== ParseNodeType.Argument
) {
// This is allowed inside of an index trailer, specifically
@ -7769,7 +7778,7 @@ export function createTypeEvaluator(
}
flags &= ~(
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType
);
@ -7872,7 +7881,7 @@ export function createTypeEvaluator(
} else {
const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClass));
if (
!populateTypeVarContextBasedOnExpectedType(
!addConstraintsForExpectedType(
evaluatorInterface,
ClassType.cloneAsInstance(tupleClass),
inferenceContext.expectedType,
@ -8001,7 +8010,7 @@ export function createTypeEvaluator(
// allowed, and it's a common mistake, so we want to emit a diagnostic
// that guides the user to the right solution.
if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.leftExpression.nodeType === ParseNodeType.Name &&
node.leftExpression.value === 'type'
) {
@ -8129,7 +8138,7 @@ export function createTypeEvaluator(
}
}
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.typeAnnotationCall(), node);
typeResult = { type: UnknownType.create() };
@ -11316,7 +11325,7 @@ export function createTypeEvaluator(
if (isClassInstance(effectiveExpectedType) && !isTypeSame(effectiveReturnType, effectiveExpectedType)) {
const tempTypeVarContext = new TypeVarContext(getTypeVarScopeId(effectiveReturnType));
if (
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluatorInterface,
effectiveReturnType,
effectiveExpectedType,
@ -11333,6 +11342,7 @@ export function createTypeEvaluator(
effectiveExpectedType = applySolvedTypeVars(genericReturnType, tempTypeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
effectiveFlags |= AssignTypeFlags.SkipPopulateUnknownExpectedType;
@ -11633,6 +11643,7 @@ export function createTypeEvaluator(
let specializedReturnType = applySolvedTypeVars(returnType, typeVarContext, {
unknownIfNotFound,
tupleClassType: getTupleClassType(),
unknownExemptTypeVars: getUnknownExemptTypeVarsForReturnType(type, returnType),
eliminateUnsolvedInUnions,
applyInScopePlaceholders: true,
@ -12067,7 +12078,7 @@ export function createTypeEvaluator(
EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowFinal |
EvaluatorFlags.DoNotSpecialize
: EvaluatorFlags.DoNotSpecialize | EvaluatorFlags.DisallowFinal;
: EvaluatorFlags.DisallowFinal | EvaluatorFlags.DoNotSpecialize;
const exprTypeResult = getTypeOfExpression(
argParam.argument.valueExpression,
flags,
@ -12516,6 +12527,7 @@ export function createTypeEvaluator(
const concreteDefaultType = makeTopLevelTypeVarsConcrete(
applySolvedTypeVars(typeVar.details.defaultType, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
})
);
@ -13006,14 +13018,12 @@ export function createTypeEvaluator(
);
}
let classFlags = baseClass.details.flags & ~(ClassTypeFlags.BuiltInClass | ClassTypeFlags.SpecialBuiltIn);
classFlags |= ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass;
const classType = ClassType.createInstantiable(
className,
ParseTreeUtils.getClassFullName(errorNode, fileInfo.moduleName, className),
fileInfo.moduleName,
fileInfo.fileUri,
classFlags,
ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass,
ParseTreeUtils.getTypeSourceId(errorNode),
/* declaredMetaclass */ undefined,
baseClass.details.effectiveMetaclass
@ -13255,7 +13265,7 @@ export function createTypeEvaluator(
inferenceContext: InferenceContext | undefined
): TypeResult {
if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.parent?.nodeType !== ParseNodeType.Argument
) {
const diag = new DiagnosticAddendum();
@ -13397,7 +13407,7 @@ export function createTypeEvaluator(
const dictTypeVarContext = new TypeVarContext(getTypeVarScopeId(builtInDict));
if (
!populateTypeVarContextBasedOnExpectedType(
!addConstraintsForExpectedType(
evaluatorInterface,
builtInDict,
inferenceContext.expectedType,
@ -13575,7 +13585,7 @@ export function createTypeEvaluator(
const keyFlags =
flags &
~(
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType
);
@ -13837,7 +13847,7 @@ export function createTypeEvaluator(
inferenceContext: InferenceContext | undefined
): TypeResult {
if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 &&
(flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.nodeType === ParseNodeType.List &&
node.parent?.nodeType !== ParseNodeType.Argument
) {
@ -13847,7 +13857,7 @@ export function createTypeEvaluator(
}
flags &= ~(
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType
);
@ -14016,7 +14026,7 @@ export function createTypeEvaluator(
const typeVarContext = new TypeVarContext(getTypeVarScopeId(expectedClassType));
if (
!populateTypeVarContextBasedOnExpectedType(
!addConstraintsForExpectedType(
evaluatorInterface,
ClassType.cloneAsInstance(expectedClassType),
inferenceContext.expectedType,
@ -14921,7 +14931,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.optionalExtraArgs(), errorNode);
return UnknownType.create();
}
@ -15139,7 +15149,7 @@ export function createTypeEvaluator(
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if (!typeArgs) {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.typeGuardArgCount(), errorNode);
}
@ -15184,7 +15194,7 @@ export function createTypeEvaluator(
const enclosingClassTypeResult = enclosingClass ? getTypeOfClass(enclosingClass) : undefined;
if (!enclosingClassTypeResult) {
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingInstantiableType)) !== 0) {
if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.ExpectingInstantiableType)) !== 0) {
addDiagnostic(DiagnosticRule.reportGeneralTypeIssues, LocMessage.selfTypeContext(), errorNode);
}
@ -15246,7 +15256,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
return { type: classType };
}
@ -15330,7 +15340,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) {
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
return classType;
}
@ -15654,7 +15664,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) {
if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.unionTypeArgCount(), errorNode);
return NeverType.createNever();
}
@ -15741,7 +15751,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or
// we're in some other context.
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.DisallowNakedGeneric)) !== 0) {
if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.DisallowNakedGeneric)) !== 0) {
addError(LocMessage.genericTypeArgMissing(), errorNode);
}
@ -16113,19 +16123,8 @@ export function createTypeEvaluator(
flags |= EvaluatorFlags.DoNotSpecialize;
}
if (isDeclaredTypeAlias(node.leftExpression)) {
flags |=
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowClassVar;
flags &= ~EvaluatorFlags.DoNotSpecialize;
}
// Is this type already cached?
let rightHandType = readTypeCache(node.rightExpression, flags);
let rightHandType = readTypeCache(node.rightExpression, /* flags */ undefined);
let isIncomplete = false;
let expectedTypeDiagAddendum: DiagnosticAddendum | undefined;
@ -16138,76 +16137,118 @@ export function createTypeEvaluator(
writeTypeCache(node.rightExpression, { type: rightHandType }, EvaluatorFlags.None);
}
}
}
if (!rightHandType) {
// Determine whether there is a declared type.
const declaredType = getDeclaredTypeForExpression(node.leftExpression, {
method: 'set',
});
if (!rightHandType) {
// Determine whether there is a declared type.
const declaredType = getDeclaredTypeForExpression(node.leftExpression, { method: 'set' });
let typeAliasNameNode: NameNode | undefined;
let isSpeculativeTypeAlias = false;
let typeAliasNameNode: NameNode | undefined;
let isSpeculativeTypeAlias = false;
let typeAliasPlaceholder: TypeVarType | undefined;
if (isDeclaredTypeAlias(node.leftExpression)) {
typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode;
if (isDeclaredTypeAlias(node.leftExpression)) {
flags =
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowClassVar;
if (!isLegalTypeAliasExpressionForm(node.rightExpression)) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.typeAliasIllegalExpressionForm(),
node.rightExpression
);
}
} else if (node.leftExpression.nodeType === ParseNodeType.Name) {
const symbolWithScope = lookUpSymbolRecursive(
node.leftExpression,
node.leftExpression.value,
/* honorCodeFlow */ false
typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode;
if (!isLegalTypeAliasExpressionForm(node.rightExpression)) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.typeAliasIllegalExpressionForm(),
node.rightExpression
);
if (symbolWithScope) {
const decls = symbolWithScope.symbol.getDeclarations();
if (decls.length === 1 && isPossibleTypeAliasOrTypedDict(decls[0])) {
}
} else if (node.leftExpression.nodeType === ParseNodeType.Name) {
const symbolWithScope = lookUpSymbolRecursive(
node.leftExpression,
node.leftExpression.value,
/* honorCodeFlow */ false
);
if (symbolWithScope) {
const decls = symbolWithScope.symbol.getDeclarations();
if (decls.length === 1) {
if (isPossibleTypeAliasDeclaration(decls[0])) {
typeAliasNameNode = node.leftExpression;
isSpeculativeTypeAlias = true;
} else if (isPossibleTypeDictFactoryCall(decls[0])) {
// Handle calls to TypedDict factory functions like type
// aliases to support recursive field type definitions.
typeAliasNameNode = node.leftExpression;
}
}
}
}
// Synthesize a type variable that represents the type alias while we're
// evaluating it. This allows us to handle recursive definitions.
let typeAliasTypeVar: TypeVarType | undefined;
if (typeAliasNameNode) {
typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${typeAliasNameNode.value}`);
typeAliasTypeVar.details.isSynthesized = true;
typeAliasTypeVar.details.recursiveTypeAliasName = typeAliasNameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(typeAliasNameNode);
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = false;
typeAliasTypeVar.scopeId = scopeId;
if (typeAliasNameNode) {
typeAliasPlaceholder = synthesizeTypeAliasPlaceholder(typeAliasNameNode);
// Write the type back to the type cache. It will be replaced below.
writeTypeCache(node, { type: typeAliasTypeVar }, /* flags */ undefined);
writeTypeCache(node.leftExpression, { type: typeAliasTypeVar }, /* flags */ undefined);
if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) {
writeTypeCache(
node.leftExpression.valueExpression,
{ type: typeAliasTypeVar },
/* flags */ undefined
);
}
writeTypeCache(node, { type: typeAliasPlaceholder }, /* flags */ undefined);
writeTypeCache(node.leftExpression, { type: typeAliasPlaceholder }, /* flags */ undefined);
if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) {
writeTypeCache(
node.leftExpression.valueExpression,
{ type: typeAliasPlaceholder },
/* flags */ undefined
);
}
}
const srcTypeResult = getTypeOfExpression(
node.rightExpression,
flags,
makeInferenceContext(declaredType)
const srcTypeResult = getTypeOfExpression(node.rightExpression, flags, makeInferenceContext(declaredType));
rightHandType = srcTypeResult.type;
expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum;
if (srcTypeResult.isIncomplete) {
isIncomplete = true;
}
// If this was a speculative type alias, it becomes a real type alias
// only if the evaluated type is an instantiable type.
if (isSpeculativeTypeAlias && !isLegalImplicitTypeAliasType(rightHandType)) {
typeAliasNameNode = undefined;
}
if (typeAliasNameNode) {
assert(typeAliasPlaceholder !== undefined);
// If this is a type alias, record its name based on the assignment target.
rightHandType = transformTypeForTypeAlias(
rightHandType,
typeAliasNameNode,
typeAliasNameNode,
/* isPep695Syntax */ false,
/* isPep695TypeVarType */ false
);
let srcType = srcTypeResult.type;
expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum;
if (srcTypeResult.isIncomplete) {
isIncomplete = true;
if (isTypeAliasRecursive(typeAliasPlaceholder, rightHandType)) {
addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
LocMessage.typeAliasIsRecursiveDirect().format({
name: typeAliasNameNode.value,
}),
node.rightExpression
);
rightHandType = UnknownType.create();
}
// Set the resulting type to the boundType of the original type alias
// to support recursive type aliases.
typeAliasPlaceholder.details.boundType = rightHandType;
// Record the type parameters within the recursive type alias so it
// can be specialized.
typeAliasPlaceholder.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
} else {
// If the RHS is a constant boolean expression, assign it a literal type.
const constExprValue = evaluateStaticBoolExpression(
node.rightExpression,
@ -16218,46 +16259,7 @@ export function createTypeEvaluator(
if (constExprValue !== undefined) {
const boolType = getBuiltInObject(node, 'bool');
if (isClassInstance(boolType)) {
srcType = ClassType.cloneWithLiteral(boolType, constExprValue);
}
}
// If this is an enum, transform the type as required.
rightHandType = srcType;
if (typeAliasNameNode) {
// If this was a speculative type alias, it becomes a real type alias
// only if the evaluated type is an instantiable type.
if (!isSpeculativeTypeAlias || isLegalImplicitTypeAliasType(rightHandType)) {
// If this is a type alias, record its name based on the assignment target.
rightHandType = transformTypeForTypeAlias(
rightHandType,
typeAliasNameNode,
typeAliasNameNode,
/* isPep695Syntax */ false,
/* isPep695TypeVarType */ false
);
assert(typeAliasTypeVar !== undefined);
if (isTypeAliasRecursive(typeAliasTypeVar, rightHandType)) {
addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
LocMessage.typeAliasIsRecursiveDirect().format({
name: typeAliasNameNode.value,
}),
node.rightExpression
);
rightHandType = UnknownType.create();
}
// Set the resulting type to the boundType of the original type alias
// to support recursive type aliases.
typeAliasTypeVar.details.boundType = rightHandType;
// Record the type parameters within the recursive type alias so it
// can be specialized.
typeAliasTypeVar.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
rightHandType = ClassType.cloneWithLiteral(boolType, constExprValue);
}
}
}
@ -16275,39 +16277,18 @@ export function createTypeEvaluator(
writeTypeCache(node, { type: rightHandType, isIncomplete }, EvaluatorFlags.None);
}
function isPossibleTypeAliasOrTypedDict(decl: Declaration) {
if (isPossibleTypeAliasDeclaration(decl)) {
return true;
}
// Synthesize a TypeVar that acts as a placeholder for a type alias. This allows
// the type alias definition to refer to itself.
function synthesizeTypeAliasPlaceholder(nameNode: NameNode): TypeVarType {
const placeholder = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`);
placeholder.details.isSynthesized = true;
placeholder.details.recursiveTypeAliasName = nameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
placeholder.details.recursiveTypeAliasScopeId = scopeId;
placeholder.details.recursiveTypeAliasIsPep695Syntax = false;
placeholder.scopeId = scopeId;
if (
decl.type === DeclarationType.Variable &&
decl.node.parent &&
decl.node.parent.nodeType === ParseNodeType.Assignment &&
decl.node.parent.rightExpression?.nodeType === ParseNodeType.Call
) {
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
// Use a simple heuristic to determine whether this is potentially
// a call to the TypedDict call. This avoids the expensive (and potentially
// recursive) call to getTypeOfExpression in cases where it's not needed.
if (
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
callLeftNode.memberName.value === 'TypedDict' &&
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
) {
// See if this is a call to TypedDict. We want to support
// recursive type references in a TypedDict call.
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
return true;
}
}
}
return false;
return placeholder;
}
// Evaluates the type of a type alias (i.e. "type") statement. This code
@ -16346,15 +16327,9 @@ export function createTypeEvaluator(
// Synthesize a type variable that represents the type alias while we're
// evaluating it. This allows us to handle recursive definitions.
const typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`);
typeAliasTypeVar.details.isSynthesized = true;
typeAliasTypeVar.details.recursiveTypeAliasName = nameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = isPep695Syntax;
typeAliasTypeVar.scopeId = scopeId;
const typeAliasTypeVar = synthesizeTypeAliasPlaceholder(nameNode);
// Write the type to the type cache. It will be replaced below.
// Write the type to the type cache to support recursive type alias definitions.
writeTypeCache(nameNode, { type: typeAliasTypeVar }, /* flags */ undefined);
// Set a partial type to handle recursive (self-referential) type aliases.
@ -18340,6 +18315,7 @@ export function createTypeEvaluator(
// Replace any unsolved TypeVars with Unknown (including all function-scoped TypeVars).
inferredParamType = applySolvedTypeVars(inferredParamType, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
}
@ -18764,6 +18740,11 @@ export function createTypeEvaluator(
return false;
}
const statements = functionDecl.node.suite.statements;
if (statements.some((statement) => statement.nodeType !== ParseNodeType.StatementList)) {
return false;
}
for (const raiseStatement of functionDecl.raiseStatements) {
if (!raiseStatement.typeExpression || raiseStatement.valueExpression) {
return false;
@ -19494,6 +19475,16 @@ export function createTypeEvaluator(
continue;
}
// Forward-declared type annotation expressions need to be be evaluated
// in context so they have the appropriate flags set. Most of these cases
// will have been detected above when calling getParentAnnotationNode,
// but TypeAlias expressions are not handled there.
const stringEnclosure = ParseTreeUtils.getParentNodeOfType(parent, ParseNodeType.StringList);
if (stringEnclosure) {
nodeToEvaluate = stringEnclosure as StringListNode;
continue;
}
// The left expression of a call or member access expression is not generally contextual.
if (parent.nodeType === ParseNodeType.Call || parent.nodeType === ParseNodeType.MemberAccess) {
if (nodeToEvaluate === parent.leftExpression) {
@ -19520,15 +19511,7 @@ export function createTypeEvaluator(
// The base expression of an index expression is not contextual.
if (nodeToEvaluate === parent.baseExpression) {
flags = EvaluatorFlags.IndexBaseDefaults;
break;
}
} else if (parent.nodeType === ParseNodeType.StringList && nodeToEvaluate === parent.typeAnnotation) {
// Forward-declared type annotation expressions need to be be evaluated
// in context so they have the appropriate flags set. Most of these cases
// will have been detected above when calling getParentAnnotationNode,
// but TypeAlias expressions are not handled there.
nodeToEvaluate = parent;
continue;
}
if (!isExpressionNode(parent)) {
@ -19873,7 +19856,19 @@ export function createTypeEvaluator(
// don't bother doing additional work.
let cacheEntry = readTypeCacheEntry(subnode);
if (cacheEntry && !cacheEntry.typeResult.isIncomplete) {
return cacheEntry.typeResult;
const typeResult = cacheEntry.typeResult;
// Handle the special case where a function or class is partially evaluated.
// Indicate that these are not complete types.
if (isFunction(typeResult.type) && FunctionType.isPartiallyEvaluated(typeResult.type)) {
return { ...typeResult, isIncomplete: true };
}
if (isClass(typeResult.type) && ClassType.isPartiallyEvaluated(typeResult.type)) {
return { ...typeResult, isIncomplete: true };
}
return typeResult;
}
callback();
@ -20024,7 +20019,7 @@ export function createTypeEvaluator(
case 'Protocol': {
if (
(flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0
) {
addError(LocMessage.protocolNotAllowed(), errorNode);
@ -20049,7 +20044,7 @@ export function createTypeEvaluator(
case 'TypedDict': {
if (
(flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0
) {
addError(LocMessage.typedDictNotAllowed(), errorNode);
@ -20060,7 +20055,7 @@ export function createTypeEvaluator(
case 'Literal': {
if (
(flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !==
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0
) {
addError(LocMessage.literalNotAllowed(), errorNode);
@ -20375,7 +20370,10 @@ export function createTypeEvaluator(
return;
}
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, { unknownIfNotFound: true });
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
typeArgTypes.push(solvedDefaultType);
if (isParamSpec(typeParam)) {
typeVarContext.setTypeVarType(typeParam, convertTypeToParamSpecValue(solvedDefaultType));
@ -20510,7 +20508,7 @@ export function createTypeEvaluator(
}
if (options?.allowRequired) {
flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeAnnotation;
flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeExpression;
}
if (options?.allowUnpackedTuple) {
@ -20524,7 +20522,7 @@ export function createTypeEvaluator(
}
if (options?.enforceTypeAnnotationRules) {
flags |= EvaluatorFlags.ExpectingTypeAnnotation;
flags |= EvaluatorFlags.ExpectingTypeExpression;
}
if (options?.disallowProtocolAndTypedDict) {
@ -22347,7 +22345,7 @@ export function createTypeEvaluator(
getEffectiveTypeOfSymbol(member.symbol),
member.classType,
/* selfClass */ undefined,
typeClass ?? UnknownType.create()
typeClass && isInstantiableClass(typeClass) ? typeClass : undefined
);
}
return UnknownType.create();
@ -25944,7 +25942,7 @@ export function createTypeEvaluator(
!assignedType.tupleTypeArguments
) {
const typeVarContext = new TypeVarContext(getTypeVarScopeId(assignedType));
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluatorInterface,
ClassType.cloneForSpecialization(
assignedType,
@ -27118,6 +27116,43 @@ export function createTypeEvaluator(
return isLegal;
}
function isPossibleTypeAliasOrTypedDict(decl: Declaration) {
return isPossibleTypeAliasDeclaration(decl) || isPossibleTypeDictFactoryCall(decl);
}
function isPossibleTypeDictFactoryCall(decl: Declaration) {
if (
decl.type !== DeclarationType.Variable ||
!decl.node.parent ||
decl.node.parent.nodeType !== ParseNodeType.Assignment ||
decl.node.parent.rightExpression?.nodeType !== ParseNodeType.Call
) {
return false;
}
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
// Use a simple heuristic to determine whether this is potentially
// a call to the TypedDict call. This avoids the expensive (and potentially
// recursive) call to getTypeOfExpression in cases where it's not needed.
if (
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
callLeftNode.memberName.value === 'TypedDict' &&
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
) {
// See if this is a call to TypedDict. We want to support
// recursive type references in a TypedDict call.
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
return true;
}
}
return false;
}
function printObjectTypeForClass(type: ClassType): string {
return TypePrinter.printObjectTypeForClass(
type,

View File

@ -86,10 +86,9 @@ export const enum EvaluatorFlags {
// than an instance (object)
ExpectingInstantiableType = 1 << 7,
// A type annotation restricts the types of expressions that are
// allowed. If this flag is set, illegal type expressions are
// flagged as errors.
ExpectingTypeAnnotation = 1 << 8,
// A type expression imposes grammatical and semantic limits on an
// expression. If this flag is set, illegal type expressions are
ExpectingTypeExpression = 1 << 8,
// Suppress the reportMissingTypeArgument diagnostic in this context.
AllowMissingTypeArgs = 1 << 9,

View File

@ -22,7 +22,7 @@ import {
} from '../parser/parseNodes';
import { KeywordType, OperatorType } from '../parser/tokenizerTypes';
import { getFileInfo } from './analyzerNodeInfo';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver';
import { addConstraintsForExpectedType } from './constraintSolver';
import { Declaration, DeclarationType } from './declaration';
import { transformTypeForEnumMember } from './enums';
import * as ParseTreeUtils from './parseTreeUtils';
@ -638,7 +638,7 @@ export function getTypeNarrowingCallback(
);
const arg1Type = arg1TypeResult.type;
const classTypeList = getIsInstanceClassTypes(arg1Type);
const classTypeList = getIsInstanceClassTypes(evaluator, arg1Type);
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
if (classTypeList) {
@ -1146,7 +1146,10 @@ function narrowTypeForIsEllipsis(evaluator: TypeEvaluator, type: Type, isPositiv
// that accepts a single class, and a more complex form that accepts a tuple
// of classes (including arbitrarily-nested tuples). This method determines
// which form and returns a list of classes or undefined.
function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | FunctionType)[] | undefined {
function getIsInstanceClassTypes(
evaluator: TypeEvaluator,
argType: Type
): (ClassType | TypeVarType | FunctionType)[] | undefined {
let foundNonClassType = false;
const classTypeList: (ClassType | TypeVarType | FunctionType)[] = [];
@ -1155,7 +1158,7 @@ function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | Func
const addClassTypesToList = (types: Type[]) => {
types.forEach((subtype) => {
if (isClass(subtype)) {
subtype = specializeWithUnknownTypeArgs(subtype);
subtype = specializeWithUnknownTypeArgs(subtype, evaluator.getTupleClassType());
if (isInstantiableClass(subtype) && ClassType.isBuiltIn(subtype, 'Callable')) {
subtype = convertToInstantiable(getUnknownTypeForCallable());
@ -1359,7 +1362,8 @@ function narrowTypeForIsInstanceInternal(
concreteFilterType,
/* typeArguments */ undefined,
/* isTypeArgumentExplicit */ false
)
),
evaluator.getTupleClassType()
);
}
@ -1451,7 +1455,7 @@ function narrowTypeForIsInstanceInternal(
);
if (
populateTypeVarContextBasedOnExpectedType(
addConstraintsForExpectedType(
evaluator,
unspecializedFilterType,
concreteVarType,
@ -1463,7 +1467,11 @@ function narrowTypeForIsInstanceInternal(
specializedFilterType = applySolvedTypeVars(
unspecializedFilterType,
typeVarContext,
{ unknownIfNotFound: true, useUnknownOverDefault: true }
{
unknownIfNotFound: true,
useUnknownOverDefault: true,
tupleClassType: evaluator.getTupleClassType(),
}
) as ClassType;
}
}
@ -1764,7 +1772,11 @@ function narrowTypeForIsInstanceInternal(
const filteredType = evaluator.mapSubtypesExpandTypeVars(
expandedTypes,
/* options */ undefined,
{
expandCallback: (type) => {
return evaluator.expandPromotionTypes(errorNode, type);
},
},
(subtype, unexpandedSubtype) => {
// If we fail to filter anything in the negative case, we need to decide
// whether to retain the original TypeVar or replace it with its specialized
@ -2459,33 +2471,69 @@ function narrowTypeForClassComparison(
isPositiveTest: boolean
): Type {
return mapSubtypes(referenceType, (subtype) => {
const concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
let concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
if (isPositiveTest) {
if (isNoneInstance(concreteSubtype)) {
return undefined;
return isNoneTypeClass(classType) ? classType : undefined;
}
if (isClassInstance(concreteSubtype) && TypeBase.isInstance(subtype)) {
if (ClassType.isBuiltIn(concreteSubtype, 'type')) {
return classType;
if (
isClassInstance(concreteSubtype) &&
TypeBase.isInstance(subtype) &&
ClassType.isBuiltIn(concreteSubtype, 'type')
) {
concreteSubtype =
concreteSubtype.typeArguments && concreteSubtype.typeArguments.length > 0
? convertToInstantiable(concreteSubtype.typeArguments[0])
: UnknownType.create();
}
if (isAnyOrUnknown(concreteSubtype)) {
return classType;
}
if (isClass(concreteSubtype)) {
if (TypeBase.isInstance(concreteSubtype)) {
return ClassType.isBuiltIn(concreteSubtype, 'object') ? classType : undefined;
}
return undefined;
}
const isSuperType = isIsinstanceFilterSuperclass(
evaluator,
subtype,
concreteSubtype,
classType,
classType,
/* isInstanceCheck */ false
);
if (isInstantiableClass(concreteSubtype) && ClassType.isFinal(concreteSubtype)) {
if (
!ClassType.isSameGenericClass(concreteSubtype, classType) &&
!isIsinstanceFilterSuperclass(
if (!classType.includeSubclasses) {
// Handle the case where the LHS and RHS operands are specific
// classes, as opposed to types that represent classes and their
// subclasses.
if (!concreteSubtype.includeSubclasses) {
return ClassType.isSameGenericClass(concreteSubtype, classType) ? classType : undefined;
}
const isSubType = isIsinstanceFilterSubclass(
evaluator,
subtype,
concreteSubtype,
classType,
classType,
/* isInstanceCheck */ false
)
) {
);
if (isSuperType) {
return classType;
}
if (isSubType) {
return addConditionToType(classType, getTypeCondition(concreteSubtype));
}
return undefined;
}
if (ClassType.isFinal(concreteSubtype) && !isSuperType) {
return undefined;
}
}

View File

@ -245,12 +245,13 @@ export const enum AssignTypeFlags {
}
export interface ApplyTypeVarOptions {
typeClassType?: ClassType;
tupleClassType?: ClassType;
unknownIfNotFound?: boolean;
useUnknownOverDefault?: boolean;
unknownExemptTypeVars?: TypeVarType[];
useNarrowBoundOnly?: boolean;
eliminateUnsolvedInUnions?: boolean;
typeClassType?: Type;
applyInScopePlaceholders?: boolean;
}
@ -1073,7 +1074,7 @@ export function specializeWithDefaultTypeArgs(type: ClassType): ClassType {
// Specializes the class with "Unknown" type args (or the equivalent for ParamSpecs
// or TypeVarTuples).
export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
export function specializeWithUnknownTypeArgs(type: ClassType, tupleClassType?: ClassType): ClassType {
if (type.details.typeParameters.length === 0) {
return type;
}
@ -1091,18 +1092,22 @@ export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
return ClassType.cloneForSpecialization(
type,
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param)),
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param, tupleClassType)),
/* isTypeArgumentExplicit */ false,
/* includeSubclasses */ type.includeSubclasses
);
}
// Returns "Unknown" for simple TypeVars or the equivalent for a ParamSpec.
export function getUnknownTypeForTypeVar(typeVar: TypeVarType): Type {
export function getUnknownTypeForTypeVar(typeVar: TypeVarType, tupleClassType?: ClassType): Type {
if (typeVar.details.isParamSpec) {
return getUnknownTypeForParamSpec();
}
if (typeVar.details.isVariadic && tupleClassType) {
return getUnknownTypeForVariadicTypeVar(tupleClassType);
}
return UnknownType.create();
}
@ -1118,6 +1123,19 @@ export function getUnknownTypeForParamSpec(): FunctionType {
return newFunction;
}
export function getUnknownTypeForVariadicTypeVar(tupleClassType: ClassType): Type {
assert(isInstantiableClass(tupleClassType) && ClassType.isBuiltIn(tupleClassType, 'tuple'));
return ClassType.cloneAsInstance(
specializeTupleClass(
tupleClassType,
[{ type: UnknownType.create(), isUnbounded: true }],
/* isTypeArgumentExplicit */ true,
/* isUnpackedTuple */ true
)
);
}
// Returns the equivalent of "Callable[..., Unknown]".
export function getUnknownTypeForCallable(): FunctionType {
const newFunction = FunctionType.createSynthesizedInstance('', FunctionTypeFlags.GradualCallableForm);
@ -1374,7 +1392,7 @@ export function partiallySpecializeType(
type: Type,
contextClassType: ClassType,
selfClass?: ClassType | TypeVarType,
typeClassType?: Type
typeClassType?: ClassType
): Type {
// If the context class is not specialized (or doesn't need specialization),
// then there's no need to do any more work.
@ -3115,7 +3133,7 @@ export function computeMroLinearization(classType: ClassType): boolean {
// The first class in the MRO is the class itself.
const typeVarContext = buildTypeVarContextFromSpecializedClass(classType);
let specializedClassType = applySolvedTypeVars(classType, typeVarContext);
if (!isClass(specializedClassType) && !isAny(specializedClassType) && !isUnknown(specializedClassType)) {
if (!isClass(specializedClassType) && !isAnyOrUnknown(specializedClassType)) {
specializedClassType = UnknownType.create();
}
@ -3159,11 +3177,16 @@ export function computeMroLinearization(classType: ClassType): boolean {
if (!isInstantiableClass(classList[0])) {
foundValidHead = true;
assert(isClass(classList[0]) || isAnyOrUnknown(classList[0]));
classType.details.mro.push(classList[0]);
let head = classList[0];
if (!isClass(head) && !isAnyOrUnknown(head)) {
head = UnknownType.create();
}
classType.details.mro.push(head);
classList.shift();
break;
} else if (!isInTail(classList[0], classListsToMerge)) {
}
if (!isInTail(classList[0], classListsToMerge)) {
foundValidHead = true;
classType.details.mro.push(classList[0]);
filterClass(classList[0], classListsToMerge);
@ -3186,8 +3209,11 @@ export function computeMroLinearization(classType: ClassType): boolean {
// Handle the situation by pull the head off the first empty list.
// This allows us to make forward progress.
if (!isInstantiableClass(nonEmptyList[0])) {
assert(isClass(nonEmptyList[0]) || isAnyOrUnknown(nonEmptyList[0]));
classType.details.mro.push(nonEmptyList[0]);
let head = nonEmptyList[0];
if (!isClass(head) && !isAnyOrUnknown(head)) {
head = UnknownType.create();
}
classType.details.mro.push(head);
nonEmptyList.shift();
} else {
classType.details.mro.push(nonEmptyList[0]);
@ -3290,6 +3316,8 @@ export function convertTypeToParamSpecValue(type: Type): FunctionType {
newFunction.details.typeVarScopeId = newFunction.details.higherOrderTypeVarScopeIds.pop();
}
newFunction.details.constructorTypeVarScopeId = type.details.constructorTypeVarScopeId;
return newFunction;
}
@ -3328,6 +3356,7 @@ export function convertParamSpecValueToType(type: FunctionType): Type {
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.typeVarScopeId);
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.higherOrderTypeVarScopeIds);
functionType.details.constructorTypeVarScopeId = withoutParamSpec.details.constructorTypeVarScopeId;
withoutParamSpec.details.parameters.forEach((entry, index) => {
FunctionType.addParameter(functionType, {
@ -4122,7 +4151,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
if (this._options.unknownIfNotFound) {
return this._options.useUnknownOverDefault
? specializeWithUnknownTypeArgs(subtype)
? specializeWithUnknownTypeArgs(subtype, this._options.tupleClassType)
: specializeWithDefaultTypeArgs(subtype);
}
}
@ -4160,7 +4189,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
return this._solveDefaultType(typeVar.details.defaultType, recursionCount);
}
return UnknownType.create();
return getUnknownTypeForTypeVar(typeVar, this._options.tupleClassType);
}
}

View File

@ -825,9 +825,7 @@ export namespace ClassType {
newClassType.includeSubclasses = true;
}
newClassType.tupleTypeArguments = tupleTypeArguments?.map((t) =>
isNever(t.type) ? { type: UnknownType.create(), isUnbounded: t.isUnbounded, isOptional: t.isOptional } : t
);
newClassType.tupleTypeArguments = tupleTypeArguments ? [...tupleTypeArguments] : undefined;
if (isEmptyContainer !== undefined) {
newClassType.isEmptyContainer = isEmptyContainer;
@ -1766,6 +1764,7 @@ export namespace FunctionType {
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.typeVarScopeId);
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.higherOrderTypeVarScopeIds);
newFunction.details.constructorTypeVarScopeId = paramSpecValue.details.constructorTypeVarScopeId;
if (!newFunction.details.methodClass && paramSpecValue.details.methodClass) {
newFunction.details.methodClass = paramSpecValue.details.methodClass;

View File

@ -24,11 +24,13 @@ export class BackgroundAnalysis extends BackgroundAnalysisBase {
constructor(serviceProvider: ServiceProvider) {
super(serviceProvider.console());
const index = ++BackgroundAnalysis._workerIndex;
const initialData: InitializationData = {
rootUri: getRootUri(serviceProvider)?.toString() ?? '',
serviceId: index.toString(),
cancellationFolderName: getCancellationFolderName(),
runner: undefined,
workerIndex: ++BackgroundAnalysis._workerIndex,
workerIndex: index,
};
// this will load this same file in BG thread and start listener

View File

@ -310,7 +310,14 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
const console = this.getConsole();
this.logTracker = new LogTracker(console, `BG(${threadId})`);
this._program = new Program(this.importResolver, this._configOptions, serviceProvider, this.logTracker);
this._program = new Program(
this.importResolver,
this._configOptions,
serviceProvider,
this.logTracker,
undefined,
data.serviceId
);
}
get program(): Program {

View File

@ -251,10 +251,10 @@ export function getBackgroundWaiter<T>(port: MessagePort, deserializer: (v: any)
export interface InitializationData {
rootUri: string;
serviceId: string;
workerIndex: number;
cancellationFolderName: string | undefined;
runner: string | undefined;
title?: string;
workerIndex: number;
}
export interface RequestResponse {

View File

@ -6,7 +6,7 @@
* Helper functions relating to collections and arrays.
*/
import { compareValues, Comparison, equateValues, isArray } from './core';
import { compareValues, Comparison, equateValues, isArray, MapLike } from './core';
export const emptyArray: never[] = [] as never[];
export type EqualityComparer<T> = (a: T, b: T) => boolean;
@ -318,7 +318,7 @@ export function getNestedProperty(object: any, property: string) {
return value;
}
export function getOrAdd<K, V>(map: Map<K, V>, key: K, newValueFactory: () => V): V {
export function getOrAdd<K, V>(map: MapLike<K, V>, key: K, newValueFactory: () => V): V {
const value = map.get(key);
if (value !== undefined) {
return value;

View File

@ -102,8 +102,11 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
* The `in` and `for-in` operators can *not* be safely used,
* since `Object.prototype` may be modified by outside code.
*/
export interface MapLike<T> {
[index: string]: T;
export interface MapLike<K, V> {
readonly [Symbol.toStringTag]: string;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
}
/**
@ -112,7 +115,7 @@ export interface MapLike<T> {
* @param map A map-like.
* @param key A property key.
*/
export function hasProperty(map: MapLike<any>, key: string): boolean {
export function hasProperty(map: { [index: string]: any }, key: string): boolean {
return hasOwnProperty.call(map, key);
}

View File

@ -70,6 +70,7 @@ export function expandPathVariables(path: string, rootPath: Uri, workspaces: Wor
const ws_regexp = RegExp(`\\$\\{workspaceFolder:${escapedWorkspaceName}\\}`, 'g');
path = path.replace(ws_regexp, workspace.rootUri.getPath());
}
if (process.env.HOME !== undefined) {
replace(/\$\{env:HOME\}/g, process.env.HOME || '');
}

View File

@ -46,6 +46,7 @@ import { printLiteralValue } from '../analyzer/typePrinter';
import {
ClassType,
combineTypes,
EnumLiteral,
FunctionType,
isClass,
isClassInstance,
@ -127,6 +128,7 @@ import {
import { DocumentSymbolCollector } from './documentSymbolCollector';
import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils';
import '../common/serviceProviderExtensions';
import { transformTypeForEnumMember } from '../analyzer/enums';
namespace Keywords {
const base: string[] = [
@ -705,13 +707,7 @@ export class CompletionProvider {
// Handle enum members specially. Enum members normally look like
// variables, but the are declared using assignment expressions
// within an enum class.
if (
primaryDecl.type === DeclarationType.Variable &&
detail.boundObjectOrClass &&
isInstantiableClass(detail.boundObjectOrClass) &&
ClassType.isEnumClass(detail.boundObjectOrClass) &&
primaryDecl.node.parent?.nodeType === ParseNodeType.Assignment
) {
if (this._isEnumMember(detail.boundObjectOrClass, name)) {
itemKind = CompletionItemKind.EnumMember;
}
@ -757,19 +753,16 @@ export class CompletionProvider {
if (isClass(subtype)) {
const instance = TypeBase.isInstance(subtype);
if (ClassType.isEnumClass(subtype) && instance) {
// We don't add members for instances of enum members, but do add members of `enum.Enum` itself.
// ex) 'MyEnum.member.' <= here
const enumType = subtype.details.baseClasses.find(
(t) => isClass(t) && ClassType.isBuiltIn(t, 'Enum')
) as ClassType | undefined;
if (!enumType) {
return;
}
getMembersForClass(subtype, symbolTable, instance);
getMembersForClass(enumType, symbolTable, /* instance */ true);
} else {
getMembersForClass(subtype, symbolTable, instance);
if (ClassType.isEnumClass(subtype) && instance) {
// Don't show enum member out of another enum member
// ex) Enum.Member. <= shouldn't show `Member` again.
for (const name of symbolTable.keys()) {
if (this._isEnumMember(subtype, name)) {
symbolTable.delete(name);
}
}
}
} else if (isModule(subtype)) {
getMembersForModule(subtype, symbolTable);
@ -3143,6 +3136,21 @@ export class CompletionProvider {
// before doing more expensive type evaluation.
return decl.isMethod && decl.node.decorators.length > 0;
}
private _isEnumMember(containingType: ClassType | undefined, name: string) {
if (!containingType || !ClassType.isEnumClass(containingType)) {
return false;
}
const symbolType = transformTypeForEnumMember(this.evaluator, containingType, name);
return (
symbolType &&
isClassInstance(symbolType) &&
ClassType.isSameGenericClass(symbolType, containingType) &&
symbolType.literalValue instanceof EnumLiteral
);
}
}
export class CompletionMap {

View File

@ -118,7 +118,7 @@ export function setLocaleOverride(locale: string) {
localeOverride = locale.toLowerCase();
}
export function getLocaleFromEnv() {
export function getLocaleFromEnv(): string {
if (localeOverride) {
return localeOverride;
}
@ -130,7 +130,7 @@ export function getLocaleFromEnv() {
const vscodeConfigString = env?.VSCODE_NLS_CONFIG;
if (vscodeConfigString) {
try {
return JSON.parse(vscodeConfigString).locale;
return JSON.parse(vscodeConfigString).locale || defaultLocale;
} catch {
// Fall through
}
@ -142,7 +142,7 @@ export function getLocaleFromEnv() {
// This string may contain a local followed by an encoding (e.g. "en-us.UTF-8").
const localeStringSplit = localeString.split('.');
if (localeStringSplit.length > 0 && localeStringSplit[0]) {
return localeStringSplit[0];
return localeStringSplit[0] || defaultLocale;
}
}
} catch {

View File

@ -158,8 +158,8 @@
"enumMemberDelete": "Člen výčtu {name} se nedá odstranit.",
"enumMemberSet": "Člen výčtu {name} se nedá přiřadit.",
"enumMemberTypeAnnotation": "Poznámky typu nejsou pro členy výčtu povolené",
"exceptionGroupIncompatible": "Syntaxe skupiny výjimek (except*) vyžaduje Python 3.11 nebo novější",
"exceptionGroupTypeIncorrect": "Typ výjimky v kromě* se nedá odvodit z BaseGroupException.",
"exceptionGroupIncompatible": "Syntaxe skupiny výjimek (\"except*\") vyžaduje Python 3.11 nebo novější",
"exceptionGroupTypeIncorrect": "Typ výjimky v except* se nedá odvodit z BaseGroupException.",
"exceptionTypeIncorrect": "„{type}“ se neodvozuje od BaseException",
"exceptionTypeNotClass": "{type} není platná třída výjimky",
"exceptionTypeNotInstantiable": "Konstruktor pro výjimku typu {type} vyžaduje jeden nebo více argumentů",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumenty typu nejsou u třídy Protocol povoleny při použití syntaxe parametru typu",
"protocolIllegal": "Použití protokolu vyžaduje Python 3.7 nebo novější",
"protocolNotAllowed": "„Protocol“ nejde v tomto kontextu použít.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "Argument typu pro „protokol“ musí být parametr typu",
"protocolUnsafeOverlap": "Třída se nebezpečně překrývá s názvem „{name}“ a může vytvořit shodu při spuštění.",
"protocolVarianceContravariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kontravariantní",
"protocolVarianceCovariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kovariantní",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "Das Enumerationselement \"{name}\" kann nicht zugewiesen werden.",
"enumMemberTypeAnnotation": "Typanmerkungen sind für Enumerationsmember nicht zulässig",
"exceptionGroupIncompatible": "Die Ausnahmegruppensyntax (\"except*\") erfordert Python 3.11 oder höher.",
"exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.",
"exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.",
"exceptionTypeIncorrect": "\"{type}\" ist nicht von BaseException abgeleitet.",
"exceptionTypeNotClass": "\"{type}\" ist keine gültige Ausnahmeklasse.",
"exceptionTypeNotInstantiable": "Der Konstruktor für den Ausnahmetyp \"{type}\" erfordert mindestens ein Argument.",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Typargumente sind mit der Protokollklasse nicht zulässig, wenn die Typparametersyntax verwendet wird.",
"protocolIllegal": "Die Verwendung von \"Protocol\" erfordert Python 3.7 oder höher.",
"protocolNotAllowed": "\"Protocol\" kann in diesem Kontext nicht verwendet werden.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "Das Typargument für „Protocol“ muss ein Typparameter sein.",
"protocolUnsafeOverlap": "Die Klasse überlappt unsicher mit „{name}“ und könnte zur Laufzeit eine Übereinstimmung erzeugen.",
"protocolVarianceContravariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"contravariant\" sein.",
"protocolVarianceCovariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"covariant\" sein.",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "No se permiten argumentos de tipo con la clase Protocol cuando se usa la sintaxis de parámetro de tipo",
"protocolIllegal": "El uso de \"Protocolo\" requiere Python 3.7 o posterior.",
"protocolNotAllowed": "\"Protocolo\" no puede utilizarse en este contexto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "El argumento de tipo para \"Protocol\" debe ser un parámetro de tipo",
"protocolUnsafeOverlap": "La clase se superpone \"{name}\" de forma no segura y podría producir una coincidencia en tiempo de ejecución",
"protocolVarianceContravariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser contravariante.",
"protocolVarianceCovariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Les arguments de type ne sont pas autorisés avec la classe Protocol lors de l'utilisation de la syntaxe des paramètres de type",
"protocolIllegal": "Lutilisation de « Protocole » nécessite Python 3.7 ou une version plus récente",
"protocolNotAllowed": "\"Protocole\" ne peut pas être utilisé dans ce contexte",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "Largument de type pour « Protocol » doit être un paramètre de type",
"protocolUnsafeOverlap": "La classe chevauche « {name} » de manière non sécurisée et peut produire une correspondance au moment de lexécution",
"protocolVarianceContravariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être contravariante",
"protocolVarianceCovariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Gli argomenti tipo non sono consentiti con la classe Protocollo quando si usa la sintassi dei parametri tipo",
"protocolIllegal": "L'uso del \"protocollo\" richiede Python 3.7 o versione successiva",
"protocolNotAllowed": "\"Protocol\" non può essere usato in questo contesto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "L'argomento di tipo per \"Protocol\" deve essere un parametro di tipo",
"protocolUnsafeOverlap": "La classe si sovrappone a \"{name}\" in modo non sicuro e può produrre una corrispondenza in fase di esecuzione",
"protocolVarianceContravariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere controvariante",
"protocolVarianceCovariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "型パラメーター構文を使用する場合、Protocol クラスでは型引数を使用できません",
"protocolIllegal": "\"Protocol\" を使用するには Python 3.7 以降が必要です",
"protocolNotAllowed": "\"Protocol\" はこのコンテキストでは使用できません",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "\"Protocol\" の型引数は型パラメーターである必要があります",
"protocolUnsafeOverlap": "クラスが安全でない方法で \"{name}\" と重複しており、実行時に一致する可能性があります",
"protocolVarianceContravariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は反変である必要があります",
"protocolVarianceCovariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は共変である必要があります",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "열거형 멤버 \"{name}\"을(를) 할당할 수 없음",
"enumMemberTypeAnnotation": "열거형 멤버에는 형식 주석을 사용할 수 없습니다.",
"exceptionGroupIncompatible": "예외 그룹 구문(\"except*\")에는 Python 3.11 이상이 필요합니다.",
"exceptionGroupTypeIncorrect": "exception*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.",
"exceptionGroupTypeIncorrect": "except*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.",
"exceptionTypeIncorrect": "{type}’은 BaseException에서 파생되지 않습니다.",
"exceptionTypeNotClass": "\"{type}\"은(는) 올바른 예외 클래스가 아닙니다.",
"exceptionTypeNotInstantiable": "예외 형식 \"{type}\"에 대한 생성자에는 하나 이상의 인수가 필요합니다.",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "형식 매개 변수 구문을 사용할 때는 Protocol 클래스에 형식 인수가 허용되지 않습니다.",
"protocolIllegal": "\"프로토콜\"을 사용하려면 Python 3.7 이상이 필요합니다.",
"protocolNotAllowed": "이 컨텍스트에서는 \"Protocol\"을 사용할 수 없습니다.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "\"Protocol\"의 형식 인수는 형식 매개 변수여야 합니다.",
"protocolUnsafeOverlap": "클래스가 \"{name}\"과(와) 안전하지 않게 겹치며 런타임에 일치 항목을 생성할 수 있습니다.",
"protocolVarianceContravariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 반공변이어야 합니다.",
"protocolVarianceCovariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 공변이어야 합니다",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumenty typu są niedozwolone w przypadku klasy protokołu, gdy jest używana składnia parametru typu",
"protocolIllegal": "Użycie elementu „Protocol” wymaga języka Python w wersji 3.7 lub nowszej",
"protocolNotAllowed": "„Protokół” nie może być używany w tym kontekście",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "Argument typu dla elementy „Protocol” musi być parametrem typu",
"protocolUnsafeOverlap": "Klasa nakłada się niebezpiecznie na element „{name}” i może utworzyć dopasowanie w czasie wykonywania",
"protocolVarianceContravariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kontrawariantna",
"protocolVarianceCovariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kowariantna",

View File

@ -158,8 +158,8 @@
"enumMemberDelete": "O membro enumerado \"{name}\" não pode ser excluído",
"enumMemberSet": "O membro enumerado \"{name}\" não pode ser atribuído",
"enumMemberTypeAnnotation": "Anotações de tipo não são permitidas para membros de enumeração",
"exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"exceto*\") requer o Python 3.11 ou mais recente",
"exceptionGroupTypeIncorrect": "O tipo de exceção em exceto* não pode derivar de BaseGroupException",
"exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"except*\") requer o Python 3.11 ou mais recente",
"exceptionGroupTypeIncorrect": "O tipo de exceção em except* não pode derivar de BaseGroupException",
"exceptionTypeIncorrect": "\"{type}\" não deriva de BaseException",
"exceptionTypeNotClass": "\"{type}\" não é uma classe de exceção válida",
"exceptionTypeNotInstantiable": "O construtor para o tipo de exceção \"{type}\" requer um ou mais argumentos",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumentos de tipo não são permitidos com a classe Protocol ao usar a sintaxe de parâmetro de tipo",
"protocolIllegal": "O uso de \"Protocol\" requer o Python 3.7 ou mais recente",
"protocolNotAllowed": "\"Protocol\" não pode ser usado nesse contexto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "O argumento de tipo para o \"Protocolo\" deve ser um parâmetro de tipo",
"protocolUnsafeOverlap": "A classe se sobrepõe a \"{name}\" de forma não segura e pode produzir uma correspondência em runtime",
"protocolVarianceContravariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser contravariante",
"protocolVarianceCovariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Аргументы типа не допускаются с классом протокола при использовании синтаксиса параметра типа",
"protocolIllegal": "Ключевое слово \"Protocol\" можно использовать в Python версии не ниже 3.7",
"protocolNotAllowed": "Невозможно использовать \"Protocol\" в этом контексте",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "Аргумент типа для параметра \"Protocol\" должен быть параметром типа",
"protocolUnsafeOverlap": "Класс небезопасно перекрывает \"{name}\" и может вызвать совпадение во время выполнения",
"protocolVarianceContravariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть контравариантной.",
"protocolVarianceCovariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть ковариантной",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "Sabit liste üyesi \"{name}\" atanamıyor",
"enumMemberTypeAnnotation": "Sabit listesi üyeleri için tür ek açıklamalarına izin verilmiyor",
"exceptionGroupIncompatible": "Özel durum grubu söz dizimi (\"except*\") için Python 3.11 veya daha yeni bir sürümü gerekiyor",
"exceptionGroupTypeIncorrect": "Except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor",
"exceptionGroupTypeIncorrect": "except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor",
"exceptionTypeIncorrect": "\"{type}\", BaseException türevi değil",
"exceptionTypeNotClass": "\"{type}\" geçerli bir özel durum sınıfı değil",
"exceptionTypeNotInstantiable": "\"{type}\" özel durum türü oluşturucusu bir veya daha fazla bağımsız değişken gerektiriyor",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Tür parametresi söz dizimi kullanılırken, tür bağımsız değişkenlerinin Protokol sınıfıyla kullanılmasına izin verilmez",
"protocolIllegal": "\"Protocol\" kullanımı için Python 3.7 veya daha yeni bir sürümü gerekiyor",
"protocolNotAllowed": "\"Protokol\" bu bağlamda kullanılamaz",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "“Protokol” için tür bağımsız değişkeni bir tür parametresi olmalıdır",
"protocolUnsafeOverlap": "Sınıf, \"{name}\" ile güvenli olmayan bir şekilde çakışıyor ve çalışma zamanında bir eşleşme üretebilir",
"protocolVarianceContravariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni, değişken karşıtı olmalıdır",
"protocolVarianceCovariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni birlikte değişen olmalıdır",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "使用类型参数语法时,协议类不允许使用类型参数",
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更高版本",
"protocolNotAllowed": "\"Protocol\" 不能用于此上下文",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "“协议”的类型参数必须是类型参数",
"protocolUnsafeOverlap": "类与“{name}”不安全地重叠,并且可能在运行时生成匹配项",
"protocolVarianceContravariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为逆变",
"protocolVarianceCovariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为协变",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "使用型別參數語法時,通訊協定類別不允許使用型別引數",
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更新版本",
"protocolNotAllowed": "\"Protocol\" 不能用在此內容中",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter",
"protocolTypeArgMustBeTypeParam": "“Protocol” 的型別引數必須是型別參數",
"protocolUnsafeOverlap": "類別以不安全方式重疊 \"{name}\",且可能會在運行時間產生相符專案",
"protocolVarianceContravariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為逆變數",
"protocolVarianceCovariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為共變數",

View File

@ -1302,3 +1302,90 @@ test('import from completion for namespace package', async () => {
},
});
});
test('members off enum member', async () => {
const code = `
// @filename: test.py
//// from enum import Enum
//// class Planet(Enum):
//// MERCURY = (3.303e+23, 2.4397e6)
//// EARTH = (5.976e+24, 6.37814e6)
////
//// def __init__(self, mass, radius):
//// self.mass = mass # in kilograms
//// self.radius = radius # in meters
////
//// @property
//// def surface_gravity(self):
//// # universal gravitational constant (m3 kg-1 s-2)
//// G = 6.67300E-11
//// return G * self.mass / (self.radius * self.radius)
////
//// Planet.EARTH.[|/*marker*/|]
`;
const state = parseAndGetTestState(code).state;
await state.verifyCompletion('excluded', 'markdown', {
['marker']: {
completions: [
{
label: 'MERCURY',
kind: CompletionItemKind.EnumMember,
},
{
label: 'EARTH',
kind: CompletionItemKind.EnumMember,
},
],
},
});
await state.verifyCompletion('included', 'markdown', {
['marker']: {
completions: [
{
label: 'mass',
kind: CompletionItemKind.Variable,
},
{
label: 'radius',
kind: CompletionItemKind.Variable,
},
{
label: 'surface_gravity',
kind: CompletionItemKind.Property,
},
],
},
});
});
test('enum with regular base type', async () => {
const code = `
// @filename: test.py
//// from enum import Enum
//// from datetime import timedelta
//// class Period(timedelta, Enum):
//// Today = -1
////
//// Period.Today.[|/*marker*/|]
`;
const state = parseAndGetTestState(code).state;
await state.verifyCompletion('included', 'markdown', {
['marker']: {
completions: [
{
label: 'days',
kind: CompletionItemKind.Property,
},
{
label: 'seconds',
kind: CompletionItemKind.Property,
},
],
},
});
});

View File

@ -192,4 +192,47 @@ describe(`Basic language server tests`, () => {
assert.equal(diagnostic.diagnostics[3].code, 'reportUnusedImport');
assert.equal(diagnostic.diagnostics[5].code, 'reportUnusedImport');
});
test('Diagnostic severity overrides test', async () => {
const code = `
// @filename: test.py
//// def test([|/*marker*/x|]): ...
////
// @filename: pyproject.toml
////
`;
const settings = [
{
item: {
scopeUri: `file://${normalizeSlashes(DEFAULT_WORKSPACE_ROOT, '/')}`,
section: 'python.analysis',
},
value: {
diagnosticSeverityOverrides: {
reportUnknownParameterType: 'warning',
},
},
},
];
const info = await runLanguageServer(
DEFAULT_WORKSPACE_ROOT,
code,
/* callInitialize */ true,
settings,
undefined,
/* supportsBackgroundThread */ true
);
// get the file containing the marker that also contains our task list comments
await openFile(info, 'marker');
// Wait for the diagnostics to publish
const diagnostics = await waitForDiagnostics(info);
const diagnostic = diagnostics.find((d) => d.uri.includes('test.py'));
assert(diagnostic);
// Make sure the error has a special rule
assert.equal(diagnostic.diagnostics[0].code, 'reportUnknownParameterType');
});
});

View File

@ -7,8 +7,7 @@ from abc import ABC, abstractmethod
class A(ABC):
@staticmethod
@abstractmethod
def method1() -> None:
...
def method1() -> None: ...
@staticmethod
@abstractmethod
@ -66,8 +65,7 @@ def func1(a: type[A]):
a.method3()
class C(A):
...
class C(A): ...
# This should generate an error.

View File

@ -18,8 +18,7 @@ class Foo(ABC):
@overload
@abstractmethod
def func1(self, a: str) -> str:
...
def func1(self, a: str) -> str: ...
# This should generate an error because this overload is
# missing an abstractmethod overload.
@ -27,8 +26,7 @@ class Foo(ABC):
raise NotImplementedError()
@overload
def func2(self, a: str) -> str:
...
def func2(self, a: str) -> str: ...
@overload
@abstractmethod

View File

@ -23,5 +23,4 @@ class Bar(Foo):
@final
# This should generate an error because Foo.foo, Bar.bar, and Bar.bar1
# are abstract.
class Baz(Bar):
...
class Baz(Bar): ...

View File

@ -9,8 +9,7 @@ from typing import NamedTuple
class ClassA(ABC):
@property
@abstractmethod
def myproperty(self) -> str:
...
def myproperty(self) -> str: ...
MixinB = NamedTuple("MixinB", [("myproperty", str)])

View File

@ -10,9 +10,7 @@ v1: Annotated[str, ClassA, func1(), v2[0]] = ""
v2 = [1, 2, 3]
class ClassA:
...
class ClassA: ...
def func1():
...
def func1(): ...

View File

@ -64,8 +64,7 @@ class ClassD:
str: "str"
def int(self):
...
def int(self): ...
foo: "int"
@ -147,4 +146,3 @@ x12: b"int"
# This should generate an error because format strings aren't allowed.
x13: f"int"

View File

@ -27,8 +27,7 @@ class ClassB(ClassA):
def func5(self, x: ClassA):
x.func0()
class ClassA:
...
class ClassA: ...
def func6(self, x: ClassC):
x.my_int

View File

@ -53,8 +53,7 @@ e = [3]
e: list[int]
def register(fn: Callable[[], None]) -> None:
...
def register(fn: Callable[[], None]) -> None: ...
# These should be be fine because they use the "_" name.

View File

@ -11,12 +11,10 @@ v1 = cast(Any, 0)
v2 = cast(typing.Any, 0)
class A(Any):
...
class A(Any): ...
class B(typing.Any):
...
class B(typing.Any): ...
# This should generate an error because Any is not callable.

View File

@ -20,8 +20,7 @@ class A:
T = TypeVar("T")
class B(Generic[T]):
...
class B(Generic[T]): ...
def func1(v1: list[Any | None], v2: list[int | str]):

View File

@ -38,8 +38,7 @@ d4: dict[str, tuple[int, Callable[[int], int]]] = {
class Adder(Protocol):
def __call__(self, x: int, y: dict[str, int]) -> int:
...
def __call__(self, x: int, y: dict[str, int]) -> int: ...
v1: Adder = lambda x, y: x + y["hi"]

View File

@ -7,12 +7,10 @@ from typing import Any, TypeVar, overload
class Foo:
@overload
def bar(self, obj: None) -> object:
...
def bar(self, obj: None) -> object: ...
@overload
def bar(self, obj: object) -> Any:
...
def bar(self, obj: object) -> Any: ...
def bar(self, obj: object | None) -> Any:
pass

View File

@ -17,8 +17,7 @@ def func1() -> Tuple[str, int]:
return (a, y)
def get_value(x: int) -> int:
...
def get_value(x: int) -> int: ...
x = sum(max(value for x in range(10) if (value := get_value(x))) for _ in range(10))

View File

@ -7,8 +7,7 @@ from typing import Any, Callable, TypeVar, overload
_T = TypeVar("_T")
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]:
...
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]: ...
@decorator(
@ -19,7 +18,7 @@ def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]:
],
)
def decorated(
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])]
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])],
):
pass
@ -29,13 +28,11 @@ reveal_type(walrus_target_2, expected_text="list[str]")
@overload
def func1(value: None = None) -> None:
...
def func1(value: None = None) -> None: ...
@overload
def func1(value: str) -> str:
...
def func1(value: str) -> str: ...
def func1(value: str | None = None) -> str | None:

View File

@ -19,15 +19,12 @@ class MyPartial[**P, R]:
self.first = first
self.func = func
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
...
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
class CallbackKeyed[*Ts](Protocol):
def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]:
...
def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]: ...
def invoke_keyed[*Ts](fn: CallbackKeyed[*Ts], *args: *Ts) -> tuple[*Ts]:
return fn(*args, keyed=True)

View File

@ -7,12 +7,15 @@ T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
T_contra = TypeVar("T_contra", contravariant=True)
class Parent_Invariant(Generic[T]):
pass
class ShouldBeInvariant[T](Parent_Invariant[T]):
pass
# This should generate an error.
a1: ShouldBeInvariant[int] = ShouldBeInvariant[float]()
@ -23,9 +26,11 @@ a2: ShouldBeInvariant[float] = ShouldBeInvariant[int]()
class Parent_Covariant(Generic[T_co]):
pass
class ShouldBeCovariant[T](Parent_Covariant[T]):
pass
# This should generate an error.
b1: ShouldBeCovariant[int] = ShouldBeCovariant[float]()
@ -35,11 +40,12 @@ b2: ShouldBeCovariant[float] = ShouldBeCovariant[int]()
class Parent_Contravariant(Generic[T_contra]):
pass
class ShouldBeContravariant[T](Parent_Contravariant[T]):
pass
c1: ShouldBeContravariant[int] = ShouldBeContravariant[float]()
# This should generate an error.
c2: ShouldBeContravariant[float] = ShouldBeContravariant[int]()

View File

@ -4,12 +4,10 @@
from typing import Any, Hashable, Mapping, Protocol
def requires_hashable_tuple(p1: tuple[Hashable, ...]):
...
def requires_hashable_tuple(p1: tuple[Hashable, ...]): ...
def requires_hashable_dict(p1: dict[str, Hashable]):
...
def requires_hashable_dict(p1: dict[str, Hashable]): ...
def test_args(*args: Hashable):
@ -24,8 +22,7 @@ def test_kwargs(**kwargs: Hashable):
requires_hashable_dict(kwargs)
class StrSubclass(str):
...
class StrSubclass(str): ...
def test_kwargs2(
@ -51,30 +48,26 @@ def test_kwargs2(
class Callback1(Protocol):
def __call__(self) -> None:
...
def __call__(self) -> None: ...
def func1(
value: str = ...,
*args: object,
) -> None:
...
) -> None: ...
def func2(
value: str = ...,
**kwargs: object,
) -> None:
...
) -> None: ...
def func3(
value: str = ...,
*args: object,
**kwargs: object,
) -> None:
...
) -> None: ...
v1: Callback1 = func1

View File

@ -71,8 +71,7 @@ for a, b in zip(*q6):
reveal_type(b, expected_text="int")
def func1(a: list[str], c: list[int]):
...
def func1(a: list[str], c: list[int]): ...
func1(*q6)

View File

@ -5,31 +5,25 @@
from typing import Any, Generic, TypeVar, Mapping, KeysView
class MyMapping(Mapping[str, Any]):
...
class MyMapping(Mapping[str, Any]): ...
class StrRecord:
def __getitem__(self, __key: str) -> str:
...
def __getitem__(self, __key: str) -> str: ...
def keys(self) -> KeysView[str]:
...
def keys(self) -> KeysView[str]: ...
T = TypeVar("T")
class GenericRecord(Generic[T]):
def __getitem__(self, __key: str) -> T:
...
def __getitem__(self, __key: str) -> T: ...
def keys(self) -> KeysView[T]:
...
def keys(self) -> KeysView[T]: ...
def func1(**kwargs: Any) -> None:
...
def func1(**kwargs: Any) -> None: ...
m = MyMapping()

View File

@ -9,16 +9,14 @@ from typing import Any, Awaitable, Callable, Iterable, Sequence, TypeVar
_T1 = TypeVar("_T1")
def func1(__iterable: Iterable[_T1]) -> _T1:
...
def func1(__iterable: Iterable[_T1]) -> _T1: ...
a: Callable[[Sequence[float]], float] = func1
b: Callable[[Sequence[Any]], Any] = func1
def func2(__iterable: Sequence[_T1]) -> _T1:
...
def func2(__iterable: Sequence[_T1]) -> _T1: ...
# This should generate an error because an Iterable parameter
@ -29,8 +27,7 @@ c: Callable[[Iterable[float]], float] = func2
_T2 = TypeVar("_T2", bound=float)
def func3(__iterable: Iterable[_T2]) -> _T2:
...
def func3(__iterable: Iterable[_T2]) -> _T2: ...
d: Callable[[Sequence[int]], int] = func3

View File

@ -8,8 +8,7 @@ T = TypeVar("T")
R = TypeVar("R")
class ClassA(Generic[R]):
...
class ClassA(Generic[R]): ...
class ClassB(Generic[T]):

View File

@ -8,17 +8,14 @@ T = TypeVar("T")
@overload
def func1(real: float):
...
def func1(real: float): ...
@overload
def func1(real: str):
...
def func1(real: str): ...
def func1(real: float | str) -> None:
...
def func1(real: float | str) -> None: ...
def func2(f: Callable[[T], Any], p: T):

View File

@ -1,5 +1,6 @@
# This sample tests the handling of the `__call__` attribute.
class A:
def __init__(self):
self.__call__ = self.method1

View File

@ -140,7 +140,7 @@ class TestClass7:
pass
def test_func7(*args: * tuple[int, *tuple[int, ...]]) -> int:
def test_func7(*args: *tuple[int, *tuple[int, ...]]) -> int:
return 123

View File

@ -9,8 +9,7 @@ OutputT = TypeVar("OutputT", covariant=True)
class MyCallable(Protocol[InputT, OutputT]):
def __call__(self, inputs: InputT) -> OutputT:
...
def __call__(self, inputs: InputT) -> OutputT: ...
class Class1:

View File

@ -7,17 +7,14 @@ TE = TypeVar("TE", bound=Exception)
class CallbackProtocol1(Protocol[TE]):
def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE:
...
def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE:
...
def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
def func2(
s_exc_class: Exception,
t_exc_class: Type[TE],
mapper: CallbackProtocol1[TE] = func1,
):
...
): ...

View File

@ -6,15 +6,12 @@ from typing import Any, Protocol, overload
class P1(Protocol):
@overload
def __call__(self, x: int) -> int:
...
def __call__(self, x: int) -> int: ...
@overload
def __call__(self, x: str) -> str:
...
def __call__(self, x: str) -> str: ...
def __call__(self, x: Any) -> Any:
...
def __call__(self, x: Any) -> Any: ...
def func0(x: Any) -> Any:
@ -32,13 +29,11 @@ a1: P1 = func1
@overload
def of1(x: int) -> int:
...
def of1(x: int) -> int: ...
@overload
def of1(x: str) -> str:
...
def of1(x: str) -> str: ...
def of1(x: Any) -> Any:
@ -46,13 +41,11 @@ def of1(x: Any) -> Any:
@overload
def of2(x: int) -> complex:
...
def of2(x: int) -> complex: ...
@overload
def of2(x: str) -> str:
...
def of2(x: str) -> str: ...
def of2(x: Any) -> Any:
@ -66,8 +59,7 @@ b1: P1 = of2
class P2(Protocol):
def __call__(self, *args: int) -> Any:
...
def __call__(self, *args: int) -> Any: ...
a: P2 = lambda *args: map(lambda arg: arg + 0, args)

View File

@ -6,22 +6,18 @@ from typing import Protocol
# Callback with positional parameter with default arg value.
class Callback1(Protocol):
def __call__(self, path: str = ...) -> str:
...
def __call__(self, path: str = ...) -> str: ...
# Callback with positional parameter without default arg value.
class Callback2(Protocol):
def __call__(self, path: str) -> str:
...
def __call__(self, path: str) -> str: ...
def func1_1(path: str = "") -> str:
...
def func1_1(path: str = "") -> str: ...
def func1_2(path: str) -> str:
...
def func1_2(path: str) -> str: ...
val1_1: Callback1 = func1_1
@ -36,22 +32,18 @@ val2_2: Callback2 = func1_2
# Callback with keyword parameter with default arg value.
class Callback3(Protocol):
def __call__(self, *, path: str = ...) -> str:
...
def __call__(self, *, path: str = ...) -> str: ...
# Callback with keyword parameter without default arg value.
class Callback4(Protocol):
def __call__(self, *, path: str) -> str:
...
def __call__(self, *, path: str) -> str: ...
def func3_1(*, path: str = "") -> str:
...
def func3_1(*, path: str = "") -> str: ...
def func3_2(*, path: str) -> str:
...
def func3_2(*, path: str) -> str: ...
val3_1: Callback3 = func3_1

View File

@ -5,11 +5,10 @@ from typing import Any, Protocol
class X(Protocol):
def __call__(self, x: int, /, y: str) -> Any:
...
def __call__(self, x: int, /, y: str) -> Any: ...
def f1(x: int, /, y: str, z: None = None) -> Any:
...
def f1(x: int, /, y: str, z: None = None) -> Any: ...
x: X = f1

View File

@ -5,12 +5,10 @@ from typing import Any, Protocol
class P(Protocol):
def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None:
...
def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None:
...
def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
p: P = f

View File

@ -15,8 +15,7 @@ class A:
_T = TypeVar("_T", bound=A)
class B(Generic[_T]):
...
class B(Generic[_T]): ...
class C(A):

View File

@ -9,8 +9,7 @@ class ClassA:
# This should generate a warning because __class_getitem__
# is implicitly a classmethod and should use cls rather than
# self.
def __class_getitem__(self, args: tuple[int, ...]) -> None:
...
def __class_getitem__(self, args: tuple[int, ...]) -> None: ...
reveal_type(ClassA[10, 63], expected_text="type[ClassA]")
@ -23,8 +22,7 @@ _S = TypeVar("_S")
class ClassB(Generic[_T, _S]):
# Even though this class has a __class_getitem__ method,
# it will be assumed to follow normal generic class semantics.
def __class_getitem__(cls, args: tuple[int, ...]) -> None:
...
def __class_getitem__(cls, args: tuple[int, ...]) -> None: ...
reveal_type(ClassB[int, str], expected_text="type[ClassB[int, str]]")

View File

@ -19,7 +19,6 @@ def dynamic_subclass1(cls: type[T_A]):
def dynamic_subclass2(base: type[A] | None):
class SubClass(base or A):
...
class SubClass(base or A): ...
return SubClass

View File

@ -6,34 +6,27 @@ from typing import Collection, Iterator, Mapping, Sequence, TypeVar
# This should generate an error.
class A(Mapping[str, int], Collection[int]):
def __len__(self) -> int:
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[str]:
...
def __iter__(self) -> Iterator[str]: ...
# This should generate an error.
class B(Mapping[str, int], Sequence[int]):
...
class B(Mapping[str, int], Sequence[int]): ...
# This should generate an error.
class C(Sequence[int], Mapping[str, int]):
...
class C(Sequence[int], Mapping[str, int]): ...
class D(Sequence[float], Mapping[float, int]):
...
class D(Sequence[float], Mapping[float, int]): ...
class E(Sequence[float], Mapping[int, int]):
...
class E(Sequence[float], Mapping[int, int]): ...
# This should generate an error.
class F(Mapping[int, int], Sequence[float]):
...
class F(Mapping[int, int], Sequence[float]): ...
T = TypeVar("T")
@ -41,16 +34,13 @@ S = TypeVar("S")
class G(Mapping[T, S], Collection[T]):
def __len__(self) -> int:
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[T]: ...
def __iter__(self) -> Iterator[T]:
...
# This should generate an error.
class H(Mapping[T, S], Collection[S]):
def __len__(self) -> int:
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[T]:
...
def __iter__(self) -> Iterator[T]: ...

View File

@ -215,8 +215,7 @@ class SubclassTuple2(ParentClass2):
cv_decl_1, cv_decl_2, cv_decl_3 = (3, 4.5, None)
class ConfigBase:
...
class ConfigBase: ...
class ParentClass3(Protocol):
@ -225,13 +224,11 @@ class ParentClass3(Protocol):
class ChildClass3(ParentClass3):
class Config1(ConfigBase):
...
class Config1(ConfigBase): ...
# This should generate an error if reportIncompatibleVariableOverride
# is enabled.
class Config2:
...
class Config2: ...
class PeerClass1:

View File

@ -66,5 +66,4 @@ class TD_A2(TypedDict):
# This should generate an error for x but not y.
class TD_A(TD_A1, TD_A2):
...
class TD_A(TD_A1, TD_A2): ...

View File

@ -5,31 +5,25 @@
from typing import Any, Callable, overload
class C:
...
class C: ...
@overload
def func1(v: Callable[[], int]) -> int:
...
def func1(v: Callable[[], int]) -> int: ...
@overload
def func1(v: Callable[[], list[C]]) -> list[C]:
...
def func1(v: Callable[[], list[C]]) -> list[C]: ...
def func1(v: Any) -> Any:
...
def func1(v: Any) -> Any: ...
def func2(v: list[C]):
...
def func2(v: list[C]): ...
t = func1(lambda: func3())
t.append(C())
def func3() -> list[C]:
...
def func3() -> list[C]: ...

View File

@ -5,31 +5,25 @@
from typing import Any, Callable, overload
class C:
...
class C: ...
@overload
def func1(v: Callable[[], int]) -> int:
...
def func1(v: Callable[[], int]) -> int: ...
@overload
def func1(v: Callable[[], list[C]]) -> list[C]:
...
def func1(v: Callable[[], list[C]]) -> list[C]: ...
def func1(v: Any) -> Any:
...
def func1(v: Any) -> Any: ...
def func2(v: list[C]):
...
def func2(v: list[C]): ...
t = func1(lambda: func3())
t.append(C())
def func3() -> list[C]:
...
def func3() -> list[C]: ...

View File

@ -30,12 +30,10 @@ def func1(os: OS, val: Literal[1, "linux"]):
return True
class ClassA:
...
class ClassA: ...
class ClassB:
...
class ClassB: ...
_T1 = TypeVar("_T1")

View File

@ -8,8 +8,7 @@ b = a + 4
c = 1.2 * a
def requires_complex(val: complex):
...
def requires_complex(val: complex): ...
requires_complex(a)

View File

@ -18,8 +18,7 @@ def add1(value: _T1) -> _T1:
class IntSubclass2(int):
def __add__(self, value: object) -> "IntSubclass2":
...
def __add__(self, value: object) -> "IntSubclass2": ...
_T2 = TypeVar("_T2", int, IntSubclass2)

View File

@ -6,8 +6,7 @@ from os import PathLike
from typing import AnyStr
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr:
...
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr: ...
def func2(value: AnyStr) -> AnyStr:

View File

@ -5,16 +5,13 @@
from typing import TypeVar, Generic
class A:
...
class A: ...
class B:
...
class B: ...
class A2(A):
...
class A2(A): ...
T = TypeVar("T", A, B)

View File

@ -5,8 +5,7 @@ from typing import AnyStr, Iterable, TypeVar, Generic
from dataclasses import dataclass
class ClassA:
...
class ClassA: ...
_T = TypeVar("_T", int | float, ClassA)

View File

@ -13,12 +13,10 @@ _T1 = TypeVar("_T1")
AnyStr = TypeVar("AnyStr", str, bytes)
def exists2(path: AnyStr) -> bool:
...
def exists2(path: AnyStr) -> bool: ...
def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]:
...
def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]: ...
result = filter2(exists2, ["hello", "world"])

View File

@ -8,12 +8,10 @@
from typing import Any, AnyStr, Optional, Protocol, TypeVar, Union
class Array:
...
class Array: ...
class MMap:
...
class MMap: ...
# Note that this union contains types that are not compatible
@ -25,29 +23,24 @@ _T_co = TypeVar("_T_co", covariant=True)
class BufferedWriter:
def write(self, __buffer: ReadableBuffer) -> int:
...
def write(self, __buffer: ReadableBuffer) -> int: ...
class SupportsWrite(Protocol[_T_contra]):
def write(self, __s: _T_contra) -> Any:
...
def write(self, __s: _T_contra) -> Any: ...
class SupportsRead(Protocol[_T_co]):
def read(self, __length: int = ...) -> _T_co:
...
def read(self, __length: int = ...) -> _T_co: ...
class BufferedReader:
def read(self, __size: Optional[int] = ...) -> bytes:
...
def read(self, __size: Optional[int] = ...) -> bytes: ...
def copyfileobj(
fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...
) -> AnyStr:
...
) -> AnyStr: ...
def f(fr: BufferedReader, fw: BufferedWriter):

View File

@ -9,13 +9,11 @@ T = TypeVar("T")
class Async:
def fn(self, returnable: T) -> Awaitable[T]:
...
def fn(self, returnable: T) -> Awaitable[T]: ...
class Sync:
def fn(self, returnable: T) -> T:
...
def fn(self, returnable: T) -> T: ...
T = TypeVar("T", Async, Sync)

View File

@ -42,8 +42,7 @@ archive_path = data_dir / "hello"
shutil.rmtree(archive_path)
def func1(a: AnyStr, b: AnyStr) -> None:
...
def func1(a: AnyStr, b: AnyStr) -> None: ...
def func2(a: Union[str, bytes], b: Union[str, bytes]):
@ -51,27 +50,22 @@ def func2(a: Union[str, bytes], b: Union[str, bytes]):
func1(a, b)
class A:
...
class A: ...
class B:
...
class B: ...
class C:
...
class C: ...
class D:
...
class D: ...
T3 = TypeVar("T3", A, B, Union[C, D])
def do_something(value: T3) -> T3:
...
def do_something(value: T3) -> T3: ...
def func10(value: Union[C, D]):

View File

@ -4,8 +4,7 @@
from typing import Iterator, Optional, Sequence, TypeVar, Union
def func0(a: Union[int, float]):
...
def func0(a: Union[int, float]): ...
_T1 = TypeVar("_T1", int, float)
@ -39,12 +38,10 @@ def func5(xs: Sequence[Optional[_T2]]) -> Iterator[_T2]:
return func3(xs)
class A:
...
class A: ...
class B(A):
...
class B(A): ...
_T4 = TypeVar("_T4", A, B)

View File

@ -10,8 +10,7 @@ _T = TypeVar("_T")
class A(Iterator[_T_co]):
def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]":
...
def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]": ...
def __next__(self) -> _T_co: ...
@ -22,8 +21,7 @@ def func1(iterable: Iterable[_T]) -> Iterator[tuple[_T, _T, _T]]:
class B(Generic[_T_co]):
def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]":
...
def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]": ...
def func2(p1: list[dict]):

View File

@ -9,38 +9,32 @@ _M = TypeVar("_M")
class A(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "A[_M, _N]":
...
def __new__(cls, m: _M, n: _N) -> "A[_M, _N]": ...
a: A[Literal[3], Literal[4]] = A(3, 4)
class B(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "B[_M, _N]":
...
def __new__(cls, m: _M, n: _N) -> "B[_M, _N]": ...
def __init__(self, *args: Any, **kwargs: Any) -> None:
...
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
b: B[Literal[3], Literal[4]] = B(3, 4)
class C(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "C[_M, _N]":
...
def __new__(cls, m: _M, n: _N) -> "C[_M, _N]": ...
def __init__(self, m: _M, n: _N) -> None:
...
def __init__(self, m: _M, n: _N) -> None: ...
c: C[Literal[3], Literal[4]] = C(3, 4)
class D(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> Self:
...
def __new__(cls, m: _M, n: _N) -> Self: ...
d: D[Literal[3], Literal[4]] = D(3, 4)

View File

@ -13,24 +13,21 @@ class A(Generic[T]):
class B(Generic[T]):
def __init__(self):
...
def __init__(self): ...
class C(Generic[T]):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __init__(self):
...
def __init__(self): ...
class D(Generic[T]):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __init__(self, a: T):
...
def __init__(self, a: T): ...
class E(Generic[T]):

View File

@ -178,8 +178,7 @@ def s18():
class Plant(Generic[_T1]):
def __new__(cls, o: _T1) -> Self:
...
def __new__(cls, o: _T1) -> Self: ...
plant: Plant[float] = Plant(0)

View File

@ -9,14 +9,11 @@ T = TypeVar("T", covariant=True)
class A(Protocol[T]):
def a(self) -> "A[Tuple[T]]":
...
def a(self) -> "A[Tuple[T]]": ...
def b(self) -> "A[Tuple[T]]":
...
def b(self) -> "A[Tuple[T]]": ...
def c(self) -> "T":
...
def c(self) -> "T": ...
class B(Generic[T]):

View File

@ -72,20 +72,17 @@ def func1(obv: Container[T], default_value: T = None) -> None:
obv.on_next(default_value)
class A:
...
class A: ...
T_A = TypeVar("T_A", bound=A)
class B(Generic[T]):
def __init__(self, c: Callable[[], T]):
...
def __init__(self, c: Callable[[], T]): ...
def func2(cls: type[T_A] = A) -> Callable[[], T_A]:
...
def func2(cls: type[T_A] = A) -> Callable[[], T_A]: ...
B(func2())

View File

@ -11,22 +11,18 @@ T = TypeVar("T", contravariant=True)
S = TypeVar("S", contravariant=True)
class ClassA(Generic[T]):
...
class ClassA(Generic[T]): ...
class ClassB(Generic[S, T], ClassA[T]):
...
class ClassB(Generic[S, T], ClassA[T]): ...
class ClassC(ClassB[S, T]):
def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]:
...
def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]: ...
class ClassD(ClassB[S, T]):
def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]:
...
def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]: ...
c = ClassA[int]()

View File

@ -29,3 +29,11 @@ def func1(t: type[TA]) -> TA: ...
b = B(func1, A)
reveal_type(b, expected_text="B[(t: type[A]), A]")
class C(Generic[TA]):
def __init__(self, _type: type[TA]) -> None: ...
c = B(C, A)
reveal_type(c, expected_text="B[(_type: type[A]), C[A]]")

View File

@ -9,8 +9,7 @@ T_A = TypeVar("T_A", bound="A")
class A(ABC):
@abstractmethod
def some_method(self) -> str:
...
def some_method(self) -> str: ...
def some_factory_method_1(self):
return type(self)()

View File

@ -0,0 +1,17 @@
# This sample tests the case where an inner coroutine with an inferred
# return type is referenced in a manner that results in recursion.
import asyncio
def func1(replace_inner: bool) -> None:
inner = lambda: None
async def wrapper():
inner()
wrapped_fn = wrapper()
asyncio.create_task(wrapped_fn)
if replace_inner:
inner = lambda: None

View File

@ -12,8 +12,9 @@ class IsDataclass(Protocol):
__dataclass_fields__: ClassVar[dict[str, Any]]
def dataclass_only(x: IsDataclass):
... # do something that only makes sense with a dataclass
def dataclass_only(
x: IsDataclass,
): ... # do something that only makes sense with a dataclass
@dataclass

View File

@ -7,12 +7,10 @@ from typing import Any, cast, overload
class MyDescriptor:
@overload
def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor":
...
def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor": ...
@overload
def __get__(self, __obj: object, __owner: Any) -> int:
...
def __get__(self, __obj: object, __owner: Any) -> int: ...
def __get__(self, __obj: object | None, __owner: Any) -> "int | MyDescriptor":
if __obj is None:

Some files were not shown because too many files have changed in this diff Show More