Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions crates/ty_ide/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,13 +1759,13 @@ C.<CURSOR>
__name__ :: str
__ne__ :: def __ne__(self, value: object, /) -> bool
__new__ :: def __new__(cls) -> Self@__new__
__or__ :: bound method <class 'C'>.__or__(value: Any, /) -> UnionType
__or__ :: bound method <class 'C'>.__or__[Self](value: Any, /) -> UnionType | Self@__or__
__prepare__ :: bound method <class 'Meta'>.__prepare__(name: str, bases: tuple[type, ...], /, **kwds: Any) -> MutableMapping[str, object]
__qualname__ :: str
__reduce__ :: def __reduce__(self) -> str | tuple[Any, ...]
__reduce_ex__ :: def __reduce_ex__(self, protocol: SupportsIndex, /) -> str | tuple[Any, ...]
__repr__ :: def __repr__(self) -> str
__ror__ :: bound method <class 'C'>.__ror__(value: Any, /) -> UnionType
__ror__ :: bound method <class 'C'>.__ror__[Self](value: Any, /) -> UnionType | Self@__ror__
__setattr__ :: def __setattr__(self, name: str, value: Any, /) -> None
__sizeof__ :: def __sizeof__(self) -> int
__str__ :: def __str__(self) -> str
Expand Down Expand Up @@ -1827,13 +1827,13 @@ Meta.<CURSOR>
__mro__ :: tuple[<class 'Meta'>, <class 'type'>, <class 'object'>]
__name__ :: str
__ne__ :: def __ne__(self, value: object, /) -> bool
__or__ :: def __or__(self, value: Any, /) -> UnionType
__or__ :: def __or__[Self](self: Self@__or__, value: Any, /) -> UnionType | Self@__or__
__prepare__ :: bound method <class 'Meta'>.__prepare__(name: str, bases: tuple[type, ...], /, **kwds: Any) -> MutableMapping[str, object]
__qualname__ :: str
__reduce__ :: def __reduce__(self) -> str | tuple[Any, ...]
__reduce_ex__ :: def __reduce_ex__(self, protocol: SupportsIndex, /) -> str | tuple[Any, ...]
__repr__ :: def __repr__(self) -> str
__ror__ :: def __ror__(self, value: Any, /) -> UnionType
__ror__ :: def __ror__[Self](self: Self@__ror__, value: Any, /) -> UnionType | Self@__ror__
__setattr__ :: def __setattr__(self, name: str, value: Any, /) -> None
__sizeof__ :: def __sizeof__(self) -> int
__str__ :: def __str__(self) -> str
Expand Down Expand Up @@ -1936,13 +1936,13 @@ Quux.<CURSOR>
__name__ :: str
__ne__ :: def __ne__(self, value: object, /) -> bool
__new__ :: def __new__(cls) -> Self@__new__
__or__ :: bound method <class 'Quux'>.__or__(value: Any, /) -> UnionType
__or__ :: bound method <class 'Quux'>.__or__[Self](value: Any, /) -> UnionType | Self@__or__
__prepare__ :: bound method <class 'type'>.__prepare__(name: str, bases: tuple[type, ...], /, **kwds: Any) -> MutableMapping[str, object]
__qualname__ :: str
__reduce__ :: def __reduce__(self) -> str | tuple[Any, ...]
__reduce_ex__ :: def __reduce_ex__(self, protocol: SupportsIndex, /) -> str | tuple[Any, ...]
__repr__ :: def __repr__(self) -> str
__ror__ :: bound method <class 'Quux'>.__ror__(value: Any, /) -> UnionType
__ror__ :: bound method <class 'Quux'>.__ror__[Self](value: Any, /) -> UnionType | Self@__ror__
__setattr__ :: def __setattr__(self, name: str, value: Any, /) -> None
__sizeof__ :: def __sizeof__(self) -> int
__str__ :: def __str__(self) -> str
Expand Down Expand Up @@ -2013,14 +2013,14 @@ Answer.<CURSOR>
__name__ :: str
__ne__ :: def __ne__(self, value: object, /) -> bool
__new__ :: def __new__(cls, value: object) -> Self@__new__
__or__ :: bound method <class 'Answer'>.__or__(value: Any, /) -> UnionType
__or__ :: bound method <class 'Answer'>.__or__[Self](value: Any, /) -> UnionType | Self@__or__
__order__ :: str
__prepare__ :: bound method <class 'EnumMeta'>.__prepare__(cls: str, bases: tuple[type, ...], **kwds: Any) -> _EnumDict
__qualname__ :: str
__reduce__ :: def __reduce__(self) -> str | tuple[Any, ...]
__repr__ :: def __repr__(self) -> str
__reversed__ :: bound method <class 'Answer'>.__reversed__[_EnumMemberT]() -> Iterator[_EnumMemberT@__reversed__]
__ror__ :: bound method <class 'Answer'>.__ror__(value: Any, /) -> UnionType
__ror__ :: bound method <class 'Answer'>.__ror__[Self](value: Any, /) -> UnionType | Self@__ror__
__setattr__ :: def __setattr__(self, name: str, value: Any, /) -> None
__sizeof__ :: def __sizeof__(self) -> int
__str__ :: def __str__(self) -> str
Expand Down
80 changes: 40 additions & 40 deletions crates/ty_ide/src/goto_type_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,13 @@ mod tests {

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:4:1
Expand All @@ -227,13 +227,13 @@ mod tests {

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:2:10
Expand Down Expand Up @@ -324,13 +324,13 @@ mod tests {

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:4:6
Expand Down Expand Up @@ -358,13 +358,13 @@ mod tests {
// is an int. Navigating to `str` would match pyright's behavior.
assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:344:7
--> stdlib/builtins.pyi:346:7
|
343 | @disjoint_base
344 | class int:
345 | @disjoint_base
346 | class int:
| ^^^
345 | """int([x]) -> integer
346 | int(x, base=10) -> integer
347 | """int([x]) -> integer
348 | int(x, base=10) -> integer
|
info: Source
--> main.py:4:6
Expand All @@ -391,13 +391,13 @@ f(**kwargs<CURSOR>)

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:2916:7
--> stdlib/builtins.pyi:2918:7
|
2915 | @disjoint_base
2916 | class dict(MutableMapping[_KT, _VT]):
2917 | @disjoint_base
2918 | class dict(MutableMapping[_KT, _VT]):
| ^^^^
2917 | """dict() -> new empty dictionary
2918 | dict(mapping) -> new dictionary initialized from a mapping object's
2919 | """dict() -> new empty dictionary
2920 | dict(mapping) -> new dictionary initialized from a mapping object's
|
info: Source
--> main.py:6:5
Expand All @@ -421,13 +421,13 @@ f(**kwargs<CURSOR>)

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:3:5
Expand Down Expand Up @@ -513,13 +513,13 @@ f(**kwargs<CURSOR>)

assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:4:15
Expand Down Expand Up @@ -560,13 +560,13 @@ f(**kwargs<CURSOR>)
|

info[goto-type-definition]: Type definition
--> stdlib/builtins.pyi:911:7
--> stdlib/builtins.pyi:913:7
|
910 | @disjoint_base
911 | class str(Sequence[str]):
912 | @disjoint_base
913 | class str(Sequence[str]):
| ^^^
912 | """str(object='') -> str
913 | str(bytes_or_buffer[, encoding[, errors]]) -> str
914 | """str(object='') -> str
915 | str(bytes_or_buffer[, encoding[, errors]]) -> str
|
info: Source
--> main.py:3:5
Expand Down
2 changes: 1 addition & 1 deletion crates/ty_python_semantic/resources/mdtest/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,7 @@ All attribute access on literal `bytes` types is currently delegated to `builtin
```py
# revealed: bound method Literal[b"foo"].join(iterable_of_bytes: Iterable[@Todo(Support for `typing.TypeAlias`)], /) -> bytes
reveal_type(b"foo".join)
# revealed: bound method Literal[b"foo"].endswith(suffix: @Todo(Support for `typing.TypeAlias`) | tuple[@Todo(Support for `typing.TypeAlias`), ...], start: SupportsIndex | None = EllipsisType, end: SupportsIndex | None = EllipsisType, /) -> bool
# revealed: bound method Literal[b"foo"].endswith(suffix: @Todo(Support for `typing.TypeAlias`) | tuple[@Todo(Support for `typing.TypeAlias`), ...], start: SupportsIndex | None = None, end: SupportsIndex | None = None, /) -> bool
reveal_type(b"foo".endswith)
```

Expand Down
24 changes: 24 additions & 0 deletions crates/ty_python_semantic/resources/mdtest/binary/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,27 @@ class B: ...
# error: "Operator `|` is unsupported between objects of type `<class 'A'>` and `<class 'B'>`"
reveal_type(A | B) # revealed: Unknown
```

## Other binary operations resulting in `UnionType`

```toml
[environment]
python-version = "3.12"
```

```py
class A: ...
class B: ...

def _(sub_a: type[A], sub_b: type[B]):
reveal_type(A | sub_b) # revealed: UnionType
reveal_type(sub_a | B) # revealed: UnionType
reveal_type(sub_a | sub_b) # revealed: UnionType

class C[T]: ...
class D[T]: ...

reveal_type(C | D) # revealed: UnionType

reveal_type(C[int] | D[str]) # revealed: UnionType
```
6 changes: 3 additions & 3 deletions crates/ty_python_semantic/resources/mdtest/call/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ static_assert(is_assignable_to(TypeOf[property.__set__], Callable))
reveal_type(MyClass.my_property.__set__)
static_assert(is_assignable_to(TypeOf[MyClass.my_property.__set__], Callable))

# revealed: def startswith(self, prefix: str | tuple[str, ...], start: SupportsIndex | None = EllipsisType, end: SupportsIndex | None = EllipsisType, /) -> bool
# revealed: def startswith(self, prefix: str | tuple[str, ...], start: SupportsIndex | None = None, end: SupportsIndex | None = None, /) -> bool
reveal_type(str.startswith)
static_assert(is_assignable_to(TypeOf[str.startswith], Callable))

Expand Down Expand Up @@ -689,7 +689,7 @@ def _(
# revealed: (obj: type) -> None
reveal_type(e)

# revealed: (fget: ((Any, /) -> Any) | None = EllipsisType, fset: ((Any, Any, /) -> None) | None = EllipsisType, fdel: ((Any, /) -> None) | None = EllipsisType, doc: str | None = EllipsisType) -> property
# revealed: (fget: ((Any, /) -> Any) | None = None, fset: ((Any, Any, /) -> None) | None = None, fdel: ((Any, /) -> None) | None = None, doc: str | None = None) -> property
reveal_type(f)

# revealed: Overload[(self: property, instance: None, owner: type, /) -> Unknown, (self: property, instance: object, owner: type | None = None, /) -> Unknown]
Expand All @@ -707,7 +707,7 @@ def _(
# revealed: (instance: object, value: object, /) -> Unknown
reveal_type(j)

# revealed: (self, prefix: str | tuple[str, ...], start: SupportsIndex | None = EllipsisType, end: SupportsIndex | None = EllipsisType, /) -> bool
# revealed: (self, prefix: str | tuple[str, ...], start: SupportsIndex | None = None, end: SupportsIndex | None = None, /) -> bool
reveal_type(k)

# revealed: (prefix: str | tuple[str, ...], start: SupportsIndex | None = None, end: SupportsIndex | None = None, /) -> bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ error[invalid-await]: `Literal[1]` is not awaitable
2 | await 1 # error: [invalid-await]
| ^
|
::: stdlib/builtins.pyi:344:7
::: stdlib/builtins.pyi:346:7
|
343 | @disjoint_base
344 | class int:
345 | @disjoint_base
346 | class int:
| --- type defined here
345 | """int([x]) -> integer
346 | int(x, base=10) -> integer
347 | """int([x]) -> integer
348 | int(x, base=10) -> integer
|
info: `__await__` is missing
info: rule `invalid-await` is enabled by default
Expand Down
15 changes: 15 additions & 0 deletions crates/ty_python_semantic/src/types/infer/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7957,6 +7957,21 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
)))
}

// Special-case `X | Y` with `X` and `Y` instances of `type` to produce a `types.UnionType` instance, in order to
// overwrite the typeshed return type for `type.__or__`, which would result in `types.UnionType | X`. We currently
// do this to avoid false positives when a legacy type alias like `IntOrStr = int | str` is later used in a type
// expression, because `types.UnionType` will result in a `@Todo` type, while `types.UnionType | <class 'int'>` does
// not.
//
// TODO: Remove this special case once we add support for legacy type aliases.
(
Type::ClassLiteral(..) | Type::SubclassOf(..) | Type::GenericAlias(..),
Type::ClassLiteral(..) | Type::SubclassOf(..) | Type::GenericAlias(..),
ast::Operator::BitOr,
) if Program::get(self.db()).python_version(self.db()) >= PythonVersion::PY310 => {
Some(KnownClass::UnionType.to_instance(self.db()))
}

// We've handled all of the special cases that we support for literals, so we need to
// fall back on looking for dunder methods on one of the operand types.
(
Expand Down
2 changes: 1 addition & 1 deletion crates/ty_vendored/vendor/typeshed/source_commit.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
91055c730ffcda6311654cf32d663858ece69bad
d6f4a0f7102b1400a21742cf9b7ea93614e2b6ec
7 changes: 4 additions & 3 deletions crates/ty_vendored/vendor/typeshed/stdlib/_csv.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ else:
def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ...

def writer(
csvfile: SupportsWrite[str],
fileobj: SupportsWrite[str],
/,
dialect: _DialectLike = "excel",
*,
Expand Down Expand Up @@ -164,7 +164,7 @@ def writer(
"""

def reader(
csvfile: Iterable[str],
iterable: Iterable[str],
/,
dialect: _DialectLike = "excel",
*,
Expand Down Expand Up @@ -194,7 +194,8 @@ def reader(

def register_dialect(
name: str,
dialect: type[Dialect | csv.Dialect] = ...,
/,
dialect: type[Dialect | csv.Dialect] | str = "excel",
*,
delimiter: str = ",",
quotechar: str | None = '"',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class SourceLoader(_LoaderBasics):
"""

def source_to_code(
self, data: ReadableBuffer | str | _ast.Module | _ast.Expression | _ast.Interactive, path: ReadableBuffer | StrPath
self, data: ReadableBuffer | str | _ast.Module | _ast.Expression | _ast.Interactive, path: bytes | StrPath
) -> types.CodeType:
"""Return the code object compiled from source.

Expand Down Expand Up @@ -281,10 +281,10 @@ class FileLoader:
def get_data(self, path: str) -> bytes:
"""Return the data from path as raw bytes."""

def get_filename(self, name: str | None = None) -> str:
def get_filename(self, fullname: str | None = None) -> str:
"""Return the path to the source file as found by the finder."""

def load_module(self, name: str | None = None) -> types.ModuleType:
def load_module(self, fullname: str | None = None) -> types.ModuleType:
"""Load a module from a file.

This method is deprecated. Use exec_module() instead.
Expand All @@ -311,7 +311,7 @@ class SourceFileLoader(importlib.abc.FileLoader, FileLoader, importlib.abc.Sourc
def source_to_code( # type: ignore[override] # incompatible with InspectLoader.source_to_code
self,
data: ReadableBuffer | str | _ast.Module | _ast.Expression | _ast.Interactive,
path: ReadableBuffer | StrPath,
path: bytes | StrPath,
*,
_optimize: int = -1,
) -> types.CodeType:
Expand All @@ -335,7 +335,7 @@ class ExtensionFileLoader(FileLoader, _LoaderBasics, importlib.abc.ExecutionLoad
"""

def __init__(self, name: str, path: str) -> None: ...
def get_filename(self, name: str | None = None) -> str:
def get_filename(self, fullname: str | None = None) -> str:
"""Return the path to the source file as found by the finder."""

def get_source(self, fullname: str) -> None:
Expand Down
Loading
Loading