mirror of
https://github.com/microsoft/pyright.git
synced 2024-07-14 19:10:39 +03:00
Removed provisional support for PEP 677 (Alternate Call Syntax) because the proposal was rejected by the Python steering council.
This commit is contained in:
parent
ef72e4079c
commit
9949577ced
@ -30,7 +30,6 @@ Pyright supports [configuration files](/docs/configuration.md) that provide gran
|
||||
* [PEP 655](https://www.python.org/dev/peps/pep-0655/) required typed dictionary items
|
||||
* [PEP 673](https://www.python.org/dev/peps/pep-0673/) Self type
|
||||
* [PEP 675](https://www.python.org/dev/peps/pep-0675/) arbitrary literal strings
|
||||
* [PEP 677](https://www.python.org/dev/peps/pep-0677/) callable type syntax
|
||||
* [PEP 681](https://www.python.org/dev/peps/pep-0681/) dataclass transform
|
||||
* Type inference for function return values, instance variables, class variables, and globals
|
||||
* Type guards that understand conditional code flow constructs like if/else statements
|
||||
|
@ -433,25 +433,6 @@ export function printExpression(node: ExpressionNode, flags = PrintExpressionFla
|
||||
case ParseNodeType.Set: {
|
||||
return node.entries.map((entry) => printExpression(entry, flags)).join(', ');
|
||||
}
|
||||
|
||||
case ParseNodeType.ArrowCallable: {
|
||||
const paramsText = node.parameters.map((param) => {
|
||||
let prefix = '';
|
||||
if (param.category === ParameterCategory.VarArgList) {
|
||||
prefix = '*';
|
||||
} else if (param.category === ParameterCategory.VarArgDictionary) {
|
||||
prefix = '**';
|
||||
}
|
||||
|
||||
const typeText = printExpression(param.typeAnnotation);
|
||||
|
||||
return `${prefix}${typeText}`;
|
||||
});
|
||||
|
||||
const optionalAsync = node.isAsync ? 'async ' : '';
|
||||
|
||||
return `${optionalAsync}(${paramsText.join(', ')}) -> ${printExpression(node.returnTypeAnnotation)}`;
|
||||
}
|
||||
}
|
||||
|
||||
return '<Expression>';
|
||||
@ -1762,9 +1743,6 @@ export function printParseNodeType(type: ParseNodeType) {
|
||||
|
||||
case ParseNodeType.PatternClassArgument:
|
||||
return 'PatternClassArgument';
|
||||
|
||||
case ParseNodeType.ArrowCallable:
|
||||
return 'ArrowCallable';
|
||||
}
|
||||
|
||||
assertNever(type);
|
||||
|
@ -10,7 +10,6 @@
|
||||
import { fail } from '../common/debug';
|
||||
import {
|
||||
ArgumentNode,
|
||||
ArrowCallableNode,
|
||||
AssertNode,
|
||||
AssignmentExpressionNode,
|
||||
AssignmentNode,
|
||||
@ -572,12 +571,6 @@ export class ParseTreeWalker {
|
||||
}
|
||||
break;
|
||||
|
||||
case ParseNodeType.ArrowCallable:
|
||||
if (this.visitArrowCallable(node)) {
|
||||
return [...node.parameters.map((param) => param.typeAnnotation), node.returnTypeAnnotation];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fail('Unexpected node type');
|
||||
break;
|
||||
@ -591,10 +584,6 @@ export class ParseTreeWalker {
|
||||
return true;
|
||||
}
|
||||
|
||||
visitArrowCallable(node: ArrowCallableNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
visitAssert(node: AssertNode) {
|
||||
return true;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ import { TextRange } from '../common/textRange';
|
||||
import { Localizer } from '../localization/localize';
|
||||
import {
|
||||
ArgumentCategory,
|
||||
ArrowCallableNode,
|
||||
AssignmentNode,
|
||||
AugmentedAssignmentNode,
|
||||
BinaryOperationNode,
|
||||
@ -1071,11 +1070,6 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
break;
|
||||
}
|
||||
|
||||
case ParseNodeType.ArrowCallable: {
|
||||
typeResult = getTypeFromArrowCallable(node, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
case ParseNodeType.Assignment: {
|
||||
typeResult = getTypeOfExpression(node.rightExpression);
|
||||
assignTypeToExpression(
|
||||
@ -11457,136 +11451,6 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
return type;
|
||||
}
|
||||
|
||||
function getTypeFromArrowCallable(node: ArrowCallableNode, flags: EvaluatorFlags): TypeResult {
|
||||
// Emit an error if this will cause a runtime exception.
|
||||
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
|
||||
if (
|
||||
!fileInfo.isStubFile &&
|
||||
fileInfo.executionEnvironment.pythonVersion < PythonVersion.V3_11 &&
|
||||
(flags & EvaluatorFlags.NotParsedByInterpreter) === 0
|
||||
) {
|
||||
addError(Localizer.Diagnostic.arrowCallableIllegal(), node);
|
||||
}
|
||||
|
||||
const isIncomplete = false;
|
||||
const functionType = FunctionType.createInstantiable('', '', '', FunctionTypeFlags.None);
|
||||
|
||||
const enclosingScope = ParseTreeUtils.getEnclosingClassOrFunction(node);
|
||||
|
||||
// Handle the case where the Callable has no enclosing scope. This can
|
||||
// happen in the case where a generic function return type is annotated
|
||||
// with a generic type alias that includes a Callable in its definition.
|
||||
functionType.details.typeVarScopeId = enclosingScope
|
||||
? getScopeIdForNode(enclosingScope)
|
||||
: WildcardTypeVarScopeId;
|
||||
|
||||
const returnAnnotationOptions: AnnotationTypeOptions = {};
|
||||
if ((flags & EvaluatorFlags.AssociateTypeVarsWithCurrentScope) !== 0) {
|
||||
returnAnnotationOptions.associateTypeVarsWithScope = true;
|
||||
}
|
||||
if ((flags & EvaluatorFlags.NotParsedByInterpreter) !== 0) {
|
||||
returnAnnotationOptions.notParsedByInterpreter = true;
|
||||
}
|
||||
|
||||
let returnType = getTypeOfAnnotation(node.returnTypeAnnotation, returnAnnotationOptions);
|
||||
if (node.isAsync) {
|
||||
functionType.details.flags |= FunctionTypeFlags.Async;
|
||||
const awaitableType = getTypingType(node, 'Awaitable');
|
||||
if (awaitableType && isInstantiableClass(awaitableType)) {
|
||||
returnType = ClassType.cloneForSpecialization(
|
||||
ClassType.cloneAsInstance(awaitableType),
|
||||
[returnType],
|
||||
/* isTypeArgumentExplicit */ true
|
||||
);
|
||||
} else {
|
||||
returnType = UnknownType.create();
|
||||
}
|
||||
}
|
||||
|
||||
functionType.details.declaredReturnType = returnType;
|
||||
|
||||
let addPositionalOnly = true;
|
||||
|
||||
const paramAnnotationOptions: AnnotationTypeOptions = {
|
||||
allowParamSpec: true,
|
||||
allowTypeVarTuple: true,
|
||||
};
|
||||
|
||||
if ((flags & EvaluatorFlags.AssociateTypeVarsWithCurrentScope) !== 0) {
|
||||
paramAnnotationOptions.associateTypeVarsWithScope = true;
|
||||
}
|
||||
|
||||
node.parameters.forEach((param, paramIndex) => {
|
||||
const paramType = getTypeOfAnnotation(param.typeAnnotation, paramAnnotationOptions);
|
||||
|
||||
if (isEllipsisType(paramType)) {
|
||||
if (param.category !== ParameterCategory.Simple || paramIndex !== 0 || node.parameters.length > 1) {
|
||||
addError(Localizer.Diagnostic.ellipsisContext(), param.typeAnnotation);
|
||||
FunctionType.addParameter(functionType, {
|
||||
category: ParameterCategory.Simple,
|
||||
name: `__p${paramIndex}`,
|
||||
isNameSynthesized: true,
|
||||
type: UnknownType.create(),
|
||||
hasDeclaredType: true,
|
||||
});
|
||||
} else {
|
||||
functionType.details.flags |= FunctionTypeFlags.SkipArgsKwargsCompatibilityCheck;
|
||||
FunctionType.addDefaultParameters(functionType);
|
||||
addPositionalOnly = false;
|
||||
}
|
||||
} else if (param.category === ParameterCategory.Simple) {
|
||||
if (isTypeVar(paramType) && paramType.details.isParamSpec) {
|
||||
addError(Localizer.Diagnostic.arrowCallableParamSpec(), param.typeAnnotation);
|
||||
}
|
||||
|
||||
if (isTypeVar(paramType) && paramType.details.isVariadic && !paramType.isVariadicUnpacked) {
|
||||
addError(Localizer.Diagnostic.arrowCallableVariadicTypeVar(), param.typeAnnotation);
|
||||
}
|
||||
|
||||
FunctionType.addParameter(functionType, {
|
||||
category: ParameterCategory.Simple,
|
||||
name: `__p${paramIndex}`,
|
||||
isNameSynthesized: true,
|
||||
type: convertToInstance(paramType),
|
||||
hasDeclaredType: true,
|
||||
});
|
||||
} else if (param.category === ParameterCategory.VarArgList) {
|
||||
if (!isVariadicTypeVar(paramType)) {
|
||||
addError(Localizer.Diagnostic.arrowCallableNotVariadicTypeVar(), param.typeAnnotation);
|
||||
} else {
|
||||
if (paramType.isVariadicUnpacked) {
|
||||
addError(Localizer.Diagnostic.arrowCallableVariadicTypeVarUnpacked(), param.typeAnnotation);
|
||||
}
|
||||
|
||||
FunctionType.addParameter(functionType, {
|
||||
category: ParameterCategory.Simple,
|
||||
name: `__p${paramIndex}`,
|
||||
isNameSynthesized: true,
|
||||
type: convertToInstance(TypeVarType.cloneForUnpacked(paramType)),
|
||||
hasDeclaredType: true,
|
||||
});
|
||||
}
|
||||
} else if (param.category === ParameterCategory.VarArgDictionary) {
|
||||
if (!isParamSpec(paramType)) {
|
||||
addError(Localizer.Diagnostic.arrowCallableNotParamSpec(), param.typeAnnotation);
|
||||
} else if (paramIndex !== node.parameters.length - 1) {
|
||||
addError(Localizer.Diagnostic.arrowCallableParamSpecNotLast(), param.typeAnnotation);
|
||||
} else {
|
||||
functionType.details.paramSpec = paramType;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (addPositionalOnly) {
|
||||
FunctionType.addParameter(functionType, {
|
||||
category: ParameterCategory.Simple,
|
||||
type: UnknownType.create(),
|
||||
});
|
||||
}
|
||||
|
||||
return { node, type: functionType, isIncomplete };
|
||||
}
|
||||
|
||||
function getTypeFromDictionary(node: DictionaryNode, expectedType: Type | undefined): TypeResult {
|
||||
// If the expected type is a union, analyze for each of the subtypes
|
||||
// to find one that matches.
|
||||
@ -16421,8 +16285,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
node.nodeType === ParseNodeType.PatternMapping ||
|
||||
node.nodeType === ParseNodeType.PatternValue ||
|
||||
node.nodeType === ParseNodeType.PatternMappingKeyEntry ||
|
||||
node.nodeType === ParseNodeType.PatternMappingExpandEntry ||
|
||||
node.nodeType === ParseNodeType.ArrowCallable
|
||||
node.nodeType === ParseNodeType.PatternMappingExpandEntry
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -207,15 +207,6 @@ export namespace Localizer {
|
||||
export const argPositionalExpectedOne = () => getRawString('Diagnostic.argPositionalExpectedOne');
|
||||
export const argTypePartiallyUnknown = () => getRawString('Diagnostic.argTypePartiallyUnknown');
|
||||
export const argTypeUnknown = () => getRawString('Diagnostic.argTypeUnknown');
|
||||
export const arrowCallableIllegal = () => getRawString('Diagnostic.arrowCallableIllegal');
|
||||
export const arrowCallableNeedsParen = () => getRawString('Diagnostic.arrowCallableNeedsParen');
|
||||
export const arrowCallableNotParamSpec = () => getRawString('Diagnostic.arrowCallableNotParamSpec');
|
||||
export const arrowCallableNotVariadicTypeVar = () => getRawString('Diagnostic.arrowCallableNotVariadicTypeVar');
|
||||
export const arrowCallableParamSpec = () => getRawString('Diagnostic.arrowCallableParamSpec');
|
||||
export const arrowCallableParamSpecNotLast = () => getRawString('Diagnostic.arrowCallableParamSpecNotLast');
|
||||
export const arrowCallableVariadicTypeVar = () => getRawString('Diagnostic.arrowCallableVariadicTypeVar');
|
||||
export const arrowCallableVariadicTypeVarUnpacked = () =>
|
||||
getRawString('Diagnostic.arrowCallableVariadicTypeVarUnpacked');
|
||||
export const assertAlwaysTrue = () => getRawString('Diagnostic.assertAlwaysTrue');
|
||||
export const assignmentExprContext = () => getRawString('Diagnostic.assignmentExprContext');
|
||||
export const assignmentExprComprehension = () =>
|
||||
|
@ -19,14 +19,6 @@
|
||||
"argPositionalExpectedOne": "Expected 1 positional argument",
|
||||
"argTypePartiallyUnknown": "Argument type is partially unknown",
|
||||
"argTypeUnknown": "Argument type is unknown",
|
||||
"arrowCallableIllegal": "Callable syntax requires Python 3.11 or newer",
|
||||
"arrowCallableNeedsParen": "Callable expression requires parentheses when used in union or with other operators",
|
||||
"arrowCallableNotParamSpec": "Expected ParamSpec after \"**\"",
|
||||
"arrowCallableNotVariadicTypeVar": "Expected TypeVarTuple after \"*\"",
|
||||
"arrowCallableParamSpec": "Expected \"**\" before ParamSpec",
|
||||
"arrowCallableParamSpecNotLast": "ParamSpec must be the last parameter",
|
||||
"arrowCallableVariadicTypeVarUnpacked": "TypeVarTuple is already unpacked; \"*\" is redundant",
|
||||
"arrowCallableVariadicTypeVar": "Expected \"*\" before TypeVarTuple",
|
||||
"assertAlwaysTrue": "Assert expression always evaluates to true",
|
||||
"assignmentExprContext": "Assignment expression must be within module, function or lambda",
|
||||
"assignmentExprComprehension": "Assignment expression target \"{name}\" cannot use same name as comprehension for target",
|
||||
|
@ -104,7 +104,6 @@ export const enum ParseNodeType {
|
||||
PatternMappingExpandEntry,
|
||||
PatternValue,
|
||||
PatternClassArgument,
|
||||
ArrowCallable,
|
||||
}
|
||||
|
||||
export const enum ErrorExpressionCategory {
|
||||
@ -687,8 +686,7 @@ export type ExpressionNode =
|
||||
| ListNode
|
||||
| SetNode
|
||||
| DecoratorNode
|
||||
| FunctionAnnotationNode
|
||||
| ArrowCallableNode;
|
||||
| FunctionAnnotationNode;
|
||||
|
||||
export function isExpressionNode(node: ParseNode): node is ExpressionNode {
|
||||
switch (node.nodeType) {
|
||||
@ -720,7 +718,6 @@ export function isExpressionNode(node: ParseNode): node is ExpressionNode {
|
||||
case ParseNodeType.DictionaryExpandEntry:
|
||||
case ParseNodeType.List:
|
||||
case ParseNodeType.Set:
|
||||
case ParseNodeType.ArrowCallable:
|
||||
return true;
|
||||
|
||||
default:
|
||||
@ -2247,52 +2244,6 @@ export namespace PatternValueNode {
|
||||
}
|
||||
}
|
||||
|
||||
export interface ArrowCallableParameter {
|
||||
category: ParameterCategory;
|
||||
typeAnnotation: ExpressionNode;
|
||||
starToken?: Token;
|
||||
}
|
||||
|
||||
export interface ArrowCallableNode extends ParseNodeBase {
|
||||
readonly nodeType: ParseNodeType.ArrowCallable;
|
||||
isAsync?: boolean;
|
||||
parameters: ArrowCallableParameter[];
|
||||
returnTypeAnnotation: ExpressionNode;
|
||||
}
|
||||
|
||||
export namespace ArrowCallableNode {
|
||||
export function create(
|
||||
openParenToken: Token,
|
||||
parameters: ArrowCallableParameter[],
|
||||
returnTypeAnnotation: ExpressionNode,
|
||||
asyncToken?: Token
|
||||
) {
|
||||
const node: ArrowCallableNode = {
|
||||
start: openParenToken.start,
|
||||
length: openParenToken.length,
|
||||
nodeType: ParseNodeType.ArrowCallable,
|
||||
id: _nextNodeId++,
|
||||
parameters,
|
||||
returnTypeAnnotation,
|
||||
};
|
||||
|
||||
if (asyncToken) {
|
||||
node.isAsync = true;
|
||||
extendRange(node, asyncToken);
|
||||
}
|
||||
|
||||
extendRange(node, returnTypeAnnotation);
|
||||
|
||||
parameters.forEach((expr) => {
|
||||
expr.typeAnnotation.parent = node;
|
||||
});
|
||||
|
||||
returnTypeAnnotation.parent = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export type PatternAtomNode =
|
||||
| PatternSequenceNode
|
||||
| PatternLiteralNode
|
||||
@ -2306,7 +2257,6 @@ export type PatternAtomNode =
|
||||
export type ParseNode =
|
||||
| ErrorNode
|
||||
| ArgumentNode
|
||||
| ArrowCallableNode
|
||||
| AssertNode
|
||||
| AssignmentExpressionNode
|
||||
| AssignmentNode
|
||||
|
@ -25,8 +25,6 @@ import { Localizer } from '../localization/localize';
|
||||
import {
|
||||
ArgumentCategory,
|
||||
ArgumentNode,
|
||||
ArrowCallableNode,
|
||||
ArrowCallableParameter,
|
||||
AssertNode,
|
||||
AssignmentExpressionNode,
|
||||
AssignmentNode,
|
||||
@ -2846,14 +2844,6 @@ export class Parser {
|
||||
|
||||
// or_test: and_test ('or' and_test)*
|
||||
private _parseOrTest(): ExpressionNode {
|
||||
// Is the next expression possibly an arrow callable?
|
||||
if (this._peekKeywordType() === KeywordType.Async || this._peekTokenType() === TokenType.OpenParenthesis) {
|
||||
const possibleArrowCall = this._parseArrowCall();
|
||||
if (possibleArrowCall) {
|
||||
return possibleArrowCall;
|
||||
}
|
||||
}
|
||||
|
||||
let leftExpr = this._parseAndTest();
|
||||
if (leftExpr.nodeType === ParseNodeType.Error) {
|
||||
return leftExpr;
|
||||
@ -3545,12 +3535,6 @@ export class Parser {
|
||||
}
|
||||
|
||||
if (nextToken.type === TokenType.OpenParenthesis) {
|
||||
const possibleArrowCall = this._parseArrowCall();
|
||||
if (possibleArrowCall) {
|
||||
this._addError(Localizer.Diagnostic.arrowCallableNeedsParen(), possibleArrowCall);
|
||||
return possibleArrowCall;
|
||||
}
|
||||
|
||||
const possibleTupleNode = this._parseTupleAtom();
|
||||
if (
|
||||
possibleTupleNode.nodeType === ParseNodeType.Tuple &&
|
||||
@ -3610,14 +3594,6 @@ export class Parser {
|
||||
return ConstantNode.create(this._getNextToken() as KeywordToken);
|
||||
}
|
||||
|
||||
if (keywordToken.keywordType === KeywordType.Async) {
|
||||
const possibleArrowCall = this._parseArrowCall();
|
||||
if (possibleArrowCall) {
|
||||
this._addError(Localizer.Diagnostic.arrowCallableNeedsParen(), possibleArrowCall);
|
||||
return possibleArrowCall;
|
||||
}
|
||||
}
|
||||
|
||||
// Make an identifier out of the keyword.
|
||||
const keywordAsIdentifier = this._getTokenIfIdentifier();
|
||||
if (keywordAsIdentifier) {
|
||||
@ -3685,114 +3661,6 @@ export class Parser {
|
||||
return this._parseLambdaExpression(allowConditional);
|
||||
}
|
||||
|
||||
// Attempts to parse an arrow call. If it is not a valid arrow call,
|
||||
// it returns undefined without emitting any diagnostics. If it is
|
||||
// an arrow call (as evidenced by a "->" token after the close paren),
|
||||
// it returns an ArrowCallableNode. This method should be called when
|
||||
// the next token is either an open paren or an "async" keyword.
|
||||
// arrow_call: 'async'? '(' arrow_parameters ')' '->' test
|
||||
private _parseArrowCall(): ArrowCallableNode | undefined {
|
||||
let smellsLikeArrowCall = false;
|
||||
|
||||
// Do a lookahead operation to see if this smells like an arrow
|
||||
// call. If not, it's probably a normal parenthesis or tuple
|
||||
// expression.
|
||||
const curTokenIndex = this._tokenIndex;
|
||||
this._consumeTokenIfKeyword(KeywordType.Async);
|
||||
|
||||
if (this._consumeTokenIfType(TokenType.OpenParenthesis)) {
|
||||
let parenLevel = 1;
|
||||
smellsLikeArrowCall = true;
|
||||
|
||||
while (parenLevel > 0) {
|
||||
const nextToken = this._getNextToken();
|
||||
if (nextToken.type === TokenType.OpenParenthesis) {
|
||||
parenLevel++;
|
||||
} else if (nextToken.type === TokenType.CloseParenthesis) {
|
||||
parenLevel--;
|
||||
} else if (nextToken.type === TokenType.EndOfStream) {
|
||||
smellsLikeArrowCall = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._consumeTokenIfType(TokenType.Arrow)) {
|
||||
smellsLikeArrowCall = false;
|
||||
}
|
||||
}
|
||||
|
||||
this._tokenIndex = curTokenIndex;
|
||||
|
||||
if (!smellsLikeArrowCall) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let asyncToken: Token | undefined = this._peekToken();
|
||||
if (!this._consumeTokenIfKeyword(KeywordType.Async)) {
|
||||
asyncToken = undefined;
|
||||
}
|
||||
|
||||
const openParenToken = this._peekToken();
|
||||
if (openParenToken.type !== TokenType.OpenParenthesis) {
|
||||
return undefined;
|
||||
}
|
||||
this._getNextToken();
|
||||
|
||||
const arrowCallableParams = this._parseArrowCallableParameterList();
|
||||
|
||||
// Consume the close paren and arrow tokens.
|
||||
this._getNextToken();
|
||||
this._getNextToken();
|
||||
|
||||
const returnTypeAnnotation = this._parseTypeAnnotation();
|
||||
|
||||
return ArrowCallableNode.create(openParenToken, arrowCallableParams, returnTypeAnnotation, asyncToken);
|
||||
}
|
||||
|
||||
private _parseArrowCallableParameterList(): ArrowCallableParameter[] {
|
||||
const paramList: ArrowCallableParameter[] = [];
|
||||
|
||||
while (true) {
|
||||
if (this._peekTokenType() === TokenType.CloseParenthesis) {
|
||||
break;
|
||||
}
|
||||
|
||||
const param = this._parseArrowCallableParameter();
|
||||
if (!param) {
|
||||
this._consumeTokensUntilType([TokenType.CloseParenthesis]);
|
||||
break;
|
||||
}
|
||||
|
||||
paramList.push(param);
|
||||
|
||||
const foundComma = this._consumeTokenIfType(TokenType.Comma);
|
||||
|
||||
if (!foundComma) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return paramList;
|
||||
}
|
||||
|
||||
private _parseArrowCallableParameter(): ArrowCallableParameter {
|
||||
const nextToken = this._peekToken();
|
||||
let category = ParameterCategory.Simple;
|
||||
let starToken: Token | undefined;
|
||||
|
||||
if (this._consumeTokenIfOperator(OperatorType.Multiply)) {
|
||||
category = ParameterCategory.VarArgList;
|
||||
starToken = nextToken;
|
||||
} else if (this._consumeTokenIfOperator(OperatorType.Power)) {
|
||||
category = ParameterCategory.VarArgDictionary;
|
||||
starToken = nextToken;
|
||||
}
|
||||
|
||||
const typeAnnotation = this._parseTypeAnnotation(/* allowUnpack */ true);
|
||||
|
||||
return { category, typeAnnotation, starToken };
|
||||
}
|
||||
|
||||
// ('(' [yield_expr | testlist_comp] ')'
|
||||
// testlist_comp: (test | star_expr) (comp_for | (',' (test | star_expr))* [','])
|
||||
private _parseTupleAtom(): ExpressionNode {
|
||||
|
@ -1,128 +0,0 @@
|
||||
# This sample tests the callable syntax described in PEP 677.
|
||||
|
||||
from typing import Callable, Concatenate, ParamSpec, TypeVar
|
||||
from typing_extensions import TypeVarTuple, Unpack
|
||||
|
||||
P = ParamSpec("P")
|
||||
T = TypeVar("T")
|
||||
Ts = TypeVarTuple("Ts")
|
||||
|
||||
def func0(
|
||||
a: (int, str) -> float,
|
||||
b: (int | str) -> (int | str),
|
||||
c: (...) -> (complex, str) -> int | None
|
||||
) -> (int, str) -> None:
|
||||
...
|
||||
reveal_type(func0, expected_text='(a: (int, str) -> float, b: (int | str) -> (int | str), c: (...) -> ((complex, str) -> int | None)) -> ((int, str) -> None)')
|
||||
|
||||
def func1() -> async (int, str) -> bool:
|
||||
...
|
||||
reveal_type(func1, expected_text='() -> ((int, str) -> Awaitable[bool])')
|
||||
|
||||
def func2() -> ((int, str) -> bool):
|
||||
...
|
||||
reveal_type(func2, expected_text='() -> ((int, str) -> bool)')
|
||||
|
||||
def func3() -> (int) -> (str) -> bool:
|
||||
...
|
||||
reveal_type(func3, expected_text='() -> ((int) -> ((str) -> bool))')
|
||||
|
||||
def func4() -> ((int) -> ((str) -> bool)):
|
||||
...
|
||||
reveal_type(func4, expectedText='() -> ((int) -> ((str) -> bool))')
|
||||
|
||||
def func5() -> (T) -> T:
|
||||
...
|
||||
reveal_type(func5, expected_text='() -> ((T@func5) -> T@func5)')
|
||||
|
||||
|
||||
A1 = (int) -> str | bool
|
||||
reveal_type(A1, expected_text='(int) -> (str | bool)')
|
||||
|
||||
A2 = (int) -> (str | bool)
|
||||
reveal_type(A2, expected_text='(int) -> (str | bool)')
|
||||
|
||||
|
||||
B1 = (int) -> (str) -> bool
|
||||
reveal_type(B1, expected_text='(int) -> ((str) -> bool)')
|
||||
|
||||
B2 = (int) -> ((str) -> bool)
|
||||
reveal_type(B2, expected_text='(int) -> ((str) -> bool)')
|
||||
|
||||
|
||||
# This should generate an error because parens are needed.
|
||||
C1 = () -> int | () -> bool
|
||||
|
||||
C2 = () -> int | (() -> bool)
|
||||
reveal_type(C2, expected_text='() -> (int | (() -> bool))')
|
||||
|
||||
C3 = (() -> int) | (() -> bool)
|
||||
reveal_type(C3, expected_text='(() -> int) | (() -> bool)')
|
||||
|
||||
D0 = (int,) -> bool
|
||||
reveal_type(D0, expected_text='(int) -> bool')
|
||||
|
||||
D1 = (int) -> bool
|
||||
reveal_type(D1, expected_text='(int) -> bool')
|
||||
|
||||
D2 = (int, T, **P,) -> bool
|
||||
reveal_type(D2, expected_text='(int, T@D2, **P@D2) -> bool')
|
||||
|
||||
D3 = (int, T, **P) -> bool
|
||||
reveal_type(D3, expected_text='(int, T@D3, **P@D3) -> bool')
|
||||
|
||||
D4 = (...,) -> bool
|
||||
reveal_type(D4, expected_text='(...) -> bool')
|
||||
|
||||
D5 = (...) -> bool
|
||||
reveal_type(D5, expected_text='(...) -> bool')
|
||||
|
||||
E1 = Callable[Concatenate[int, T, P], bool]
|
||||
reveal_type(E1, expected_text='(int, T@E1, **P@E1) -> bool')
|
||||
|
||||
E2 = (int, T, **P) -> bool
|
||||
reveal_type(E2, expected_text='(int, T@E2, **P@E2) -> bool')
|
||||
|
||||
F1 = (...) -> int
|
||||
reveal_type(F1, expected_text='(...) -> int')
|
||||
|
||||
# This should generate an error because * can't be used with ellipsis.
|
||||
F2 = (*...) -> int
|
||||
|
||||
# This should generate an error because ** can't be used with ellipsis.
|
||||
F3 = (**...) -> int
|
||||
|
||||
# This should generate an error because ellipsis must be the only parameter.
|
||||
F4 = (..., str) -> int
|
||||
|
||||
# This should generate an error because ellipsis must be the only parameter.
|
||||
F5 = (int, str, ...) -> int
|
||||
|
||||
|
||||
G1 = (int, *Ts, str) -> int
|
||||
reveal_type(G1, expected_text='(int, *Ts@G1, str) -> int')
|
||||
|
||||
G2 = (int, Unpack[Ts], str) -> int
|
||||
reveal_type(G2, expected_text='(int, *Ts@G2, str) -> int')
|
||||
|
||||
# This should generate an error because Ts is doubly unpacked.
|
||||
G3 = (int, *Unpack[Ts], str) -> int
|
||||
|
||||
# This should generate an error because int isn't a TypeVarTuple
|
||||
G4 = (*int, str) -> int
|
||||
|
||||
# This should generate an error because P isn't a TypeVarTuple
|
||||
G5 = (*P, str) -> int
|
||||
|
||||
|
||||
H1 = (int, **P) -> int
|
||||
reveal_type(H1, expected_text='(int, **P@H1) -> int')
|
||||
|
||||
# This should generate an error because P isn't preceded by **.
|
||||
H2 = (int, P) -> int
|
||||
|
||||
# This should generate an error because int isn't a ParamSpec.
|
||||
H3 = (int, **int) -> int
|
||||
|
||||
# This should generate an error because P isn't the last parameter.
|
||||
H4 = (**P, int) -> int
|
@ -1,26 +0,0 @@
|
||||
# This sample tests the callable syntax described in PEP 677. Specifically,
|
||||
# it tests that an error is generated when not using Python 3.11.
|
||||
|
||||
from typing import TypeAlias, TypeVar
|
||||
|
||||
|
||||
# This should generate an error when using versions of Python prior to 3.11.
|
||||
A1 = (int) -> int
|
||||
|
||||
A2: TypeAlias = "(int) -> int"
|
||||
|
||||
def func1(a: "(int) -> (() -> None)") -> "(...) -> int":
|
||||
...
|
||||
|
||||
# This should generate an error when using versions of Python prior to 3.11.
|
||||
def func2(a: (int) -> int) -> int:
|
||||
...
|
||||
|
||||
# This should generate an error when using versions of Python prior to 3.11.
|
||||
# Although the annotation is enclosed in parentheses, the interpreter
|
||||
# still attempts to parse it.
|
||||
T1 = TypeVar("T1", bound="(int) -> int")
|
||||
|
||||
# This should generate an error when using versions of Python prior to 3.11.
|
||||
T2 = TypeVar("T2", int, "(int) -> int")
|
||||
|
@ -1,83 +0,0 @@
|
||||
# This sample tests deeply-nested parentheses, which can cause problems
|
||||
# in the parser for arrow callables.
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def func(*args: Any):
|
||||
...
|
||||
|
||||
|
||||
def func2(*args: Any) -> str:
|
||||
...
|
||||
|
||||
|
||||
def func3(a: str | None, b: str | None, x: str | None, y: str | None, z1: int, z2: int):
|
||||
func(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
"text "
|
||||
+ func2(
|
||||
(
|
||||
"null"
|
||||
if a is None
|
||||
else a
|
||||
)
|
||||
+ (
|
||||
"null"
|
||||
if b is None
|
||||
else b
|
||||
)
|
||||
)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ (
|
||||
"null"
|
||||
if x is None
|
||||
else x
|
||||
)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ ("null" if y is None else y)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ func2(
|
||||
(("null" if ((y is None)) else str(y)))
|
||||
)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ ("null" if y is None else y)
|
||||
)
|
||||
+ " => "
|
||||
)
|
||||
+ str(z1)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ str(z2)
|
||||
)
|
||||
+ " "
|
||||
)
|
||||
+ str(type(z1))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
x: (((((((((((((() -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None) -> None)
|
@ -1,7 +1,7 @@
|
||||
# This sample validates that the await keyword participates in
|
||||
# bidirectional type inference.
|
||||
|
||||
from typing import TypeVar, Generic
|
||||
from typing import Callable, TypeVar, Generic
|
||||
|
||||
T = TypeVar("T")
|
||||
AnyMsg = TypeVar("AnyMsg", bound="Msg")
|
||||
@ -15,7 +15,7 @@ class Request:
|
||||
id: int
|
||||
|
||||
|
||||
async def func1(check: "(AnyMsg) -> bool") -> AnyMsg:
|
||||
async def func1(check: "Callable[[AnyMsg], bool]") -> AnyMsg:
|
||||
...
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# bidirectional type inference and one or more of the parameters
|
||||
# corresponds to a generic type.
|
||||
|
||||
from typing import TypeVar, Generic, Any
|
||||
from typing import Callable, TypeVar, Generic, Any
|
||||
|
||||
T = TypeVar("T")
|
||||
MsgT = TypeVar("MsgT", bound="Msg[Any]")
|
||||
@ -16,7 +16,7 @@ class Request:
|
||||
...
|
||||
|
||||
|
||||
def check(func: "(MsgT, int) -> object") -> MsgT:
|
||||
def check(func: "Callable[[MsgT, int], object]") -> MsgT:
|
||||
...
|
||||
|
||||
|
||||
|
@ -1197,34 +1197,6 @@ test('Descriptor1', () => {
|
||||
TestUtils.validateResults(analysisResults, 6);
|
||||
});
|
||||
|
||||
test('ArrowCallable1', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_11;
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['arrowCallable1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults, 11);
|
||||
});
|
||||
|
||||
test('ArrowCallable2', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['arrowCallable2.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults1, 4);
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_11;
|
||||
const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['arrowCallable2.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults2, 0);
|
||||
});
|
||||
|
||||
test('ArrowCallable3', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_11;
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['arrowCallable3.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('Partial1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['partial1.py']);
|
||||
|
||||
|
@ -30,7 +30,8 @@ Pyright supports [configuration files](/docs/configuration.md) that provide gran
|
||||
* [PEP 647](https://www.python.org/dev/peps/pep-0647/) user-defined type guards
|
||||
* [PEP 655](https://www.python.org/dev/peps/pep-0655/) required typed dictionary items
|
||||
* [PEP 673](https://www.python.org/dev/peps/pep-0673/) Self type
|
||||
* [PEP 677](https://www.python.org/dev/peps/pep-0677/) callable type syntax
|
||||
* [PEP 675](https://www.python.org/dev/peps/pep-0675/) arbitrary literal strings
|
||||
* [PEP 681](https://www.python.org/dev/peps/pep-0681/) dataclass transform
|
||||
* Type inference for function return values, instance variables, class variables, and globals
|
||||
* Type guards that understand conditional code flow constructs like if/else statements
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user