Removed provisional support for PEP 677 (Alternate Call Syntax) because the proposal was rejected by the Python steering council.

This commit is contained in:
Eric Traut 2022-02-16 22:19:39 -08:00
parent ef72e4079c
commit 9949577ced
15 changed files with 8 additions and 642 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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
);
}

View File

@ -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 = () =>

View File

@ -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",

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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:
...

View File

@ -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:
...

View File

@ -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']);

View File

@ -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