-
Notifications
You must be signed in to change notification settings - Fork 263
Add conformance tests for basic generic spec #1553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
47cb3b1
Add conformance tests for basic generic spec
hauntsaninja b64195b
.
hauntsaninja d8124a7
.
hauntsaninja a5dc7b4
.
hauntsaninja 6d77e04
.
hauntsaninja 957d3a6
.
hauntsaninja 72a9527
fix
hauntsaninja 1632287
fix
hauntsaninja 638cc1f
add
hauntsaninja be44ad5
alias
hauntsaninja 4ae4478
update
hauntsaninja 7e029b1
generic order
hauntsaninja 09de5c8
grading
hauntsaninja File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_basic.py:36: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:37: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:44: error: TypeVar cannot have only a single constraint [misc] | ||
generics_basic.py:48: error: Type variable "generics_basic.T" is unbound [valid-type] | ||
generics_basic.py:48: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_basic.py:48: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_basic.py:59: error: Value of type variable "AnyStr" of "concat" cannot be "Sequence[object]" [type-var] | ||
generics_basic.py:107: error: Duplicate type variables in Generic[...] or Protocol[...] [misc] | ||
generics_basic.py:140: error: Invalid index type "int" for "MyMap1[str, int]"; expected type "str" [index] | ||
generics_basic.py:141: error: Invalid index type "int" for "MyMap2[int, str]"; expected type "str" [index] | ||
generics_basic.py:167: error: Dynamic metaclass not supported for "GenericMetaInstance" [misc] | ||
generics_basic.py:167: error: Type variable "generics_basic.T" is unbound [valid-type] | ||
generics_basic.py:167: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_basic.py:167: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False negative on generic class nested within generic class with same type variable. | ||
""" | ||
output = """ | ||
generics_scoping.py:25: error: Argument 1 to "meth_2" of "MyClass" has incompatible type "str"; expected "int" [arg-type] | ||
generics_scoping.py:46: error: Type variable "generics_scoping.S" is unbound [valid-type] | ||
generics_scoping.py:46: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) | ||
generics_scoping.py:46: note: (Hint: Use "S" in function signature to bind "S" inside a function) | ||
generics_scoping.py:50: error: Type variable "generics_scoping.S" is unbound [valid-type] | ||
generics_scoping.py:50: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) | ||
generics_scoping.py:50: note: (Hint: Use "S" in function signature to bind "S" inside a function) | ||
generics_scoping.py:61: error: Free type variable expected in Generic[...] [misc] | ||
generics_scoping.py:74: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:74: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:74: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:80: error: Can't use bound type variable "T" to define generic alias [valid-type] | ||
generics_scoping.py:84: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:84: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:84: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:85: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:85: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:85: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
generics_scoping.py:86: error: Type variable "generics_scoping.T" is unbound [valid-type] | ||
generics_scoping.py:86: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) | ||
generics_scoping.py:86: note: (Hint: Use "T" in function signature to bind "T" inside a function) | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False positives in examples using constrained type variables. | ||
False negative in custom map example. | ||
False positive using `iter`. | ||
False negative for generic metaclass. | ||
""" | ||
output = """ | ||
generics_basic.py:31:4 Incompatible return type [7]: Expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:31:15 Incompatible parameter type [6]: In call `bytes.__add__`, for 1st positional argument, expected `Union[array[typing.Any], bytearray, bytes, _CData, memoryview, mmap, PickleBuffer]` but got `Variable[AnyStr <: [str, bytes]]`. | ||
generics_basic.py:36:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:37:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `str`. | ||
generics_basic.py:44:0 Invalid type [31]: TypeVar can't have a single explicit constraint. Did you mean `bound=str`? | ||
generics_basic.py:48:0 Invalid type [31]: Expression `Variable[BadConstraint2 <: [str, Variable[generics_basic.T]]]` is not a valid type. Type variables cannot contain other type variables in their constraints. | ||
generics_basic.py:59:14 Incompatible parameter type [6]: In call `concat`, for 2nd positional argument, expected `Variable[AnyStr <: [str, bytes]]` but got `bytes`. | ||
generics_basic.py:107:0 Duplicate type variables [59]: Duplicate type variable `T` in Generic[...]. | ||
generics_basic.py:161:25 Undefined attribute [16]: `typing.Iterator` has no attribute `__getitem__`. | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False negative on generic class nested within generic function with same type variable. | ||
False negative on generic class nested within generic class with same type variable. | ||
""" | ||
output = """ | ||
generics_scoping.py:25:9 Incompatible parameter type [6]: In call `MyClass.meth_2`, for 1st positional argument, expected `int` but got `str`. | ||
generics_scoping.py:46:7 Invalid type variable [34]: The type variable `Variable[S]` isn't present in the function's parameters. | ||
generics_scoping.py:50:13 Invalid type variable [34]: The current class isn't generic with respect to the type variable `Variable[S]`. To reference the type variable, you can modify the class to inherit from `typing.Generic[S]`. | ||
generics_scoping.py:70:0 Uninitialized attribute [13]: Attribute `attr` is declared in class `Outer` to have type `Outer.Inner[Variable[T]]` but is never initialized. | ||
generics_scoping.py:73:4 Uninitialized attribute [13]: Attribute `x` is declared in class `Outer.AlsoBad` to have type `typing.List[Variable[T]]` but is never initialized. | ||
generics_scoping.py:74:11 Invalid type variable [34]: The current class isn't generic with respect to the type variable `Variable[T]`. To reference the type variable, you can modify the class to inherit from `typing.Generic[T]`. | ||
generics_scoping.py:80:4 Incompatible attribute type [8]: Attribute `alias` declared in class `Outer` has type `TypeAlias` but is used as type `Type[List[Variable[_T]]]`. | ||
generics_scoping.py:80:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. | ||
generics_scoping.py:84:13 Invalid type variable [34]: The type variable `Variable[T]` can only be used to annotate generic classes or functions. | ||
generics_scoping.py:85:13 Invalid type variable [34]: The type variable `Variable[T]` can only be used to annotate generic classes or functions. | ||
generics_scoping.py:86:5 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_basic.py:36:15 - error: Argument of type "bytes" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"bytes" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:37:15 - error: Argument of type "str" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"str" is incompatible with "bytes" (reportGeneralTypeIssues) | ||
generics_basic.py:44:44 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues) | ||
generics_basic.py:48:49 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_basic.py:48:49 - error: TypeVar constraint type cannot be generic | ||
generics_basic.py:59:15 - error: Argument of type "bytes" cannot be assigned to parameter "y" of type "AnyStr@concat" in function "concat" | ||
"bytes" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:107:24 - error: Type arguments for "Generic" must be unique | ||
generics_basic.py:140:5 - error: Argument of type "Literal[0]" cannot be assigned to parameter "__key" of type "str" in function "__getitem__" | ||
"Literal[0]" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:141:5 - error: Argument of type "Literal[0]" cannot be assigned to parameter "__key" of type "str" in function "__getitem__" | ||
"Literal[0]" is incompatible with "str" (reportGeneralTypeIssues) | ||
generics_basic.py:167:37 - error: Metaclass cannot be generic (reportGeneralTypeIssues) | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
conformant = "Pass" | ||
output = """ | ||
generics_scoping.py:25:10 - error: Argument of type "Literal['a']" cannot be assigned to parameter "x" of type "int" in function "meth_2" | ||
"Literal['a']" is incompatible with "int" (reportGeneralTypeIssues) | ||
generics_scoping.py:46:13 - error: Type variable "S" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:50:19 - error: Type variable "S" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:61:29 - error: TypeVar "T" is already in use by an outer scope (reportGeneralTypeIssues) | ||
generics_scoping.py:71:24 - error: TypeVar "T" is already in use by an outer scope (reportGeneralTypeIssues) | ||
generics_scoping.py:74:17 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:80:5 - error: Generic type alias within class cannot use bound type variables T | ||
generics_scoping.py:84:14 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:85:19 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
generics_scoping.py:86:6 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
conformant = "Partial" | ||
notes = """ | ||
False positives in examples using constrained type variables. | ||
False negative for generic metaclass. | ||
""" | ||
output = """ | ||
File "generics_basic.py", line 31, in concat: bad return type [bad-return-type] | ||
Expected: MyStr | ||
Actually returned: str | ||
Called from (traceback): | ||
line 57, in test_concat_subtype | ||
File "generics_basic.py", line 36, in test_concat: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: str) | ||
Actually passed: (x, y: bytes) | ||
File "generics_basic.py", line 37, in test_concat: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: bytes) | ||
Actually passed: (x, y: str) | ||
File "generics_basic.py", line 44, in <module>: Invalid TypeVar: the number of constraints must be 0 or more than 1 [invalid-typevar] | ||
File "generics_basic.py", line 48, in <module>: Invalid TypeVar: constraint cannot contain TypeVars [invalid-typevar] | ||
File "generics_basic.py", line 57, in test_concat_subtype: MyStr [assert-type] | ||
Expected: str | ||
Actual: MyStr | ||
File "generics_basic.py", line 58, in test_concat_subtype: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: MyStr) | ||
Actually passed: (x, y: str) | ||
File "generics_basic.py", line 58, in test_concat_subtype: Any [assert-type] | ||
Expected: str | ||
Actual: Any | ||
File "generics_basic.py", line 59, in test_concat_subtype: Function concat was called with the wrong arguments [wrong-arg-types] | ||
Expected: (x, y: MyStr) | ||
Actually passed: (x, y: bytes) | ||
File "generics_basic.py", line 107, in <module>: Invalid type annotation 'Generic' [invalid-annotation] | ||
Parameters to Generic[...] must all be unique | ||
File "generics_basic.py", line 140, in test_my_map: unsupported operand type(s) for item retrieval: MyMap1[str, int] and int [unsupported-operands] | ||
Function __getitem__ on MyMap1[str, int] expects str | ||
File "generics_basic.py", line 141, in test_my_map: unsupported operand type(s) for item retrieval: MyMap2[int, str] and int [unsupported-operands] | ||
Function __getitem__ on MyMap2[int, str] expects str | ||
File "generics_basic.py", line 161, in test_my_iterable_any: Iterator[nothing] [assert-type] | ||
Expected: Iterator | ||
Actual: Iterator[nothing] | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
conformant = "Pass" | ||
output = """ | ||
File "generics_scoping.py", line 9, in fun_1: bad return type [bad-return-type] | ||
Expected: int | ||
Actually returned: None | ||
Called from (traceback): | ||
line 12, in current file | ||
File "generics_scoping.py", line 10, in fun_2: bad return type [bad-return-type] | ||
Expected: str | ||
Actually returned: None | ||
Called from (traceback): | ||
line 13, in current file | ||
File "generics_scoping.py", line 20, in meth_1: bad return type [bad-return-type] | ||
Expected: int | ||
Actually returned: None | ||
Called from (traceback): | ||
line 24, in current file | ||
File "generics_scoping.py", line 25, in <module>: Function MyClass.meth_2 was called with the wrong arguments [wrong-arg-types] | ||
Expected: (self, x: int) | ||
Actually passed: (self, x: str) | ||
File "generics_scoping.py", line 35, in method: bad return type [bad-return-type] | ||
Expected: str | ||
Actually returned: None | ||
Called from (traceback): | ||
line 38, in current file | ||
File "generics_scoping.py", line 35, in method: bad return type [bad-return-type] | ||
Expected: bytes | ||
Actually returned: None | ||
Called from (traceback): | ||
line 39, in current file | ||
File "generics_scoping.py", line 46, in fun_3: Invalid type annotation 'List[S]' for z [invalid-annotation] | ||
TypeVar(s) 'S' not in scope for method 'fun_3' | ||
File "generics_scoping.py", line 50, in Bar: Invalid type annotation 'List[S]' for an_attr [invalid-annotation] | ||
TypeVar(s) 'S' not in scope for class 'Bar' | ||
File "generics_scoping.py", line 59, in fun_4: Invalid type annotation 'T' [invalid-annotation] | ||
Function [fun_4] and its nested generic class [MyGeneric] cannot use the same type variable T | ||
File "generics_scoping.py", line 70, in <module>: Invalid type annotation 'Outer' [invalid-annotation] | ||
Generic class [Outer] and its nested generic class [Bad] cannot use the same type variable T. | ||
File "generics_scoping.py", line 74, in AlsoBad: Invalid type annotation 'List[T]' for x [invalid-annotation] | ||
TypeVar(s) 'T' not in scope for class 'Outer.AlsoBad' | ||
File "generics_scoping.py", line 84, in <module>: Invalid type annotation 'T' for global_var1 [invalid-annotation] | ||
TypeVar(s) 'T' not in scope | ||
File "generics_scoping.py", line 85, in <module>: Invalid type annotation 'List[T]' for global_var2 [invalid-annotation] | ||
TypeVar(s) 'T' not in scope | ||
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
""" | ||
Tests for basic usage of generics. | ||
""" | ||
|
||
# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#introduction | ||
|
||
from __future__ import annotations | ||
|
||
from collections.abc import Sequence | ||
from typing import Any, Generic, TypeVar, assert_type | ||
|
||
T = TypeVar('T') | ||
|
||
# > Generics can be parameterized by using a factory available in | ||
# > ``typing`` called ``TypeVar``. | ||
|
||
def first(l: Sequence[T]) -> T: | ||
return l[0] | ||
|
||
|
||
def test_first(seq_int: Sequence[int], seq_str: Sequence[str]) -> None: | ||
assert_type(first(seq_int), int) | ||
assert_type(first(seq_str), str) | ||
|
||
# > ``TypeVar`` supports constraining parametric types to a fixed set of | ||
# > possible types | ||
|
||
AnyStr = TypeVar('AnyStr', str, bytes) | ||
|
||
def concat(x: AnyStr, y: AnyStr) -> AnyStr: | ||
return x + y | ||
|
||
def test_concat(s: str, b: bytes, a: Any) -> None: | ||
concat(s, s) # OK | ||
concat(b, b) # OK | ||
concat(s, b) # Type error | ||
concat(b, s) # Type error | ||
|
||
concat(s, a) # OK | ||
concat(a, b) # OK | ||
|
||
# > Specifying a single constraint is disallowed. | ||
|
||
BadConstraint1 = TypeVar('BadConstraint1', str) # Type error | ||
|
||
# > Note: those types cannot be parameterized by type variables | ||
|
||
BadConstraint2 = TypeVar('BadConstraint2', str, T) # Type error | ||
|
||
# > Subtypes of types constrained by a type variable should be treated | ||
# > as their respective explicitly listed base types in the context of the | ||
# > type variable. | ||
|
||
class MyStr(str): ... | ||
|
||
def test_concat_subtype(s: str, b: bytes, a: Any, m: MyStr) -> None: | ||
assert_type(concat(m, m), str) | ||
assert_type(concat(m, s), str) | ||
concat(m, b) # Type error | ||
|
||
# TODO: should these be str or Any? | ||
# reveal_type(concat(m, a)) | ||
# reveal_type(concat(a, m)) | ||
|
||
# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#user-defined-generic-classes | ||
|
||
# > You can include a ``Generic`` base class to define a user-defined class | ||
# > as generic. | ||
|
||
from logging import Logger | ||
from collections.abc import Iterable | ||
|
||
class LoggedVar(Generic[T]): | ||
def __init__(self, value: T, name: str, logger: Logger) -> None: | ||
self.name = name | ||
self.logger = logger | ||
self.value = value | ||
|
||
def set(self, new: T) -> None: | ||
self.log('Set ' + repr(self.value)) | ||
self.value = new | ||
|
||
def get(self) -> T: | ||
self.log('Get ' + repr(self.value)) | ||
return self.value | ||
|
||
def log(self, message: str) -> None: | ||
self.logger.info('{}: {}'.format(self.name, message)) | ||
|
||
|
||
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: | ||
for var in vars: | ||
var.set(0) | ||
assert_type(var.get(), int) | ||
|
||
|
||
# > A generic type can have any number of type variables, and type variables | ||
# > may be constrained. | ||
|
||
S = TypeVar('S') | ||
|
||
class Pair1(Generic[T, S]): | ||
... | ||
|
||
# > Each type variable argument to ``Generic`` must be distinct. | ||
|
||
class Pair2(Generic[T, T]): # Type error | ||
... | ||
|
||
# > The ``Generic[T]`` base class is redundant in simple cases where you | ||
# > subclass some other generic class and specify type variables for its | ||
# > parameters. | ||
|
||
from collections.abc import Iterator, Mapping | ||
|
||
class MyIter1(Iterator[T]): | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... | ||
|
||
class MyIter2(Iterator[T], Generic[T]): | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... | ||
|
||
def test_my_iter(m1: MyIter1[int], m2: MyIter2[int]): | ||
assert_type(next(m1), int) | ||
assert_type(next(m2), int) | ||
|
||
|
||
K = TypeVar("K") | ||
V = TypeVar("V") | ||
|
||
class MyMap1(Mapping[K, V], Generic[K, V]): | ||
... | ||
|
||
class MyMap2(Mapping[K, V], Generic[V, K]): | ||
... | ||
|
||
def test_my_map(m1: MyMap1[str, int], m2: MyMap2[int, str]): | ||
assert_type(m1["key"], int) | ||
assert_type(m2["key"], int) | ||
|
||
m1[0] # Type error | ||
m2[0] # Type error | ||
|
||
# > You can use multiple inheritance with ``Generic`` | ||
|
||
from collections.abc import Sized, Container | ||
|
||
class LinkedList(Sized, Generic[T]): | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... | ||
|
||
class MyMapping(Iterable[tuple[K, V]], Container[tuple[K, V]], Generic[K, V]): | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... | ||
|
||
# > Subclassing a generic class without specifying type parameters assumes | ||
# > ``Any`` for each position. In the following example, ``MyIterable`` | ||
# > is not generic but implicitly inherits from ``Iterable[Any]``:: | ||
|
||
class MyIterableAny(Iterable): # Same as Iterable[Any] | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
... | ||
|
||
def test_my_iterable_any(m: MyIterableAny): | ||
assert_type(iter(m), Iterator[Any]) | ||
|
||
# > Generic metaclasses are not supported | ||
|
||
class GenericMeta(type, Generic[T]): ... | ||
|
||
class GenericMetaInstance(metaclass=GenericMeta[T]): # Type error | ||
... | ||
hauntsaninja marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may also be useful to add tests for accessing a TypeVar as a runtime object — to make sure that this isn't disallowed. assert_type(T.__name__, str)
assert_type(T.__bound__, Any | None)
T.other # Type error
runtime_typevar: TypeVar = T # OK |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gets into constraint-solving behavior which is underspecified, but I'm still surprised to see that mypy generates an
Any
in this case. That's not what I would expect, and it seems inconsistent with mypy's handling of non-constrained TypeVars.