Skip to content

Commit

Permalink
Merge tag '1.1.385' into merge-1.1.385
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/configuration.md
#	packages/pyright-internal/src/localization/package.nls.zh-cn.json
#	packages/pyright/package-lock.json
#	packages/pyright/package.json
#	packages/vscode-pyright/package.json
  • Loading branch information
DetachHead committed Oct 16, 2024
2 parents 2ca13d8 + 7f8764c commit a34288d
Show file tree
Hide file tree
Showing 47 changed files with 327 additions and 127 deletions.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "1.1.384",
"version": "1.1.385",
"command": {
"version": {
"push": false,
Expand Down
4 changes: 2 additions & 2 deletions packages/pyright-internal/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/pyright-internal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "pyright-internal",
"displayName": "pyright",
"description": "Type checker for the Python language",
"version": "1.1.384",
"version": "1.1.385",
"license": "MIT",
"private": true,
"files": [
Expand Down
6 changes: 4 additions & 2 deletions packages/pyright-internal/src/analyzer/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ import {
UnresolvedModuleMarker,
VariableDeclaration,
} from './declaration';
import { extractParameterDocumentation } from './docStringUtils';
import { ImplicitImport, ImportResult, ImportType } from './importResult';
import * as ParseTreeUtils from './parseTreeUtils';
import { ParseTreeWalker } from './parseTreeWalker';
Expand Down Expand Up @@ -563,7 +562,10 @@ export class Binder extends ParseTreeWalker {
// Extract the parameter docString from the function docString
let docString = ParseTreeUtils.getDocString(node?.d.suite?.d.statements ?? []);
if (docString !== undefined) {
docString = extractParameterDocumentation(docString, paramNode.d.name.d.value);
docString = this._docStringService.extractParameterDocumentation(
docString,
paramNode.d.name.d.value
);
}

if (symbol) {
Expand Down
5 changes: 0 additions & 5 deletions packages/pyright-internal/src/analyzer/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1288,11 +1288,6 @@ export class Checker extends ParseTreeWalker {
}

override visitBinaryOperation(node: BinaryOperationNode): boolean {
if (node.d.operator === OperatorType.And || node.d.operator === OperatorType.Or) {
this._validateConditionalIsBool(node.d.leftExpr);
this._validateConditionalIsBool(node.d.rightExpr);
}

if (node.d.operator === OperatorType.Equals || node.d.operator === OperatorType.NotEquals) {
// Don't apply this rule if it's within an assert.
if (!ParseTreeUtils.isWithinAssertExpression(node)) {
Expand Down
18 changes: 10 additions & 8 deletions packages/pyright-internal/src/analyzer/constructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,15 +595,17 @@ function validateMetaclassCall(
);
});

// If the return type is unannotated, don't use the inferred return type.
const callType = metaclassCallMethodInfo.type;
if (isFunction(callType) && !callType.shared.declaredReturnType) {
return undefined;
}
if (!callResult.argumentErrors) {
// If the return type is unannotated, don't use the inferred return type.
const callType = metaclassCallMethodInfo.type;
if (isFunction(callType) && !callType.shared.declaredReturnType) {
return undefined;
}

// If the return type is unknown, ignore it.
if (callResult.returnType && isUnknown(callResult.returnType)) {
return undefined;
// If the return type is unknown, ignore it.
if (callResult.returnType && isUnknown(callResult.returnType)) {
return undefined;
}
}

return callResult;
Expand Down
39 changes: 37 additions & 2 deletions packages/pyright-internal/src/analyzer/dataClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ import {
ParseNodeType,
TypeAnnotationNode,
} from '../parser/parseNodes';
import { Tokenizer } from '../parser/tokenizer';
import * as AnalyzerNodeInfo from './analyzerNodeInfo';
import { getFileInfo } from './analyzerNodeInfo';
import { ConstraintSolution } from './constraintSolution';
import { ConstraintTracker } from './constraintTracker';
import { createFunctionFromConstructor, getBoundInitMethod } from './constructors';
import { DeclarationType, VariableDeclaration } from './declaration';
import { updateNamedTupleBaseClass } from './namedTuples';
import { getClassFullName, getEnclosingClassOrFunction, getScopeIdForNode, getTypeSourceId } from './parseTreeUtils';
import {
getClassFullName,
getEnclosingClassOrFunction,
getScopeIdForNode,
getTypeSourceId,
getTypeVarScopesForNode,
} from './parseTreeUtils';
import { evaluateStaticBoolExpression } from './staticExpressions';
import { Symbol, SymbolFlags } from './symbol';
import { isPrivateName } from './symbolNameUtils';
Expand Down Expand Up @@ -73,6 +80,9 @@ import {
getTypeVarScopeIds,
isLiteralType,
isMetaclassInstance,
makeInferenceContext,
makeTypeVarsBound,
makeTypeVarsFree,
requiresSpecialization,
specializeTupleClass,
synthesizeTypeVarForSelfCls,
Expand Down Expand Up @@ -325,6 +335,14 @@ export function synthesizeDataClassMethods(
isLiteralType(valueType)
) {
aliasName = valueType.priv.literalValue as string;

if (!Tokenizer.isPythonIdentifier(aliasName)) {
evaluator.addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
LocMessage.dataClassFieldInvalidAlias().format({ aliasName }),
aliasArg.d.valueExpr
);
}
}
}

Expand Down Expand Up @@ -571,7 +589,24 @@ export function synthesizeDataClassMethods(
if (entry.isDefaultFactory || !entry.defaultExpr) {
defaultType = entry.type;
} else {
defaultType = evaluator.getTypeOfExpression(entry.defaultExpr).type;
const defaultExpr = entry.defaultExpr;
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
const flags = fileInfo.isStubFile ? EvalFlags.ConvertEllipsisToAny : EvalFlags.None;
const liveTypeVars = getTypeVarScopesForNode(entry.defaultExpr);
const boundEffectiveType = makeTypeVarsBound(effectiveType, liveTypeVars);

// Use speculative mode here so we don't cache the results.
// We'll want to re-evaluate this expression later, potentially
// with different evaluation flags.
defaultType = evaluator.useSpeculativeMode(defaultExpr, () => {
return evaluator.getTypeOfExpression(
defaultExpr,
flags,
makeInferenceContext(boundEffectiveType)
).type;
});

defaultType = makeTypeVarsFree(defaultType, liveTypeVars);
}
}
}
Expand Down
14 changes: 2 additions & 12 deletions packages/pyright-internal/src/analyzer/importResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import * as StringUtils from '../common/stringUtils';
import { equateStringsCaseInsensitive } from '../common/stringUtils';
import { Uri } from '../common/uri/uri';
import { getFileSystemEntriesFromDirEntries, isDirectory, isFile, tryRealpath, tryStat } from '../common/uri/uriUtils';
import { isIdentifierChar, isIdentifierStartChar } from '../parser/characters';
import { Tokenizer } from '../parser/tokenizer';
import { ImplicitImport, ImportResult, ImportType } from './importResult';
import { getDirectoryLeadingDotsPointsTo } from './importStatementUtils';
import { ImportPath, ParentDirectoryCache } from './parentDirectoryCache';
Expand Down Expand Up @@ -2834,7 +2834,7 @@ function _getModuleNameInfoFromPath(
}

// Check whether parts contains invalid characters.
const containsInvalidCharacters = parts.some((p) => !_isIdentifier(p));
const containsInvalidCharacters = parts.some((p) => !Tokenizer.isPythonIdentifier(p));

return {
moduleName: parts.join('.'),
Expand All @@ -2849,13 +2849,3 @@ function _isNativeModuleFileExtension(fileExtension: string): boolean {
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;
}
3 changes: 2 additions & 1 deletion packages/pyright-internal/src/analyzer/parameterUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export enum ParamKind {
Positional,
Standard,
Keyword,
ExpandedArgs,
}

export interface VirtualParamDetails {
Expand Down Expand Up @@ -185,7 +186,7 @@ export function getParamListDetails(type: FunctionType): ParamListDetails {
index,
tupleArg.type,
/* defaultArgTypeOverride */ undefined,
ParamKind.Positional
ParamKind.ExpandedArgs
);

if (category === ParamCategory.Simple) {
Expand Down
82 changes: 51 additions & 31 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3552,11 +3552,6 @@ export function createTypeEvaluator(
}
}

if (declaredType) {
const liveScopeIds = ParseTreeUtils.getTypeVarScopesForNode(nameNode);
declaredType = makeTypeVarsBound(declaredType, liveScopeIds);
}

// We found an existing declared type. Make sure the type is assignable.
let destType = typeResult.type;
const isTypeAlias =
Expand All @@ -3565,7 +3560,11 @@ export function createTypeEvaluator(
if (declaredType && !isTypeAlias) {
let diagAddendum = new DiagnosticAddendum();

if (!assignType(declaredType, typeResult.type, diagAddendum)) {
const liveScopeIds = ParseTreeUtils.getTypeVarScopesForNode(nameNode);
const boundDeclaredType = makeTypeVarsBound(declaredType, liveScopeIds);
const srcType = makeTypeVarsBound(typeResult.type, liveScopeIds);

if (!assignType(boundDeclaredType, srcType, diagAddendum)) {
// If there was an expected type mismatch, use that diagnostic
// addendum because it will be more informative.
if (expectedTypeDiagAddendum) {
Expand Down Expand Up @@ -3892,7 +3891,7 @@ export function createTypeEvaluator(
const tupleType = getSpecializedTupleType(subtype);
if (tupleType && tupleType.priv.tupleTypeArgs) {
const sourceEntryTypes = tupleType.priv.tupleTypeArgs.map((t) =>
addConditionToType(t.type, getTypeCondition(subtype), /* skipSelfCondition */ true)
addConditionToType(t.type, getTypeCondition(subtype), { skipSelfCondition: true })
);

const unboundedIndex = tupleType.priv.tupleTypeArgs.findIndex((t) => t.isUnbounded);
Expand Down Expand Up @@ -5716,11 +5715,10 @@ export function createTypeEvaluator(

if (typeResult) {
if (!typeResult.typeErrors) {
type = addConditionToType(
typeResult.type,
getTypeCondition(baseType),
/* skipSelfCondition */ true
);
type = addConditionToType(typeResult.type, getTypeCondition(baseType), {
skipSelfCondition: true,
skipBoundTypeVars: true,
});
} else {
typeErrors = true;
}
Expand All @@ -5737,7 +5735,7 @@ export function createTypeEvaluator(
narrowedTypeForSet = addConditionToType(
typeResult.narrowedTypeForSet,
getTypeCondition(baseType),
/* skipSelfCondition */ true
{ skipSelfCondition: true, skipBoundTypeVars: true }
);
}

Expand Down Expand Up @@ -5869,7 +5867,9 @@ export function createTypeEvaluator(
const typeResult = getTypeOfBoundMember(node.d.member, subtype, memberName, usage, diag);

if (typeResult && !typeResult.typeErrors) {
type = addConditionToType(typeResult.type, getTypeCondition(baseType));
type = addConditionToType(typeResult.type, getTypeCondition(baseType), {
skipBoundTypeVars: true,
});
if (typeResult.isIncomplete) {
isIncomplete = true;
}
Expand Down Expand Up @@ -12104,7 +12104,7 @@ export function createTypeEvaluator(
eliminateUnsolvedInUnions,
},
});
specializedReturnType = addConditionToType(specializedReturnType, typeCondition);
specializedReturnType = addConditionToType(specializedReturnType, typeCondition, { skipBoundTypeVars: true });

// If the function includes a ParamSpec and the captured signature(s) includes
// generic types, we may need to apply those solved TypeVars.
Expand Down Expand Up @@ -15456,17 +15456,32 @@ export function createTypeEvaluator(
// As per the specification, we support None, int, bool, str, bytes literals
// plus enum values.
const literalTypes: Type[] = [];
let isValidTypeForm = true;

for (const item of node.d.items) {
let type: Type | undefined;
const itemExpr = item.d.valueExpr;

if (item.d.argCategory !== ArgCategory.Simple) {
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.unpackedArgInTypeArgument(), itemExpr);
type = UnknownType.create();
if ((flags & EvalFlags.TypeExpression) !== 0) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.unpackedArgInTypeArgument(),
itemExpr
);
type = UnknownType.create();
isValidTypeForm = false;
}
} else if (item.d.name) {
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.keywordArgInTypeArgument(), itemExpr);
type = UnknownType.create();
if ((flags & EvalFlags.TypeExpression) !== 0) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.keywordArgInTypeArgument(),
itemExpr
);
type = UnknownType.create();
isValidTypeForm = false;
}
} else if (itemExpr.nodeType === ParseNodeType.StringList) {
const isBytes = (itemExpr.d.strings[0].d.token.flags & StringTokenFlags.Bytes) !== 0;
const value = itemExpr.d.strings.map((s) => s.d.value).join('');
Expand All @@ -15476,15 +15491,18 @@ export function createTypeEvaluator(
type = cloneBuiltinClassWithLiteral(node, classType, 'str', value);
}

itemExpr.d.strings.forEach((stringNode) => {
if ((stringNode.d.token.flags & StringTokenFlags.NamedUnicodeEscape) !== 0) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.literalNamedUnicodeEscape(),
stringNode
);
}
});
if ((flags & EvalFlags.TypeExpression) !== 0) {
itemExpr.d.strings.forEach((stringNode) => {
if ((stringNode.d.token.flags & StringTokenFlags.NamedUnicodeEscape) !== 0) {
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm,
LocMessage.literalNamedUnicodeEscape(),
stringNode
);
isValidTypeForm = false;
}
});
}
} else if (itemExpr.nodeType === ParseNodeType.Number) {
if (!itemExpr.d.isImaginary && itemExpr.d.isInteger) {
type = cloneBuiltinClassWithLiteral(node, classType, 'int', itemExpr.d.value);
Expand Down Expand Up @@ -15549,6 +15567,7 @@ export function createTypeEvaluator(
if ((flags & EvalFlags.TypeExpression) !== 0) {
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.literalUnsupportedType(), item);
type = UnknownType.create();
isValidTypeForm = false;
} else {
return ClassType.cloneAsInstance(classType);
}
Expand All @@ -15563,7 +15582,7 @@ export function createTypeEvaluator(
result = TypeBase.cloneAsSpecialForm(result, ClassType.cloneAsInstance(unionTypeClass));
}

if (isTypeFormSupported(node)) {
if (isTypeFormSupported(node) && isValidTypeForm) {
result = TypeBase.cloneWithTypeForm(result, convertToInstance(result));
}

Expand Down Expand Up @@ -25860,13 +25879,14 @@ export function createTypeEvaluator(
const destParamName = destParam.param.name ?? '';
const srcParamName = srcParam.param.name ?? '';
if (destParamName) {
const isDestPositionalOnly = destParam.kind === ParamKind.Positional;
const isDestPositionalOnly =
destParam.kind === ParamKind.Positional || destParam.kind === ParamKind.ExpandedArgs;
if (
!isDestPositionalOnly &&
destParam.param.category !== ParamCategory.ArgsList &&
srcParam.param.category !== ParamCategory.ArgsList
) {
if (srcParam.kind === ParamKind.Positional) {
if (srcParam.kind === ParamKind.Positional || srcParam.kind === ParamKind.ExpandedArgs) {
diag?.createAddendum().addMessage(
LocAddendum.functionParamPositionOnly().format({
name: destParamName,
Expand Down
Loading

0 comments on commit a34288d

Please sign in to comment.