mirror of https://github.com/astral-sh/ruff
[ty] Improve rendering of default values for function args (#22010)
## Summary We're actually quite good at computing this but the main issue is just that we compute it at the type-level and so wrap it in `Literal[...]`. So just special-case the rendering of these to omit `Literal[...]` and fallback to `...` in cases where the thing we'll show is probably useless (i.e. `x: str = str`). Fixes https://github.com/astral-sh/ty/issues/1882
This commit is contained in:
parent
2214a46139
commit
ad3de4e488
|
|
@ -3212,7 +3212,7 @@ quux.<CURSOR>
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
builder.skip_keywords().skip_builtins().type_signatures().build().snapshot(), @r"
|
builder.skip_keywords().skip_builtins().type_signatures().build().snapshot(), @r"
|
||||||
count :: bound method Quux.count(value: Any, /) -> int
|
count :: bound method Quux.count(value: Any, /) -> int
|
||||||
index :: bound method Quux.index(value: Any, start: SupportsIndex = Literal[0], stop: SupportsIndex = int, /) -> int
|
index :: bound method Quux.index(value: Any, start: SupportsIndex = 0, stop: SupportsIndex = ..., /) -> int
|
||||||
x :: int
|
x :: int
|
||||||
y :: str
|
y :: str
|
||||||
__add__ :: Overload[(value: tuple[int | str, ...], /) -> tuple[int | str, ...], (value: tuple[_T@__add__, ...], /) -> tuple[int | str | _T@__add__, ...]]
|
__add__ :: Overload[(value: tuple[int | str, ...], /) -> tuple[int | str, ...], (value: tuple[_T@__add__, ...], /) -> tuple[int | str | _T@__add__, ...]]
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ We can access attributes on objects of all kinds:
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
reveal_type(inspect.getattr_static(sys, "dont_write_bytecode")) # revealed: bool
|
reveal_type(inspect.getattr_static(sys, "dont_write_bytecode")) # revealed: bool
|
||||||
# revealed: def getattr_static(obj: object, attr: str, default: Any | None = EllipsisType) -> Any
|
# revealed: def getattr_static(obj: object, attr: str, default: Any | None = ...) -> Any
|
||||||
reveal_type(inspect.getattr_static(inspect, "getattr_static"))
|
reveal_type(inspect.getattr_static(inspect, "getattr_static"))
|
||||||
|
|
||||||
reveal_type(inspect.getattr_static(1, "real")) # revealed: property
|
reveal_type(inspect.getattr_static(1, "real")) # revealed: property
|
||||||
|
|
@ -144,7 +144,7 @@ from typing import Any
|
||||||
def _(a: Any, tuple_of_any: tuple[Any]):
|
def _(a: Any, tuple_of_any: tuple[Any]):
|
||||||
reveal_type(inspect.getattr_static(a, "x", "default")) # revealed: Any | Literal["default"]
|
reveal_type(inspect.getattr_static(a, "x", "default")) # revealed: Any | Literal["default"]
|
||||||
|
|
||||||
# revealed: def index(self, value: Any, start: SupportsIndex = Literal[0], stop: SupportsIndex = int, /) -> int
|
# revealed: def index(self, value: Any, start: SupportsIndex = 0, stop: SupportsIndex = ..., /) -> int
|
||||||
reveal_type(inspect.getattr_static(tuple_of_any, "index", "default"))
|
reveal_type(inspect.getattr_static(tuple_of_any, "index", "default"))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -598,9 +598,9 @@ from typing_extensions import Self
|
||||||
|
|
||||||
reveal_type(object.__new__) # revealed: def __new__(cls) -> Self@__new__
|
reveal_type(object.__new__) # revealed: def __new__(cls) -> Self@__new__
|
||||||
reveal_type(object().__new__) # revealed: def __new__(cls) -> Self@__new__
|
reveal_type(object().__new__) # revealed: def __new__(cls) -> Self@__new__
|
||||||
# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = Literal[0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__]
|
# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = 0, /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__]
|
||||||
reveal_type(int.__new__)
|
reveal_type(int.__new__)
|
||||||
# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = Literal[0], /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__]
|
# revealed: Overload[(cls, x: str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc = 0, /) -> Self@__new__, (cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self@__new__]
|
||||||
reveal_type((42).__new__)
|
reveal_type((42).__new__)
|
||||||
|
|
||||||
class X:
|
class X:
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class Point:
|
||||||
x: int
|
x: int
|
||||||
y: int
|
y: int
|
||||||
|
|
||||||
reveal_type(Point.__replace__) # revealed: (self: Point, *, x: int = int, y: int = int) -> Point
|
reveal_type(Point.__replace__) # revealed: (self: Point, *, x: int = ..., y: int = ...) -> Point
|
||||||
```
|
```
|
||||||
|
|
||||||
The `__replace__` method can either be called directly or through the `replace` function:
|
The `__replace__` method can either be called directly or through the `replace` function:
|
||||||
|
|
|
||||||
|
|
@ -87,25 +87,25 @@ class C:
|
||||||
def inner_a(positional=self.a):
|
def inner_a(positional=self.a):
|
||||||
return
|
return
|
||||||
self.a = inner_a
|
self.a = inner_a
|
||||||
# revealed: def inner_a(positional=Unknown | (def inner_a(positional=Unknown) -> Unknown)) -> Unknown
|
# revealed: def inner_a(positional=...) -> Unknown
|
||||||
reveal_type(inner_a)
|
reveal_type(inner_a)
|
||||||
|
|
||||||
def inner_b(*, kw_only=self.b):
|
def inner_b(*, kw_only=self.b):
|
||||||
return
|
return
|
||||||
self.b = inner_b
|
self.b = inner_b
|
||||||
# revealed: def inner_b(*, kw_only=Unknown | (def inner_b(*, kw_only=Unknown) -> Unknown)) -> Unknown
|
# revealed: def inner_b(*, kw_only=...) -> Unknown
|
||||||
reveal_type(inner_b)
|
reveal_type(inner_b)
|
||||||
|
|
||||||
def inner_c(positional_only=self.c, /):
|
def inner_c(positional_only=self.c, /):
|
||||||
return
|
return
|
||||||
self.c = inner_c
|
self.c = inner_c
|
||||||
# revealed: def inner_c(positional_only=Unknown | (def inner_c(positional_only=Unknown, /) -> Unknown), /) -> Unknown
|
# revealed: def inner_c(positional_only=..., /) -> Unknown
|
||||||
reveal_type(inner_c)
|
reveal_type(inner_c)
|
||||||
|
|
||||||
def inner_d(*, kw_only=self.d):
|
def inner_d(*, kw_only=self.d):
|
||||||
return
|
return
|
||||||
self.d = inner_d
|
self.d = inner_d
|
||||||
# revealed: def inner_d(*, kw_only=Unknown | (def inner_d(*, kw_only=Unknown) -> Unknown)) -> Unknown
|
# revealed: def inner_d(*, kw_only=...) -> Unknown
|
||||||
reveal_type(inner_d)
|
reveal_type(inner_d)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ We do, however, still check assignability of the default value to the parameter
|
||||||
```py
|
```py
|
||||||
class D:
|
class D:
|
||||||
def f(self: "D"):
|
def f(self: "D"):
|
||||||
# error: [invalid-parameter-default] "Default value of type `Unknown | (def inner_a(a: int = Unknown | (def inner_a(a: int = Unknown) -> Unknown)) -> Unknown)` is not assignable to annotated parameter type `int`"
|
# error: [invalid-parameter-default] "Default value of type `Unknown | (def inner_a(a: int = ...) -> Unknown)` is not assignable to annotated parameter type `int`"
|
||||||
def inner_a(a: int = self.a): ...
|
def inner_a(a: int = self.a): ...
|
||||||
self.a = inner_a
|
self.a = inner_a
|
||||||
```
|
```
|
||||||
|
|
@ -129,16 +129,16 @@ class C:
|
||||||
self.c = lambda positional_only=self.c, /: positional_only
|
self.c = lambda positional_only=self.c, /: positional_only
|
||||||
self.d = lambda *, kw_only=self.d: kw_only
|
self.d = lambda *, kw_only=self.d: kw_only
|
||||||
|
|
||||||
# revealed: (positional=Unknown | ((positional=Unknown) -> Unknown)) -> Unknown
|
# revealed: (positional=...) -> Unknown
|
||||||
reveal_type(self.a)
|
reveal_type(self.a)
|
||||||
|
|
||||||
# revealed: (*, kw_only=Unknown | ((*, kw_only=Unknown) -> Unknown)) -> Unknown
|
# revealed: (*, kw_only=...) -> Unknown
|
||||||
reveal_type(self.b)
|
reveal_type(self.b)
|
||||||
|
|
||||||
# revealed: (positional_only=Unknown | ((positional_only=Unknown, /) -> Unknown), /) -> Unknown
|
# revealed: (positional_only=..., /) -> Unknown
|
||||||
reveal_type(self.c)
|
reveal_type(self.c)
|
||||||
|
|
||||||
# revealed: (*, kw_only=Unknown | ((*, kw_only=Unknown) -> Unknown)) -> Unknown
|
# revealed: (*, kw_only=...) -> Unknown
|
||||||
reveal_type(self.d)
|
reveal_type(self.d)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -749,8 +749,8 @@ class Outer:
|
||||||
outer_a: int = outer_field(init=False)
|
outer_a: int = outer_field(init=False)
|
||||||
outer_b: str = inner_field(init=False)
|
outer_b: str = inner_field(init=False)
|
||||||
|
|
||||||
reveal_type(Outer.__init__) # revealed: (self: Outer, outer_b: str = Any) -> None
|
reveal_type(Outer.__init__) # revealed: (self: Outer, outer_b: str = ...) -> None
|
||||||
reveal_type(Outer.Inner.__init__) # revealed: (self: Inner, inner_b: str = Any) -> None
|
reveal_type(Outer.Inner.__init__) # revealed: (self: Inner, inner_b: str = ...) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overloaded dataclass-like decorators
|
## Overloaded dataclass-like decorators
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ class D:
|
||||||
y: str = "default"
|
y: str = "default"
|
||||||
z: int | None = 1 + 2
|
z: int | None = 1 + 2
|
||||||
|
|
||||||
reveal_type(D.__init__) # revealed: (self: D, x: int, y: str = Literal["default"], z: int | None = Literal[3]) -> None
|
reveal_type(D.__init__) # revealed: (self: D, x: int, y: str = "default", z: int | None = 3) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
This also works if the declaration and binding are split:
|
This also works if the declaration and binding are split:
|
||||||
|
|
@ -221,7 +221,7 @@ class D:
|
||||||
(x): int = 1
|
(x): int = 1
|
||||||
|
|
||||||
# TODO: should ideally not include a `x` parameter
|
# TODO: should ideally not include a `x` parameter
|
||||||
reveal_type(D.__init__) # revealed: (self: D, x: int = Literal[1]) -> None
|
reveal_type(D.__init__) # revealed:(self: D, x: int = 1) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
## `@dataclass` calls with arguments
|
## `@dataclass` calls with arguments
|
||||||
|
|
@ -670,7 +670,7 @@ class A:
|
||||||
a: str = field(kw_only=False)
|
a: str = field(kw_only=False)
|
||||||
b: int = 0
|
b: int = 0
|
||||||
|
|
||||||
reveal_type(A.__init__) # revealed: (self: A, a: str, *, b: int = Literal[0]) -> None
|
reveal_type(A.__init__) # revealed:(self: A, a: str, *, b: int = 0) -> None
|
||||||
|
|
||||||
A("hi")
|
A("hi")
|
||||||
```
|
```
|
||||||
|
|
@ -991,7 +991,7 @@ class C:
|
||||||
class_variable1: ClassVar[Final[int]] = 1
|
class_variable1: ClassVar[Final[int]] = 1
|
||||||
class_variable2: ClassVar[Final[int]] = 1
|
class_variable2: ClassVar[Final[int]] = 1
|
||||||
|
|
||||||
reveal_type(C.__init__) # revealed: (self: C, instance_variable_no_default: int, instance_variable: int = Literal[1]) -> None
|
reveal_type(C.__init__) # revealed:(self: C, instance_variable_no_default: int, instance_variable: int = 1) -> None
|
||||||
|
|
||||||
c = C(1)
|
c = C(1)
|
||||||
# error: [invalid-assignment] "Cannot assign to final attribute `instance_variable` on type `C`"
|
# error: [invalid-assignment] "Cannot assign to final attribute `instance_variable` on type `C`"
|
||||||
|
|
@ -1082,7 +1082,7 @@ class C(Base):
|
||||||
z: int = 10
|
z: int = 10
|
||||||
x: int = 15
|
x: int = 15
|
||||||
|
|
||||||
reveal_type(C.__init__) # revealed: (self: C, x: int = Literal[15], y: int = Literal[0], z: int = Literal[10]) -> None
|
reveal_type(C.__init__) # revealed:(self: C, x: int = 15, y: int = 0, z: int = 10) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
## Conditionally defined fields
|
## Conditionally defined fields
|
||||||
|
|
@ -1243,7 +1243,7 @@ class UppercaseString:
|
||||||
class C:
|
class C:
|
||||||
upper: UppercaseString = UppercaseString()
|
upper: UppercaseString = UppercaseString()
|
||||||
|
|
||||||
reveal_type(C.__init__) # revealed: (self: C, upper: str = str) -> None
|
reveal_type(C.__init__) # revealed: (self: C, upper: str = ...) -> None
|
||||||
|
|
||||||
c = C("abc")
|
c = C("abc")
|
||||||
reveal_type(c.upper) # revealed: str
|
reveal_type(c.upper) # revealed: str
|
||||||
|
|
@ -1289,7 +1289,7 @@ class ConvertToLength:
|
||||||
class C:
|
class C:
|
||||||
converter: ConvertToLength = ConvertToLength()
|
converter: ConvertToLength = ConvertToLength()
|
||||||
|
|
||||||
reveal_type(C.__init__) # revealed: (self: C, converter: str = Literal[""]) -> None
|
reveal_type(C.__init__) # revealed: (self: C, converter: str = "") -> None
|
||||||
|
|
||||||
c = C("abc")
|
c = C("abc")
|
||||||
reveal_type(c.converter) # revealed: int
|
reveal_type(c.converter) # revealed: int
|
||||||
|
|
@ -1328,7 +1328,7 @@ class AcceptsStrAndInt:
|
||||||
class C:
|
class C:
|
||||||
field: AcceptsStrAndInt = AcceptsStrAndInt()
|
field: AcceptsStrAndInt = AcceptsStrAndInt()
|
||||||
|
|
||||||
reveal_type(C.__init__) # revealed: (self: C, field: str | int = int) -> None
|
reveal_type(C.__init__) # revealed: (self: C, field: str | int = ...) -> None
|
||||||
```
|
```
|
||||||
|
|
||||||
## `dataclasses.field`
|
## `dataclasses.field`
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class Member:
|
||||||
role: str = field(default="user")
|
role: str = field(default="user")
|
||||||
tag: str | None = field(default=None, init=False)
|
tag: str | None = field(default=None, init=False)
|
||||||
|
|
||||||
# revealed: (self: Member, name: str, role: str = Literal["user"]) -> None
|
# revealed: (self: Member, name: str, role: str = "user") -> None
|
||||||
reveal_type(Member.__init__)
|
reveal_type(Member.__init__)
|
||||||
|
|
||||||
alice = Member(name="Alice", role="admin")
|
alice = Member(name="Alice", role="admin")
|
||||||
|
|
@ -37,7 +37,7 @@ class Data:
|
||||||
content: list[int] = field(default_factory=list)
|
content: list[int] = field(default_factory=list)
|
||||||
timestamp: datetime = field(default_factory=datetime.now, init=False)
|
timestamp: datetime = field(default_factory=datetime.now, init=False)
|
||||||
|
|
||||||
# revealed: (self: Data, content: list[int] = list[int]) -> None
|
# revealed: (self: Data, content: list[int] = ...) -> None
|
||||||
reveal_type(Data.__init__)
|
reveal_type(Data.__init__)
|
||||||
|
|
||||||
data = Data([1, 2, 3])
|
data = Data([1, 2, 3])
|
||||||
|
|
@ -63,7 +63,7 @@ class Person:
|
||||||
age: int | None = field(default=None, kw_only=True)
|
age: int | None = field(default=None, kw_only=True)
|
||||||
role: str = field(default="user", kw_only=True)
|
role: str = field(default="user", kw_only=True)
|
||||||
|
|
||||||
# revealed: (self: Person, name: str, *, age: int | None = None, role: str = Literal["user"]) -> None
|
# revealed: (self: Person, name: str, *, age: int | None = None, role: str = "user") -> None
|
||||||
reveal_type(Person.__init__)
|
reveal_type(Person.__init__)
|
||||||
|
|
||||||
alice = Person(role="admin", name="Alice")
|
alice = Person(role="admin", name="Alice")
|
||||||
|
|
|
||||||
|
|
@ -591,9 +591,9 @@ try:
|
||||||
reveal_type(x) # revealed: B | D
|
reveal_type(x) # revealed: B | D
|
||||||
reveal_type(x) # revealed: B | D
|
reveal_type(x) # revealed: B | D
|
||||||
x = foo
|
x = foo
|
||||||
reveal_type(x) # revealed: def foo(param=A) -> Unknown
|
reveal_type(x) # revealed: def foo(param=...) -> Unknown
|
||||||
except:
|
except:
|
||||||
reveal_type(x) # revealed: Literal[1] | (def foo(param=A) -> Unknown)
|
reveal_type(x) # revealed: Literal[1] | (def foo(param=...) -> Unknown)
|
||||||
|
|
||||||
class Bar:
|
class Bar:
|
||||||
x = could_raise_returns_E()
|
x = could_raise_returns_E()
|
||||||
|
|
@ -603,9 +603,9 @@ except:
|
||||||
reveal_type(x) # revealed: <class 'Bar'>
|
reveal_type(x) # revealed: <class 'Bar'>
|
||||||
finally:
|
finally:
|
||||||
# TODO: should be `Literal[1] | <class 'foo'> | <class '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=...) -> Unknown) | <class 'Bar'>
|
||||||
|
|
||||||
reveal_type(x) # revealed: (def foo(param=A) -> Unknown) | <class 'Bar'>
|
reveal_type(x) # revealed: (def foo(param=...) -> Unknown) | <class 'Bar'>
|
||||||
```
|
```
|
||||||
|
|
||||||
[1]: https://astral-sh.notion.site/Exception-handler-control-flow-11348797e1ca80bb8ce1e9aedbbe439d
|
[1]: https://astral-sh.notion.site/Exception-handler-control-flow-11348797e1ca80bb8ce1e9aedbbe439d
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ reveal_type(lambda a, b: a + b) # revealed: (a, b) -> Unknown
|
||||||
But, it can have default values:
|
But, it can have default values:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(lambda a=1: a) # revealed: (a=Literal[1]) -> Unknown
|
reveal_type(lambda a=1: a) # revealed: (a=1) -> Unknown
|
||||||
reveal_type(lambda a, b=2: a) # revealed: (a, b=Literal[2]) -> Unknown
|
reveal_type(lambda a, b=2: a) # revealed: (a, b=2) -> Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
And, positional-only parameters:
|
And, positional-only parameters:
|
||||||
|
|
@ -37,7 +37,7 @@ reveal_type(lambda a, b, /, c: c) # revealed: (a, b, /, c) -> Unknown
|
||||||
And, keyword-only parameters:
|
And, keyword-only parameters:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(lambda a, *, b=2, c: b) # revealed: (a, *, b=Literal[2], c) -> Unknown
|
reveal_type(lambda a, *, b=2, c: b) # revealed: (a, *, b=2, c) -> Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
And, variadic parameter:
|
And, variadic parameter:
|
||||||
|
|
@ -55,7 +55,7 @@ reveal_type(lambda **kwargs: kwargs) # revealed: (**kwargs) -> Unknown
|
||||||
Mixing all of them together:
|
Mixing all of them together:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
# revealed: (a, b, /, c=Literal[True], *args, *, d=Literal["default"], e=Literal[5], **kwargs) -> Unknown
|
# revealed: (a, b, /, c=True, *args, *, d="default", e=5, **kwargs) -> Unknown
|
||||||
reveal_type(lambda a, b, /, c=True, *args, d="default", e=5, **kwargs: None)
|
reveal_type(lambda a, b, /, c=True, *args, d="default", e=5, **kwargs: None)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ Here, a `lambda` expression is used as the default value for a parameter in anot
|
||||||
expression.
|
expression.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
reveal_type(lambda a=lambda x, y: 0: 2) # revealed: (a=(x, y) -> Unknown) -> Unknown
|
reveal_type(lambda a=lambda x, y: 0: 2) # revealed: (a=...) -> Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
## Assignment
|
## Assignment
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class Product(BaseModel):
|
||||||
name: str = Field(..., kw_only=False, min_length=1)
|
name: str = Field(..., kw_only=False, min_length=1)
|
||||||
internal_price_cent: int = Field(..., gt=0, alias="price_cent")
|
internal_price_cent: int = Field(..., gt=0, alias="price_cent")
|
||||||
|
|
||||||
reveal_type(Product.__init__) # revealed: (self: Product, name: str = Any, *, price_cent: int = Any) -> None
|
reveal_type(Product.__init__) # revealed: (self: Product, name: str = ..., *, price_cent: int = ...) -> None
|
||||||
|
|
||||||
product = Product("Laptop", price_cent=999_00)
|
product = Product("Laptop", price_cent=999_00)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class User:
|
||||||
id: int
|
id: int
|
||||||
role: str = strawberry.field(default="user")
|
role: str = strawberry.field(default="user")
|
||||||
|
|
||||||
reveal_type(User.__init__) # revealed: (self: User, *, id: int, role: str = Any) -> None
|
reveal_type(User.__init__) # revealed: (self: User, *, id: int, role: str = ...) -> None
|
||||||
|
|
||||||
user = User(id=1)
|
user = User(id=1)
|
||||||
reveal_type(user.id) # revealed: int
|
reveal_type(user.id) # revealed: int
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,7 @@ def keyword_only_with_default_2(*, y: int = 42) -> int:
|
||||||
# parameter list i.e., `()`
|
# parameter list i.e., `()`
|
||||||
# TODO: This shouldn't error
|
# TODO: This shouldn't error
|
||||||
# error: [invalid-argument-type]
|
# error: [invalid-argument-type]
|
||||||
# revealed: (*, x: int = Literal[42]) -> bool
|
# revealed: (*, x: int = 42) -> bool
|
||||||
reveal_type(multiple(keyword_only_with_default_1, keyword_only_with_default_2))
|
reveal_type(multiple(keyword_only_with_default_1, keyword_only_with_default_2))
|
||||||
|
|
||||||
def keyword_only1(*, x: int) -> int:
|
def keyword_only1(*, x: int) -> int:
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ inside the module:
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
reveal_type(typing.__name__) # revealed: str
|
reveal_type(typing.__name__) # revealed: str
|
||||||
reveal_type(typing.__init__) # revealed: bound method ModuleType.__init__(name: str, doc: str | None = EllipsisType) -> None
|
reveal_type(typing.__init__) # revealed: bound method ModuleType.__init__(name: str, doc: str | None = ...) -> None
|
||||||
|
|
||||||
# For a stub module, we don't know that `__file__` is a string (at runtime it may be entirely
|
# For a stub module, we don't know that `__file__` is a string (at runtime it may be entirely
|
||||||
# unset, but we follow typeshed here):
|
# unset, but we follow typeshed here):
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ error[missing-argument]: No argument provided for required parameter `a` of func
|
||||||
13 |
|
13 |
|
||||||
14 | Foo().method() # error: [missing-argument]
|
14 | Foo().method() # error: [missing-argument]
|
||||||
|
|
|
|
||||||
info: Union variant `def f(a, b=Literal[42]) -> Unknown` is incompatible with this call site
|
info: Union variant `def f(a, b=42) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `missing-argument` is enabled by default
|
info: rule `missing-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -91,7 +91,7 @@ error[missing-argument]: No argument provided for required parameter `a` of func
|
||||||
14 | Foo().method() # error: [missing-argument]
|
14 | Foo().method() # error: [missing-argument]
|
||||||
|
|
|
|
||||||
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `missing-argument` is enabled by default
|
info: rule `missing-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ error[too-many-positional-arguments]: Too many positional arguments to function
|
||||||
13 |
|
13 |
|
||||||
14 | Foo().method(1, 2) # error: [too-many-positional-arguments]
|
14 | Foo().method(1, 2) # error: [too-many-positional-arguments]
|
||||||
|
|
|
|
||||||
info: Union variant `def f(a, b=Literal[42]) -> Unknown` is incompatible with this call site
|
info: Union variant `def f(a, b=42) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `too-many-positional-arguments` is enabled by default
|
info: rule `too-many-positional-arguments` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -91,7 +91,7 @@ error[too-many-positional-arguments]: Too many positional arguments to function
|
||||||
14 | Foo().method(1, 2) # error: [too-many-positional-arguments]
|
14 | Foo().method(1, 2) # error: [too-many-positional-arguments]
|
||||||
|
|
|
|
||||||
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `too-many-positional-arguments` is enabled by default
|
info: rule `too-many-positional-arguments` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ error[unknown-argument]: Argument `d` does not match any known parameter of func
|
||||||
13 |
|
13 |
|
||||||
14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument]
|
14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument]
|
||||||
|
|
|
|
||||||
info: Union variant `def f(a, b, c=Literal[42]) -> Unknown` is incompatible with this call site
|
info: Union variant `def f(a, b, c=42) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b, c=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b, c=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `unknown-argument` is enabled by default
|
info: rule `unknown-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -91,7 +91,7 @@ error[unknown-argument]: Argument `d` does not match any known parameter of func
|
||||||
14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument]
|
14 | Foo().method(a=1, b=2, c=3) # error: [unknown-argument]
|
||||||
|
|
|
|
||||||
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
info: Union variant `def g(a, b) -> Unknown` is incompatible with this call site
|
||||||
info: Attempted to call union type `(def f(a, b, c=Literal[42]) -> Unknown) | (def g(a, b) -> Unknown)`
|
info: Attempted to call union type `(def f(a, b, c=42) -> Unknown) | (def g(a, b) -> Unknown)`
|
||||||
info: rule `unknown-argument` is enabled by default
|
info: rule `unknown-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ class Person:
|
||||||
|
|
||||||
metadata: InitVar[str] = "default"
|
metadata: InitVar[str] = "default"
|
||||||
|
|
||||||
reveal_type(Person.__init__) # revealed: (self: Person, name: str, age: int, metadata: str = Literal["default"]) -> None
|
reveal_type(Person.__init__) # revealed: (self: Person, name: str, age: int, metadata: str = "default") -> None
|
||||||
|
|
||||||
alice = Person("Alice", 30)
|
alice = Person("Alice", 30)
|
||||||
bob = Person("Bob", 25, "custom metadata")
|
bob = Person("Bob", 25, "custom metadata")
|
||||||
|
|
|
||||||
|
|
@ -1838,15 +1838,39 @@ impl<'db> FmtDetailed<'db> for DisplayParameter<'_, 'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Default value can only be specified if `name` is given.
|
// Default value can only be specified if `name` is given.
|
||||||
if let Some(default_ty) = self.param.default_type() {
|
if let Some(default_type) = self.param.default_type() {
|
||||||
if self.param.annotated_type().is_some() {
|
if self.param.annotated_type().is_some() {
|
||||||
f.write_str(" = ")?;
|
f.write_str(" = ")?;
|
||||||
} else {
|
} else {
|
||||||
f.write_str("=")?;
|
f.write_str("=")?;
|
||||||
}
|
}
|
||||||
default_ty
|
match default_type {
|
||||||
.display_with(self.db, self.settings.clone())
|
Type::IntLiteral(_)
|
||||||
.fmt_detailed(f)?;
|
| Type::BooleanLiteral(_)
|
||||||
|
| Type::StringLiteral(_)
|
||||||
|
| Type::EnumLiteral(_)
|
||||||
|
| Type::BytesLiteral(_) => {
|
||||||
|
// For Literal types display the value without `Literal[..]` wrapping
|
||||||
|
let representation =
|
||||||
|
default_type.representation(self.db, self.settings.clone());
|
||||||
|
representation.fmt_detailed(f)?;
|
||||||
|
}
|
||||||
|
Type::NominalInstance(instance) => {
|
||||||
|
// Some key default types like `None` are worth showing
|
||||||
|
let class = instance.class(self.db);
|
||||||
|
|
||||||
|
match (class, class.known(self.db)) {
|
||||||
|
(_, Some(KnownClass::NoneType)) => {
|
||||||
|
f.with_type(default_type).write_str("None")?;
|
||||||
|
}
|
||||||
|
(_, Some(KnownClass::NoDefaultType)) => {
|
||||||
|
f.with_type(default_type).write_str("NoDefault")?;
|
||||||
|
}
|
||||||
|
_ => f.write_str("...")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => f.write_str("...")?,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(ty) = self.param.annotated_type() {
|
} else if let Some(ty) = self.param.annotated_type() {
|
||||||
// This case is specifically for the `Callable` signature where name and default value
|
// This case is specifically for the `Callable` signature where name and default value
|
||||||
|
|
@ -2598,7 +2622,7 @@ mod tests {
|
||||||
],
|
],
|
||||||
Some(Type::none(&db))
|
Some(Type::none(&db))
|
||||||
),
|
),
|
||||||
@"(x=int, y: str = str) -> None"
|
@"(x=..., y: str = ...) -> None"
|
||||||
);
|
);
|
||||||
|
|
||||||
// All positional only parameters.
|
// All positional only parameters.
|
||||||
|
|
@ -2683,9 +2707,7 @@ mod tests {
|
||||||
],
|
],
|
||||||
Some(KnownClass::Bytes.to_instance(&db))
|
Some(KnownClass::Bytes.to_instance(&db))
|
||||||
),
|
),
|
||||||
@"(a, b: int, c=Literal[1], d: int = Literal[2], \
|
@"(a, b: int, c=1, d: int = 2, /, e=3, f: int = 4, *args: object, *, g=5, h: int = 6, **kwargs: str) -> bytes"
|
||||||
/, e=Literal[3], f: int = Literal[4], *args: object, \
|
|
||||||
*, g=Literal[5], h: int = Literal[6], **kwargs: str) -> bytes"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2727,8 +2749,8 @@ mod tests {
|
||||||
),
|
),
|
||||||
@r"
|
@r"
|
||||||
(
|
(
|
||||||
x=int,
|
x=...,
|
||||||
y: str = str
|
y: str = ...
|
||||||
) -> None
|
) -> None
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
@ -2843,15 +2865,15 @@ mod tests {
|
||||||
(
|
(
|
||||||
a,
|
a,
|
||||||
b: int,
|
b: int,
|
||||||
c=Literal[1],
|
c=1,
|
||||||
d: int = Literal[2],
|
d: int = 2,
|
||||||
/,
|
/,
|
||||||
e=Literal[3],
|
e=3,
|
||||||
f: int = Literal[4],
|
f: int = 4,
|
||||||
*args: object,
|
*args: object,
|
||||||
*,
|
*,
|
||||||
g=Literal[5],
|
g=5,
|
||||||
h: int = Literal[6],
|
h: int = 6,
|
||||||
**kwargs: str
|
**kwargs: str
|
||||||
) -> bytes
|
) -> bytes
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ expression: signature_help
|
||||||
{
|
{
|
||||||
"signatures": [
|
"signatures": [
|
||||||
{
|
{
|
||||||
"label": "(pattern: str | Pattern[str], string: str, flags: int = Literal[0]) -> Match[str] | None",
|
"label": "(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None",
|
||||||
"documentation": "Try to apply the pattern at the start of the string, returning/na Match object, or None if no match was found.\n",
|
"documentation": "Try to apply the pattern at the start of the string, returning/na Match object, or None if no match was found.\n",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
|
|
@ -15,12 +15,12 @@ expression: signature_help
|
||||||
"label": "string: str"
|
"label": "string: str"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "flags: int = Literal[0]"
|
"label": "flags: int = 0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "(pattern: bytes | Pattern[bytes], string: Buffer, flags: int = Literal[0]) -> Match[bytes] | None",
|
"label": "(pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"label": "pattern: bytes | Pattern[bytes]"
|
"label": "pattern: bytes | Pattern[bytes]"
|
||||||
|
|
@ -29,7 +29,7 @@ expression: signature_help
|
||||||
"label": "string: Buffer"
|
"label": "string: Buffer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "flags: int = Literal[0]"
|
"label": "flags: int = 0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue