chore(vipeye-internal): 修剪 samples 残留与孤儿测试辅助
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled

- samples 根目录 1277 个散落 .py/.pyi 夹具删除,仅保留被现存用例引用的 15 个
  (badToken1/test_file1/lines1/parser1-2/suiteExpectedColon1-3/maxParseDepth1-2/
   parserRecovery1-3/fstring6/finallyExit1)+ 2 个 viper_*.vp;子目录夹具不动
- 删除已无引用的 harness/fourslash/runner.ts(fourslash 夹具与 testState.test 已删)
- 保留 tests/lsp/languageServerTestUtils.ts:仍被 typeServer.virtualFileRedirect 引用

验证: 全量串行 53 套件通过、1 跳过,732 用例全绿
This commit is contained in:
TermiNexus committed 2026-09-18 23:10:41 +08:00
1 parent 04d5a32502
commit c9acd4ecb8
1269 files changed
-61780

No files matched your search

@@ -1,93 +0,0 @@
/*
* runner.ts
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*
* Provide APIs to run fourslash tests from provided fourslash markup contents
*/
import * as ts from 'typescript';
import { combinePaths } from '../../../common/pathUtils';
import * as host from '../testHost';
import { parseTestData } from './fourSlashParser';
import { FourSlashData } from './fourSlashTypes';
import { TestState, TestStateOptions } from './testState';
import { Consts } from './testState.Consts';
export type TestStateFactory = (basePath: string, testData: FourSlashData, options?: TestStateOptions) => TestState;
/**
* run given fourslash test file
*
* @param basePath this is used as a base path of the virtual file system the test will run upon
* @param fileName this is the file path where fourslash test file will be read from
*/
export function runFourSlashTest(
basePath: string,
fileName: string,
cb?: jest.DoneCallback,
stateOptions?: TestStateOptions,
testStateFactory?: TestStateFactory
) {
const content = host.HOST.readFile(fileName)!;
runFourSlashTestContent(basePath, fileName, content, cb, stateOptions, testStateFactory);
}
/**
* run given fourslash markup content
*
* @param basePath this is used as a base path of the virtual file system the test will run upon
* @param fileName this will be used as a filename of the given `content` in the virtual file system
* if fourslash markup `content` doesn't have explicit `@filename` option
* @param content this is fourslash markup string
*/
export function runFourSlashTestContent(
basePath: string,
fileName: string,
content: string,
cb?: jest.DoneCallback,
stateOptions?: TestStateOptions,
testStateFactory?: TestStateFactory
) {
// give file paths an absolute path for the virtual file system
const absoluteBasePath = combinePaths('/', basePath);
const absoluteFileName = combinePaths('/', fileName);
// parse out the files and their metadata
const testData = parseTestData(absoluteBasePath, content, absoluteFileName);
const state =
testStateFactory !== undefined
? testStateFactory(absoluteBasePath, testData, stateOptions)
: new TestState(absoluteBasePath, testData, stateOptions);
const output = ts.transpileModule(content, {
reportDiagnostics: true,
compilerOptions: { target: ts.ScriptTarget.ES2019 },
});
if (output.diagnostics!.length > 0) {
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics![0].messageText}`);
}
runCode(output.outputText, state, cb);
}
async function runCode(code: string, state: TestState, cb?: jest.DoneCallback) {
// Compile and execute the test
try {
const wrappedCode = `(async function(helper, Consts) {
${code}
})`;
const f = eval(wrappedCode); // CodeQL [SM01632] test code that doesn't need to be secure.
await f(state, Consts);
markDone();
} catch (ex) {
markDone(ex);
}
function markDone(...args: any[]) {
if (cb) {
cb(...args);
}
state.dispose();
}
}
@@ -1,55 +0,0 @@
# This sample tests the type analyzer's ability to flag attempts
# to instantiate abstract base classes.
from abc import ABC, abstractmethod
class AbstractClassA(ABC):
@abstractmethod
def foo1(self):
pass
@abstractmethod
def foo2(self):
pass
def foo3(self):
return 3
@classmethod
def foo4(cls):
# This should not generate an error even though
# it would appear to be attempting to instantiate
# an abstract class. That's because we need to
# assume that the caller is making this call on
# a non-abstract subclass.
return cls()
v1 = [subclass() for subclass in AbstractClassA.__subclasses__()]
reveal_type(v1, expected_text="list[AbstractClassA]")
# This should generate an error because AbstractFoo
# is an abstract class.
a = AbstractClassA()
class AbstractClassB(AbstractClassA):
def foo1(self):
pass
# This should generate an error because AbstractBar1
# is an abstract class.
b = AbstractClassB()
class AbstractClassC(AbstractClassB):
def foo2(self):
pass
# This should not generate an error because AbstractBar2
# overrides all of the abstract methods it inherits.
c = AbstractClassC()
@@ -1,75 +0,0 @@
# This sample tests the detection of static or class method invocations
# where the method is marked abstract.
from abc import ABC, abstractmethod
class A(ABC):
@staticmethod
@abstractmethod
def method1() -> None: ...
@staticmethod
@abstractmethod
def method2() -> None:
pass
@classmethod
@abstractmethod
def method3(cls) -> None:
raise NotImplementedError
@classmethod
@abstractmethod
def method4(cls) -> None:
pass
# This should generate an error.
A.method1()
A.method2()
# This should generate an error.
A.method3()
A.method4()
class B(A):
@staticmethod
def method1() -> None:
# This should generate an error.
return super(B).method1()
@staticmethod
def method2() -> None:
return super(B).method2()
@classmethod
def method3(cls) -> None:
# This should generate an error.
return super().method3()
@classmethod
def method4(cls) -> None:
return super().method4()
B.method1()
B.method2()
def func1(a: type[A]):
a.method1()
a.method3()
class C(A): ...
# This should generate an error.
C.method1()
# This should generate an error.
C.method3()
@@ -1,25 +0,0 @@
# This sample tests the handling of a class that is created from a subclass
# of ABCMeta.
from abc import ABCMeta, abstractmethod
from typing import final
class CustomMeta(ABCMeta):
pass
class A(metaclass=CustomMeta):
@abstractmethod
def abstract(self):
pass
@final
# This should generate an error.
class B(A):
pass
# This should generate an error.
B()
@@ -1,30 +0,0 @@
# This sample tests the cases where a mixin class
# overrides an abstract method, making it no longer abstract.
import abc
class InterfaceA(abc.ABC):
@abc.abstractmethod
def a(self) -> None:
print("InterfaceA.a")
class MixinA(InterfaceA):
def a(self) -> None:
print("MixinA.a")
class InterfaceAB(InterfaceA):
@abc.abstractmethod
def b(self) -> None:
print("InterfaceAB.b")
class ClassAB(InterfaceAB, MixinA):
def b(self) -> None:
print("ClassAB.b")
ab = ClassAB()
ab.a()
@@ -1,30 +0,0 @@
# This sample tests the checks for abstract method
# overrides. They depend on the order of the subclasses.
import abc
class MixinA(abc.ABC):
pass
class MixinB(abc.ABC):
def get_model(self):
print("MixinB.get_model")
class MixinC(abc.ABC):
@abc.abstractmethod
def get_model(self):
pass
def use_model(self):
print("MixinC.get_model")
class Trainer_1a(MixinA, MixinB, MixinC):
pass
# This should not generate an error
trainer = Trainer_1a()
@@ -1,30 +0,0 @@
# This sample tests the checks for abstract method
# overrides. They depend on the order of the subclasses.
import abc
class MixinA(abc.ABC):
pass
class MixinB(abc.ABC):
def get_model(self):
print("MixinB.get_model")
class MixinC(abc.ABC):
@abc.abstractmethod
def get_model(self):
pass
def use_model(self):
print("MixinC.get_model")
class Trainer_1b(MixinA, MixinC, MixinB):
pass
# This should generate an error
trainer = Trainer_1b()
@@ -1,54 +0,0 @@
# This sample tests the type checker's reporting of abstract
# overload mismatches.
from abc import ABC, abstractmethod
from typing import Union, overload
class ClassA(ABC):
@overload
def func1(self, a: int) -> int:
pass
@overload
@abstractmethod
# This should generate an error because this overload is
# missing an abstractmethod overload.
def func1(self, a: float) -> float:
pass
@overload
def func1(self, a: str) -> str: ...
def func1(self, a: Union[int, float, str]) -> Union[int, float, str]:
raise NotImplementedError()
@overload
def func2(self, a: str) -> str: ...
@overload
@abstractmethod
def func2(self, a: int) -> int:
pass
@abstractmethod
def func2(self, a: Union[int, str]) -> Union[int, str]:
raise NotImplementedError()
@overload
def func3(self, a: str) -> str: # viper: ignore[reportNoOverloadImplementation]
...
@overload
@abstractmethod
# This should generate an error because the abstract status is inconsistent.
def func3(self, a: int) -> int: ...
@overload
@abstractmethod
def func4(self, a: str) -> str: # viper: ignore[reportNoOverloadImplementation]
...
@overload
# This should generate an error because the abstract status is inconsistent.
def func4(self, a: int) -> int: ...
@@ -1,37 +0,0 @@
# This sample validates that a variable that is annotated as
# Type[X] where X refers to an abstract base class does not
# emit an error when the variable is instantiated.
from abc import ABC, abstractmethod
from typing import Type, TypeVar
class Base(ABC):
@abstractmethod
def method1(self, x: int) -> int:
pass
def func1(base_cls: Type[Base]):
base_cls()
def func2():
# This should generate an error.
Base()
def func3(base_cls: type[Base]):
base_cls()
T = TypeVar("T")
def create_instance(cls: Type[T]) -> T:
return cls()
def func4():
base = create_instance(Base)
base.method1(1)
@@ -1,22 +0,0 @@
# This sample verifies that Protocol classes are treated as
# abstract even though they don't derive from ABCMeta.
from typing import Protocol, Tuple
from abc import abstractmethod
class RGB(Protocol):
rgb: Tuple[int, int, int]
@abstractmethod
def intensity(self) -> int:
return 0
class Point(RGB):
def __init__(self, red: int, green: int, blue: int) -> None:
self.rgb = red, green, blue
# This should generate an error because "intensity" is not implemented.
p = Point(1, 2, 3)
@@ -1,26 +0,0 @@
# This sample tests the check for abstract methods on a final class.
from typing import final
from abc import ABC, abstractmethod
class Foo(ABC):
@abstractmethod
def foo(self):
pass
class Bar(Foo):
@abstractmethod
def bar(self):
pass
@abstractmethod
def bar2(self):
pass
@final
# This should generate an error because Foo.foo, Bar.bar, and Bar.bar1
# are abstract.
class Baz(Bar): ...
@@ -1,22 +0,0 @@
# This sample tests that named tuple fields override abstract methods.
# viper: reportIncompatibleVariableOverride=false
from abc import ABC, abstractmethod
from typing import NamedTuple
class ClassA(ABC):
@property
@abstractmethod
def myproperty(self) -> str: ...
MixinB = NamedTuple("MixinB", [("myproperty", str)])
class ClassB(MixinB, ClassA):
pass
ClassB(myproperty="myproperty")
@@ -1,102 +0,0 @@
# This sample tests handling of the Python 3.9 "Annotated" feature
# described in PEP 593.
from dataclasses import InitVar, dataclass
from typing import Annotated, ClassVar, Final, TypeVar
class struct2:
@staticmethod
def ctype(a: str):
pass
class Packed:
pass
UnsignedShort = Annotated[int, struct2.ctype("H")]
SignedChar = Annotated[int, struct2.ctype("b")]
class Student(struct2.Packed):
name: Annotated[str, struct2.ctype("<10s")]
serial_num: UnsignedShort
school: SignedChar
def ValueRange(a: int, b: int):
pass
T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]
a: Annotated[Annotated[int, "hi"], "hi"] = 3
b: T2 = 5
TypeWithStringArg = Annotated["int", "this string should not be parsed"]
def func2(a: TypeWithStringArg):
return 3
# This should generate an error because the first type argument
# is not a valid type.
c: Annotated["this", "should generate an error"]
# This should generate an error because all Annotated types should
# include at least two type arguments.
d: Annotated[int]
# Verify that generic type aliases can be defined using Annotated.
_T = TypeVar("_T")
Param = Annotated[_T, "x"]
x1: Param[int] = 3
print(Param[int])
class A:
classvar: Annotated[ClassVar[int], (2, 5)] = 4
const: Annotated[Final[int], "metadata"] = 4
@dataclass
class B:
x: Annotated[InitVar[int], "metadata"]
d1 = B(x=4)
# This should generate an error because x is not an actual member.
d1.x
Alias1 = Annotated[_T, ""]
Alias2 = str
Alias3 = Alias1[Alias2]
reveal_type(Alias3, expected_text="type[str]")
x2: Annotated[str, [*(1, 2)]]
x3: Annotated[str, (temp := 1)]
async def func3():
x4: Annotated[str, await func3()]
x5: Annotated[str, f""]
x6: Annotated[str, "abc"]
x7: Annotated[str, "a\nb"]
x8: Annotated[str, *(1, 2, 3)]
def func4():
return Annotated[int, 2 + 2]
reveal_type(func4(), expected_text="Annotated")
x9 = list[Annotated[int, ""]]()
reveal_type(x9, expected_text="list[int]")
@@ -1,16 +0,0 @@
# This sample tests the case where Annotated is used with deferred
# annotation evaluation.
from __future__ import annotations
from typing import Annotated
v1: Annotated[str, ClassA, func1(), v2[0]] = ""
v2 = [1, 2, 3]
class ClassA: ...
def func1(): ...
@@ -1,20 +0,0 @@
# This sample tests type annotations on variables.
array1 = [1, 2, 3]
# This should generate an error because the LHS can't
# have a declared type.
array1[2] = 4 # type: int
dict1 = {}
# This should generate an error because the LHS can't
# have a declared type.
dict1["hello"] = 4 # type: int
def foo():
a: int = 3
b: float = 4.5
c: str = ""
d: int = yield 42
@@ -1,28 +0,0 @@
# This sample tests annotated types on global variables.
# This should generate an error because the declared
# type below does not match the assigned type.
glob_var1 = 4
# This should generate an error because the declared
# type doesn't match the later declared type.
glob_var1 = Exception() # type: str
glob_var1 = Exception() # type: Exception
# This should generate an error because the assigned
# type doesn't match the declared type.
glob_var1 = "hello" # type: Exception
# This should generate an error.
glob_var2 = 5
def func1():
global glob_var1
global glob_var2
# This should generate an error.
glob_var1 = 3
glob_var2 = "hello" # type: str
@@ -1,54 +0,0 @@
# This sample tests annotated types on local variables.
from typing import Any, Optional, Union
class ClassB(object):
def __enter__(self) -> bytes:
return b"hello"
def __exit__(
self,
t: Optional[type] = None,
exc: Optional[BaseException] = None,
tb: Optional[Any] = None,
) -> bool:
return True
def func2():
local_var = 3 # type: Union[int, str]
local_var = "hello"
# This should generate an error because the assigned
# type doesn't match the declared type.
local_var = b"hello"
local_var2 = 3 # type: int
if local_var:
# This should generate an error because the
# assigned type doesn't match.
local_var = 3.4
else:
# This should generate an error because the assigned
# type doesn't match the declared type.
local_var2 = b"hello"
# This should generate an error because the declared type
# of local_var is not compatible.
with ClassB() as local_var:
pass
bytes_list = [b"hello"]
# This should generate an error because the declared type
# of local_var is not compatible.
for local_var in bytes_list:
pass
# This should generate an error.
(local_var, local_var2) = (b"hello", 3)
# This should generate an error.
(local_var, local_var2) = ("hello", b"h")
@@ -1,24 +0,0 @@
# This sample tests annotated types for class variables.
class ClassA(object):
# This should generate an error because the declared
# type doesn't match the latter declared type.
class_var1 = 4 # type: str
# This should generate an error because the assigned
# value doesn't match the declared type.
class_var1 = "hello" # type: int
class_var1 = 3 # type: int
# This should generate an error because the declared
# type doesn't match the latter declared type.
class_var2 = 3 # type: int
def __init__(self):
# This should generate an error because the assigned
# type doesn't match the declared type.
self.class_var2 = 3 # type: str
self.class_var2 = "hello"
@@ -1,37 +0,0 @@
# This sample tests type annotations for instance variables.
class ClassC(object):
def __init__(self):
self.inst_var1 = 3
@property
def prop1(self):
return 1
@prop1.setter
def prop1(self, val):
pass
def foo(self):
# This should generate an error because the assigned
# type doesn't match the declared type.
self.inst_var1 = 3 # type: str
self.inst_var1: str = "hello"
# This should generate an error because the declared
# type doesn't match the previously declared type.
self.inst_var1: int = "hello"
# This should generate an error because the assigned
# type doesn't match the declared type.
self.inst_var1 = "hello" # type: int
self.prop1 = 3
class ClassE(ClassC):
def __init__(self):
# This should generate an error.
self.inst_var1 = 3
@@ -1,22 +0,0 @@
# This sample tests that class-scoped variables with a declared type
# but without a ClassVar designation are treated as instance variables.
# Notably, Callable variables should be assumed to be pre-bound to
# the object.
from typing import Callable
def add1(n: int):
return n + 1
class Foo:
f: Callable[[int], int]
def m(self):
print(self.f(1))
foo = Foo()
foo.f = add1
foo.m()
@@ -1,13 +0,0 @@
# This sample tests the reportTypeCommentUsage diagnostic check.
# This should generate an error if reportTypeCommentUsage is enabled.
x = 3 # type: int
class Foo:
# This should generate an error if reportTypeCommentUsage is enabled.
y = 0 # type: int
def __init__(self):
# This should generate an error if reportTypeCommentUsage is enabled.
self.x = 2 # type: int
@@ -1,29 +0,0 @@
# This sample tests that incompatible types implicitly assigned
# to an annotated variable via an import statement are flagged
# as an error.
from typing import Callable, Final
# This should generate an error because random is already declared.
import random
random: int = 3
# This should generate an error because os is Final
import os.path
os: Final = 3
# This should generate an error because x is already declared.
from math import pow as x
x: Callable[[], None]
# This should generate an error because pow is already declared.
from math import pow
pow: int = 3
y: Callable[[float, float], float]
from math import pow as y
@@ -1,159 +0,0 @@
# This sample tests the handling of type annotations within a
# python source file (as opposed to a stub file).
from typing import Any, Callable, TypeVar, Union
import uuid
from datetime import datetime
class ClassA:
# This should generate an error because ClassA
# is not yet defined at the time it's used.
def func0(self) -> ClassA | None:
return None
class ClassB(ClassA):
def func1(self) -> ClassA:
return ClassA()
# This should generate an error because ClassC
# is a forward reference, which is not allowed
# in a python source file.
def func2(self) -> ClassC | None:
return None
def func3(self) -> "ClassC | None":
return None
def func4(self) -> "ClassC | None":
return None
def func5(self) -> "int | None":
return None
class ClassC:
pass
def func10():
pass
# This should generate an error because function calls
# are not allowed within a type annotation.
x1: func10()
x2: """
Union[
int,
str
]
"""
class ClassD:
ClassA: "ClassA"
# This should generate an error because ClassF refers
# to itself, and there is no ClassF declared at the module
# level. It should also generate a second error because
# ClassF is a variable and can't be used as an annotation.
ClassF: "ClassF"
str: "str"
def int(self): ...
foo: "int"
# This should generate an error because it refers to the local
# "int" symbol rather than the builtins "int".
bar: int
# This should generate an error because modules are not allowed in
# type annotations.
x3: typing
class ClassG:
uuid = uuid.uuid4()
class ClassH:
# This should generate an error because uuid refers to the local
# symbol in this case, which is a circular reference.
uuid: uuid.UUID = uuid.uuid4()
def func11():
for t in [str, float]:
# This should generate an error because t is not a valid annotation.
def f(x: str) -> t:
return t(x) + 1
f("")
def func12(x: type[int]):
# These should not generate an error because they are used
# in a location that is not considered a type annotation, so the
# normal annotation limitations do not apply here.
print(Union[x, x])
print(x | None)
# This should generate an error because x4 isn't defined.
x4: int = x4
class ClassJ:
datetime: datetime
T = TypeVar("T")
x5: type[int] = int
# This should generate an error because variables are not allowed
# in a type annotation.
x6: x5 = 1
# This should generate an error because variables are not allowed
# in a type annotation.
x7: list[x5] = [1]
# This should generate an error because a Callable isn't allowed
# in a "type".
x8: type[Callable]
# This should generate an error because a Callable isn't allowed
# in a "type".
x9: type[func11]
# This should generate an error because a Callable isn't allowed
# in a "type".
x10: type[Callable[..., Any]]
# This should generate an error because raw strings aren't allowed.
x11: r"int"
# This should generate an error because bytes strings aren't allowed.
x12: b"int"
# This should generate an error because format strings aren't allowed.
x13: f"int"
class A:
def method1(self):
# This should result in an error.
x: self
@classmethod
def method2(cls):
# This should result in an error.
x: cls
@@ -1,33 +0,0 @@
# This sample tests the parser and type checker's ability to use
# type annotations in comments following assignment expressions.
# These are used in some older typestub files because they're
# compatible with versions of Python before 3.6.
from typing import List, Optional, Tuple
a = 3 # type: int
b = "3" # type: str
c = [1, 2, 3] # type: Optional[List[int]]
# A type on the next line shouldn't be honored
d = "hello"
# type: int
# A type comment with a space between the type and
# the colon is also not honored.
e = "hello" # type : int
# Neither is a capital "Type"
f = "hello" # Type: int
# This should generate an error because the type doesn't match
g = "hello" # type: int
# This should generate an error because the last entry
# of the tuple is the wrong type.
h = (1, "hello", (5,)) # type: Tuple[int, str, Tuple[str]]
@@ -1,37 +0,0 @@
# This sample tests the handling of type annotations within a
# python source file with the __future__ annotations symbol present.
from __future__ import annotations
from typing import Optional
class ClassA:
def func0(self) -> Optional[ClassA]:
return None
class ClassB(ClassA):
def func1(self) -> ClassA:
return ClassA()
def func2(self) -> Optional[ClassC]:
return None
def func3(self) -> "Optional[ClassC]":
return None
def func4(self) -> Optional["ClassC"]:
return None
def func5(self, x: ClassA):
x.func0()
class ClassA: ...
def func6(self, x: ClassC):
x.my_int
class ClassC:
my_int: int
@@ -1,67 +0,0 @@
# This sample tests the type checker's reporting of
# incompatible declared types.
from collections.abc import Callable
def a():
pass
# This should generate an error for an incompatible assignment.
a = 1
# This should generate an error for an obscured type.
def b():
pass
b: int = 1
# This should generate an error for an obscured type.
c: int = 1
c: float = 1.1
# This should generate two errors - one for an
# obscured type, the second for an incompatible assignment.
d: int = 2
def d():
pass
class Foo:
# This should generate an error because aa is redeclared.
aa: int
def aa(self):
return 3
# This should generate two errors, one for each param.
def my_func(param1: int, param2):
param1: int = 3
param2: int = 4
# This should be fine because both declarations of 'e'
# use the same type.
e: list[int]
e = [3]
e: list[int]
def register(fn: Callable[[], None]) -> None: ...
# These should be be fine because they use the "_" name.
@register
def _():
print("Callback 1 called")
@register
def _():
print("Callback 2 called")
@@ -1,9 +0,0 @@
# This sample tests the handling of tuple expressions within a subscript
# when used with type annotations.
a1: dict[(str, str)] = {"hi": "there"}
# This should generate an error because there are too many type arguments.
a2: dict[(str, str, str)] = {"hi": "there"}
b1: list[(int,)] = [3, 4, 5]
@@ -1,29 +0,0 @@
# This sample verifies that the Type[] and type[] annotations work
# as expected when the type argument is Any.
from typing import Type, Any
def is_type1(x: object, y: Type[Any]) -> bool:
return isinstance(x, y)
is_type1(1, int)
# This should generate an error.
is_type1(1, 1)
def is_type2(x: object, y: type[Any]) -> bool:
return isinstance(x, y)
is_type2(1, int)
# This should generate an error.
is_type2(1, 1)
def func1(v1: Type[Any], v2: type[Any]):
reveal_type(v1, expected_text="Type[Any]")
reveal_type(v2, expected_text="type[Any]")
@@ -1,45 +0,0 @@
# This sample tests certain uses of Any that should be flagged as illegal.
import typing
from typing import Any, cast
# This should generate an error because Any is not valid for isinstance.
isinstance(0, Any)
# This should generate an error because Any is not valid for isinstance.
isinstance(0, typing.Any)
v1 = cast(Any, 0)
v2 = cast(typing.Any, 0)
class A(Any): ...
class B(typing.Any): ...
# This should generate an error because Any is not callable.
Any()
# This should generate an error because Any is not callable.
typing.Any()
def func1() -> int:
# This should generate an error because Any cannot be used as a value.
return Any
def func2() -> int:
# This should generate an error because Any cannot be used as a value.
return typing.Any
v3: type[Any] = type(Any)
# This should generate an error.
v4: type[type] = type(Any)
# This should generate an error.
v5: type = Any
@@ -1,22 +0,0 @@
# This sample tests the ability to detect errant assert calls
# that are always true - the "reportAssertAlwaysTrue" option.
from typing import Any, Tuple
# This should generate a warning.
assert (1 != 2, "Error message")
def foo(a: Tuple[int, ...]):
assert a
b = ()
assert b
c = (2, 3)
# This should generate a warning.
assert c
@@ -1,48 +0,0 @@
# This sample tests the assert_type call.
from typing import Any, Literal
from typing_extensions import assert_type # viper: ignore[reportMissingModuleSource]
def func1():
# This should generate an error.
assert_type()
# This should generate an error.
assert_type(1)
# This should generate an error.
assert_type(1, 2, 3)
# This should generate an error.
assert_type(*[])
def func2(x: int, y: int | str, z: list):
assert_type(x, int)
# This should generate an error.
assert_type(x, str)
# This should generate an error.
assert_type(x, Any)
x = 3
assert_type(x, Literal[3])
# This should generate an error.
assert_type(x, int)
assert_type(y, int | str)
assert_type(y, str | int)
# This should generate an error.
assert_type(y, str)
# This should generate an error.
assert_type(y, None)
# This should generate two errors.
assert_type(y, 3)
assert_type(z[0], Any)
@@ -1,72 +0,0 @@
# This sample tests the type checker's handling of
# member assignments.
from not_present import NotPresentClass # type: ignore
class ClassA:
def __init__(self):
self.string_list: list[str] = []
def do_something(self, num: int) -> str:
return ""
a = ClassA()
a.string_list = ["yep"]
# This should generate an error because of a type mismatch.
a.string_list = "bbb"
# This should generate an error because of a type mismatch.
a.string_list = {}
# This should generate an error because of a type mismatch.
a.string_list = [1]
# This should generate an error because there is no member
# called string_list2 defined.
a.string_list2 = 4
def patch1(num: int) -> str:
return ""
def patch2(self, num: int) -> str:
return ""
a.do_something = lambda num: "hello"
a.do_something = patch1
# This should generate an error because of a param count mismatch
a.do_something = lambda: "hello"
# This should generate an error because of a return type mismatch
a.do_something = lambda x: 1
ClassA.do_something = patch2
# This should generate an error because of a param count mismatch
ClassA.do_something = patch1
class ClassB:
# This should generate an error because assignment expressions
# can't be used within a class.
[(j := i) for i in range(5)]
class ClassC:
def __init__(self):
self.x = NotPresentClass # type: int
self.y: int
self.y = NotPresentClass
self.z: int = NotPresentClass
reveal_type(self.x, expected_text="Unknown | int")
reveal_type(self.y, expected_text="Unknown | int")
reveal_type(self.z, expected_text="Unknown | int")
@@ -1,83 +0,0 @@
# This sample tests some cases where types are narrowed on assignment,
# including some cases that involve "Any".
from typing import Any, Generic, Iterable, TypeVar
class A:
instance: "A | None"
def __init__(self) -> None:
self.foo: bool
@classmethod
def method1(cls) -> bool:
if cls.instance is None:
cls.instance = cls()
return cls.instance.foo
T = TypeVar("T")
class B(Generic[T]): ...
def func1(v1: list[Any | None], v2: list[int | str]):
x1: list[int | None] = v1
reveal_type(x1, expected_text="list[int | None]")
x2: list[Any] = v2
reveal_type(x2, expected_text="list[Any]")
x3: list[Any | str] = v2
reveal_type(x3, expected_text="list[Any | str]")
def func2(v1: dict[int, Any | None], v2: dict[int, int | str]):
x1: dict[int, int | None] = v1
reveal_type(x1, expected_text="dict[int, int | None]")
x2: dict[Any, Any] = v2
reveal_type(x2, expected_text="dict[Any, Any]")
x3: dict[Any, Any | str] = v2
reveal_type(x3, expected_text="dict[Any, Any | str]")
def func3(y: list[int]):
x1: Iterable[int | B[Any]] = y
reveal_type(x1, expected_text="list[int]")
x2: Iterable[Any | B[Any]] = y
reveal_type(x2, expected_text="list[int]")
x3: Iterable[Any] = y
reveal_type(x3, expected_text="list[int]")
def func4(y: list[Any]):
x1: Iterable[int | B[Any]] = y
reveal_type(x1, expected_text="list[Any]")
x2: Iterable[Any | B[Any]] = y
reveal_type(x2, expected_text="list[Any]")
x3: Iterable[Any] = y
reveal_type(x3, expected_text="list[Any]")
def func5(v1: list[Any | None]):
x1: list[int | None] = v1
reveal_type(x1, expected_text="list[int | None]")
def func6(v1: tuple[Any], v2: tuple[int, Any], v3: tuple[Any, ...]):
x1: tuple[int] = v1
reveal_type(x1, expected_text="tuple[int]")
x2: tuple[int, str] = v2
reveal_type(x2, expected_text="tuple[int, str]")
x3: tuple[str, ...] = v3
reveal_type(x3, expected_text="tuple[str, ...]")
@@ -1,20 +0,0 @@
# This sample tests the type checker's handling of chained assignments.
a1 = b1 = c1 = d1 = 3
my_list = [10]
a2 = my_list[a2] = b2 = my_list[b2] = 0
# This should generate an error because a3 is read before written.
my_list[a3] = a3 = 0
# This should generate an error because type comments are not
# allowed for chained assignments.
x1 = x2 = x3 = [3] # type: list[float]
# Bidirectional type inference should be used in this case.
y2: list[list[float]]
y1 = y2 = [[3]]
reveal_type(y1, expected_text="list[list[float]]")
@@ -1,24 +0,0 @@
# This sample tests the case where a variable with a declared type
# is assigned an unknown value or partially-unknown value.
def a_test(x1: int, x2: list):
u = x1.upper() # type: ignore
reveal_type(u, expected_text="Unknown")
# This should generate an error if reportUnknownVariableType is enabled.
y: str = u
reveal_type(y, expected_text="Unknown | str")
# This should generate an error if reportUnknownVariableType is enabled.
z: list[str] = x2
reveal_type(z, expected_text="list[str]")
def b_test(x: int | str):
u = x.upper() # type: ignore
reveal_type(u, expected_text="str | Unknown")
# This should generate an error if reportUnknownVariableType is enabled.
y: str = u
reveal_type(y, expected_text="str | Unknown")
@@ -1,43 +0,0 @@
# This sample tests assignments to indexed expressions
# where the base is a specialized object.
# Enable the reportUnknownArgumentType check so we can verify that it
# doesn't generate an error when assigning an empty list to an indexed
# expression.
# viper: reportUnknownArgumentType=true
v1: list[int] = [1, 2, 3, 4, 5]
# This should generate an error because the assigned type is wrong.
v1[0] = "a"
v2: dict[int, str] = {1: "str"}
# This should generate an error because the assigned type is wrong.
v2[1] = 123
v3: list[int | str] = ["a"]
v3[0] = 3
reveal_type(v3[0], expected_text="Literal[3]")
v4: dict[str, int | str] = {}
v4["aaa"] = 3
v4["bbb"] = "bbb"
reveal_type(v4["aaa"], expected_text="Literal[3]")
reveal_type(v4["bbb"], expected_text="Literal['bbb']")
reveal_type(v4["ccc"], expected_text="int | str")
class Asymmetric:
def __setitem__(self, i: int, value: object) -> None: ...
def __getitem__(self, i: int) -> int: ...
v5 = Asymmetric()
v5[0] = 3
reveal_type(v5[0], expected_text="int")
v6 = [1, 2, 3]
v6[1:] = []
@@ -1,51 +0,0 @@
# This sample tests various assignment scenarios where
# there is an expected type, so bidirectional type
# inference is used.
from typing import Callable, Literal, Protocol
f1: Callable[[int, int], int] = lambda a, b: a + b
# This should generate an error because x should be
# determined to be an "int", so "len(x)" is invalid.
map(lambda x: len(x), [1, 2, 3])
def must_be_int(val: int):
return val
d1: dict[str, tuple[int, Callable[[int], int]]] = {
"hello": (3, lambda x: must_be_int(x))
}
d2: dict[str, tuple[int, Callable[[int], int]]] = {
# This should generate an error because the key is not a str.
3: (3, lambda x: must_be_int(x))
}
d3: dict[str, tuple[int, Callable[[int], int]]] = {
# This should generate an error because the first element
# of the tuple is not the correct type.
"3": (3.0, lambda x: must_be_int(x))
}
d4: dict[str, tuple[int, Callable[[int], int]]] = {
# This should generate an error because the lambda
# type doesn't match.
"3": (3, lambda _: 3.4)
}
class Adder(Protocol):
def __call__(self, x: int, y: dict[str, int]) -> int: ...
v1: Adder = lambda x, y: x + y["hi"]
reveal_type(v1, expected_text="(x: int, y: dict[str, int]) -> int")
class A:
@classmethod
def method1(cls):
cls.v1: list[Literal[0]] = [] if issubclass(cls, int) else [0]
@@ -1,20 +0,0 @@
# This sample tests various assignment scenarios where
# there is an expected type, so bidirectional type
# inference is used.
# viper: strict
from typing import Callable, Sequence
AAA = float
BBB = int
CCC = str
DDD = str
AAATuple = tuple[AAA, BBB, Callable[[Sequence[int], AAA], Sequence[float]]]
def foo():
var1: dict[str, tuple[AAA, BBB, CCC, DDD]] = {}
var2: dict[str, AAATuple] = {}
for k, (var3, var4, _, _) in var1.items():
var2[k] = (var3, var4, lambda var5, var6: [v * var6 for v in var5])
@@ -1,16 +0,0 @@
# This sample tests the handling of tuple assignments
# where the order of assignment within the tuple is important.
from typing import Optional
class Node:
key: str
next: Optional["Node"] = None
node = Node()
# This should analyze fine because node.next should be assigned
# None before node is assigned None.
node.next, node = None, None
@@ -1,25 +0,0 @@
# This sample tests that the type checker handles the case
# where a symbol within a class scope is assigned an expression
# that includes the same symbol, but that same symbol is defined
# in an outer scope.
a = 0
b = 1
c = 4
class MyClass:
# This should not generate an error because
# the RHS of the assignment refers to a different
# "a", declared in an outer scope.
a = a
# Same with "b" here.
(b, a) = (b, 3)
# Same with "c" here.
[c] = [c]
# This should generate an error because "d" is
# not declared in the outer scope.
e = d
@@ -1,13 +0,0 @@
# This sample tests a particularly difficult set of dependent
# assignments that involve tuple packing and unpacking.
# viper: strict
v1 = ""
v3 = ""
v2, _ = v1, v3
v4 = v2
for _ in range(1):
v1 = v4
v2, v3 = v1, ""
@@ -1,38 +0,0 @@
# This sample ensures that a variable of type "object" can be
# assigned any other type.
import os
from typing import Any, TypeVar, overload
class Foo:
@overload
def bar(self, obj: None) -> object: ...
@overload
def bar(self, obj: object) -> Any: ...
def bar(self, obj: object | None) -> Any:
pass
@staticmethod
def baz():
return 3
_T = TypeVar("_T")
my_obj: object
my_obj = None
my_obj = os
my_obj = Foo
my_obj = Foo()
my_obj = Foo.bar
my_obj = Foo.baz
my_obj = ()
my_obj = lambda x: x
my_obj = _T
# This should generate an error because a is unbound.
my_obj = a
@@ -1,23 +0,0 @@
# This sample tests assignment when the types are invariant and the
# source or destination are unions that contains subtypes which are
# subclasses of each other.
from datetime import datetime
class FloatSubclass(float):
pass
float_list: list[float] = [1.0, 2.0]
v1: list[float | FloatSubclass] = float_list
v2: list[int | float] = float_list
# This should generate an error.
v3: list[int | float | datetime] = float_list
v4: list[FloatSubclass | float] = []
v5: list[float] = v4
@@ -1,26 +0,0 @@
# This sample tests the Python 3.8 assignment expressions.
# viper: reportUnusedExpression=false
def func1():
b = 'a'
d = 'b'
a = (b := 3)
# This should generate an error because the
# item to the left of an assignment expression
# must be a name.
a + 3 := 3
# This should generate an error because parens
# are required in this case.
c = d := 3
# This should generate an error because parens are required in this case.
val if val := 1 + 2 else None
val2 if (val2 := 1 + 2) else None
# This should generate an error because parens are not allowed in asserts.
assert e := 1
@@ -1,67 +0,0 @@
# This sample tests the Python 3.8 assignment expressions. This sample
# is taken from PEP 257.
# viper: reportUnusedExpression=false
import re
def func1(x: float):
...
def pep572_examples():
if (match := re.search('123', '252')) is not None:
print(match)
print(match)
file = open('hello')
while chunk := file.read(8192):
print(chunk)
print(chunk)
def f(x: float):
return x
mylist = [y := f(25), y**2, y**3]
data = [1, 2, 3]
filtered_data = [y for x in data if (y := f(x)) is not None]
print(filtered_data)
# This should generate an error.
y := f(25) # INVALID
(y := f(25)) # Valid, though not recommended
y1 = 1
# This should generate an error.
y0 = y1 := f(25) # INVALID
y0 = (y1 := f(25)) # Valid, though discouraged
# This should generate an error.
func1(x = y := f(25)) # INVALID
func1(x=(y := f(25))) # Valid, though probably confusing
# This should generate an error.
[y for x in [0, 1] if y := x - 1]
[y for x in [0, 1] if (y := x - 1)]
def func2():
# This should generate an error.
yield y := 1
def func3():
# This should generate an error.
yield from y := [1]
def func4():
# This should generate an error.
v1 = {x := 'a': 0}
v2 = {(x := 'a'): 0}
# This should generate an error.
v3 = {x := 'a': i for i in range(4)}
v4 = {(x := 'a'): i for i in range(4)}
@@ -1,27 +0,0 @@
# This sample tests the Python 3.8 assignment expressions.
import re
def foo1(x: float):
...
p = 3
# This should generate an error.
def foo2(answer = p := 42): # INVALID
...
def foo3(answer=(p := 42)): # Valid, though not great style
...
default_value: int = 3
# This should generate two errors.
def foo4(answer: p := default_value = 5): # INVALID
...
# This should generate an error.
(lambda: x := 1) # INVALID
lambda: (x := 1) # Valid, but unlikely to be useful
(x := lambda: 1) # Valid
lambda line: (m := re.match('pattern', 'line')) and m.group(1) # Valid
@@ -1,49 +0,0 @@
# This sample tests error detection for certain cases that
# are explicitly disallowed by PEP 572 for assignment expressions
# when used in context of a list comprehension.
pairs = []
stuff = []
# These should generate an error because assignment
# expressions aren't allowed within an iterator expression
# in a "for" clause of a list comprehension.
[x for x, y in (pairs2 := pairs) if x % 2 == 0]
[x for x, y in ([1, 2, 3, pairs2 := pairs]) if x % 2 == 0]
{x: y for x, y in (pairs2 := pairs) if x % 2 == 0}
{x for x, y in (pairs2 := pairs) if x % 2 == 0}
foo = (x for x, y in ([1, 2, 3, pairs2 := pairs]) if x % 2 == 0)
# This should generate an error because 'j' is used as a
# "for target" and the target of an assignment expression.
[[(j := j) for i in range(5)] for j in range(5)]
[i := 0 for i, j in stuff]
[i + 1 for i in (i := stuff)]
[False and (i := 0) for i, j in stuff]
[i for i, j in stuff if True or (j := 1)]
# These should generate an error because assignment
# expressions aren't allowed within an iterator expression
# in a "for" clause of a list comprehension.
[i + 1 for i in (j := stuff)]
[i + 1 for i in range(2) for j in (k := stuff)]
[i + 1 for i in [j for j in (k := stuff)]]
[i + 1 for i in (lambda: (j := stuff))()]
class Example:
# This should generate an error because the containing
# scope for the list comprehension is a class.
[(j := i) for i in range(5)]
x = ((y := 1), (z := 2))
Example.x
Example.y
Example.z
# This should generate an error because 'j' is used as a
# "for target" and the target of an assignment expression.
[i for i in [1, 2] if True or (j := 1) for j in range(10)]
@@ -1,23 +0,0 @@
# This sample tests the scoping rules for assignment expressions
# within a list comprehension.
# viper: strict
from typing import Tuple
def func1() -> Tuple[str, int]:
a = 3
y = 4
_ = [(a := x) for x in ["1", "2"] for _ in ["1", "2"]]
# The type of "y" should be int because the "y" within
# the list comprehension doesn't leak outside. On the
# other hand, "a" does leak outside the list comprehension.
return (a, y)
def get_value(x: int) -> int: ...
x = sum(max(value for x in range(10) if (value := get_value(x))) for _ in range(10))
@@ -1,10 +0,0 @@
# This sample tests that type guards work correctly
# with the walrus operator.
import re
def foo(s: str) -> str:
if m := re.fullmatch("(test).+", s):
return m.group(1)
return "oops"
@@ -1,23 +0,0 @@
# This sample tests assignment expressions used within arguments.
from dataclasses import dataclass
from typing import Mapping
import collections
class NearestKeyDict(collections.UserDict):
def method1(self, key):
a = len(keys := [k for k in sorted(self.data) if k >= key])
# This should generate an error because walrus operators
# are not allowed with named arguments.
b = list(iterable = keys := [k for k in sorted(self.data) if k >= key])
@dataclass
class DC1:
x: str
def func1(mapping: Mapping[str, dict]):
return [DC1(temp := "x", **mapping[temp])]
@@ -1,11 +0,0 @@
# This sample checks that parsing for the assignment expression
# operator is using the correct precedence. It should be parsing
# the RHS as a "test expression" which allows for ternary
# expressions.
result = None
if items := 3 if result else None:
pass
print(items)
@@ -1,42 +0,0 @@
# This sample tests the case where an assignment expression target
# is found within a function decorator or a function default value expression.
from typing import Any, Callable, TypeVar, overload
_T = TypeVar("_T")
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]: ...
@decorator(
[
walrus_target_1
for combination in [[1]]
if None not in (walrus_target_1 := set(combination))
],
)
def decorated(
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])],
):
pass
reveal_type(walrus_target_1, expected_text="set[int]")
reveal_type(walrus_target_2, expected_text="list[str]")
@overload
def func1(value: None = None) -> None: ...
@overload
def func1(value: str) -> str: ...
def func1(value: str | None = None) -> str | None:
return value
func1(value=(param_value := "test"))
@@ -1,49 +0,0 @@
# This sample validates that "async" is flagged as an error when
# used in inappropriate locations.
from contextlib import AsyncExitStack
async def b():
for i in range(5):
yield i
cm = AsyncExitStack()
def func1():
# This should generate an error because
# "async" cannot be used in a non-async function.
async for x in b():
print("")
# This is allowed because it's in a generator.
y = (x async for x in b())
# This should generate an error because
# "async" cannot be used in a non-async function.
async with cm:
pass
# This should generate an error because
# "async" cannot be used in a non-async function.
return [x async for x in b()]
# This should generate an error because
# "async" cannot be used in a non-async function.
async for x in b():
print("")
# This is allowed because it's in a generator.
y = (x async for x in b())
# This should generate an error because
# "async" cannot be used in a non-async function.
async with cm:
pass
# This should generate an error because
# "async" cannot be used in a non-async function.
[x async for x in b()]
@@ -1,62 +0,0 @@
# This sample tests the type checker's handling of
# augmented assignments (combining a binary operator
# with an assignment).
a = 1
b = 3.4
a += b
reveal_type(a, expected_text="float")
a -= b
reveal_type(a, expected_text="float")
a *= b
reveal_type(a, expected_text="float")
a /= b
reveal_type(a, expected_text="float")
a //= b
reveal_type(a, expected_text="float")
a %= b
reveal_type(a, expected_text="float")
a **= b
reveal_type(a, expected_text="Any")
a = 1
# This should generate an error because
# matrix multiply isn't supported by int.
a @= b
a |= b
a &= b
a ^= b
a <<= b
a >>= b
list1 = [1, 2, 3]
list1 += [4]
# This should generate an error
list1 += 4
# This should generate an error
list2 = [1]
list2 *= 4
# This should generate an error
list2 *= [4]
# Test __iadd__ override in list class, which accepts
# any iterator as an argument.
bar = ("d",)
foo = ["a", "b"]
foo += ["c"]
foo += bar
@@ -1,18 +0,0 @@
# This sample tests expected diagnostics for augmented assignment
# expressions.
def func1(values1: list[float] = [], values2: list[float] | None = None) -> None:
values3 = None
# This should generate an error
values1 += values2
if values2 is not None:
values1 += values2
# This should generate an error
values1 -= values2
# This should generate an error
values1 += values3
@@ -1,21 +0,0 @@
# This sample tests the case where a class-scoped variable
# type needs to be inferred from an augmented assignment.
class ClassA:
y = 0
z = 0
z += 0.5
def __init__(self):
self.x = 0
self.x += 0.5
@classmethod
def method1(cls):
cls.y += 0.5
reveal_type(ClassA().x, expected_text="int | float")
reveal_type(ClassA.y, expected_text="int | float")
reveal_type(ClassA.z, expected_text="int | float")
@@ -1,164 +0,0 @@
# This sample tests variance inference for type variables that use
# autovariance.
from dataclasses import dataclass
from typing import Final, Iterator, Sequence, overload
class ShouldBeCovariant1[T]:
def __getitem__(self, index: int) -> T: ...
def __iter__(self) -> Iterator[T]: ...
vco1_1: ShouldBeCovariant1[float] = ShouldBeCovariant1[int]()
# This should generate an error based on variance.
vco1_2: ShouldBeCovariant1[int] = ShouldBeCovariant1[float]()
class ShouldBeCovariant2[T](Sequence[T]):
def __len__(self) -> int: ...
@overload
def __getitem__(self, index: int) -> T: ...
@overload
def __getitem__(self, index: slice) -> Sequence[T]: ...
def __getitem__(self, index: int | slice) -> T | Sequence[T]: ...
vco2_1: ShouldBeCovariant2[float] = ShouldBeCovariant2[int]()
# This should generate an error based on variance.
vco2_2: ShouldBeCovariant2[int] = ShouldBeCovariant2[float]()
class ShouldBeCovariant3[T]:
def method1(self) -> "ShouldBeCovariant2[T]": ...
vco3_1: ShouldBeCovariant3[float] = ShouldBeCovariant3[int]()
# This should generate an error based on variance.
vco3_2: ShouldBeCovariant3[int] = ShouldBeCovariant3[float]()
@dataclass(frozen=True)
class ShouldBeCovariant4[T]:
x: T
vo4_1: ShouldBeCovariant4[float] = ShouldBeCovariant4[int](1)
# This should generate an error based on variance.
vo4_2: ShouldBeCovariant4[int] = ShouldBeCovariant4[float](1)
class ShouldBeCovariant5[T]:
def __init__(self, x: T) -> None:
self._x = x
@property
def x(self) -> T:
return self._x
vo5_1: ShouldBeCovariant5[float] = ShouldBeCovariant5[int](1)
# This should generate an error based on variance.
vo5_2: ShouldBeCovariant5[int] = ShouldBeCovariant5[float](1)
class ShouldBeCovariant6[T]:
def f1[T2: int](self: "ShouldBeCovariant6[T2]") -> T2: ...
@property
def f2[T2: int](self: "ShouldBeCovariant6[T2]") -> T2: ...
# This should generate an error based on variance.
vo6_1: ShouldBeCovariant6[int] = ShouldBeCovariant6[float]()
vo6_2: ShouldBeCovariant6[float] = ShouldBeCovariant6[int]()
class ShouldBeInvariant1[T]:
def __init__(self, value: T) -> None:
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value: T):
self._value = value
# This should generate an error based on variance.
vinv1_1: ShouldBeInvariant1[float] = ShouldBeInvariant1[int](1)
# This should generate an error based on variance.
vinv1_2: ShouldBeInvariant1[int] = ShouldBeInvariant1[float](1.1)
class ShouldBeInvariant2[T]:
def __init__(self, value: T) -> None:
self._value = value
def get_value(self) -> T:
return self._value
def set_value(self, value: T):
self._value = value
# This should generate an error based on variance.
vinv2_1: ShouldBeInvariant2[float] = ShouldBeInvariant2[int](1)
# This should generate an error based on variance
vinv2_2: ShouldBeInvariant2[int] = ShouldBeInvariant2[float](1.1)
class ShouldBeInvariant3[K, V](dict[K, V]):
pass
# This should generate an error based on variance.
vinv3_1: ShouldBeInvariant3[float, str] = ShouldBeInvariant3[int, str]()
# This should generate an error based on variance.
vinv3_2: ShouldBeInvariant3[int, str] = ShouldBeInvariant3[float, str]()
# This should generate an error based on variance.
vinv3_3: ShouldBeInvariant3[str, float] = ShouldBeInvariant3[str, int]()
# This should generate an error based on variance.
vinv3_4: ShouldBeInvariant3[str, int] = ShouldBeInvariant3[str, float]()
@dataclass
class ShouldBeInvariant4[T]:
x: T
# This should generate an error based on variance
vinv4_1: ShouldBeInvariant4[float] = ShouldBeInvariant4[int](1)
class ShouldBeInvariant5[T]:
def __init__(self, x: T) -> None:
self.x = x
# This should generate an error based on variance.
vinv5_1: ShouldBeInvariant5[float] = ShouldBeInvariant5[int](1)
class ShouldBeContravariant1[T]:
def __init__(self, value: T) -> None:
pass
def set_value(self, value: T) -> None:
pass
# This should generate an error based on variance.
vcontra1_1: ShouldBeContravariant1[float] = ShouldBeContravariant1[int](1)
vcontra1_2: ShouldBeContravariant1[int] = ShouldBeContravariant1[float](1.2)
@@ -1,30 +0,0 @@
# This sample tests an auto-invariance case that involves recursive types.
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Concatenate, Protocol
@dataclass
class Node[T]:
left: Node[T]
right: Node[T]
value: T
class MyPartial[**P, R]:
def __init__(self, first: int, func: Callable[Concatenate[int, P], R]) -> None:
self.first = first
self.func = func
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
class CallbackKeyed[*Ts](Protocol):
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)
@@ -1,163 +0,0 @@
# This sample tests variance inference for traditional type variables.
from typing import Generic, Iterator, Sequence, overload
from typing_extensions import TypeVar # viper: ignore[reportMissingModuleSource]
from dataclasses import dataclass
T = TypeVar("T", infer_variance=True)
K = TypeVar("K", infer_variance=True)
V = TypeVar("V", infer_variance=True)
# This should generate an error because covariant cannot be used
# with infer_variance.
S1 = TypeVar("S1", covariant=True, infer_variance=True)
# This should generate an error because contravariant cannot be used
# with infer_variance.
S2 = TypeVar("S2", contravariant=True, infer_variance=True)
class ShouldBeCovariant1(Generic[T]):
def __getitem__(self, index: int) -> T: ...
def __iter__(self) -> Iterator[T]: ...
vco1_1: ShouldBeCovariant1[float] = ShouldBeCovariant1[int]()
# This should generate an error based on variance.
vco1_2: ShouldBeCovariant1[int] = ShouldBeCovariant1[float]()
class ShouldBeCovariant2(Sequence[T]):
def __len__(self) -> int: ...
@overload
def __getitem__(self, index: int) -> T: ...
@overload
def __getitem__(self, index: slice) -> Sequence[T]: ...
def __getitem__(self, index: int | slice) -> T | Sequence[T]: ...
vco2_1: ShouldBeCovariant2[float] = ShouldBeCovariant2[int]()
# This should generate an error based on variance.
vco2_2: ShouldBeCovariant2[int] = ShouldBeCovariant2[float]()
class ShouldBeCovariant3(Generic[T]):
def method1(self) -> "ShouldBeCovariant2[T]": ...
vco3_1: ShouldBeCovariant3[float] = ShouldBeCovariant3[int]()
# This should generate an error based on variance.
vco3_2: ShouldBeCovariant3[int] = ShouldBeCovariant3[float]()
@dataclass(frozen=True)
class ShouldBeCovariant4(Generic[T]):
x: T
vo4_1: ShouldBeCovariant4[float] = ShouldBeCovariant4[int](1)
# This should generate an error based on variance.
vo4_4: ShouldBeCovariant4[int] = ShouldBeCovariant4[float](1.0)
class ShouldBeCovariant5(Generic[T]):
def __init__(self, x: T) -> None:
self._x = x
@property
def x(self) -> T:
return self._x
vo5_1: ShouldBeCovariant5[float] = ShouldBeCovariant5[int](1)
# This should generate an error based on variance.
vo5_2: ShouldBeCovariant5[int] = ShouldBeCovariant5[float](1.0)
class ShouldBeInvariant1(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value: T):
self._value = value
# This should generate an error based on variance.
vinv1_1: ShouldBeInvariant1[float] = ShouldBeInvariant1[int](1)
# This should generate an error based on variance.
vinv1_2: ShouldBeInvariant1[int] = ShouldBeInvariant1[float](1.1)
class ShouldBeInvariant2(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
def get_value(self) -> T:
return self._value
def set_value(self, value: T):
self._value = value
# This should generate an error based on variance.
vinv2_1: ShouldBeInvariant2[float] = ShouldBeInvariant2[int](1)
# This should generate an error based on variance.
vinv2_2: ShouldBeInvariant2[int] = ShouldBeInvariant2[float](1.1)
class ShouldBeInvariant3(dict[K, V]):
pass
# This should generate an error based on variance.
vinv3_1: ShouldBeInvariant3[float, str] = ShouldBeInvariant3[int, str]()
# This should generate an error based on variance.
vinv3_2: ShouldBeInvariant3[int, str] = ShouldBeInvariant3[float, str]()
# This should generate an error based on variance.
vinv3_3: ShouldBeInvariant3[str, float] = ShouldBeInvariant3[str, int]()
# This should generate an error based on variance.
vinv3_4: ShouldBeInvariant3[str, int] = ShouldBeInvariant3[str, float]()
@dataclass
class ShouldBeInvariant4[T]:
x: T
# This should generate an error based on variance.
vinv4_1: ShouldBeInvariant4[float] = ShouldBeInvariant4[int](1)
class ShouldBeInvariant5[T]:
def __init__(self, x: T) -> None:
self.x = x
# This should generate an error based on variance.
vinv5_1: ShouldBeInvariant5[float] = ShouldBeInvariant5[int](1)
class ShouldBeContravariant1(Generic[T]):
def __init__(self, value: T) -> None:
pass
def set_value(self, value: T):
pass
# This should generate an error based on variance.
vcontra1_1: ShouldBeContravariant1[float] = ShouldBeContravariant1[int](1)
vcontra1_2: ShouldBeContravariant1[int] = ShouldBeContravariant1[float](1.2)
@@ -1,51 +0,0 @@
# This sample tests the case where a class uses auto-variance but derives
# from a class that does not.
from typing import Generic, TypeVar
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]()
# This should generate an error.
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]()
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]()
@@ -1,20 +0,0 @@
# This sample tests a case that involves an interaction between a class
# that uses auto-variance and a decorator that uses a generic type alias.
from typing import Any, Concatenate, Generic, ParamSpec, TypeAlias, Callable
from typing_extensions import TypeVar # viper: ignore[reportMissingModuleSource]
T = TypeVar("T", infer_variance=True)
P = ParamSpec("P")
R = TypeVar("R")
S = TypeVar("S", bound="A[Any]")
TA1: TypeAlias = Callable[Concatenate[S, P], R]
def deco(func: TA1[S, P, R], /) -> TA1[S, P, R]: ...
class A(Generic[T]):
@deco
def select_all(self, *args: object) -> list[Any]: ...
@@ -1,57 +0,0 @@
# This sample validates that the await keyword participates in
# bidirectional type inference.
from typing import (
Any,
AsyncIterator,
Callable,
Iterable,
Literal,
TypeVar,
Generic,
overload,
)
T = TypeVar("T")
AnyMsg = TypeVar("AnyMsg", bound="Msg")
class Msg(Generic[T]):
body: T
class Request:
id: int
async def func1(check: "Callable[[AnyMsg], bool]") -> AnyMsg: ...
async def func2():
_: Msg[Request] = await func1(check=lambda msg: (msg.body.id == 12345))
async def func3() -> AsyncIterator[int]:
yield 1
async def func4() -> int:
return await anext(func3())
async def func5(__fn: Callable[..., T]) -> T: ...
@overload
def sum(__iterable: Iterable[Literal[0]]) -> int: ...
@overload
def sum(__iterable: Iterable[T]) -> T: ...
def sum(__iterable: Iterable[Any]) -> Any: ...
async def func6(f: Callable[[], list[int]]):
sum(await func5(f))
@@ -1,31 +0,0 @@
# This sample tests that types defined by type variables can be
# awaited.
from typing import Generator, Any, NoReturn
class MyAwaitable:
def __await__(self) -> Generator[Any, None, int]:
async def foo() -> int:
return 1
return foo().__await__()
async def foo(self) -> int:
return await self
async def func1() -> None:
p = MyAwaitable()
print(await p.foo())
print(await p)
async def func2() -> NoReturn:
raise Exception()
async def func3(x: int | None):
if x is None:
await func2()
print(x.bit_count())
@@ -1,37 +0,0 @@
# This sample tests various places where await is invalid.
from typing import Any
def func1() -> Any: ...
def func2():
# These are OK because generators can be called
# outside of the context of the current function.
(v async for v in func1())
(await v for v in func1())
# This should generate an error because async
# cannot be used outside of an async function.
[x async for x in func1()]
# This should generate an error because async
# cannot be used outside of an async function.
{x async for x in func1()}
# This should generate an error because async
# cannot be used outside of an async function.
{k: v async for k, v in func1()}
# This should generate an error because await
# cannot be used outside of an async function.
(x for x in await func1())
# This should generate an error because await
# cannot be used outside of an async function.
[await x for x in func1()]
# This should generate an error because await
# cannot be used outside of an async function.
{await k: v for k, v in func1()}
@@ -1,2 +0,0 @@
# This file is intentionally blank. It's used to test
# the implicitly-imported builtins module and its symbols.
@@ -1,7 +0,0 @@
# This sample tests that builtins can be overridden at the module level
# without generating a "possibly unbound" error.
if input():
print = lambda *x: None
print("")
@@ -1,93 +0,0 @@
# This sample tests various function type checking
# behavior including arg/param matching.
from typing import Callable
# ------------------------------------------------------
# Test function type matching
class FooBase:
pass
class Foo(FooBase):
pass
class Bar(Foo):
pass
def needs_function1(callback: Callable[[Foo], Foo]):
pass
def callback1():
pass
def callback2(a: Foo) -> Foo:
return Foo()
def callback3(a: Foo) -> str:
return "1"
def callback4(a: Foo, b: Foo) -> Foo:
return Foo()
def callback5(a: Foo, b: int = 3) -> Foo:
return Foo()
def callback6(*a) -> Foo:
return Foo()
def callback7(a: str) -> Foo:
return Foo()
def callback8(a: Bar) -> Foo:
return Foo()
def callback9(a: FooBase) -> Foo:
return Foo()
# This should generate an error because callback1
# takes no parameters.
needs_function1(callback1)
needs_function1(callback2)
# This should generate an error because the return
# type of callback3 doesn't match.
needs_function1(callback3)
# This should generate an error because callback4
# takes too many parameters.
needs_function1(callback4)
needs_function1(callback5)
needs_function1(callback6)
# This should fail because the parameter is the
# wrong type.
needs_function1(callback7)
# This should fail because the parameter is the
# wrong type.
needs_function1(callback8)
needs_function1(callback9)
import typing
# This should generate an error because modules are not callable.
typing()
@@ -1,75 +0,0 @@
# This sample tests that the type checker properly handles
# types of args and kwargs correctly.
from typing import Any, Hashable, Mapping, Protocol
def requires_hashable_tuple(p1: tuple[Hashable, ...]): ...
def requires_hashable_dict(p1: dict[str, Hashable]): ...
def test_args(*args: Hashable):
if args:
aaa = list(args)
bbb = tuple(aaa)
args = bbb
requires_hashable_tuple(args)
def test_kwargs(**kwargs: Hashable):
requires_hashable_dict(kwargs)
class StrSubclass(str): ...
def test_kwargs2(
a: Mapping[str, Any],
b: Mapping[Any, Hashable],
c: dict[StrSubclass, Hashable],
d: int,
e: Mapping[int, Hashable],
f: tuple[str, ...],
):
test_kwargs(**a)
test_kwargs(**b)
test_kwargs(**c)
# This should generate an error
test_kwargs(**d)
# This should generate an error
test_kwargs(**e)
# This should generate an error
test_kwargs(**f)
class Callback1(Protocol):
def __call__(self) -> None: ...
def func1(
value: str = ...,
*args: object,
) -> None: ...
def func2(
value: str = ...,
**kwargs: object,
) -> None: ...
def func3(
value: str = ...,
*args: object,
**kwargs: object,
) -> None: ...
v1: Callback1 = func1
v2: Callback1 = func2
v3: Callback1 = func3
@@ -1,44 +0,0 @@
# This sample tests the case where a call expression involves a union
# on the LHS where the subtypes of the union have different signatures.
# viper: strict
from __future__ import annotations
from typing import Any, Callable, Generic, Self, TypeAlias, TypeVar
T = TypeVar("T")
E = TypeVar("E")
U = TypeVar("U")
F = TypeVar("F")
Either: TypeAlias = "Left[T]" | "Right[E]"
class Left(Generic[T]):
def __init__(self, value: T) -> None:
self.value = value
def map_left(self, fn: Callable[[T], U]) -> Left[U]:
return Left(fn(self.value))
def map_right(self, fn: Callable[[Any], Any]) -> Self:
return self
class Right(Generic[E]):
def __init__(self, value: E) -> None:
self.value = value
def map_left(self, fn: Callable[[Any], Any]) -> Self:
return self
def map_right(self, fn: Callable[[E], F]) -> Right[F]:
return Right(fn(self.value))
def func() -> Either[int, str]:
raise NotImplementedError
result = func().map_left(lambda lv: lv + 1).map_right(lambda rv: rv + "a")
reveal_type(result, expected_text="Right[str] | Left[int]")
@@ -1,47 +0,0 @@
# This sample tests that positional arg expressions are evaluated prior
# to keyword arg expressions even if they don't appear in that order
# within the arg list.
from typing import TypedDict
def func1(a: int | None = None, b: int | None = None, c: int | None = None) -> None:
pass
func1((v1 := 1), b=v1 + 1)
# This should generate an error.
func1(b=(v2 := 1), *[v2 + 1])
func1(b=v3 + 1, *[(v3 := 1)])
class A(TypedDict):
a: int
class B(TypedDict):
b: int
class C(TypedDict):
c: int
func1(a=(v4 := 1), **B(b=(v4 + 1)))
# This should generate an error.
func1(**A(a=(v5 + 1)), b=(v5 := 1))
func1(**A(a=(v5 := 1)), b=(v5 + 1))
func1(b=(v6 + 1), *[(v6 := 1)], **C(c=(v6 + 2)))
def func2(a: int, b: int):
pass
func2(b=1, *(2,))
@@ -1,15 +0,0 @@
# This sample tests the case where a call invokes a generic function that
# uses a default argument assigned to a parameter whose type is generic.
from typing import TypeVar, Iterable, Callable
T1 = TypeVar("T1")
T2 = TypeVar("T2")
def func1(values: Iterable[T1], func: Callable[[T1], T2] = lambda x: x) -> list[T2]:
return [func(value) for value in values]
v1 = func1([1, 2, 3])
reveal_type(v1, expected_text="list[int]")
@@ -1,57 +0,0 @@
# This sample tests the pre-3.8 position-only parameter convention.
from typing import Any
def func1(__a: int, __b: int, c: int) -> None: ...
func1(1, 2, c=3)
# This should generate an error because __b is position-only.
func1(1, __b=2, c=3)
# This should generate an error because a position-only parameter cannot
# follow a non-position-only parameter.
def func2(a: int, __b: int) -> None: ...
def func3(a: int, *args: Any, __b: int) -> None: ...
func3(a=1, __b=2)
def func4(a: int, /, __b: int) -> None: ...
func4(1, __b=2)
class A:
def m1(self, __a: int, b: int) -> None:
pass
# This should generate an error.
def m2(self, a: int, __b: int) -> None:
pass
@classmethod
def c1(cls, __a, int, b: int) -> None:
pass
@classmethod
# This should generate an error.
def c2(cls, a, int, __b: int) -> None:
pass
@staticmethod
def s1(__a: int, b: int) -> None:
pass
@staticmethod
# This should generate an error.
def s2(a: int, __b: int) -> None:
pass
@@ -1,66 +0,0 @@
# This sample tests the case where a generic function has a default argument
# value for a parameter with a generic type.
from collections.abc import Callable
from typing import Iterable, TypeVar
T = TypeVar("T")
default_value: dict[str, int] = {}
def func1(x: T, y: dict[str, T] = default_value, /) -> T: ...
def func2(x: T, y: dict[str, T] = default_value) -> T: ...
def func3(x: T, *, y: dict[str, T] = default_value) -> T: ...
def test1(func: Callable[[T], T], value: T) -> T:
return func(value)
# This should generate an error.
test1(func1, "")
# This should generate an error.
test1(func2, "")
# This should generate an error.
test1(func3, "")
reveal_type(test1(func1, 1), expected_text="int")
reveal_type(test1(func2, 1), expected_text="int")
reveal_type(test1(func3, 1), expected_text="int")
def func4(x: T, y: Iterable[T] = default_value, z: T = "", /) -> T: ...
def func5(x: T, y: Iterable[T] = default_value, z: T = "") -> T: ...
def func6(x: T, *, y: Iterable[T] = default_value, z: T = "") -> T: ...
reveal_type(test1(func4, 1), expected_text="str | int")
reveal_type(test1(func5, 1), expected_text="str | int")
reveal_type(test1(func6, 1), expected_text="str | int")
class A[T]:
def __init__(self, value: T) -> None:
self._value: T = value
def update(self, value: T = 0, /) -> "A[T]":
return A(value)
a = A("")
a.update("")
# This should generate an error.
a.update()
@@ -1,38 +0,0 @@
# This sample tests bidirectional type inference for calls where the expected
# type is a union.
from typing import Any, AnyStr, Iterable, Literal, TypeVar, overload
T = TypeVar("T")
class ItemBase: ...
class Item(ItemBase): ...
def gen_items() -> Iterable[Item]:
return []
def make_list(val: Iterable[T]) -> list[T]:
return list(val)
x: ItemBase | list[ItemBase | None] = make_list(gen_items())
@overload
def urlunsplit(components: Iterable[None]) -> Literal[b""]: ...
@overload
def urlunsplit(components: Iterable[AnyStr | None]) -> AnyStr: ...
def urlunsplit(components: Iterable[Any]) -> Any: ...
def func(url: str, candidates: list[Any]) -> str | None:
return urlunsplit(candidates[0])
@@ -1,32 +0,0 @@
# This sample tests a case of bidirectional type inference for calls
# that involves a union in the expected type.
# viper: strict
from __future__ import annotations
from collections.abc import Callable
from typing import Generic, TypeVar
T_co = TypeVar("T_co", covariant=True)
E_co = TypeVar("E_co", covariant=True)
F = TypeVar("F")
class Ok(Generic[T_co]):
def or_else(self, op: object) -> Ok[T_co]: ...
class Err(Generic[E_co]):
def or_else(self, op: Callable[[E_co], Result[T_co, F]]) -> Result[T_co, F]: ...
Result = Ok[T_co] | Err[E_co]
def inner(func: Callable[[E_co], Err[F]], r: Result[T_co, E_co]) -> Result[T_co, F]:
match r:
case Ok():
return r.or_else(func)
case Err():
return r.or_else(func)
@@ -1,183 +0,0 @@
# This sample tests function parameter matching logic.
from typing import Any, Callable, Literal
def func1(a: int, *b: int):
pass
func1(3)
func1(3, 4)
func1(3, *[1, 2, 3])
# This should generate an error
func1(3, "hello")
# This should generate an error
func1(3, 5, 2, "str")
# This should generate an error
func1("hello", 3)
str_list = ["he", "2", "3"]
# This should generate an error
func1(3, *str_list)
def func2(a: str, **b: int):
pass
func2("hi")
func2("hi", b=3, c=4, d=5)
str_dict = {"a": "3", "b": "2"}
# This should generate a type error
func2("hi", **str_dict)
# This should generate a type error
func2("hi", 3)
# This should generate a type error
func2("hi", b="hi")
def func4(*args: int):
pass
def func5(a: int, *args):
pass
tuple1 = (2, 3)
func4(*tuple1)
func5(*tuple1)
# This should generate an error because a is assigned twice.
func2(a="", a="")
# This should generate an error because c is assigned twice.
func2("", c=4, d=5, c=5)
def func6(param1: int, param2: str):
pass
def func7(*args: Any, param0: int, param1: int, param2: str):
func6(*args, param1=param1, param2=param2)
func6(param0, param2=param2)
# This should generate two errors because param0 has no match
# and param2 is missing.
func6(param0, param1=param1)
def func8(
y: str,
z: bool = ...,
) -> None: ...
kwargs1: dict[str, int] = {}
# This should generate an error because int is not compatible with str.
func8(z=False, **kwargs1)
class MyStr(str): ...
kwargs2: dict[MyStr, MyStr] = {}
func8(z=False, **kwargs2)
def func9(
x: int,
y: str,
*,
a: str = ...,
b: str,
c: str,
) -> None: ...
kwargs3: dict[str, str] = {}
func9(0, "", **kwargs3)
args4: list[str] = ["hi"]
func9(0, *args4, **kwargs3)
# This should generate an error.
func9(*args4, **kwargs3)
def func10(x: int): ...
func10(1, *())
# This should generate an error.
func10(1, *(1,))
func10(*(1,))
# This should generate an error.
func10(*(1, 1))
# This should generate an error.
func10(*("",))
def func11(y: tuple[int, ...]):
func10(1, *y)
def func12(x: int, /, y: str):
pass
# This should generate an error.
func12(1, **{"z": None})
def func13(*, a: str, b: str, c: int | None = None):
...
func_args1: dict[Literal["a", "b", "d"], str] = {
"a": "a",
"b": "b",
"d": "d",
}
func13(**func_args1)
func_args2: dict[Literal["a", "b", "c"], str] = {
"a": "a",
"b": "b",
"c": "c",
}
# This should generate an error.
func13(**func_args2)
def func14(cb1: Callable[..., Any], cb2: Any, x: None):
cb1(**x) # This should generate an error
cb2(**x) # This should generate an error
def func15(cb1: Callable[..., Any], cb2: Any, a: int, b: None | str):
print(*a) # This should generate an error
print(*b) # This should generate an error
cb1(*a) # This should generate an error
cb2(*b) # This should generate an error
@@ -1,180 +0,0 @@
# This sample tests the Python 3.8 "positional-only parameter" feature.
from typing import Any, Dict, Protocol, Tuple
def f0(a: int, b: int):
return 3
def f1(a: int, b: int, /):
return 3
# This should generate an error because only one
# '/' parameter is allowed.
def f2(a: int, /, b: int, /):
return 3
def f3(a: int, /, b: int):
return 3
def f4(a: int, /, b: int, *, c: int):
return 3
# This should generate an error because a '/'
# parameter shouldn't appear after '*'.
def f5(a: int, *, b: int, /, c: int):
return 3
# This should generate an error because a '/'
# parameter cannot be the first in a param list.
def f6(/, a: int, *, b: int):
return 3
f0(2, 3)
f1(2, 3)
# This should generate an error because b
# is a position-only parameter.
f1(2, b=3)
# This should generate an error because a and b
# are position-only parameters.
f1(a=2, b=3)
f2(2, 3)
# This should generate an error.
f2(a=2, b=3)
f3(2, 3)
f3(2, b=3)
# This should generate 1 error because a is a
# position-only parameter.
f3(a=2, b=3)
f4(1, 2, c=3)
f4(1, b=2, c=3)
# This should generate an error because c is a
# keyword-only parameter.
f4(1, 2, 3)
# This should generate an error because a is a
# positional-only parameter.
f4(a=1, b=2, c=3)
# This will an error because of the bad
# declaration. Test to make sure we don't crash.
f5(1, b=2, c=3)
f6(1, b=2)
f6(a=1, b=2)
class A:
def f(self, g: bool = False, /, **kwargs) -> None:
...
a = A()
a.f(hello="world")
def f7(name: str, /, **kwargs: Any):
return 3
f7("hi", name=3)
# This should generate an error
f7("hi", name=3, name=4)
class P1(Protocol):
def f(self, x: Any, /):
...
class C1:
def f(
self,
y: Any,
):
...
c1: P1 = C1()
class P2(Protocol):
def f(self, x: Any):
...
class C2:
def f(self, y: Any, /):
...
# This should generate an error
c2: P2 = C2()
def f8(a: int, b: int = 3, /):
...
kwargs: Dict[str, Any] = {}
# This should generate an error
f8()
# This should generate an error
f8(**kwargs)
f8(0, **kwargs)
def f9(*, c: int):
pass
# This should generate an error because it is missing a keyword
# argument for keyword parameter "c".
f9(*[1, 2, 3])
# This should generate an error because "/" cannot be used after "*args"
def f10(x, *args, /, y):
pass
# This should generate an error because "*" cannot be used after "*args"
def f11(x, *args, *, y):
pass
def f15(x, /, *args):
pass
# This should generate an error because x
# is a position-only parameter.
f15(x=1)
def f16(x, /, *args, **kw):
pass
# This should generate an error because x
# is a position-only parameter.
f16(x=1)
def f12(a: int, b: str, /):
...
def f13(v: Tuple[int, str]):
f12(*v)
def f14(v: Tuple[int]):
# This should generate an error because parameter "b" has
# no corresponding argument.
f12(*v)
@@ -1,11 +0,0 @@
# This sample tests that the TypeVar matching logic for
# functions is working correctly.
a: list[str] = ["a", "bc"]
# This should work because the "sorted" is defined
# with the first parameter of Iterable[_T] and the
# 'key' parameter Callable[[_T], Any]. Since "len"
# is a function that takes a "Sized" and "str" is
# a "Sized", the result of this should be List[str].
b: list[str] = sorted(a, key=len)
@@ -1,94 +0,0 @@
# This sample tests handling of unpack operators used
# for arguments that are of a specified length (specifically,
# tuples with a specified list of elements types).
from typing import NamedTuple, List, Tuple
X = NamedTuple("X", [("a", int), ("b", str), ("c", str)])
q0: List[Tuple[int, str, str]] = [(1, "", ""), (2, "", "")]
[X(*item) for item in q0]
q1: List[Tuple[int, str, float]] = [(1, "a", 3), (2, "b", 4), (3, "c", 5)]
# This should generate an error because the items in q1 are not the
# right type for the X constructor.
[X(*item) for item in q1]
q2: List[Tuple[int, str]] = [(1, "1"), (2, "2"), (3, "3")]
# This should generate an error because the items in q2 contain only
# two elements, and we need three to populate all three parameters
# in the X constructor.
[X(*item) for item in q2]
q3: List[Tuple[int, str, str, float]] = [
(1, "a", "3", 4),
(2, "b", "4", 5),
(3, "c", "5", 6),
]
# This should generate an error because the items in q3 contain
# four elements, and we need three to populate all parameters
# in the X constructor.
[X(*item) for item in q3]
q4: List[Tuple[int, ...]] = [
(1, 3),
(2, 5),
(3, 6),
]
# This should generate two errors because it isn't assignable to parameter
# b or c.
[X(*item) for item in q4]
Y = NamedTuple("Y", [("a", str), ("b", str), ("c", str)])
q5: List[Tuple[str, ...]] = [
("a", "b"),
("a", "b"),
]
[Y(*item) for item in q5]
class Z(NamedTuple):
a: list[str]
b: list[int]
q6 = Z(["1"], [3])
for a, b in zip(*q6):
reveal_type(a, expected_text="str")
reveal_type(b, expected_text="int")
def func1(a: list[str], c: list[int]): ...
func1(*q6)
class ABC(NamedTuple):
a: float
b: float
c: float
def to_rgba(self) -> "ABC":
return ABC(*self)
class AB(NamedTuple):
a: float
b: float
def to_abc(self) -> ABC:
return ABC(*self, 1)
@@ -1,50 +0,0 @@
# This sample tests the handling of unpack operators
# used in argument expressions when used in conjunction with
# tuples and *args parameters.
def func1(a: int, b: int):
pass
def func2(*args: int):
pass
fixed_tuple_0 = ()
func1(*fixed_tuple_0, 2, 3)
func2(*fixed_tuple_0, 2)
fixed_tuple_1 = (1,)
# This should generate an error because there
# are too many parameters.
func1(*fixed_tuple_1, 2, 3)
func2(*fixed_tuple_1, 2, *fixed_tuple_0)
fixed_tuple_3 = (1, 3, 5)
# This should generate an error because there
# are too many parameters.
func1(*fixed_tuple_3, 2)
func2(*fixed_tuple_3, 2, *fixed_tuple_0)
unbounded_tuple: tuple[int, ...] = (1, 5, 3)
func2(*unbounded_tuple)
func2(*unbounded_tuple, 2)
def func3(*args: str): ...
def func4(v1: list[str] | None, v2: None, v3: list[str]):
# This should generate an error.
func3(*v1)
# This should generate an error.
func3(*v2)
func3(*v3)
@@ -1,85 +0,0 @@
# This sample tests the handling of an unpacked TypedDict passed as
# an argument to a function.
from typing import TypedDict, Unpack
class TD1(TypedDict):
arg1: int
arg2: str
class TD2(TD1):
arg3: float
def func1(arg1: int, arg2: str):
pass
def func2(arg1: int, arg2: str, arg3: float):
pass
def func3(arg1: int, arg2: str, **kwargs: float):
pass
def func4(arg1: int, arg2: str, **kwargs: int):
pass
def func5(arg1: int, arg2: str, **kwargs: object):
pass
td1: TD1 = {"arg1": 10, "arg2": "something"}
td2: TD2 = {"arg1": 10, "arg2": "something", "arg3": 3.4}
func1(**td1)
# This should generate an error because "arg1" is already assigned
func1(arg1=3, **td1)
# This should generate an error because "arg3" isn't provided
func1(**td2)
# This should generate an error because "arg3" isn't matched
func2(**td1)
func2(**td2)
# This should generate an error because the extra entries
# in the TD are of type object.
func3(**td1)
# This should generate an error because the extra entries
# in the TD are of type object.
func3(**td2)
# This should generate an error because the extra entries
# in the TD are of type object.
func4(**td1)
func5(**td1)
func5(**td2)
# This should generate two errors because "arg3" cannot be matched
# due to the type of the **kwargs parameter. Also, the extra entries
# in the TD are of type object.
func4(**td2)
class Options(TypedDict, total=False):
opt1: bool
opt2: str
def func6(code: str | None = None, **options: Unpack[Options]):
pass
func6(**{})
func6(**{"opt1": True})
func6(**{"opt2": "hi"})
@@ -1,40 +0,0 @@
# This sample tests a case where multiple overloaded calls are nested
# within each other.
from typing import Any, Iterable, TypeVar, Protocol, overload
from typing_extensions import ( # viper: ignore[reportMissingModuleSource]
LiteralString,
)
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
class SupportsLenAndGetItem(Protocol[_T_co]):
def __getitem__(self, __k: int) -> _T_co: ...
def choices(population: SupportsLenAndGetItem[_T]) -> list[_T]: ...
@overload
def join(__iterable: Iterable[LiteralString]) -> LiteralString: # type:ignore
...
@overload
def join(__iterable: Iterable[str]) -> str: ...
@overload
def array(object: int) -> list[Any]: ...
@overload
def array(object: object) -> list[Any]: ...
def array(object: object) -> list[Any]: ...
array([join(choices("")) for i in range(1)])
@@ -1,51 +0,0 @@
# This sample tests the case where a dictionary expansion operator
# is used in a call. The type checker should verify that the
# type supports a SupportsKeyAndGetItem protocol.
from typing import Any, Generic, Iterator, TypeVar, Mapping, KeysView
class MyMapping(Mapping[str, Any]):
def __getitem__(self, __key: str) -> Any: ...
def __iter__(self) -> Iterator[str]: ...
def __len__(self) -> int: ...
class StrRecord:
def __getitem__(self, __key: str) -> str: ...
def keys(self) -> KeysView[str]: ...
T = TypeVar("T")
class GenericRecord(Generic[T]):
def __getitem__(self, __key: str) -> T: ...
def keys(self) -> KeysView[T]: ...
def func1(**kwargs: Any) -> None: ...
m = MyMapping()
r = StrRecord()
def func2(
m: MyMapping,
r: StrRecord,
g: GenericRecord[str],
mrg: MyMapping | StrRecord | GenericRecord[str],
bad: GenericRecord[bytes],
):
func1(**m)
func1(**r)
func1(**g)
func1(**mrg)
# This should generate an error.
func1(**bad)
@@ -1,35 +0,0 @@
# This sample tests pyright's ability to perform return type
# analysis of functions based on call-site arguments.
# This function has no type annotations
from typing import TypeVar
T = TypeVar("T")
def add(a, b):
return a + b
async def async_call(x):
return x
def deco1(f: T) -> T:
return f
@deco1
def add2(a, b):
return a + b
def identity(a):
return a
def func1(x: T) -> T:
a = identity(x)
reveal_type(a, expected_text="T@func1")
return a
@@ -1,16 +0,0 @@
# This sample tests pyright's ability to perform return type
# analysis of functions based on call-site arguments.
from .callSite1 import add, add2, async_call
v1 = add(1, 2)
reveal_type(v1, expected_text="Literal[3]")
v2 = add("hi", "there")
reveal_type(v2, expected_text="Literal['hithere']")
v3 = add2(1, 2)
reveal_type(v3, expected_text="Unknown")
v4 = async_call(1)
reveal_type(v4, expected_text="CoroutineType[Any, Any, Unknown]")
@@ -1,50 +0,0 @@
# This sample tests the case where a call-site return type evaluation
# is invoked multiple times within a loop using different literal values
# each time.
def func1(h, ids):
for _ in ids:
h = func2(h, 1)
h = func2(h, 2)
h = func2(h, 3)
h = func2(h, 4)
h = func2(h, 5)
h = func2(h, 6)
h = func2(h, 7)
h = func2(h, 8)
h = func2(h, 9)
h = func2(h, 10)
h = func2(h, 11)
h = func2(h, 12)
h = func2(h, 13)
h = func2(h, 14)
h = func2(h, 15)
h = func2(h, 16)
h = func2(h, 17)
h = func2(h, 18)
h = func2(h, 19)
h = func2(h, 20)
h = func2(h, 21)
h = func2(h, 22)
h = func2(h, 23)
h = func2(h, 24)
h = func2(h, 25)
h = func2(h, 26)
h = func2(h, 27)
h = func2(h, 28)
h = func2(h, 29)
h = func2(h, 30)
h = func2(h, 31)
h = func2(h, 32)
h = func2(h, 33)
h = func2(h, 34)
h = func2(h, 35)
h = func2(h, 36)
h = func2(h, 37)
h = func2(h, 38)
h = func2(h, 39)
def func2(a, unused):
return a
@@ -1,51 +0,0 @@
# This sample tests the type checker's handling of the
# builtin "Callable" class.
from typing import Callable
Callable1 = Callable[["A"], None]
class A:
pass
Callable2 = Callable[[A], None]
def func1(a: Callable1):
a(A())
def func2(a: Callable2):
a(A())
Callable3 = Callable[..., int]
def func3(a: Callable3) -> int:
return a(1, 2, 3) + a() + a("hello") + a([])
# This should generate an error (... not allowed in param list).
Callable4 = Callable[[...], int]
# This should generate an error (too many arguments).
Callable5 = Callable[..., int, int]
# Test Callable with no parameters
Callable6 = Callable[[], str]
def func6(a: Callable6):
a()
# This should generate an error.
a(1)
def func7(a: Callable):
reveal_type(a, expected_text="(...) -> Unknown")
b = a(3, 4, 5)
reveal_type(b, expected_text="Unknown")
@@ -1,55 +0,0 @@
# This sample tests the assignment of generic callables
# to concrete callable types.
from asyncio.futures import Future
from asyncio.tasks import ensure_future
from typing import Any, Awaitable, Callable, Iterable, Sequence, TypeVar
_T1 = TypeVar("_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: ...
# This should generate an error because an Iterable parameter
# is not assignable to a Sequence parameter.
c: Callable[[Iterable[float]], float] = func2
_T2 = TypeVar("_T2", bound=float)
def func3(__iterable: Iterable[_T2]) -> _T2: ...
d: Callable[[Sequence[int]], int] = func3
# This should generate an error because Sequence[str]
# is not compatible with the bound TypeVar _T2.
e: Callable[[Sequence[str]], Any] = func3
_T3 = TypeVar("_T3")
TA1 = Callable[[_T3], None]
TA2 = Callable[[TA1[_T3]], None]
def func4(cb: TA2[_T3]) -> Awaitable[_T3]:
future: Future[_T3] = Future()
return ensure_future(future)
def func5(done: TA1[int]) -> None:
pass
reveal_type(func4(func5), expected_text="Awaitable[int]")
@@ -1,23 +0,0 @@
# This sample tests the case where a callable type contains a
# callable type as an input parameter, and the latter callable
# contains generic types.
from typing import Callable, Generic, TypeVar
T = TypeVar("T")
R = TypeVar("R")
class ClassA(Generic[R]): ...
class ClassB(Generic[T]):
def method1(self, val: Callable[[ClassA[R]], T]) -> R | None:
return None
b1: ClassB[tuple[int, ClassA[str]]] = ClassB()
v1: Callable[[ClassA[str]], tuple[int, ClassA[str]]] = lambda r: (42, r)
ret = b1.method1(v1)
reveal_type(ret, expected_text="str | None")
@@ -1,32 +0,0 @@
# This sample tests the case where a callable type within a function
# signature contains a generic return type within a union.
from typing import TypeVar
from collections.abc import Callable
T = TypeVar("T")
U = TypeVar("U")
def func1(f: Callable[[T], U | None], x: T) -> U:
y = f(x)
reveal_type(y, expected_text="U@func1 | None")
if y is not None:
reveal_type(y, expected_text="U@func1")
return y
raise ValueError()
def func2(x: T, f: Callable[[T], U | None]) -> U:
def g() -> U:
y = f(x)
if y is not None:
return y
raise ValueError()
return g()
@@ -1,37 +0,0 @@
# This sample covers the case where a function accepts a generic callable
# as a parameter along with another parameter that uses the same type variable
# and a caller provides an overloaded function as an argument.
from typing import Any, Callable, TypeVar, overload
T = TypeVar("T")
@overload
def func1(real: float): ...
@overload
def func1(real: str): ...
def func1(real: float | str) -> None: ...
def func2(f: Callable[[T], Any], p: T):
return f(p)
func2(func1, 4)
func2(func1, "4")
# This should generate an error because a "bytes" argument
# doesn't match any of the overloads.
func2(func1, b"")
map(complex, ["3j", "4"])
# This should generate two errors because a "bytes" argument
# doesn't match any of the overloads in the "complex" constructor.
map(complex, [b"3j"])
@@ -1,91 +0,0 @@
# This sample tests the use of unpacked tuples in a Callable, as described
# in PEP 646.
from typing import Callable, TypeVar
from typing_extensions import ( # viper: ignore[reportMissingModuleSource]
TypeVarTuple,
Unpack,
)
_T = TypeVar("_T", bound=int)
TA1 = Callable[[_T, Unpack[tuple[int, ...]], tuple[int, int, str], str], _T]
# This should generate an error.
TA2 = Callable[
[int, Unpack[tuple[int, ...]], Unpack[tuple[int, int, str, ...]], str], int
]
TA3 = Callable[[int, Unpack[tuple[int, int]], str], int]
TA4 = Callable[[Unpack[tuple[int, ...]]], _T]
def func1(x: TA1[int]):
r1 = x(3, 4, 5, (1, 2, "hi"), "hi")
reveal_type(r1, expected_text="int")
x(3, (1, 2, "hi"), "hi")
# This should generate an error because the first argument is not an int.
x(None, (1, 2, "hi"), "hi")
y = [1, 2, 3]
x(1, *y, (1, 2, "hi"), "hi")
def func2(x: TA3):
x(3, 4, 5, "hi")
# This should generate an error.
x(3, 4, "hi")
# This should generate an error.
x(3, 4, "hi", "hi")
def func6(x: TA4):
x()
Ts = TypeVarTuple("Ts")
def func3(
path: str, *args: Unpack[tuple[Unpack[Ts], str]]
) -> tuple[Unpack[Ts], int]: ...
v3 = func3("", 1, "2", 3.3, None, "")
reveal_type(v3, expected_text="tuple[int, str, float, None, int]")
func3("", "")
# This should generate an error because the type of the first arg is wrong.
func3(1, "")
# This should generate an error because the type of the last arg is wrong.
func3("", 1)
# This should generate an error because the type of the last arg is wrong.
func3("", 1, 2, 3, "hi", 1)
def func4(
path: str, *args: Unpack[tuple[Unpack[Ts], str]]
) -> tuple[Unpack[Ts], complex]: ...
v4 = func4("", 1, "2", 3.3, None, "")
reveal_type(v4, expected_text="tuple[int, str, float, None, complex]")
def func5(path: str, *args: Unpack[tuple[str, ...]]) -> None: ...
# This should generate an errors.
func5("", 1, "2", "")
func5("", "1", "2", "3.3", "None", "")
# This should generate one error.
func5("", "1", "2", "3.3", "None", 3)
@@ -1,33 +0,0 @@
# This sample tests the handling of the `__call__` attribute.
from typing import Iterable, Iterator
class A:
def __init__(self):
self.__call__ = self.method1
def method1(self, a: int):
return a
# This should generate an error because `__call__` is
# callable only if it's a class variable.
A()(0)
class B:
def method1(self, a: int):
return a
__call__ = method1
B()(0)
class C[K](Iterable[K]):
def keys(self) -> Iterator[K]: ...
__iter__ = keys
@@ -1,159 +0,0 @@
# This sample tests support for callback protocols (defined in PEP 544).
from typing import Callable, Protocol
class TestClass1(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]:
return []
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
return []
def bad_cb1(*vals: bytes, maxlen: int | None, maxitems: int | None) -> list[bytes]:
return []
def bad_cb2(*vals: bytes) -> list[bytes]:
return []
def bad_cb3(*vals: bytes, maxlen: str | None) -> list[bytes]:
return []
var1: TestClass1 = good_cb
# This should generate an error because maxitems is unmatched.
var1 = bad_cb1
# This should generate an error because maxlen is unmatched.
var1 = bad_cb2
# This should generate an error because maxlen is the wrong type.
var1 = bad_cb3
class TestClass2(Protocol):
def __call__(self, *vals: bytes, **kwargs: str) -> None:
pass
def func1(*a: bytes, **b: str):
pass
def func2(*a: bytes):
pass
def func3(*a: str, **b: str):
pass
def func4(*a: bytes, **b: bytes):
pass
def func5(**b: str):
pass
var2: TestClass2 = func1
# This should generate an error.
var2 = func2
# This should generate an error.
var2 = func3
# This should generate an error.
var2 = func4
# This should generate an error.
var2 = func5
class NotProto:
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]:
return []
# This should generate an error because NotProto is not a protocol class.
not_proto: NotProto = good_cb
class TestClass3(Protocol):
def __call__(self) -> None:
pass
var3: TestClass3 = func1
var3 = func2
var3 = func3
var3 = func4
var3 = func5
class TestClass4(Protocol):
foo: int
def __call__(self, x: int) -> None:
pass
def test_func4(x: int) -> None:
pass
# This should generate an error.
var4: TestClass4 = test_func4
class TestClass5(Protocol):
def __call__(self, *, a: int, b: str) -> int: ...
def test_func5(a: int, b: str) -> int:
return 123
f5: TestClass5 = test_func5
class TestClass6(Protocol):
def __call__(self, a: int, /, *, b: str) -> int: ...
def test_func6(a: int, b: str) -> int:
return 123
f6: TestClass6 = test_func6
class TestClass7:
def __call__(self) -> None:
pass
def test_func7(*args: *tuple[int, *tuple[int, ...]]) -> int:
return 123
# This should generate an error.
f7: TestClass7 = test_func7
class TestClass8:
def __call__(self: Callable[[int], int], v: int) -> int:
return v
def func8(f: Callable[[int], int]): ...
func8(TestClass8())
@@ -1,61 +0,0 @@
# This sample tests the case where a callback protocol uses
# a (*args: Any, **kwargs: Any) signature.
from typing import Any, Callable, Concatenate, ParamSpec, Protocol, TypeVar
P = ParamSpec("P")
T_contra = TypeVar("T_contra", contravariant=True)
class Proto1(Protocol):
def __call__(self, *args, **kwargs) -> None: ...
class Proto2(Protocol):
def __call__(self, a: int, /, *args, **kwargs) -> None: ...
class Proto3(Protocol):
def __call__(self, a: int, *args: Any, **kwargs: Any) -> None: ...
class Proto4(Protocol[P]):
def __call__(self, a: int, *args: P.args, **kwargs: P.kwargs) -> None: ...
class Proto5(Protocol[T_contra]):
def __call__(self, *args: T_contra, **kwargs: T_contra) -> None: ...
class Proto6(Protocol):
def __call__(self, a: int, /, *args: Any, k: str, **kwargs: Any) -> None:
pass
class Proto7(Protocol):
def __call__(self, a: float, /, b: int, *, k: str, m: str) -> None:
pass
def func(
p1: Proto1,
p2: Proto2,
p3: Proto3,
p4: Proto4[...],
p5: Proto5[Any],
p7: Proto7,
c1: Callable[..., None],
c2: Callable[Concatenate[int, ...], None],
):
x1: Callable[..., None] = p1
x2: Proto1 = c1
x3: Callable[..., None] = p5
x4: Proto5[Any] = c1
x5: Callable[Concatenate[int, ...], None] = p2
x6: Proto2 = c2
x7: Callable[..., None] = p3
x8: Proto3 = c1
x9: Proto4[...] = p3
x10: Proto3 = p4
x11: Proto6 = p7
@@ -1,21 +0,0 @@
# This sample tests the case where a callback protocol uses a function-
# scoped type variable.
from typing import Generic, Protocol, TypeVar
T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
U_co = TypeVar("U_co", covariant=True)
class A(Generic[T_co, U_co]): ...
class BProto(Protocol):
def __call__(self, x: T) -> A[list[T], T]: ...
def func1() -> BProto:
def make_a(x: T) -> A[list[T], T]: ...
return make_a
@@ -1,28 +0,0 @@
# This sample tests the case where an object is assigned to a
# callback protocol and the object's "__call__" has unannotated
# or "Any" parameter types.
from typing import Any, Protocol, TypeVar
InputT = TypeVar("InputT", contravariant=True)
OutputT = TypeVar("OutputT", covariant=True)
class MyCallable(Protocol[InputT, OutputT]):
def __call__(self, inputs: InputT) -> OutputT: ...
class Class1:
def __call__(self, inputs) -> int:
return 5
g1: MyCallable[int, int] = Class1()
class Class2:
def __call__(self, inputs: Any) -> int:
return 5
g2: MyCallable[int, int] = Class2()
@@ -1,20 +0,0 @@
# This sample tests the case where a callback protocol uses a
# class-level type variable and a combination of Type[T] and T.
from typing import Protocol, TypeVar, Type
TE = TypeVar("TE", bound=Exception)
class CallbackProtocol1(Protocol[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 func2(
s_exc_class: Exception,
t_exc_class: Type[TE],
mapper: CallbackProtocol1[TE] = func1,
): ...
@@ -1,65 +0,0 @@
# This sample tests the case where a callback protocol uses
# an overloaded __call__ method.
from typing import Any, Protocol, overload
class P1(Protocol):
@overload
def __call__(self, x: int) -> int: ...
@overload
def __call__(self, x: str) -> str: ...
def __call__(self, x: Any) -> Any: ...
def func0(x: Any) -> Any:
return x
def func1(x: int) -> Any:
return x
a0: P1 = func0
# This should generate an error
a1: P1 = func1
@overload
def of1(x: int) -> int: ...
@overload
def of1(x: str) -> str: ...
def of1(x: Any) -> Any:
return x
@overload
def of2(x: int) -> complex: ...
@overload
def of2(x: str) -> str: ...
def of2(x: Any) -> Any:
return x
b0: P1 = of1
# This should generate an error
b1: P1 = of2
class P2(Protocol):
def __call__(self, *args: int) -> Any: ...
a: P2 = lambda *args: map(lambda arg: arg + 0, args)
@@ -1,84 +0,0 @@
# This sample tests the case where a callback protocol defines additional
# attributes.
from typing import Any, Callable, Protocol, TypeVar, cast
from typing_extensions import ParamSpec # viper: ignore[reportMissingModuleSource]
P = ParamSpec("P")
R = TypeVar("R", covariant=True)
class CallbackProto1(Protocol[P, R]):
__name__: str
other_attribute: int
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
def decorator1(f: Callable[P, R]) -> CallbackProto1[P, R]:
converted = cast(CallbackProto1, f)
print(converted.__name__)
converted.other_attribute = 1
# This should generate an error
converted.other_attribute = "str"
# This should generate an error
converted.xxx = 3
return converted
@decorator1
def func1(x: int) -> str: ...
reveal_type(func1, expected_text="CallbackProto1[(x: int), str]")
func1.other_attribute
# This should generate an error
func1.other_attribute2
func1(x=3)
class CallbackProto2(Protocol):
__name__: str
__module__: str
__qualname__: str
__annotations__: dict[str, Any]
__slots__ = ()
def __call__(self) -> None: ...
def func2() -> None: ...
v: CallbackProto2 = func2
class TestClass7(Protocol):
def __call__(self, x: int, /, y: str) -> Any: ...
def func8(x: int, y: str, /) -> Any:
pass
def func9(__x: int, __y: str) -> Any:
pass
# This should generate an error because "y" is position-only
# in the source but not the dest.
var7: TestClass7 = func8
# This should generate an error because "y" is position-only
# in the source but not the dest.
var8: TestClass7 = func9
Loaded 100 of 1269 files, more files were not shown because too many files have changed in this diff. Show more