mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Update class literal display to use <class 'Foo'>
style (#17889)
## Summary Closes https://github.com/astral-sh/ruff/issues/17238.
This commit is contained in:
parent
b2de749c32
commit
a2e9a7732a
48 changed files with 311 additions and 309 deletions
|
@ -76,7 +76,7 @@ from typing_extensions import Annotated
|
|||
class C(Annotated[int, "foo"]): ...
|
||||
|
||||
# TODO: Should be `tuple[Literal[C], Literal[int], Literal[object]]`
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], @Todo(Inference of subscript on special form), Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, @Todo(Inference of subscript on special form), <class 'object'>]
|
||||
```
|
||||
|
||||
### Not parameterized
|
||||
|
@ -88,5 +88,5 @@ from typing_extensions import Annotated
|
|||
# error: [invalid-base]
|
||||
class C(Annotated): ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Unknown, Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
|
|
@ -59,7 +59,7 @@ from typing import Any
|
|||
|
||||
class SubclassOfAny(Any): ...
|
||||
|
||||
reveal_type(SubclassOfAny.__mro__) # revealed: tuple[Literal[SubclassOfAny], Any, Literal[object]]
|
||||
reveal_type(SubclassOfAny.__mro__) # revealed: tuple[<class 'SubclassOfAny'>, Any, <class 'object'>]
|
||||
|
||||
x: SubclassOfAny = 1 # error: [invalid-assignment]
|
||||
y: int = SubclassOfAny()
|
||||
|
|
|
@ -85,25 +85,25 @@ import typing
|
|||
class ListSubclass(typing.List): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[ListSubclass], Literal[list], Literal[MutableSequence], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'ListSubclass'>, <class 'list'>, <class 'MutableSequence'>, <class 'Sequence'>, <class 'Reversible'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, <class 'object'>]
|
||||
reveal_type(ListSubclass.__mro__)
|
||||
|
||||
class DictSubclass(typing.Dict): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[DictSubclass], Literal[dict[Unknown, Unknown]], Literal[MutableMapping[Unknown, Unknown]], Literal[Mapping[Unknown, Unknown]], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], Literal[object]]
|
||||
# revealed: tuple[<class 'DictSubclass'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], <class 'object'>]
|
||||
reveal_type(DictSubclass.__mro__)
|
||||
|
||||
class SetSubclass(typing.Set): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[SetSubclass], Literal[set], Literal[MutableSet], Literal[AbstractSet], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'SetSubclass'>, <class 'set'>, <class 'MutableSet'>, <class 'AbstractSet'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, <class 'object'>]
|
||||
reveal_type(SetSubclass.__mro__)
|
||||
|
||||
class FrozenSetSubclass(typing.FrozenSet): ...
|
||||
|
||||
# TODO: should have `Generic`, should not have `Unknown`
|
||||
# revealed: tuple[Literal[FrozenSetSubclass], Literal[frozenset], Unknown, Literal[object]]
|
||||
# revealed: tuple[<class 'FrozenSetSubclass'>, <class 'frozenset'>, Unknown, <class 'object'>]
|
||||
reveal_type(FrozenSetSubclass.__mro__)
|
||||
|
||||
####################
|
||||
|
@ -113,30 +113,30 @@ reveal_type(FrozenSetSubclass.__mro__)
|
|||
class ChainMapSubclass(typing.ChainMap): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[ChainMapSubclass], Literal[ChainMap[Unknown, Unknown]], Literal[MutableMapping[Unknown, Unknown]], Literal[Mapping[Unknown, Unknown]], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], Literal[object]]
|
||||
# revealed: tuple[<class 'ChainMapSubclass'>, <class 'ChainMap[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], <class 'object'>]
|
||||
reveal_type(ChainMapSubclass.__mro__)
|
||||
|
||||
class CounterSubclass(typing.Counter): ...
|
||||
|
||||
# TODO: Should be (CounterSubclass, Counter, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
|
||||
# revealed: tuple[Literal[CounterSubclass], Literal[Counter[Unknown]], Literal[dict[Unknown, int]], Literal[MutableMapping[Unknown, int]], Literal[Mapping[Unknown, int]], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], typing.Generic[_T], Literal[object]]
|
||||
# revealed: tuple[<class 'CounterSubclass'>, <class 'Counter[Unknown]'>, <class 'dict[Unknown, int]'>, <class 'MutableMapping[Unknown, int]'>, <class 'Mapping[Unknown, int]'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], typing.Generic[_T], <class 'object'>]
|
||||
reveal_type(CounterSubclass.__mro__)
|
||||
|
||||
class DefaultDictSubclass(typing.DefaultDict): ...
|
||||
|
||||
# TODO: Should be (DefaultDictSubclass, defaultdict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
|
||||
# revealed: tuple[Literal[DefaultDictSubclass], Literal[defaultdict[Unknown, Unknown]], Literal[dict[Unknown, Unknown]], Literal[MutableMapping[Unknown, Unknown]], Literal[Mapping[Unknown, Unknown]], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], Literal[object]]
|
||||
# revealed: tuple[<class 'DefaultDictSubclass'>, <class 'defaultdict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], <class 'object'>]
|
||||
reveal_type(DefaultDictSubclass.__mro__)
|
||||
|
||||
class DequeSubclass(typing.Deque): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[DequeSubclass], Literal[deque], Literal[MutableSequence], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'DequeSubclass'>, <class 'deque'>, <class 'MutableSequence'>, <class 'Sequence'>, <class 'Reversible'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, <class 'object'>]
|
||||
reveal_type(DequeSubclass.__mro__)
|
||||
|
||||
class OrderedDictSubclass(typing.OrderedDict): ...
|
||||
|
||||
# TODO: Should be (OrderedDictSubclass, OrderedDict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
|
||||
# revealed: tuple[Literal[OrderedDictSubclass], Literal[OrderedDict[Unknown, Unknown]], Literal[dict[Unknown, Unknown]], Literal[MutableMapping[Unknown, Unknown]], Literal[Mapping[Unknown, Unknown]], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], Literal[object]]
|
||||
# revealed: tuple[<class 'OrderedDictSubclass'>, <class 'OrderedDict[Unknown, Unknown]'>, <class 'dict[Unknown, Unknown]'>, <class 'MutableMapping[Unknown, Unknown]'>, <class 'Mapping[Unknown, Unknown]'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, typing.Generic[_KT, _VT_co], <class 'object'>]
|
||||
reveal_type(OrderedDictSubclass.__mro__)
|
||||
```
|
||||
|
|
|
@ -73,7 +73,7 @@ class E(Concatenate): ... # error: [invalid-base]
|
|||
class F(Callable): ...
|
||||
class G(Generic): ... # error: [invalid-base] "Cannot inherit from plain `Generic`"
|
||||
|
||||
reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for Callable as a base class), Literal[object]]
|
||||
reveal_type(F.__mro__) # revealed: tuple[<class 'F'>, @Todo(Support for Callable as a base class), <class 'object'>]
|
||||
```
|
||||
|
||||
## Subscriptability
|
||||
|
|
|
@ -54,11 +54,11 @@ c_instance.declared_and_bound = False
|
|||
c_instance.declared_and_bound = "incompatible"
|
||||
|
||||
# mypy shows no error here, but pyright raises "reportAttributeAccessIssue"
|
||||
# error: [unresolved-attribute] "Attribute `inferred_from_value` can only be accessed on instances, not on the class object `Literal[C]` itself."
|
||||
# error: [unresolved-attribute] "Attribute `inferred_from_value` can only be accessed on instances, not on the class object `<class 'C'>` itself."
|
||||
reveal_type(C.inferred_from_value) # revealed: Unknown
|
||||
|
||||
# mypy shows no error here, but pyright raises "reportAttributeAccessIssue"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `inferred_from_value` from the class object `Literal[C]`"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `inferred_from_value` from the class object `<class 'C'>`"
|
||||
C.inferred_from_value = "overwritten on class"
|
||||
|
||||
# This assignment is fine:
|
||||
|
@ -90,11 +90,11 @@ reveal_type(c_instance.declared_and_bound) # revealed: str | None
|
|||
|
||||
# Note that both mypy and pyright show no error in this case! So we may reconsider this in
|
||||
# the future, if it turns out to produce too many false positives. We currently emit:
|
||||
# error: [unresolved-attribute] "Attribute `declared_and_bound` can only be accessed on instances, not on the class object `Literal[C]` itself."
|
||||
# error: [unresolved-attribute] "Attribute `declared_and_bound` can only be accessed on instances, not on the class object `<class 'C'>` itself."
|
||||
reveal_type(C.declared_and_bound) # revealed: Unknown
|
||||
|
||||
# Same as above. Mypy and pyright do not show an error here.
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `declared_and_bound` from the class object `Literal[C]`"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `declared_and_bound` from the class object `<class 'C'>`"
|
||||
C.declared_and_bound = "overwritten on class"
|
||||
|
||||
# error: [invalid-assignment] "Object of type `Literal[1]` is not assignable to attribute `declared_and_bound` of type `str | None`"
|
||||
|
@ -115,10 +115,10 @@ c_instance = C()
|
|||
reveal_type(c_instance.only_declared) # revealed: str
|
||||
|
||||
# Mypy and pyright do not show an error here. We treat this as a pure instance variable.
|
||||
# error: [unresolved-attribute] "Attribute `only_declared` can only be accessed on instances, not on the class object `Literal[C]` itself."
|
||||
# error: [unresolved-attribute] "Attribute `only_declared` can only be accessed on instances, not on the class object `<class 'C'>` itself."
|
||||
reveal_type(C.only_declared) # revealed: Unknown
|
||||
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `only_declared` from the class object `Literal[C]`"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `only_declared` from the class object `<class 'C'>`"
|
||||
C.only_declared = "overwritten on class"
|
||||
```
|
||||
|
||||
|
@ -191,10 +191,10 @@ reveal_type(c_instance.declared_only) # revealed: bytes
|
|||
|
||||
reveal_type(c_instance.declared_and_bound) # revealed: bool
|
||||
|
||||
# error: [unresolved-attribute] "Attribute `inferred_from_value` can only be accessed on instances, not on the class object `Literal[C]` itself."
|
||||
# error: [unresolved-attribute] "Attribute `inferred_from_value` can only be accessed on instances, not on the class object `<class 'C'>` itself."
|
||||
reveal_type(C.inferred_from_value) # revealed: Unknown
|
||||
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `inferred_from_value` from the class object `Literal[C]`"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `inferred_from_value` from the class object `<class 'C'>`"
|
||||
C.inferred_from_value = "overwritten on class"
|
||||
```
|
||||
|
||||
|
@ -718,7 +718,7 @@ reveal_type(C.pure_class_variable) # revealed: Unknown
|
|||
|
||||
# TODO: should be no error when descriptor protocol is supported
|
||||
# and the assignment is properly attributed to the class method.
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `pure_class_variable` from the class object `Literal[C]`"
|
||||
# error: [invalid-attribute-access] "Cannot assign to instance attribute `pure_class_variable` from the class object `<class 'C'>`"
|
||||
C.pure_class_variable = "overwritten on class"
|
||||
|
||||
# TODO: should be `Unknown | Literal["value set in class method"]` or
|
||||
|
@ -925,7 +925,7 @@ def _(flag: bool):
|
|||
reveal_type(C1.y) # revealed: int | str
|
||||
|
||||
C1.y = 100
|
||||
# error: [invalid-assignment] "Object of type `Literal["problematic"]` is not assignable to attribute `y` on type `Literal[C1, C1]`"
|
||||
# error: [invalid-assignment] "Object of type `Literal["problematic"]` is not assignable to attribute `y` on type `<class 'C1'> | <class 'C1'>`"
|
||||
C1.y = "problematic"
|
||||
|
||||
class C2:
|
||||
|
@ -1002,10 +1002,10 @@ def _(flag1: bool, flag2: bool):
|
|||
|
||||
C = C1 if flag1 else C2 if flag2 else C3
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `<class 'C1'> | <class 'C2'> | <class 'C3'>` is possibly unbound"
|
||||
reveal_type(C.x) # revealed: Unknown | Literal[1, 3]
|
||||
|
||||
# error: [invalid-assignment] "Object of type `Literal[100]` is not assignable to attribute `x` on type `Literal[C1, C2, C3]`"
|
||||
# error: [invalid-assignment] "Object of type `Literal[100]` is not assignable to attribute `x` on type `<class 'C1'> | <class 'C2'> | <class 'C3'>`"
|
||||
C.x = 100
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `C1 | C2 | C3` is possibly unbound"
|
||||
|
@ -1034,7 +1034,7 @@ def _(flag: bool, flag1: bool, flag2: bool):
|
|||
|
||||
C = C1 if flag1 else C2 if flag2 else C3
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `<class 'C1'> | <class 'C2'> | <class 'C3'>` is possibly unbound"
|
||||
reveal_type(C.x) # revealed: Unknown | Literal[1, 2, 3]
|
||||
|
||||
# error: [possibly-unbound-attribute]
|
||||
|
@ -1165,12 +1165,12 @@ def _(flag: bool):
|
|||
class C2: ...
|
||||
C = C1 if flag else C2
|
||||
|
||||
# error: [unresolved-attribute] "Type `Literal[C1, C2]` has no attribute `x`"
|
||||
# error: [unresolved-attribute] "Type `<class 'C1'> | <class 'C2'>` has no attribute `x`"
|
||||
reveal_type(C.x) # revealed: Unknown
|
||||
|
||||
# TODO: This should ideally be a `unresolved-attribute` error. We need better union
|
||||
# handling in `validate_attribute_assignment` for this.
|
||||
# error: [invalid-assignment] "Object of type `Literal[1]` is not assignable to attribute `x` on type `Literal[C1, C2]`"
|
||||
# error: [invalid-assignment] "Object of type `Literal[1]` is not assignable to attribute `x` on type `<class 'C1'> | <class 'C2'>`"
|
||||
C.x = 1
|
||||
```
|
||||
|
||||
|
@ -1206,7 +1206,7 @@ class C(D, F): ...
|
|||
class B(E, D): ...
|
||||
class A(B, C): ...
|
||||
|
||||
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'A'>, <class 'B'>, <class 'E'>, <class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(A.__mro__)
|
||||
|
||||
# `E` is earlier in the MRO than `F`, so we should use the type of `E.X`
|
||||
|
@ -1399,7 +1399,7 @@ class A:
|
|||
class B(Any): ...
|
||||
class C(B, A): ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[B], Any, Literal[A], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, Any, <class 'A'>, <class 'object'>]
|
||||
reveal_type(C.x) # revealed: Literal[1] & Any
|
||||
```
|
||||
|
||||
|
@ -1556,31 +1556,31 @@ The type of `x.__class__` is the same as `x`'s meta-type. `x.__class__` is alway
|
|||
```py
|
||||
import typing_extensions
|
||||
|
||||
reveal_type(typing_extensions.__class__) # revealed: Literal[ModuleType]
|
||||
reveal_type(type(typing_extensions)) # revealed: Literal[ModuleType]
|
||||
reveal_type(typing_extensions.__class__) # revealed: <class 'ModuleType'>
|
||||
reveal_type(type(typing_extensions)) # revealed: <class 'ModuleType'>
|
||||
|
||||
a = 42
|
||||
reveal_type(a.__class__) # revealed: Literal[int]
|
||||
reveal_type(type(a)) # revealed: Literal[int]
|
||||
reveal_type(a.__class__) # revealed: <class 'int'>
|
||||
reveal_type(type(a)) # revealed: <class 'int'>
|
||||
|
||||
b = "42"
|
||||
reveal_type(b.__class__) # revealed: Literal[str]
|
||||
reveal_type(b.__class__) # revealed: <class 'str'>
|
||||
|
||||
c = b"42"
|
||||
reveal_type(c.__class__) # revealed: Literal[bytes]
|
||||
reveal_type(c.__class__) # revealed: <class 'bytes'>
|
||||
|
||||
d = True
|
||||
reveal_type(d.__class__) # revealed: Literal[bool]
|
||||
reveal_type(d.__class__) # revealed: <class 'bool'>
|
||||
|
||||
e = (42, 42)
|
||||
reveal_type(e.__class__) # revealed: Literal[tuple]
|
||||
reveal_type(e.__class__) # revealed: <class 'tuple'>
|
||||
|
||||
def f(a: int, b: typing_extensions.LiteralString, c: int | str, d: type[str]):
|
||||
reveal_type(a.__class__) # revealed: type[int]
|
||||
reveal_type(type(a)) # revealed: type[int]
|
||||
|
||||
reveal_type(b.__class__) # revealed: Literal[str]
|
||||
reveal_type(type(b)) # revealed: Literal[str]
|
||||
reveal_type(b.__class__) # revealed: <class 'str'>
|
||||
reveal_type(type(b)) # revealed: <class 'str'>
|
||||
|
||||
reveal_type(c.__class__) # revealed: type[int] | type[str]
|
||||
reveal_type(type(c)) # revealed: type[int] | type[str]
|
||||
|
@ -1591,11 +1591,11 @@ def f(a: int, b: typing_extensions.LiteralString, c: int | str, d: type[str]):
|
|||
# All we know is that the metaclass must be a (non-strict) subclass of `type`.
|
||||
reveal_type(d.__class__) # revealed: type[type]
|
||||
|
||||
reveal_type(f.__class__) # revealed: Literal[FunctionType]
|
||||
reveal_type(f.__class__) # revealed: <class 'FunctionType'>
|
||||
|
||||
class Foo: ...
|
||||
|
||||
reveal_type(Foo.__class__) # revealed: Literal[type]
|
||||
reveal_type(Foo.__class__) # revealed: <class 'type'>
|
||||
```
|
||||
|
||||
## Module attributes
|
||||
|
|
|
@ -22,6 +22,6 @@ reveal_type(A | B) # revealed: UnionType
|
|||
class A: ...
|
||||
class B: ...
|
||||
|
||||
# error: "Operator `|` is unsupported between objects of type `Literal[A]` and `Literal[B]`"
|
||||
# error: "Operator `|` is unsupported between objects of type `<class 'A'>` and `<class 'B'>`"
|
||||
reveal_type(A | B) # revealed: Unknown
|
||||
```
|
||||
|
|
|
@ -307,11 +307,11 @@ class Yes:
|
|||
class Sub(Yes): ...
|
||||
class No: ...
|
||||
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `Literal[Yes]` and `Literal[Yes]`"
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `<class 'Yes'>` and `<class 'Yes'>`"
|
||||
reveal_type(Yes + Yes) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `Literal[Sub]` and `Literal[Sub]`"
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `<class 'Sub'>` and `<class 'Sub'>`"
|
||||
reveal_type(Sub + Sub) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `Literal[No]` and `Literal[No]`"
|
||||
# error: [unsupported-operator] "Operator `+` is unsupported between objects of type `<class 'No'>` and `<class 'No'>`"
|
||||
reveal_type(No + No) # revealed: Unknown
|
||||
```
|
||||
|
||||
|
|
|
@ -388,13 +388,13 @@ class A(metaclass=Meta): ...
|
|||
class B(metaclass=Meta): ...
|
||||
|
||||
reveal_type(A + B) # revealed: int
|
||||
# error: [unsupported-operator] "Operator `-` is unsupported between objects of type `Literal[A]` and `Literal[B]`"
|
||||
# error: [unsupported-operator] "Operator `-` is unsupported between objects of type `<class 'A'>` and `<class 'B'>`"
|
||||
reveal_type(A - B) # revealed: Unknown
|
||||
|
||||
reveal_type(A < B) # revealed: bool
|
||||
reveal_type(A > B) # revealed: bool
|
||||
|
||||
# error: [unsupported-operator] "Operator `<=` is not supported for types `Literal[A]` and `Literal[B]`"
|
||||
# error: [unsupported-operator] "Operator `<=` is not supported for types `<class 'A'>` and `<class 'B'>`"
|
||||
reveal_type(A <= B) # revealed: Unknown
|
||||
|
||||
reveal_type(A[0]) # revealed: str
|
||||
|
|
|
@ -312,8 +312,8 @@ class C:
|
|||
```py
|
||||
from mod import MyInt, C
|
||||
|
||||
reveal_type(MyInt) # revealed: Literal[int]
|
||||
reveal_type(C.MyStr) # revealed: Literal[str]
|
||||
reveal_type(MyInt) # revealed: <class 'int'>
|
||||
reveal_type(C.MyStr) # revealed: <class 'str'>
|
||||
```
|
||||
|
||||
### Undeclared and possibly unbound
|
||||
|
@ -336,8 +336,8 @@ if flag():
|
|||
# error: [possibly-unbound-import]
|
||||
from mod import MyInt, C
|
||||
|
||||
reveal_type(MyInt) # revealed: Literal[int]
|
||||
reveal_type(C.MyStr) # revealed: Literal[str]
|
||||
reveal_type(MyInt) # revealed: <class 'int'>
|
||||
reveal_type(C.MyStr) # revealed: <class 'str'>
|
||||
```
|
||||
|
||||
### Undeclared and unbound
|
||||
|
|
|
@ -20,7 +20,7 @@ tested more extensively in `crates/ty_python_semantic/resources/mdtest/attribute
|
|||
tests for the `__class__` attribute.)
|
||||
|
||||
```py
|
||||
reveal_type(type(1)) # revealed: Literal[int]
|
||||
reveal_type(type(1)) # revealed: <class 'int'>
|
||||
```
|
||||
|
||||
But a three-argument call to type creates a dynamic instance of the `type` class:
|
||||
|
|
|
@ -270,7 +270,7 @@ class Meta(type):
|
|||
class C(metaclass=Meta):
|
||||
pass
|
||||
|
||||
reveal_type(C.f) # revealed: bound method Literal[C].f(arg: int) -> str
|
||||
reveal_type(C.f) # revealed: bound method <class 'C'>.f(arg: int) -> str
|
||||
reveal_type(C.f(1)) # revealed: str
|
||||
```
|
||||
|
||||
|
@ -322,7 +322,7 @@ class C:
|
|||
def f(cls: type[C], x: int) -> str:
|
||||
return "a"
|
||||
|
||||
reveal_type(C.f) # revealed: bound method Literal[C].f(x: int) -> str
|
||||
reveal_type(C.f) # revealed: bound method <class 'C'>.f(x: int) -> str
|
||||
reveal_type(C().f) # revealed: bound method type[C].f(x: int) -> str
|
||||
```
|
||||
|
||||
|
@ -350,7 +350,7 @@ class D:
|
|||
# This function is wrongly annotated, it should be `type[D]` instead of `D`
|
||||
pass
|
||||
|
||||
# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `D`, found `Literal[D]`"
|
||||
# error: [invalid-argument-type] "Argument to this function is incorrect: Expected `D`, found `<class 'D'>`"
|
||||
D.f()
|
||||
```
|
||||
|
||||
|
@ -360,7 +360,7 @@ When a class method is accessed on a derived class, it is bound to that derived
|
|||
class Derived(C):
|
||||
pass
|
||||
|
||||
reveal_type(Derived.f) # revealed: bound method Literal[Derived].f(x: int) -> str
|
||||
reveal_type(Derived.f) # revealed: bound method <class 'Derived'>.f(x: int) -> str
|
||||
reveal_type(Derived().f) # revealed: bound method type[Derived].f(x: int) -> str
|
||||
|
||||
reveal_type(Derived.f(1)) # revealed: str
|
||||
|
@ -386,15 +386,15 @@ reveal_type(getattr_static(C, "f").__get__) # revealed: <method-wrapper `__get_
|
|||
But we correctly model how the `classmethod` descriptor works:
|
||||
|
||||
```py
|
||||
reveal_type(getattr_static(C, "f").__get__(None, C)) # revealed: bound method Literal[C].f() -> Unknown
|
||||
reveal_type(getattr_static(C, "f").__get__(C(), C)) # revealed: bound method Literal[C].f() -> Unknown
|
||||
reveal_type(getattr_static(C, "f").__get__(None, C)) # revealed: bound method <class 'C'>.f() -> Unknown
|
||||
reveal_type(getattr_static(C, "f").__get__(C(), C)) # revealed: bound method <class 'C'>.f() -> Unknown
|
||||
reveal_type(getattr_static(C, "f").__get__(C())) # revealed: bound method type[C].f() -> Unknown
|
||||
```
|
||||
|
||||
The `owner` argument takes precedence over the `instance` argument:
|
||||
|
||||
```py
|
||||
reveal_type(getattr_static(C, "f").__get__("dummy", C)) # revealed: bound method Literal[C].f() -> Unknown
|
||||
reveal_type(getattr_static(C, "f").__get__("dummy", C)) # revealed: bound method <class 'C'>.f() -> Unknown
|
||||
```
|
||||
|
||||
### Classmethods mixed with other decorators
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Super
|
||||
|
||||
Python defines the terms *bound super object* and *unbound super object*.
|
||||
Python defines the terms _bound super object_ and _unbound super object_.
|
||||
|
||||
An **unbound super object** is created when `super` is called with only one argument. (e.g.
|
||||
`super(A)`). This object may later be bound using the `super.__get__` method. However, this form is
|
||||
|
@ -30,24 +30,24 @@ class C(B):
|
|||
def c(self): ...
|
||||
cc: int = 3
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[B], Literal[A], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>]
|
||||
|
||||
super(C, C()).a
|
||||
super(C, C()).b
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[C], C>` has no attribute `c`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'C'>, C>` has no attribute `c`"
|
||||
super(C, C()).c
|
||||
|
||||
super(B, C()).a
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[B], C>` has no attribute `b`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'B'>, C>` has no attribute `b`"
|
||||
super(B, C()).b
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[B], C>` has no attribute `c`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'B'>, C>` has no attribute `c`"
|
||||
super(B, C()).c
|
||||
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[A], C>` has no attribute `a`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'A'>, C>` has no attribute `a`"
|
||||
super(A, C()).a
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[A], C>` has no attribute `b`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'A'>, C>` has no attribute `b`"
|
||||
super(A, C()).b
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[A], C>` has no attribute `c`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'A'>, C>` has no attribute `c`"
|
||||
super(A, C()).c
|
||||
|
||||
reveal_type(super(C, C()).a) # revealed: bound method C.a() -> Unknown
|
||||
|
@ -72,14 +72,14 @@ class A:
|
|||
|
||||
class B(A):
|
||||
def __init__(self, a: int):
|
||||
# TODO: Once `Self` is supported, this should be `<super: Literal[B], B>`
|
||||
reveal_type(super()) # revealed: <super: Literal[B], Unknown>
|
||||
# TODO: Once `Self` is supported, this should be `<super: <class 'B'>, B>`
|
||||
reveal_type(super()) # revealed: <super: <class 'B'>, Unknown>
|
||||
super().__init__(a)
|
||||
|
||||
@classmethod
|
||||
def f(cls):
|
||||
# TODO: Once `Self` is supported, this should be `<super: Literal[B], Literal[B]>`
|
||||
reveal_type(super()) # revealed: <super: Literal[B], Unknown>
|
||||
# TODO: Once `Self` is supported, this should be `<super: <class 'B'>, <class 'B'>>`
|
||||
reveal_type(super()) # revealed: <super: <class 'B'>, Unknown>
|
||||
super().f()
|
||||
|
||||
super(B, B(42)).__init__(42)
|
||||
|
@ -88,7 +88,7 @@ super(B, B).f()
|
|||
|
||||
### Unbound Super Object
|
||||
|
||||
Calling `super(cls)` without a second argument returns an *unbound super object*. This is treated as
|
||||
Calling `super(cls)` without a second argument returns an _unbound super object_. This is treated as
|
||||
a plain `super` instance and does not support name lookup via the MRO.
|
||||
|
||||
```py
|
||||
|
@ -115,7 +115,7 @@ class A:
|
|||
class B(A): ...
|
||||
|
||||
reveal_type(super(B, B()).a) # revealed: int
|
||||
# error: [invalid-assignment] "Cannot assign to attribute `a` on type `<super: Literal[B], B>`"
|
||||
# error: [invalid-assignment] "Cannot assign to attribute `a` on type `<super: <class 'B'>, B>`"
|
||||
super(B, B()).a = 3
|
||||
# error: [invalid-assignment] "Cannot assign to attribute `a` on type `super`"
|
||||
super(B).a = 5
|
||||
|
@ -134,7 +134,7 @@ def f(x):
|
|||
reveal_type(x) # revealed: Unknown
|
||||
|
||||
reveal_type(super(x, x)) # revealed: <super: Unknown, Unknown>
|
||||
reveal_type(super(A, x)) # revealed: <super: Literal[A], Unknown>
|
||||
reveal_type(super(A, x)) # revealed: <super: <class 'A'>, Unknown>
|
||||
reveal_type(super(x, A())) # revealed: <super: Unknown, A>
|
||||
|
||||
reveal_type(super(x, x).a) # revealed: Unknown
|
||||
|
@ -149,29 +149,29 @@ from __future__ import annotations
|
|||
|
||||
class A:
|
||||
def test(self):
|
||||
reveal_type(super()) # revealed: <super: Literal[A], Unknown>
|
||||
reveal_type(super()) # revealed: <super: <class 'A'>, Unknown>
|
||||
|
||||
class B:
|
||||
def test(self):
|
||||
reveal_type(super()) # revealed: <super: Literal[B], Unknown>
|
||||
reveal_type(super()) # revealed: <super: <class 'B'>, Unknown>
|
||||
|
||||
class C(A.B):
|
||||
def test(self):
|
||||
reveal_type(super()) # revealed: <super: Literal[C], Unknown>
|
||||
reveal_type(super()) # revealed: <super: <class 'C'>, Unknown>
|
||||
|
||||
def inner(t: C):
|
||||
reveal_type(super()) # revealed: <super: Literal[B], C>
|
||||
lambda x: reveal_type(super()) # revealed: <super: Literal[B], Unknown>
|
||||
reveal_type(super()) # revealed: <super: <class 'B'>, C>
|
||||
lambda x: reveal_type(super()) # revealed: <super: <class 'B'>, Unknown>
|
||||
```
|
||||
|
||||
## Built-ins and Literals
|
||||
|
||||
```py
|
||||
reveal_type(super(bool, True)) # revealed: <super: Literal[bool], bool>
|
||||
reveal_type(super(bool, bool())) # revealed: <super: Literal[bool], bool>
|
||||
reveal_type(super(int, bool())) # revealed: <super: Literal[int], bool>
|
||||
reveal_type(super(int, 3)) # revealed: <super: Literal[int], int>
|
||||
reveal_type(super(str, "")) # revealed: <super: Literal[str], str>
|
||||
reveal_type(super(bool, True)) # revealed: <super: <class 'bool'>, bool>
|
||||
reveal_type(super(bool, bool())) # revealed: <super: <class 'bool'>, bool>
|
||||
reveal_type(super(int, bool())) # revealed: <super: <class 'int'>, bool>
|
||||
reveal_type(super(int, 3)) # revealed: <super: <class 'int'>, int>
|
||||
reveal_type(super(str, "")) # revealed: <super: <class 'str'>, str>
|
||||
```
|
||||
|
||||
## Descriptor Behavior with Super
|
||||
|
@ -195,7 +195,7 @@ reveal_type(super(B, B()).a2) # revealed: bound method type[B].a2() -> Unknown
|
|||
# A.__dict__["a1"].__get__(None, B)
|
||||
reveal_type(super(B, B).a1) # revealed: def a1(self) -> Unknown
|
||||
# A.__dict__["a2"].__get__(None, B)
|
||||
reveal_type(super(B, B).a2) # revealed: bound method Literal[B].a2() -> Unknown
|
||||
reveal_type(super(B, B).a2) # revealed: bound method <class 'B'>.a2() -> Unknown
|
||||
```
|
||||
|
||||
## Union of Supers
|
||||
|
@ -213,22 +213,22 @@ class C(A, B): ...
|
|||
class D(B, A): ...
|
||||
|
||||
def f(x: C | D):
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[A], Literal[B], Literal[object]]
|
||||
reveal_type(D.__mro__) # revealed: tuple[Literal[D], Literal[B], Literal[A], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]
|
||||
reveal_type(D.__mro__) # revealed: tuple[<class 'D'>, <class 'B'>, <class 'A'>, <class 'object'>]
|
||||
|
||||
s = super(A, x)
|
||||
reveal_type(s) # revealed: <super: Literal[A], C> | <super: Literal[A], D>
|
||||
reveal_type(s) # revealed: <super: <class 'A'>, C> | <super: <class 'A'>, D>
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `b` on type `<super: Literal[A], C> | <super: Literal[A], D>` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `b` on type `<super: <class 'A'>, C> | <super: <class 'A'>, D>` is possibly unbound"
|
||||
s.b
|
||||
|
||||
def f(flag: bool):
|
||||
x = str() if flag else str("hello")
|
||||
reveal_type(x) # revealed: Literal["", "hello"]
|
||||
reveal_type(super(str, x)) # revealed: <super: Literal[str], str>
|
||||
reveal_type(super(str, x)) # revealed: <super: <class 'str'>, str>
|
||||
|
||||
def f(x: int | str):
|
||||
# error: [invalid-super-argument] "`str` is not an instance or subclass of `Literal[int]` in `super(Literal[int], str)` call"
|
||||
# error: [invalid-super-argument] "`str` is not an instance or subclass of `<class 'int'>` in `super(<class 'int'>, str)` call"
|
||||
super(int, x)
|
||||
```
|
||||
|
||||
|
@ -254,12 +254,12 @@ def f(flag: bool):
|
|||
class D(C): ...
|
||||
s = super(D, D())
|
||||
|
||||
reveal_type(s) # revealed: <super: Literal[B], B> | <super: Literal[D], D>
|
||||
reveal_type(s) # revealed: <super: <class 'B'>, B> | <super: <class 'D'>, D>
|
||||
|
||||
reveal_type(s.x) # revealed: Unknown | Literal[1, 2]
|
||||
reveal_type(s.y) # revealed: int | str
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `a` on type `<super: Literal[B], B> | <super: Literal[D], D>` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `a` on type `<super: <class 'B'>, B> | <super: <class 'D'>, D>` is possibly unbound"
|
||||
reveal_type(s.a) # revealed: str
|
||||
```
|
||||
|
||||
|
@ -339,30 +339,30 @@ def f(x: int):
|
|||
# error: [invalid-super-argument] "`typing.TypeAliasType` is not a valid class"
|
||||
super(IntAlias, 0)
|
||||
|
||||
# error: [invalid-super-argument] "`Literal[""]` is not an instance or subclass of `Literal[int]` in `super(Literal[int], Literal[""])` call"
|
||||
# error: [invalid-super-argument] "`Literal[""]` is not an instance or subclass of `<class 'int'>` in `super(<class 'int'>, Literal[""])` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(int, str()))
|
||||
|
||||
# error: [invalid-super-argument] "`Literal[str]` is not an instance or subclass of `Literal[int]` in `super(Literal[int], Literal[str])` call"
|
||||
# error: [invalid-super-argument] "`<class 'str'>` is not an instance or subclass of `<class 'int'>` in `super(<class 'int'>, <class 'str'>)` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(int, str))
|
||||
|
||||
class A: ...
|
||||
class B(A): ...
|
||||
|
||||
# error: [invalid-super-argument] "`A` is not an instance or subclass of `Literal[B]` in `super(Literal[B], A)` call"
|
||||
# error: [invalid-super-argument] "`A` is not an instance or subclass of `<class 'B'>` in `super(<class 'B'>, A)` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(B, A()))
|
||||
|
||||
# error: [invalid-super-argument] "`object` is not an instance or subclass of `Literal[B]` in `super(Literal[B], object)` call"
|
||||
# error: [invalid-super-argument] "`object` is not an instance or subclass of `<class 'B'>` in `super(<class 'B'>, object)` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(B, object()))
|
||||
|
||||
# error: [invalid-super-argument] "`Literal[A]` is not an instance or subclass of `Literal[B]` in `super(Literal[B], Literal[A])` call"
|
||||
# error: [invalid-super-argument] "`<class 'A'>` is not an instance or subclass of `<class 'B'>` in `super(<class 'B'>, <class 'A'>)` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(B, A))
|
||||
|
||||
# error: [invalid-super-argument] "`Literal[object]` is not an instance or subclass of `Literal[B]` in `super(Literal[B], Literal[object])` call"
|
||||
# error: [invalid-super-argument] "`<class 'object'>` is not an instance or subclass of `<class 'B'>` in `super(<class 'B'>, <class 'object'>)` call"
|
||||
# revealed: Unknown
|
||||
reveal_type(super(B, object))
|
||||
|
||||
|
@ -386,7 +386,7 @@ class B(A):
|
|||
# TODO: Once `Self` is supported, this should raise `unresolved-attribute` error
|
||||
super().a
|
||||
|
||||
# error: [unresolved-attribute] "Type `<super: Literal[B], B>` has no attribute `a`"
|
||||
# error: [unresolved-attribute] "Type `<super: <class 'B'>, B>` has no attribute `a`"
|
||||
super(B, B(42)).a
|
||||
```
|
||||
|
||||
|
@ -405,6 +405,6 @@ class B(A): ...
|
|||
|
||||
reveal_type(A()[0]) # revealed: int
|
||||
reveal_type(super(B, B()).__getitem__) # revealed: bound method B.__getitem__(key: int) -> int
|
||||
# error: [non-subscriptable] "Cannot subscript object of type `<super: Literal[B], B>` with no `__getitem__` method"
|
||||
# error: [non-subscriptable] "Cannot subscript object of type `<super: <class 'B'>, B>` with no `__getitem__` method"
|
||||
super(B, B())[0]
|
||||
```
|
||||
|
|
|
@ -181,7 +181,7 @@ class D:
|
|||
class_literal: TypeOf[SomeClass]
|
||||
class_subtype_of: type[SomeClass]
|
||||
|
||||
# revealed: (function_literal: def some_function() -> None, class_literal: Literal[SomeClass], class_subtype_of: type[SomeClass]) -> None
|
||||
# revealed: (function_literal: def some_function() -> None, class_literal: <class 'SomeClass'>, class_subtype_of: type[SomeClass]) -> None
|
||||
reveal_type(D.__init__)
|
||||
```
|
||||
|
||||
|
@ -489,7 +489,7 @@ class DataWithDescription[T]:
|
|||
data: T
|
||||
description: str
|
||||
|
||||
reveal_type(DataWithDescription[int]) # revealed: Literal[DataWithDescription[int]]
|
||||
reveal_type(DataWithDescription[int]) # revealed: <class 'DataWithDescription[int]'>
|
||||
|
||||
d_int = DataWithDescription[int](1, "description") # OK
|
||||
reveal_type(d_int.data) # revealed: int
|
||||
|
@ -675,7 +675,7 @@ from dataclasses import dataclass
|
|||
class C:
|
||||
x: int
|
||||
|
||||
# error: [unresolved-attribute] "Attribute `x` can only be accessed on instances, not on the class object `Literal[C]` itself."
|
||||
# error: [unresolved-attribute] "Attribute `x` can only be accessed on instances, not on the class object `<class 'C'>` itself."
|
||||
C.x
|
||||
```
|
||||
|
||||
|
@ -715,8 +715,8 @@ class Person:
|
|||
name: str
|
||||
age: int | None = None
|
||||
|
||||
reveal_type(type(Person)) # revealed: Literal[type]
|
||||
reveal_type(Person.__mro__) # revealed: tuple[Literal[Person], Literal[object]]
|
||||
reveal_type(type(Person)) # revealed: <class 'type'>
|
||||
reveal_type(Person.__mro__) # revealed: tuple[<class 'Person'>, <class 'object'>]
|
||||
```
|
||||
|
||||
The generated methods have the following signatures:
|
||||
|
|
|
@ -269,7 +269,7 @@ on the metaclass:
|
|||
```py
|
||||
C1.meta_data_descriptor = 1
|
||||
|
||||
# error: [invalid-assignment] "Invalid assignment to data descriptor attribute `meta_data_descriptor` on type `Literal[C1]` with custom `__set__` method"
|
||||
# error: [invalid-assignment] "Invalid assignment to data descriptor attribute `meta_data_descriptor` on type `<class 'C1'>` with custom `__set__` method"
|
||||
C1.meta_data_descriptor = "invalid"
|
||||
```
|
||||
|
||||
|
@ -371,7 +371,7 @@ def _(flag: bool):
|
|||
# TODO: We currently emit two diagnostics here, corresponding to the two states of `flag`. The diagnostics are not
|
||||
# wrong, but they could be subsumed under a higher-level diagnostic.
|
||||
|
||||
# error: [invalid-assignment] "Invalid assignment to data descriptor attribute `meta_data_descriptor1` on type `Literal[C5]` with custom `__set__` method"
|
||||
# error: [invalid-assignment] "Invalid assignment to data descriptor attribute `meta_data_descriptor1` on type `<class 'C5'>` with custom `__set__` method"
|
||||
# error: [invalid-assignment] "Object of type `None` is not assignable to attribute `meta_data_descriptor1` of type `Literal["value on class"]`"
|
||||
C5.meta_data_descriptor1 = None
|
||||
|
||||
|
@ -724,13 +724,13 @@ def _(flag: bool):
|
|||
non_data: NonDataDescriptor = NonDataDescriptor()
|
||||
data: DataDescriptor = DataDescriptor()
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `non_data` on type `Literal[PossiblyUnbound]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `non_data` on type `<class 'PossiblyUnbound'>` is possibly unbound"
|
||||
reveal_type(PossiblyUnbound.non_data) # revealed: int
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `non_data` on type `PossiblyUnbound` is possibly unbound"
|
||||
reveal_type(PossiblyUnbound().non_data) # revealed: int
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `data` on type `Literal[PossiblyUnbound]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `data` on type `<class 'PossiblyUnbound'>` is possibly unbound"
|
||||
reveal_type(PossiblyUnbound.data) # revealed: int
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `data` on type `PossiblyUnbound` is possibly unbound"
|
||||
|
|
|
@ -600,12 +600,12 @@ except:
|
|||
reveal_type(x) # revealed: E
|
||||
|
||||
x = Bar
|
||||
reveal_type(x) # revealed: Literal[Bar]
|
||||
reveal_type(x) # revealed: <class 'Bar'>
|
||||
finally:
|
||||
# TODO: should be `Literal[1] | Literal[foo] | Literal[Bar]`
|
||||
reveal_type(x) # revealed: (def foo(param=A) -> Unknown) | Literal[Bar]
|
||||
# TODO: should be `Literal[1] | <class 'foo'> | <class 'Bar'>`
|
||||
reveal_type(x) # revealed: (def foo(param=A) -> Unknown) | <class 'Bar'>
|
||||
|
||||
reveal_type(x) # revealed: (def foo(param=A) -> Unknown) | Literal[Bar]
|
||||
reveal_type(x) # revealed: (def foo(param=A) -> Unknown) | <class 'Bar'>
|
||||
```
|
||||
|
||||
[1]: https://astral-sh.notion.site/Exception-handler-control-flow-11348797e1ca80bb8ce1e9aedbbe439d
|
||||
|
|
|
@ -26,9 +26,9 @@ def _(flag: bool):
|
|||
|
||||
reveal_type(A.union_declared) # revealed: int | str
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `possibly_unbound` on type `Literal[A]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `possibly_unbound` on type `<class 'A'>` is possibly unbound"
|
||||
reveal_type(A.possibly_unbound) # revealed: str
|
||||
|
||||
# error: [unresolved-attribute] "Type `Literal[A]` has no attribute `non_existent`"
|
||||
# error: [unresolved-attribute] "Type `<class 'A'>` has no attribute `non_existent`"
|
||||
reveal_type(A.non_existent) # revealed: Unknown
|
||||
```
|
||||
|
|
|
@ -29,7 +29,7 @@ class RepeatedTypevar(Generic[T, T]): ...
|
|||
You can only specialize `typing.Generic` with typevars (TODO: or param specs or typevar tuples).
|
||||
|
||||
```py
|
||||
# error: [invalid-argument-type] "`Literal[int]` is not a valid argument to `typing.Generic`"
|
||||
# error: [invalid-argument-type] "`<class 'int'>` is not a valid argument to `typing.Generic`"
|
||||
class GenericOfType(Generic[int]): ...
|
||||
```
|
||||
|
||||
|
@ -436,7 +436,7 @@ T = TypeVar("T")
|
|||
class Base(Generic[T]): ...
|
||||
class Sub(Base[Sub]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
reveal_type(Sub) # revealed: <class 'Sub'>
|
||||
```
|
||||
|
||||
#### With string forward references
|
||||
|
@ -451,7 +451,7 @@ T = TypeVar("T")
|
|||
class Base(Generic[T]): ...
|
||||
class Sub(Base["Sub"]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
reveal_type(Sub) # revealed: <class 'Sub'>
|
||||
```
|
||||
|
||||
#### Without string forward references
|
||||
|
|
|
@ -19,7 +19,7 @@ in newer Python releases.
|
|||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
reveal_type(type(T)) # revealed: Literal[TypeVar]
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar
|
||||
reveal_type(T.__name__) # revealed: Literal["T"]
|
||||
```
|
||||
|
|
|
@ -362,7 +362,7 @@ Here, `Sub` is not a generic class, since it fills its superclass's type paramet
|
|||
class Base[T]: ...
|
||||
class Sub(Base[Sub]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
reveal_type(Sub) # revealed: <class 'Sub'>
|
||||
```
|
||||
|
||||
#### With string forward references
|
||||
|
@ -373,7 +373,7 @@ A similar case can work in a non-stub file, if forward references are stringifie
|
|||
class Base[T]: ...
|
||||
class Sub(Base["Sub"]): ...
|
||||
|
||||
reveal_type(Sub) # revealed: Literal[Sub]
|
||||
reveal_type(Sub) # revealed: <class 'Sub'>
|
||||
```
|
||||
|
||||
#### Without string forward references
|
||||
|
|
|
@ -16,7 +16,7 @@ instances of `typing.TypeVar`, just like legacy type variables.
|
|||
|
||||
```py
|
||||
def f[T]():
|
||||
reveal_type(type(T)) # revealed: Literal[TypeVar]
|
||||
reveal_type(type(T)) # revealed: <class 'TypeVar'>
|
||||
reveal_type(T) # revealed: typing.TypeVar
|
||||
reveal_type(T.__name__) # revealed: Literal["T"]
|
||||
```
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
from b import C as D
|
||||
|
||||
E = D
|
||||
reveal_type(E) # revealed: Literal[C]
|
||||
reveal_type(E) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`b.py`:
|
||||
|
@ -21,7 +21,7 @@ class C: ...
|
|||
import b
|
||||
|
||||
D = b.C
|
||||
reveal_type(D) # revealed: Literal[C]
|
||||
reveal_type(D) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`b.py`:
|
||||
|
@ -35,7 +35,7 @@ class C: ...
|
|||
```py
|
||||
import a.b
|
||||
|
||||
reveal_type(a.b.C) # revealed: Literal[C]
|
||||
reveal_type(a.b.C) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
@ -54,7 +54,7 @@ class C: ...
|
|||
```py
|
||||
import a.b.c
|
||||
|
||||
reveal_type(a.b.c.C) # revealed: Literal[C]
|
||||
reveal_type(a.b.c.C) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
@ -78,7 +78,7 @@ class C: ...
|
|||
```py
|
||||
import a.b as b
|
||||
|
||||
reveal_type(b.C) # revealed: Literal[C]
|
||||
reveal_type(b.C) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
@ -97,7 +97,7 @@ class C: ...
|
|||
```py
|
||||
import a.b.c as c
|
||||
|
||||
reveal_type(c.C) # revealed: Literal[C]
|
||||
reveal_type(c.C) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
|
|
@ -16,7 +16,7 @@ Or used implicitly:
|
|||
|
||||
```py
|
||||
reveal_type(chr) # revealed: def chr(i: SupportsIndex, /) -> str
|
||||
reveal_type(str) # revealed: Literal[str]
|
||||
reveal_type(str) # revealed: <class 'str'>
|
||||
```
|
||||
|
||||
## Builtin symbol from custom typeshed
|
||||
|
|
|
@ -95,6 +95,7 @@ from typing import Any, Literal
|
|||
`foo.pyi`:
|
||||
|
||||
```pyi
|
||||
|
||||
```
|
||||
|
||||
## Nested non-exports
|
||||
|
@ -187,7 +188,7 @@ reveal_type(Foo) # revealed: Unknown
|
|||
```pyi
|
||||
from b import AnyFoo as Foo
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[AnyFoo]
|
||||
reveal_type(Foo) # revealed: <class 'AnyFoo'>
|
||||
```
|
||||
|
||||
`b.pyi`:
|
||||
|
@ -251,11 +252,13 @@ class Foo: ...
|
|||
`a/b/__init__.pyi`:
|
||||
|
||||
```pyi
|
||||
|
||||
```
|
||||
|
||||
`a/b/c.pyi`:
|
||||
|
||||
```pyi
|
||||
|
||||
```
|
||||
|
||||
## Conditional re-export in stub file
|
||||
|
@ -281,7 +284,7 @@ def coinflip() -> bool: ...
|
|||
if coinflip():
|
||||
Foo: str = ...
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[Foo] | str
|
||||
reveal_type(Foo) # revealed: <class 'Foo'> | str
|
||||
```
|
||||
|
||||
`b.pyi`:
|
||||
|
@ -299,7 +302,7 @@ the other does not.
|
|||
# error: "Member `Foo` of module `a` is possibly unbound"
|
||||
from a import Foo
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[Foo]
|
||||
reveal_type(Foo) # revealed: <class 'Foo'>
|
||||
```
|
||||
|
||||
`a.pyi`:
|
||||
|
@ -312,7 +315,7 @@ if coinflip():
|
|||
else:
|
||||
from b import Foo as Foo
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[Foo]
|
||||
reveal_type(Foo) # revealed: <class 'Foo'>
|
||||
```
|
||||
|
||||
`b.pyi`:
|
||||
|
@ -327,7 +330,7 @@ class Foo: ...
|
|||
# error: "Member `Foo` of module `a` is possibly unbound"
|
||||
from a import Foo
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[Foo]
|
||||
reveal_type(Foo) # revealed: <class 'Foo'>
|
||||
```
|
||||
|
||||
`a.pyi`:
|
||||
|
|
|
@ -69,12 +69,12 @@ x = "foo" # error: [invalid-assignment] "Object of type `Literal["foo"]"
|
|||
```py
|
||||
class A: ...
|
||||
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, <class 'object'>]
|
||||
import b
|
||||
|
||||
class C(b.B): ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[B], Literal[A], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>]
|
||||
```
|
||||
|
||||
`b.py`:
|
||||
|
@ -84,5 +84,5 @@ from a import A
|
|||
|
||||
class B(A): ...
|
||||
|
||||
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[A], Literal[object]]
|
||||
reveal_type(B.__mro__) # revealed: tuple[<class 'B'>, <class 'A'>, <class 'object'>]
|
||||
```
|
||||
|
|
|
@ -255,7 +255,7 @@ python-version = "3.13"
|
|||
```py
|
||||
from foo import A
|
||||
|
||||
reveal_type(A) # revealed: Literal[A]
|
||||
reveal_type(A) # revealed: <class 'A'>
|
||||
```
|
||||
|
||||
`/src/.venv/<path-to-site-packages>/foo/__init__.py`:
|
||||
|
|
|
@ -1353,7 +1353,7 @@ are present due to `*` imports.
|
|||
```py
|
||||
import collections.abc
|
||||
|
||||
reveal_type(collections.abc.Sequence) # revealed: Literal[Sequence]
|
||||
reveal_type(collections.abc.Sequence) # revealed: <class 'Sequence'>
|
||||
reveal_type(collections.abc.Callable) # revealed: typing.Callable
|
||||
|
||||
# TODO: false positive as it's only re-exported from `_collections.abc` due to presence in `__all__`
|
||||
|
|
|
@ -27,7 +27,7 @@ has been imported.
|
|||
import a
|
||||
|
||||
# Would be an error with flow-sensitive tracking
|
||||
reveal_type(a.b.C) # revealed: Literal[C]
|
||||
reveal_type(a.b.C) # revealed: <class 'C'>
|
||||
|
||||
import a.b
|
||||
```
|
||||
|
@ -53,10 +53,10 @@ submodule `b`, even though `a.b` is never imported in the main module.
|
|||
from q import a, b
|
||||
|
||||
reveal_type(b) # revealed: <module 'a.b'>
|
||||
reveal_type(b.C) # revealed: Literal[C]
|
||||
reveal_type(b.C) # revealed: <class 'C'>
|
||||
|
||||
reveal_type(a.b) # revealed: <module 'a.b'>
|
||||
reveal_type(a.b.C) # revealed: Literal[C]
|
||||
reveal_type(a.b.C) # revealed: <class 'C'>
|
||||
```
|
||||
|
||||
`a/__init__.py`:
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
```py
|
||||
class M(type): ...
|
||||
|
||||
reveal_type(M.__class__) # revealed: Literal[type]
|
||||
reveal_type(M.__class__) # revealed: <class 'type'>
|
||||
```
|
||||
|
||||
## `object`
|
||||
|
||||
```py
|
||||
reveal_type(object.__class__) # revealed: Literal[type]
|
||||
reveal_type(object.__class__) # revealed: <class 'type'>
|
||||
```
|
||||
|
||||
## `type`
|
||||
|
||||
```py
|
||||
reveal_type(type.__class__) # revealed: Literal[type]
|
||||
reveal_type(type.__class__) # revealed: <class 'type'>
|
||||
```
|
||||
|
||||
## Basic
|
||||
|
@ -24,7 +24,7 @@ reveal_type(type.__class__) # revealed: Literal[type]
|
|||
class M(type): ...
|
||||
class B(metaclass=M): ...
|
||||
|
||||
reveal_type(B.__class__) # revealed: Literal[M]
|
||||
reveal_type(B.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Invalid metaclass
|
||||
|
@ -37,7 +37,7 @@ class M: ...
|
|||
class A(metaclass=M): ...
|
||||
|
||||
# TODO: emit a diagnostic for the invalid metaclass
|
||||
reveal_type(A.__class__) # revealed: Literal[M]
|
||||
reveal_type(A.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Linear inheritance
|
||||
|
@ -50,7 +50,7 @@ class M(type): ...
|
|||
class A(metaclass=M): ...
|
||||
class B(A): ...
|
||||
|
||||
reveal_type(B.__class__) # revealed: Literal[M]
|
||||
reveal_type(B.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Linear inheritance with PEP 695 generic class
|
||||
|
@ -68,8 +68,8 @@ class A[T](metaclass=M): ...
|
|||
class B(A): ...
|
||||
class C(A[int]): ...
|
||||
|
||||
reveal_type(B.__class__) # revealed: Literal[M]
|
||||
reveal_type(C.__class__) # revealed: Literal[M]
|
||||
reveal_type(B.__class__) # revealed: <class 'M'>
|
||||
reveal_type(C.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Conflict (1)
|
||||
|
@ -117,7 +117,7 @@ class A(metaclass=M): ...
|
|||
class B(metaclass=M): ...
|
||||
class C(A, B): ...
|
||||
|
||||
reveal_type(C.__class__) # revealed: Literal[M]
|
||||
reveal_type(C.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Metaclass metaclass
|
||||
|
@ -131,7 +131,7 @@ class M3(M2): ...
|
|||
class A(metaclass=M3): ...
|
||||
class B(A): ...
|
||||
|
||||
reveal_type(A.__class__) # revealed: Literal[M3]
|
||||
reveal_type(A.__class__) # revealed: <class 'M3'>
|
||||
```
|
||||
|
||||
## Diamond inheritance
|
||||
|
@ -159,14 +159,14 @@ from nonexistent_module import UnknownClass # error: [unresolved-import]
|
|||
class C(UnknownClass): ...
|
||||
|
||||
# TODO: should be `type[type] & Unknown`
|
||||
reveal_type(C.__class__) # revealed: Literal[type]
|
||||
reveal_type(C.__class__) # revealed: <class 'type'>
|
||||
|
||||
class M(type): ...
|
||||
class A(metaclass=M): ...
|
||||
class B(A, UnknownClass): ...
|
||||
|
||||
# TODO: should be `type[M] & Unknown`
|
||||
reveal_type(B.__class__) # revealed: Literal[M]
|
||||
reveal_type(B.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Duplicate
|
||||
|
@ -176,7 +176,7 @@ class M(type): ...
|
|||
class A(metaclass=M): ...
|
||||
class B(A, A): ... # error: [duplicate-base] "Duplicate base class `A`"
|
||||
|
||||
reveal_type(B.__class__) # revealed: Literal[M]
|
||||
reveal_type(B.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Non-class
|
||||
|
@ -191,14 +191,14 @@ def f(*args, **kwargs) -> int:
|
|||
class A(metaclass=f): ...
|
||||
|
||||
# TODO: Should be `int`
|
||||
reveal_type(A) # revealed: Literal[A]
|
||||
reveal_type(A) # revealed: <class 'A'>
|
||||
reveal_type(A.__class__) # revealed: type[int]
|
||||
|
||||
def _(n: int):
|
||||
# error: [invalid-metaclass]
|
||||
class B(metaclass=n): ...
|
||||
# TODO: Should be `Unknown`
|
||||
reveal_type(B) # revealed: Literal[B]
|
||||
reveal_type(B) # revealed: <class 'B'>
|
||||
reveal_type(B.__class__) # revealed: type[Unknown]
|
||||
|
||||
def _(flag: bool):
|
||||
|
@ -207,7 +207,7 @@ def _(flag: bool):
|
|||
# error: [invalid-metaclass]
|
||||
class C(metaclass=m): ...
|
||||
# TODO: Should be `int | Unknown`
|
||||
reveal_type(C) # revealed: Literal[C]
|
||||
reveal_type(C) # revealed: <class 'C'>
|
||||
reveal_type(C.__class__) # revealed: type[Unknown]
|
||||
|
||||
class SignatureMismatch: ...
|
||||
|
@ -216,9 +216,9 @@ class SignatureMismatch: ...
|
|||
class D(metaclass=SignatureMismatch): ...
|
||||
|
||||
# TODO: Should be `Unknown`
|
||||
reveal_type(D) # revealed: Literal[D]
|
||||
reveal_type(D) # revealed: <class 'D'>
|
||||
# TODO: Should be `type[Unknown]`
|
||||
reveal_type(D.__class__) # revealed: Literal[SignatureMismatch]
|
||||
reveal_type(D.__class__) # revealed: <class 'SignatureMismatch'>
|
||||
```
|
||||
|
||||
## Cyclic
|
||||
|
@ -244,7 +244,7 @@ python-version = "3.12"
|
|||
class M(type): ...
|
||||
class A[T: str](metaclass=M): ...
|
||||
|
||||
reveal_type(A.__class__) # revealed: Literal[M]
|
||||
reveal_type(A.__class__) # revealed: <class 'M'>
|
||||
```
|
||||
|
||||
## Metaclasses of metaclasses
|
||||
|
@ -255,9 +255,9 @@ class Bar(type, metaclass=Foo): ...
|
|||
class Baz(type, metaclass=Bar): ...
|
||||
class Spam(metaclass=Baz): ...
|
||||
|
||||
reveal_type(Spam.__class__) # revealed: Literal[Baz]
|
||||
reveal_type(Spam.__class__.__class__) # revealed: Literal[Bar]
|
||||
reveal_type(Spam.__class__.__class__.__class__) # revealed: Literal[Foo]
|
||||
reveal_type(Spam.__class__) # revealed: <class 'Baz'>
|
||||
reveal_type(Spam.__class__.__class__) # revealed: <class 'Bar'>
|
||||
reveal_type(Spam.__class__.__class__.__class__) # revealed: <class 'Foo'>
|
||||
|
||||
def test(x: Spam):
|
||||
reveal_type(x.__class__) # revealed: type[Spam]
|
||||
|
|
|
@ -16,13 +16,13 @@ For documentation on method resolution orders, see:
|
|||
```py
|
||||
class C: ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## The special case: `object` itself
|
||||
|
||||
```py
|
||||
reveal_type(object.__mro__) # revealed: tuple[Literal[object]]
|
||||
reveal_type(object.__mro__) # revealed: tuple[<class 'object'>]
|
||||
```
|
||||
|
||||
## Explicit inheritance from `object`
|
||||
|
@ -30,7 +30,7 @@ reveal_type(object.__mro__) # revealed: tuple[Literal[object]]
|
|||
```py
|
||||
class C(object): ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## Explicit inheritance from non-`object` single base
|
||||
|
@ -39,7 +39,7 @@ reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[object]]
|
|||
class A: ...
|
||||
class B(A): ...
|
||||
|
||||
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[A], Literal[object]]
|
||||
reveal_type(B.__mro__) # revealed: tuple[<class 'B'>, <class 'A'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## Linearization of multiple bases
|
||||
|
@ -49,7 +49,7 @@ class A: ...
|
|||
class B: ...
|
||||
class C(A, B): ...
|
||||
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[A], Literal[B], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## Complex diamond inheritance (1)
|
||||
|
@ -63,8 +63,8 @@ class Y(O): ...
|
|||
class A(X, Y): ...
|
||||
class B(Y, X): ...
|
||||
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
|
||||
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(B.__mro__) # revealed: tuple[<class 'B'>, <class 'Y'>, <class 'X'>, <class 'O'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## Complex diamond inheritance (2)
|
||||
|
@ -80,11 +80,11 @@ class C(D, F): ...
|
|||
class B(D, E): ...
|
||||
class A(B, C): ...
|
||||
|
||||
# revealed: tuple[Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(C.__mro__)
|
||||
# revealed: tuple[Literal[B], Literal[D], Literal[E], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'B'>, <class 'D'>, <class 'E'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(B.__mro__)
|
||||
# revealed: tuple[Literal[A], Literal[B], Literal[C], Literal[D], Literal[E], Literal[F], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'A'>, <class 'B'>, <class 'C'>, <class 'D'>, <class 'E'>, <class 'F'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(A.__mro__)
|
||||
```
|
||||
|
||||
|
@ -101,11 +101,11 @@ class C(D, F): ...
|
|||
class B(E, D): ...
|
||||
class A(B, C): ...
|
||||
|
||||
# revealed: tuple[Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(C.__mro__)
|
||||
# revealed: tuple[Literal[B], Literal[E], Literal[D], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'B'>, <class 'E'>, <class 'D'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(B.__mro__)
|
||||
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'A'>, <class 'B'>, <class 'E'>, <class 'C'>, <class 'D'>, <class 'F'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(A.__mro__)
|
||||
```
|
||||
|
||||
|
@ -125,13 +125,13 @@ class K2(D, B, E): ...
|
|||
class K3(D, A): ...
|
||||
class Z(K1, K2, K3): ...
|
||||
|
||||
# revealed: tuple[Literal[K1], Literal[A], Literal[B], Literal[C], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'K1'>, <class 'A'>, <class 'B'>, <class 'C'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(K1.__mro__)
|
||||
# revealed: tuple[Literal[K2], Literal[D], Literal[B], Literal[E], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'K2'>, <class 'D'>, <class 'B'>, <class 'E'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(K2.__mro__)
|
||||
# revealed: tuple[Literal[K3], Literal[D], Literal[A], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'K3'>, <class 'D'>, <class 'A'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(K3.__mro__)
|
||||
# revealed: tuple[Literal[Z], Literal[K1], Literal[K2], Literal[K3], Literal[D], Literal[A], Literal[B], Literal[C], Literal[E], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'Z'>, <class 'K1'>, <class 'K2'>, <class 'K3'>, <class 'D'>, <class 'A'>, <class 'B'>, <class 'C'>, <class 'E'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(Z.__mro__)
|
||||
```
|
||||
|
||||
|
@ -147,10 +147,11 @@ class D(A, B, C): ...
|
|||
class E(B, C): ...
|
||||
class F(E, A): ...
|
||||
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Unknown, Literal[object]]
|
||||
reveal_type(D.__mro__) # revealed: tuple[Literal[D], Literal[A], Unknown, Literal[B], Literal[C], Literal[object]]
|
||||
reveal_type(E.__mro__) # revealed: tuple[Literal[E], Literal[B], Literal[C], Literal[object]]
|
||||
reveal_type(F.__mro__) # revealed: tuple[Literal[F], Literal[E], Literal[B], Literal[C], Literal[A], Unknown, Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, Unknown, <class 'object'>]
|
||||
reveal_type(D.__mro__) # revealed: tuple[<class 'D'>, <class 'A'>, Unknown, <class 'B'>, <class 'C'>, <class 'object'>]
|
||||
reveal_type(E.__mro__) # revealed: tuple[<class 'E'>, <class 'B'>, <class 'C'>, <class 'object'>]
|
||||
# revealed: tuple[<class 'F'>, <class 'E'>, <class 'B'>, <class 'C'>, <class 'A'>, Unknown, <class 'object'>]
|
||||
reveal_type(F.__mro__)
|
||||
```
|
||||
|
||||
## `__bases__` lists that cause errors at runtime
|
||||
|
@ -162,11 +163,11 @@ creation to fail, we infer the class's `__mro__` as being `[<class>, Unknown, ob
|
|||
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Foo` with bases list `[<class 'object'>, <class 'int'>]`"
|
||||
class Foo(object, int): ...
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
|
||||
class Bar(Foo): ...
|
||||
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[<class 'Bar'>, <class 'Foo'>, Unknown, <class 'object'>]
|
||||
|
||||
# This is the `TypeError` at the bottom of "ex_2"
|
||||
# in the examples at <https://docs.python.org/3/howto/mro.html#the-end>
|
||||
|
@ -176,17 +177,17 @@ class Y(O): ...
|
|||
class A(X, Y): ...
|
||||
class B(Y, X): ...
|
||||
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
|
||||
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(B.__mro__) # revealed: tuple[<class 'B'>, <class 'Y'>, <class 'X'>, <class 'O'>, <class 'object'>]
|
||||
|
||||
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Z` with bases list `[<class 'A'>, <class 'B'>]`"
|
||||
class Z(A, B): ...
|
||||
|
||||
reveal_type(Z.__mro__) # revealed: tuple[Literal[Z], Unknown, Literal[object]]
|
||||
reveal_type(Z.__mro__) # revealed: tuple[<class 'Z'>, Unknown, <class 'object'>]
|
||||
|
||||
class AA(Z): ...
|
||||
|
||||
reveal_type(AA.__mro__) # revealed: tuple[Literal[AA], Literal[Z], Unknown, Literal[object]]
|
||||
reveal_type(AA.__mro__) # revealed: tuple[<class 'AA'>, <class 'Z'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## `__bases__` includes a `Union`
|
||||
|
@ -207,12 +208,12 @@ if returns_bool():
|
|||
else:
|
||||
x = B
|
||||
|
||||
reveal_type(x) # revealed: Literal[A, B]
|
||||
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||
|
||||
# error: 11 [invalid-base] "Invalid class base with type `Literal[A, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 11 [invalid-base] "Invalid class base with type `<class 'A'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
class Foo(x): ...
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## `__bases__` includes multiple `Union`s
|
||||
|
@ -236,14 +237,14 @@ if returns_bool():
|
|||
else:
|
||||
y = D
|
||||
|
||||
reveal_type(x) # revealed: Literal[A, B]
|
||||
reveal_type(y) # revealed: Literal[C, D]
|
||||
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||
reveal_type(y) # revealed: <class 'C'> | <class 'D'>
|
||||
|
||||
# error: 11 [invalid-base] "Invalid class base with type `Literal[A, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 14 [invalid-base] "Invalid class base with type `Literal[C, D]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 11 [invalid-base] "Invalid class base with type `<class 'A'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 14 [invalid-base] "Invalid class base with type `<class 'C'> | <class 'D'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
class Foo(x, y): ...
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## `__bases__` lists that cause errors... now with `Union`s
|
||||
|
@ -261,14 +262,14 @@ if returns_bool():
|
|||
else:
|
||||
foo = object
|
||||
|
||||
# error: 21 [invalid-base] "Invalid class base with type `Literal[Y, object]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 21 [invalid-base] "Invalid class base with type `<class 'Y'> | <class 'object'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
class PossibleError(foo, X): ...
|
||||
|
||||
reveal_type(PossibleError.__mro__) # revealed: tuple[Literal[PossibleError], Unknown, Literal[object]]
|
||||
reveal_type(PossibleError.__mro__) # revealed: tuple[<class 'PossibleError'>, Unknown, <class 'object'>]
|
||||
|
||||
class A(X, Y): ...
|
||||
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>]
|
||||
|
||||
if returns_bool():
|
||||
class B(X, Y): ...
|
||||
|
@ -276,13 +277,13 @@ if returns_bool():
|
|||
else:
|
||||
class B(Y, X): ...
|
||||
|
||||
# revealed: tuple[Literal[B], Literal[X], Literal[Y], Literal[O], Literal[object]] | tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
|
||||
# revealed: tuple[<class 'B'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>] | tuple[<class 'B'>, <class 'Y'>, <class 'X'>, <class 'O'>, <class 'object'>]
|
||||
reveal_type(B.__mro__)
|
||||
|
||||
# error: 12 [invalid-base] "Invalid class base with type `Literal[B, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
# error: 12 [invalid-base] "Invalid class base with type `<class 'B'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
||||
class Z(A, B): ...
|
||||
|
||||
reveal_type(Z.__mro__) # revealed: tuple[Literal[Z], Unknown, Literal[object]]
|
||||
reveal_type(Z.__mro__) # revealed: tuple[<class 'Z'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## `__bases__` lists with duplicate bases
|
||||
|
@ -290,7 +291,7 @@ reveal_type(Z.__mro__) # revealed: tuple[Literal[Z], Unknown, Literal[object]]
|
|||
```py
|
||||
class Foo(str, str): ... # error: 16 [duplicate-base] "Duplicate base class `str`"
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
|
||||
class Spam: ...
|
||||
class Eggs: ...
|
||||
|
@ -301,12 +302,12 @@ class Ham(
|
|||
Eggs, # error: [duplicate-base] "Duplicate base class `Eggs`"
|
||||
): ...
|
||||
|
||||
reveal_type(Ham.__mro__) # revealed: tuple[Literal[Ham], Unknown, Literal[object]]
|
||||
reveal_type(Ham.__mro__) # revealed: tuple[<class 'Ham'>, Unknown, <class 'object'>]
|
||||
|
||||
class Mushrooms: ...
|
||||
class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
|
||||
|
||||
reveal_type(Omelette.__mro__) # revealed: tuple[Literal[Omelette], Unknown, Literal[object]]
|
||||
reveal_type(Omelette.__mro__) # revealed: tuple[<class 'Omelette'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## `__bases__` lists with duplicate `Unknown` bases
|
||||
|
@ -330,7 +331,7 @@ reveal_type(unknown_object_2) # revealed: Unknown
|
|||
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Foo` with bases list `[Unknown, Unknown]`"
|
||||
class Foo(unknown_object_1, unknown_object_2): ...
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## Unrelated objects inferred as `Any`/`Unknown` do not have special `__mro__` attributes
|
||||
|
@ -349,15 +350,15 @@ These are invalid, but we need to be able to handle them gracefully without pani
|
|||
```pyi
|
||||
class Foo(Foo): ... # error: [cyclic-class-definition]
|
||||
|
||||
reveal_type(Foo) # revealed: Literal[Foo]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo) # revealed: <class 'Foo'>
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
|
||||
class Bar: ...
|
||||
class Baz: ...
|
||||
class Boz(Bar, Baz, Boz): ... # error: [cyclic-class-definition]
|
||||
|
||||
reveal_type(Boz) # revealed: Literal[Boz]
|
||||
reveal_type(Boz.__mro__) # revealed: tuple[Literal[Boz], Unknown, Literal[object]]
|
||||
reveal_type(Boz) # revealed: <class 'Boz'>
|
||||
reveal_type(Boz.__mro__) # revealed: tuple[<class 'Boz'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## Classes with indirect cycles in their MROs
|
||||
|
@ -369,9 +370,9 @@ class Foo(Bar): ... # error: [cyclic-class-definition]
|
|||
class Bar(Baz): ... # error: [cyclic-class-definition]
|
||||
class Baz(Foo): ... # error: [cyclic-class-definition]
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[<class 'Bar'>, Unknown, <class 'object'>]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[<class 'Baz'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## Classes with cycles in their MROs, and multiple inheritance
|
||||
|
@ -382,9 +383,9 @@ class Foo(Bar): ... # error: [cyclic-class-definition]
|
|||
class Bar(Baz): ... # error: [cyclic-class-definition]
|
||||
class Baz(Foo, Spam): ... # error: [cyclic-class-definition]
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[<class 'Bar'>, Unknown, <class 'object'>]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[<class 'Baz'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
## Classes with cycles in their MRO, and a sub-graph
|
||||
|
@ -400,8 +401,8 @@ class Bar(Foo): ...
|
|||
class Baz(Bar, BarCycle): ...
|
||||
class Spam(Baz): ...
|
||||
|
||||
reveal_type(FooCycle.__mro__) # revealed: tuple[Literal[FooCycle], Unknown, Literal[object]]
|
||||
reveal_type(BarCycle.__mro__) # revealed: tuple[Literal[BarCycle], Unknown, Literal[object]]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
|
||||
reveal_type(Spam.__mro__) # revealed: tuple[Literal[Spam], Unknown, Literal[object]]
|
||||
reveal_type(FooCycle.__mro__) # revealed: tuple[<class 'FooCycle'>, Unknown, <class 'object'>]
|
||||
reveal_type(BarCycle.__mro__) # revealed: tuple[<class 'BarCycle'>, Unknown, <class 'object'>]
|
||||
reveal_type(Baz.__mro__) # revealed: tuple[<class 'Baz'>, Unknown, <class 'object'>]
|
||||
reveal_type(Spam.__mro__) # revealed: tuple[<class 'Spam'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
|
|
@ -43,9 +43,9 @@ def _(flag: bool):
|
|||
C = A if flag else B
|
||||
|
||||
if C != A:
|
||||
reveal_type(C) # revealed: Literal[B]
|
||||
reveal_type(C) # revealed: <class 'B'>
|
||||
else:
|
||||
reveal_type(C) # revealed: Literal[A]
|
||||
reveal_type(C) # revealed: <class 'A'>
|
||||
```
|
||||
|
||||
## `x != y` where `y` has multiple single-valued options
|
||||
|
|
|
@ -14,15 +14,15 @@ def _(flag: bool):
|
|||
reveal_type(t) # revealed: Never
|
||||
|
||||
if issubclass(t, object):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
|
||||
if issubclass(t, int):
|
||||
reveal_type(t) # revealed: Literal[int]
|
||||
reveal_type(t) # revealed: <class 'int'>
|
||||
else:
|
||||
reveal_type(t) # revealed: Literal[str]
|
||||
reveal_type(t) # revealed: <class 'str'>
|
||||
|
||||
if issubclass(t, str):
|
||||
reveal_type(t) # revealed: Literal[str]
|
||||
reveal_type(t) # revealed: <class 'str'>
|
||||
if issubclass(t, int):
|
||||
reveal_type(t) # revealed: Never
|
||||
```
|
||||
|
@ -34,16 +34,16 @@ def _(flag1: bool, flag2: bool):
|
|||
t = int if flag1 else str if flag2 else bytes
|
||||
|
||||
if issubclass(t, int):
|
||||
reveal_type(t) # revealed: Literal[int]
|
||||
reveal_type(t) # revealed: <class 'int'>
|
||||
else:
|
||||
reveal_type(t) # revealed: Literal[str, bytes]
|
||||
reveal_type(t) # revealed: <class 'str'> | <class 'bytes'>
|
||||
|
||||
if issubclass(t, int):
|
||||
reveal_type(t) # revealed: Literal[int]
|
||||
reveal_type(t) # revealed: <class 'int'>
|
||||
elif issubclass(t, str):
|
||||
reveal_type(t) # revealed: Literal[str]
|
||||
reveal_type(t) # revealed: <class 'str'>
|
||||
else:
|
||||
reveal_type(t) # revealed: Literal[bytes]
|
||||
reveal_type(t) # revealed: <class 'bytes'>
|
||||
```
|
||||
|
||||
### Multiple derived classes
|
||||
|
@ -58,24 +58,24 @@ def _(flag1: bool, flag2: bool, flag3: bool):
|
|||
t1 = Derived1 if flag1 else Derived2
|
||||
|
||||
if issubclass(t1, Base):
|
||||
reveal_type(t1) # revealed: Literal[Derived1, Derived2]
|
||||
reveal_type(t1) # revealed: <class 'Derived1'> | <class 'Derived2'>
|
||||
|
||||
if issubclass(t1, Derived1):
|
||||
reveal_type(t1) # revealed: Literal[Derived1]
|
||||
reveal_type(t1) # revealed: <class 'Derived1'>
|
||||
else:
|
||||
reveal_type(t1) # revealed: Literal[Derived2]
|
||||
reveal_type(t1) # revealed: <class 'Derived2'>
|
||||
|
||||
t2 = Derived1 if flag2 else Base
|
||||
|
||||
if issubclass(t2, Base):
|
||||
reveal_type(t2) # revealed: Literal[Derived1, Base]
|
||||
reveal_type(t2) # revealed: <class 'Derived1'> | <class 'Base'>
|
||||
|
||||
t3 = Derived1 if flag3 else Unrelated
|
||||
|
||||
if issubclass(t3, Base):
|
||||
reveal_type(t3) # revealed: Literal[Derived1]
|
||||
reveal_type(t3) # revealed: <class 'Derived1'>
|
||||
else:
|
||||
reveal_type(t3) # revealed: Literal[Unrelated]
|
||||
reveal_type(t3) # revealed: <class 'Unrelated'>
|
||||
```
|
||||
|
||||
### Narrowing for non-literals
|
||||
|
@ -109,10 +109,10 @@ def _(flag: bool):
|
|||
t = int if flag else NoneType
|
||||
|
||||
if issubclass(t, NoneType):
|
||||
reveal_type(t) # revealed: Literal[NoneType]
|
||||
reveal_type(t) # revealed: <class 'NoneType'>
|
||||
|
||||
if issubclass(t, type(None)):
|
||||
reveal_type(t) # revealed: Literal[NoneType]
|
||||
reveal_type(t) # revealed: <class 'NoneType'>
|
||||
```
|
||||
|
||||
## `classinfo` contains multiple types
|
||||
|
@ -126,9 +126,9 @@ def _(flag1: bool, flag2: bool):
|
|||
t = int if flag1 else str if flag2 else bytes
|
||||
|
||||
if issubclass(t, (int, (Unrelated, (bytes,)))):
|
||||
reveal_type(t) # revealed: Literal[int, bytes]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'bytes'>
|
||||
else:
|
||||
reveal_type(t) # revealed: Literal[str]
|
||||
reveal_type(t) # revealed: <class 'str'>
|
||||
```
|
||||
|
||||
## Special cases
|
||||
|
@ -175,7 +175,7 @@ def flag() -> bool:
|
|||
|
||||
t = int if flag() else str
|
||||
if issubclass(t, int):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
```
|
||||
|
||||
### Do support narrowing if `issubclass` is aliased
|
||||
|
@ -188,7 +188,7 @@ def flag() -> bool:
|
|||
|
||||
t = int if flag() else str
|
||||
if issubclass_alias(t, int):
|
||||
reveal_type(t) # revealed: Literal[int]
|
||||
reveal_type(t) # revealed: <class 'int'>
|
||||
```
|
||||
|
||||
### Do support narrowing if `issubclass` is imported
|
||||
|
@ -201,7 +201,7 @@ def flag() -> bool:
|
|||
|
||||
t = int if flag() else str
|
||||
if imported_issubclass(t, int):
|
||||
reveal_type(t) # revealed: Literal[int]
|
||||
reveal_type(t) # revealed: <class 'int'>
|
||||
```
|
||||
|
||||
### Do not narrow if second argument is not a proper `classinfo` argument
|
||||
|
@ -217,17 +217,17 @@ t = int if flag() else str
|
|||
# TODO: this should cause us to emit a diagnostic during
|
||||
# type checking
|
||||
if issubclass(t, "str"):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
|
||||
# TODO: this should cause us to emit a diagnostic during
|
||||
# type checking
|
||||
if issubclass(t, (bytes, "str")):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
|
||||
# TODO: this should cause us to emit a diagnostic during
|
||||
# type checking
|
||||
if issubclass(t, Any):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
```
|
||||
|
||||
### Do not narrow if there are keyword arguments
|
||||
|
@ -240,7 +240,7 @@ t = int if flag() else str
|
|||
|
||||
# error: [unknown-argument]
|
||||
if issubclass(t, int, foo="bar"):
|
||||
reveal_type(t) # revealed: Literal[int, str]
|
||||
reveal_type(t) # revealed: <class 'int'> | <class 'str'>
|
||||
```
|
||||
|
||||
### `type[]` types are narrowed as well as class-literal types
|
||||
|
|
|
@ -108,12 +108,12 @@ def flag() -> bool:
|
|||
return True
|
||||
|
||||
x = int if flag() else str
|
||||
reveal_type(x) # revealed: Literal[int, str]
|
||||
reveal_type(x) # revealed: <class 'int'> | <class 'str'>
|
||||
|
||||
if x:
|
||||
reveal_type(x) # revealed: (Literal[int] & ~AlwaysFalsy) | (Literal[str] & ~AlwaysFalsy)
|
||||
reveal_type(x) # revealed: (<class 'int'> & ~AlwaysFalsy) | (<class 'str'> & ~AlwaysFalsy)
|
||||
else:
|
||||
reveal_type(x) # revealed: (Literal[int] & ~AlwaysTruthy) | (Literal[str] & ~AlwaysTruthy)
|
||||
reveal_type(x) # revealed: (<class 'int'> & ~AlwaysTruthy) | (<class 'str'> & ~AlwaysTruthy)
|
||||
```
|
||||
|
||||
## Determined Truthiness
|
||||
|
@ -276,12 +276,12 @@ def _(
|
|||
reveal_type(d) # revealed: type[DeferredClass] & ~AlwaysFalsy
|
||||
|
||||
tf = TruthyClass if flag else FalsyClass
|
||||
reveal_type(tf) # revealed: Literal[TruthyClass, FalsyClass]
|
||||
reveal_type(tf) # revealed: <class 'TruthyClass'> | <class 'FalsyClass'>
|
||||
|
||||
if tf:
|
||||
reveal_type(tf) # revealed: Literal[TruthyClass]
|
||||
reveal_type(tf) # revealed: <class 'TruthyClass'>
|
||||
else:
|
||||
reveal_type(tf) # revealed: Literal[FalsyClass]
|
||||
reveal_type(tf) # revealed: <class 'FalsyClass'>
|
||||
```
|
||||
|
||||
## Narrowing in chained boolean expressions
|
||||
|
|
|
@ -150,7 +150,7 @@ def _(x: Base):
|
|||
```py
|
||||
def _(x: object):
|
||||
if (y := type(x)) is bool:
|
||||
reveal_type(y) # revealed: Literal[bool]
|
||||
reveal_type(y) # revealed: <class 'bool'>
|
||||
if (type(y := x)) is bool:
|
||||
reveal_type(y) # revealed: bool
|
||||
```
|
||||
|
|
|
@ -28,7 +28,7 @@ from typing import Protocol
|
|||
|
||||
class MyProtocol(Protocol): ...
|
||||
|
||||
reveal_type(MyProtocol.__mro__) # revealed: tuple[Literal[MyProtocol], typing.Protocol, typing.Generic, Literal[object]]
|
||||
reveal_type(MyProtocol.__mro__) # revealed: tuple[<class 'MyProtocol'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
```
|
||||
|
||||
Just like for any other class base, it is an error for `Protocol` to appear multiple times in a
|
||||
|
@ -37,7 +37,7 @@ class's bases:
|
|||
```py
|
||||
class Foo(Protocol, Protocol): ... # error: [inconsistent-mro]
|
||||
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||
```
|
||||
|
||||
Protocols can also be generic, either by including `Generic[]` in the bases list, subscripting
|
||||
|
@ -71,7 +71,7 @@ class DuplicateBases(Protocol, Protocol[T]):
|
|||
x: T
|
||||
|
||||
# TODO: should not have `Protocol` multiple times
|
||||
# revealed: tuple[Literal[DuplicateBases], typing.Protocol, @Todo(`Protocol[]` subscript), typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'DuplicateBases'>, typing.Protocol, @Todo(`Protocol[]` subscript), typing.Generic, <class 'object'>]
|
||||
reveal_type(DuplicateBases.__mro__)
|
||||
```
|
||||
|
||||
|
@ -107,7 +107,7 @@ it is not sufficient for it to have `Protocol` in its MRO.
|
|||
```py
|
||||
class SubclassOfMyProtocol(MyProtocol): ...
|
||||
|
||||
# revealed: tuple[Literal[SubclassOfMyProtocol], Literal[MyProtocol], typing.Protocol, typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'SubclassOfMyProtocol'>, <class 'MyProtocol'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
reveal_type(SubclassOfMyProtocol.__mro__)
|
||||
|
||||
reveal_type(is_protocol(SubclassOfMyProtocol)) # revealed: Literal[False]
|
||||
|
@ -126,7 +126,7 @@ class OtherProtocol(Protocol):
|
|||
|
||||
class ComplexInheritance(SubProtocol, OtherProtocol, Protocol): ...
|
||||
|
||||
# revealed: tuple[Literal[ComplexInheritance], Literal[SubProtocol], Literal[MyProtocol], Literal[OtherProtocol], typing.Protocol, typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'ComplexInheritance'>, <class 'SubProtocol'>, <class 'MyProtocol'>, <class 'OtherProtocol'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
reveal_type(ComplexInheritance.__mro__)
|
||||
|
||||
reveal_type(is_protocol(ComplexInheritance)) # revealed: Literal[True]
|
||||
|
@ -139,13 +139,13 @@ or `TypeError` is raised at runtime when the class is created.
|
|||
# error: [invalid-protocol] "Protocol class `Invalid` cannot inherit from non-protocol class `NotAProtocol`"
|
||||
class Invalid(NotAProtocol, Protocol): ...
|
||||
|
||||
# revealed: tuple[Literal[Invalid], Literal[NotAProtocol], typing.Protocol, typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'Invalid'>, <class 'NotAProtocol'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
reveal_type(Invalid.__mro__)
|
||||
|
||||
# error: [invalid-protocol] "Protocol class `AlsoInvalid` cannot inherit from non-protocol class `NotAProtocol`"
|
||||
class AlsoInvalid(MyProtocol, OtherProtocol, NotAProtocol, Protocol): ...
|
||||
|
||||
# revealed: tuple[Literal[AlsoInvalid], Literal[MyProtocol], Literal[OtherProtocol], Literal[NotAProtocol], typing.Protocol, typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'AlsoInvalid'>, <class 'MyProtocol'>, <class 'OtherProtocol'>, <class 'NotAProtocol'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
reveal_type(AlsoInvalid.__mro__)
|
||||
```
|
||||
|
||||
|
@ -163,7 +163,7 @@ T = TypeVar("T")
|
|||
# type checkers.
|
||||
class Fine(Protocol, object): ...
|
||||
|
||||
reveal_type(Fine.__mro__) # revealed: tuple[Literal[Fine], typing.Protocol, typing.Generic, Literal[object]]
|
||||
reveal_type(Fine.__mro__) # revealed: tuple[<class 'Fine'>, typing.Protocol, typing.Generic, <class 'object'>]
|
||||
|
||||
class StillFine(Protocol, Generic[T], object): ...
|
||||
class EvenThis[T](Protocol, object): ...
|
||||
|
@ -177,7 +177,7 @@ And multiple inheritance from a mix of protocol and non-protocol classes is fine
|
|||
```py
|
||||
class FineAndDandy(MyProtocol, OtherProtocol, NotAProtocol): ...
|
||||
|
||||
# revealed: tuple[Literal[FineAndDandy], Literal[MyProtocol], Literal[OtherProtocol], typing.Protocol, typing.Generic, Literal[NotAProtocol], Literal[object]]
|
||||
# revealed: tuple[<class 'FineAndDandy'>, <class 'MyProtocol'>, <class 'OtherProtocol'>, typing.Protocol, typing.Generic, <class 'NotAProtocol'>, <class 'object'>]
|
||||
reveal_type(FineAndDandy.__mro__)
|
||||
```
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ reveal_type(typing.__init__) # revealed: bound method ModuleType.__init__(name:
|
|||
# These come from `builtins.object`, not `types.ModuleType`:
|
||||
reveal_type(typing.__eq__) # revealed: bound method ModuleType.__eq__(value: object, /) -> bool
|
||||
|
||||
reveal_type(typing.__class__) # revealed: Literal[ModuleType]
|
||||
reveal_type(typing.__class__) # revealed: <class 'ModuleType'>
|
||||
|
||||
reveal_type(typing.__dict__) # revealed: dict[str, Any]
|
||||
```
|
||||
|
|
|
@ -16,7 +16,7 @@ class C:
|
|||
if flag:
|
||||
x = 2
|
||||
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C]` is possibly unbound"
|
||||
# error: [possibly-unbound-attribute] "Attribute `x` on type `<class 'C'>` is possibly unbound"
|
||||
reveal_type(C.x) # revealed: Unknown | Literal[2]
|
||||
reveal_type(C.y) # revealed: Unknown | Literal[1]
|
||||
```
|
||||
|
|
|
@ -26,7 +26,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/attribute_as
|
|||
# Diagnostics
|
||||
|
||||
```
|
||||
warning: lint:possibly-unbound-attribute: Attribute `attr` on type `Literal[C]` is possibly unbound
|
||||
warning: lint:possibly-unbound-attribute: Attribute `attr` on type `<class 'C'>` is possibly unbound
|
||||
--> src/mdtest_snippet.py:6:5
|
||||
|
|
||||
4 | attr: int = 0
|
||||
|
|
|
@ -41,7 +41,7 @@ info: `lint:invalid-assignment` is enabled by default
|
|||
```
|
||||
|
||||
```
|
||||
error: lint:invalid-attribute-access: Cannot assign to instance attribute `attr` from the class object `Literal[C]`
|
||||
error: lint:invalid-attribute-access: Cannot assign to instance attribute `attr` from the class object `<class 'C'>`
|
||||
--> src/mdtest_snippet.py:9:1
|
||||
|
|
||||
7 | instance.attr = "wrong" # error: [invalid-assignment]
|
||||
|
|
|
@ -37,7 +37,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/attribute_as
|
|||
# Diagnostics
|
||||
|
||||
```
|
||||
error: lint:invalid-assignment: Object of type `Literal[1]` is not assignable to attribute `attr` on type `Literal[C1, C1]`
|
||||
error: lint:invalid-assignment: Object of type `Literal[1]` is not assignable to attribute `attr` on type `<class 'C1'> | <class 'C1'>`
|
||||
--> src/mdtest_snippet.py:11:5
|
||||
|
|
||||
10 | # TODO: The error message here could be improved to explain why the assignment fails.
|
||||
|
|
|
@ -23,7 +23,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/attribute_as
|
|||
# Diagnostics
|
||||
|
||||
```
|
||||
error: lint:unresolved-attribute: Unresolved attribute `non_existent` on type `Literal[C]`.
|
||||
error: lint:unresolved-attribute: Unresolved attribute `non_existent` on type `<class 'C'>`.
|
||||
--> src/mdtest_snippet.py:3:1
|
||||
|
|
||||
1 | class C: ...
|
||||
|
|
|
@ -15,8 +15,8 @@ class Foo[T]: ...
|
|||
|
||||
class Bar(Foo[Bar]): ...
|
||||
|
||||
reveal_type(Bar) # revealed: Literal[Bar]
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Literal[Foo[Bar]], Literal[object]]
|
||||
reveal_type(Bar) # revealed: <class 'Bar'>
|
||||
reveal_type(Bar.__mro__) # revealed: tuple[<class 'Bar'>, <class 'Foo[Bar]'>, <class 'object'>]
|
||||
```
|
||||
|
||||
## Access to attributes declared in stubs
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
```py
|
||||
class NotSubscriptable: ...
|
||||
|
||||
a = NotSubscriptable[0] # error: "Cannot subscript object of type `Literal[NotSubscriptable]` with no `__class_getitem__` method"
|
||||
# error: "Cannot subscript object of type `<class 'NotSubscriptable'>` with no `__class_getitem__` method"
|
||||
a = NotSubscriptable[0]
|
||||
```
|
||||
|
||||
## Class getitem
|
||||
|
@ -47,7 +48,7 @@ def _(flag: bool):
|
|||
|
||||
x = A if flag else B
|
||||
|
||||
reveal_type(x) # revealed: Literal[A, B]
|
||||
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||
reveal_type(x[0]) # revealed: str | int
|
||||
```
|
||||
|
||||
|
@ -62,7 +63,7 @@ def _(flag: bool):
|
|||
|
||||
else:
|
||||
class Spam: ...
|
||||
# error: [call-possibly-unbound-method] "Method `__class_getitem__` of type `Literal[Spam, Spam]` is possibly unbound"
|
||||
# error: [call-possibly-unbound-method] "Method `__class_getitem__` of type `<class 'Spam'> | <class 'Spam'>` is possibly unbound"
|
||||
# revealed: str
|
||||
reveal_type(Spam[42])
|
||||
```
|
||||
|
@ -79,7 +80,7 @@ def _(flag: bool):
|
|||
else:
|
||||
Eggs = 1
|
||||
|
||||
a = Eggs[42] # error: "Cannot subscript object of type `Literal[Eggs] | Literal[1]` with no `__getitem__` method"
|
||||
a = Eggs[42] # error: "Cannot subscript object of type `<class 'Eggs'> | Literal[1]` with no `__getitem__` method"
|
||||
|
||||
# TODO: should _probably_ emit `str | Unknown`
|
||||
reveal_type(a) # revealed: Unknown
|
||||
|
|
|
@ -85,7 +85,7 @@ class A(tuple[int, str]): ...
|
|||
|
||||
# Runtime value: `(A, tuple, object)`
|
||||
# TODO: Generics
|
||||
reveal_type(A.__mro__) # revealed: tuple[Literal[A], @Todo(GenericAlias instance), Literal[object]]
|
||||
reveal_type(A.__mro__) # revealed: tuple[<class 'A'>, @Todo(GenericAlias instance), <class 'object'>]
|
||||
```
|
||||
|
||||
## `typing.Tuple`
|
||||
|
@ -116,6 +116,6 @@ from typing import Tuple
|
|||
class C(Tuple): ...
|
||||
|
||||
# TODO: generic protocols
|
||||
# revealed: tuple[Literal[C], Literal[tuple], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(`Protocol[]` subscript), typing.Generic, Literal[object]]
|
||||
# revealed: tuple[<class 'C'>, <class 'tuple'>, <class 'Sequence'>, <class 'Reversible'>, <class 'Collection'>, <class 'Iterable'>, <class 'Container'>, @Todo(`Protocol[]` subscript), typing.Generic, <class 'object'>]
|
||||
reveal_type(C.__mro__)
|
||||
```
|
||||
|
|
|
@ -105,7 +105,7 @@ def explicit_unknown(x: Unknown, y: tuple[str, Unknown], z: Unknown = 1) -> None
|
|||
```py
|
||||
class C(Unknown): ...
|
||||
|
||||
# revealed: tuple[Literal[C], Unknown, Literal[object]]
|
||||
# revealed: tuple[<class 'C'>, Unknown, <class 'object'>]
|
||||
reveal_type(C.__mro__)
|
||||
|
||||
# error: "Special form `ty_extensions.Unknown` expected no type parameter"
|
||||
|
|
|
@ -147,8 +147,8 @@ _: type[A, B]
|
|||
```py
|
||||
class Foo(type[int]): ...
|
||||
|
||||
# TODO: should be `tuple[Literal[Foo], Literal[type], Literal[object]]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], @Todo(GenericAlias instance), Literal[object]]
|
||||
# TODO: should be `tuple[<class 'Foo'>, <class 'type'>, <class 'object'>]
|
||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, @Todo(GenericAlias instance), <class 'object'>]
|
||||
```
|
||||
|
||||
## `@final` classes
|
||||
|
@ -169,6 +169,6 @@ from typing import final
|
|||
class Foo: ...
|
||||
|
||||
def _(x: type[Foo], y: type[EllipsisType]):
|
||||
reveal_type(x) # revealed: Literal[Foo]
|
||||
reveal_type(y) # revealed: Literal[EllipsisType]
|
||||
reveal_type(x) # revealed: <class 'Foo'>
|
||||
reveal_type(y) # revealed: <class 'EllipsisType'>
|
||||
```
|
||||
|
|
|
@ -28,5 +28,5 @@ class C(Type): ...
|
|||
|
||||
# Runtime value: `(C, type, typing.Generic, object)`
|
||||
# TODO: Add `Generic` to the MRO
|
||||
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[type], Literal[object]]
|
||||
reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'type'>, <class 'object'>]
|
||||
```
|
||||
|
|
|
@ -52,25 +52,25 @@ class Yes:
|
|||
class Sub(Yes): ...
|
||||
class No: ...
|
||||
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `Literal[Yes]`"
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `<class 'Yes'>`"
|
||||
reveal_type(+Yes) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `Literal[Yes]`"
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `<class 'Yes'>`"
|
||||
reveal_type(-Yes) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `Literal[Yes]`"
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `<class 'Yes'>`"
|
||||
reveal_type(~Yes) # revealed: Unknown
|
||||
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `Literal[Sub]`"
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `<class 'Sub'>`"
|
||||
reveal_type(+Sub) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `Literal[Sub]`"
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `<class 'Sub'>`"
|
||||
reveal_type(-Sub) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `Literal[Sub]`"
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `<class 'Sub'>`"
|
||||
reveal_type(~Sub) # revealed: Unknown
|
||||
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(+No) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(-No) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(~No) # revealed: Unknown
|
||||
```
|
||||
|
||||
|
@ -160,10 +160,10 @@ reveal_type(+Sub) # revealed: bool
|
|||
reveal_type(-Sub) # revealed: str
|
||||
reveal_type(~Sub) # revealed: int
|
||||
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `+` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(+No) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `-` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(-No) # revealed: Unknown
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `Literal[No]`"
|
||||
# error: [unsupported-operator] "Unary operator `~` is unsupported for type `<class 'No'>`"
|
||||
reveal_type(~No) # revealed: Unknown
|
||||
```
|
||||
|
|
|
@ -42,9 +42,7 @@ impl Display for DisplayType<'_> {
|
|||
Type::IntLiteral(_)
|
||||
| Type::BooleanLiteral(_)
|
||||
| Type::StringLiteral(_)
|
||||
| Type::BytesLiteral(_)
|
||||
| Type::ClassLiteral(_)
|
||||
| Type::GenericAlias(_) => {
|
||||
| Type::BytesLiteral(_) => {
|
||||
write!(f, "Literal[{representation}]")
|
||||
}
|
||||
_ => representation.fmt(f),
|
||||
|
@ -102,9 +100,10 @@ impl Display for DisplayRepresentation<'_> {
|
|||
Type::ModuleLiteral(module) => {
|
||||
write!(f, "<module '{}'>", module.module(self.db).name())
|
||||
}
|
||||
// TODO functions and classes should display using a fully qualified name
|
||||
Type::ClassLiteral(class) => f.write_str(class.name(self.db)),
|
||||
Type::GenericAlias(generic) => generic.display(self.db).fmt(f),
|
||||
Type::ClassLiteral(class) => {
|
||||
write!(f, "<class '{}'>", class.name(self.db))
|
||||
}
|
||||
Type::GenericAlias(generic) => write!(f, "<class '{}'>", generic.display(self.db)),
|
||||
Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() {
|
||||
// Only show the bare class name here; ClassBase::display would render this as
|
||||
// type[<class 'Foo'>] instead of type[Foo].
|
||||
|
@ -605,7 +604,6 @@ impl Display for DisplayLiteralGroup<'_> {
|
|||
/// For example, `Literal[1] | Literal[2] | Literal["s"]` is displayed as `"Literal[1, 2, "s"]"`.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
enum CondensedDisplayTypeKind {
|
||||
Class,
|
||||
LiteralExpression,
|
||||
}
|
||||
|
||||
|
@ -614,7 +612,6 @@ impl TryFrom<Type<'_>> for CondensedDisplayTypeKind {
|
|||
|
||||
fn try_from(value: Type<'_>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Type::ClassLiteral(_) => Ok(Self::Class),
|
||||
Type::IntLiteral(_)
|
||||
| Type::StringLiteral(_)
|
||||
| Type::BytesLiteral(_)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue