mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-86002 Disable "python.typing.strict.unions" and revert the tests updated for PY-24834 in 253
(cherry picked from commit 3df7847e2f94e8368e15e331f16a2254154e63fa) IJ-MR-184619 GitOrigin-RevId: 213aedec5242143c1456450c214deb6f6e0fd60e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cd1307bcc5
commit
fd524cbe67
@@ -683,7 +683,7 @@
|
||||
<registryKey key="python.activate.virtualenv.on.run" defaultValue="true"
|
||||
description="Whether enabled activates virtualenv before script execution and passes environment to the process"/>
|
||||
|
||||
<registryKey key="python.typing.strict.unions" defaultValue="true" description="Enable strict union types semantics"/>
|
||||
<registryKey key="python.typing.strict.unions" defaultValue="false" description="Enable strict union types semantics"/>
|
||||
|
||||
<!-- uv -->
|
||||
<configurationType implementation="com.jetbrains.python.sdk.uv.run.UvRunConfigurationType"/>
|
||||
|
||||
@@ -5,7 +5,7 @@ def test(p1):
|
||||
for x in <warning descr="Expected type 'collections.Iterable', got 'int' instead">42</warning>:
|
||||
pass
|
||||
|
||||
for x in <warning descr="Expected type 'collections.Iterable', got 'Union[int, Any]' instead">f('foo', p1)</warning>:
|
||||
for x in f('foo', p1):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ KWARGS = {
|
||||
"little_list": ['WORLD_RET_BP_IMPALA_AB.Control', 'WORLD_RET_BP_IMPALA_AB.Impala_WS'],
|
||||
}
|
||||
|
||||
for element in <warning descr="Expected type 'collections.Iterable', got 'Union[bool, List[str]]' instead">KWARGS["little_list"]</warning>:
|
||||
for element in KWARGS["little_list"]:
|
||||
print(element)
|
||||
+2
-1
@@ -15,4 +15,5 @@ list_union_literal_incorrect: List[Union[L2, L1]] = <warning descr="Expected typ
|
||||
list_union_literal_incorrect: List[Union[L2, L1]] = <warning descr="Expected type 'list[Literal['a', 'b', 5, 'test']]', got 'list[Literal['a', 'r']]' instead">['a', 'r']</warning>
|
||||
|
||||
list_tuple: List[Tuple[L2, L1]] = [('b', 'test'), (5, 'test')]
|
||||
list_tuple_incorrect: List[Tuple[L2, L1]] = <warning descr="Expected type 'list[tuple[Literal['a', 'b', 5], Literal['test']]]', got 'list[tuple[Literal['a']] | tuple[Literal[5], Literal['test']]]' instead">[('a',), (5, 'test')]</warning>
|
||||
# TODO false negative due to PY-24834
|
||||
list_tuple_incorrect: List[Tuple[L2, L1]] = [('a',), (5, 'test')]
|
||||
@@ -14,8 +14,8 @@ def test():
|
||||
x1 = f1()
|
||||
x2 = f2()
|
||||
x3 = 1
|
||||
f(<warning descr="Expected type 'Union[int, str, list]', got 'Optional[int]' instead">x1</warning>)
|
||||
f(<warning descr="Expected type 'Union[int, str, list]', got 'Union[int, str, None]' instead">x2</warning>)
|
||||
f(x1) # Weaker union types
|
||||
f(x2) # Weaker union types
|
||||
f(x3)
|
||||
if x1:
|
||||
f(x1)
|
||||
|
||||
+2
-1
@@ -15,4 +15,5 @@ set_union_literal_incorrect: Set[Union[L2, L1]] = <warning descr="Expected type
|
||||
set_union_literal_incorrect2: Set[Union[L2, L1]] = <warning descr="Expected type 'set[Literal['a', 'b', 5, 'test']]', got 'set[Literal['a', 'r']]' instead">{'a', 'r'}</warning>
|
||||
|
||||
set_of_tuple_and_list: Set[Union[Tuple[L2, L1], List[L1]]] = {('b', 'test'), ['test', 'test'], (5, 'test')}
|
||||
set_of_tuple_and_list_incorrect: Set[Union[Tuple[L2, L1], List[L1]]] = <warning descr="Expected type 'set[tuple[Literal['a', 'b', 5], Literal['test']] | list[Literal['test']]]', got 'set[tuple[Literal['b'], Literal['r']] | list[Literal['test']] | tuple[Literal[5], Literal['test']]]' instead">{('b', 'r'), ['test', 'test'], (5, 'test')}</warning>
|
||||
# TODO false negative due to PY-24834
|
||||
set_of_tuple_and_list_incorrect: Set[Union[Tuple[L2, L1], List[L1]]] = {('b', 'r'), ['test', 'test'], (5, 'test')}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
class A:
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return 42
|
||||
|
||||
|
||||
class B:
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return 42
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
def all_union_members_match_no_any(iterable: A | B):
|
||||
for _ in iterable:
|
||||
pass
|
||||
|
||||
|
||||
def some_union_members_match_no_any(iterable: A | B | None):
|
||||
for _ in <warning descr="Expected type 'collections.Iterable', got 'A | B | None' instead">iterable</warning>:
|
||||
pass
|
||||
|
||||
|
||||
def all_union_members_dont_match_no_any(iterable: C | None):
|
||||
for _ in <warning descr="Expected type 'collections.Iterable', got 'C | None' instead">iterable</warning>:
|
||||
pass
|
||||
|
||||
|
||||
def all_union_members_match_with_any(iterable: A | B | Any):
|
||||
for _ in iterable:
|
||||
pass
|
||||
|
||||
|
||||
def some_union_members_match_with_any(iterable: A | B | None | Any):
|
||||
for _ in <warning descr="Expected type 'collections.Iterable', got 'A | B | None | Any' instead">iterable</warning>:
|
||||
pass
|
||||
|
||||
|
||||
def all_union_members_dont_match_with_any(iterable: C | None | Any):
|
||||
for _ in <warning descr="Expected type 'collections.Iterable', got 'C | None | Any' instead">iterable</warning>:
|
||||
pass
|
||||
@@ -37,8 +37,8 @@ def test():
|
||||
:type x: int or str
|
||||
"""
|
||||
x_1 = f_1()
|
||||
print_int(<warning descr="Expected type 'int', got 'Union[int, str, None]' instead">x_1</warning>)
|
||||
print_int_or_str(<warning descr="Expected type 'Union[int, str]', got 'Union[int, str, None]' instead">x_1</warning>)
|
||||
print_int(x_1) # Weaker union types
|
||||
print_int_or_str(x_1) # Weaker union types
|
||||
if isinstance(x_1, int):
|
||||
print_int(x_1)
|
||||
if isinstance(x_1, str):
|
||||
|
||||
@@ -16,7 +16,7 @@ def test(c):
|
||||
:type x: int
|
||||
"""
|
||||
x1 = f1(c)
|
||||
f2(<warning descr="Expected type 'str', got 'Union[List[Any], str, None]' instead">x1</warning>)
|
||||
f2(x1) # Weaker union types
|
||||
f3(<warning descr="Expected type 'int', got 'Union[List[Any], str, None]' instead">x1</warning>)
|
||||
|
||||
f2(<warning descr="Expected type 'str', got 'int' instead">x1.count('')</warning>)
|
||||
|
||||
@@ -57,7 +57,7 @@ def f():
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_something(self):
|
||||
with self.assertRaises(Exception):
|
||||
with self.assertRaises():
|
||||
raise Foo
|
||||
foo() # pass
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ async def expect_no_warning():
|
||||
|
||||
|
||||
async def expect_new_warning():
|
||||
await <weak_warning descr="Function 'fun_non_async()' neither declared as 'async' nor with 'Awaitable' as return type">fun_non_async()</weak_warning>
|
||||
await <warning descr="Function 'fun_non_async()' neither declared as 'async' nor with 'Awaitable' as return type">fun_non_async()</warning>
|
||||
|
||||
|
||||
def local_fun_non_async():
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ from b import fun_awaitable_imported, MyAwaitable
|
||||
|
||||
|
||||
async def expect_false_positive_warning():
|
||||
await <weak_warning descr="Function 'fun_awaitable_imported()' neither declared as 'async' nor with 'Awaitable' as return type">fun_awaitable_imported()</weak_warning>
|
||||
await <warning descr="Function 'fun_awaitable_imported()' neither declared as 'async' nor with 'Awaitable' as return type">fun_awaitable_imported()</warning>
|
||||
|
||||
|
||||
async def expect_pass_1():
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
def f(i):
|
||||
xs = []
|
||||
xs[i].<weak_warning descr="Member 'List[Any]' of 'Union[List[Any], Any]' does not have attribute 'items'">items</weak_warning>()
|
||||
xs[i].items()
|
||||
|
||||
|
||||
def g(index):
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
def foo(smth, param):
|
||||
if smth:
|
||||
param = ""
|
||||
print(param.<weak_warning descr="Member 'str' of 'Union[{smth}, str]' does not have attribute 'smth'">smth</weak_warning>())
|
||||
print(param.smth())
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
class A:
|
||||
def method(self):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
class C:
|
||||
def method(self):
|
||||
pass
|
||||
|
||||
def union_with_all_compatible_types(x: A | B | C):
|
||||
x.method()
|
||||
|
||||
def union_with_some_incompatible_types(x: A | None):
|
||||
x.<weak_warning descr="Member 'None' of 'A | None' does not have attribute 'method'">method</weak_warning>()
|
||||
|
||||
def union_with_all_incompatible_types(x: object | None):
|
||||
x.<weak_warning descr="Member 'object' of 'object | None' does not have attribute 'method'">method</weak_warning>()
|
||||
|
||||
def union_with_some_incompatible_types_and_any(x: Any | None):
|
||||
x.<weak_warning descr="Member 'None' of 'Any | None' does not have attribute 'method'">method</weak_warning>()
|
||||
|
||||
def narrowing_union_with_some_incompatible_types_after(x: Any | None):
|
||||
if isinstance(x, A):
|
||||
x.method()
|
||||
assert isinstance(x, B)
|
||||
x.method()
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
class A:
|
||||
a = 1
|
||||
|
||||
class Anish(Any):
|
||||
pass
|
||||
|
||||
a = A() if bool() else Anish()
|
||||
|
||||
_ = a.a
|
||||
_ = a.<weak_warning descr="Member 'A' of 'A | Anish' does not have attribute 'b'">b</weak_warning>
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
class A:
|
||||
def __pos__(self):
|
||||
pass
|
||||
|
||||
def __add__(self, other):
|
||||
pass
|
||||
|
||||
def __getitem__(self, item):
|
||||
pass
|
||||
|
||||
|
||||
class B:
|
||||
def __pos__(self):
|
||||
pass
|
||||
|
||||
def __add__(self, other):
|
||||
pass
|
||||
|
||||
def __getitem__(self, item):
|
||||
pass
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
def all_union_members_match_no_any(x: A | B):
|
||||
print(+x)
|
||||
print(x + 1)
|
||||
print(x[42])
|
||||
|
||||
|
||||
def some_union_members_match_no_any(x: A | B | None):
|
||||
print(<weak_warning descr="Member 'None' of 'A | B | None' does not have attribute '__pos__'">+</weak_warning>x)
|
||||
print(x <weak_warning descr="Member 'None' of 'A | B | None' does not have attribute '__add__'">+</weak_warning> 1)
|
||||
print(x<weak_warning descr="Member 'None' of 'A | B | None' does not have attribute '__getitem__'">[</weak_warning>42])
|
||||
|
||||
|
||||
def all_union_members_dont_match_no_any(x: C | None):
|
||||
print(<weak_warning descr="Member 'C' of 'C | None' does not have attribute '__pos__'">+</weak_warning>x)
|
||||
print(x <weak_warning descr="Member 'C' of 'C | None' does not have attribute '__add__'">+</weak_warning> 1)
|
||||
print(x<weak_warning descr="Member 'C' of 'C | None' does not have attribute '__getitem__'">[</weak_warning>42])
|
||||
|
||||
|
||||
def all_union_members_match_with_any(x: A | B | Any):
|
||||
print(+x)
|
||||
print(x + 1)
|
||||
print(x[42])
|
||||
|
||||
|
||||
def some_union_members_match_with_any(x: A | B | None | Any):
|
||||
print(<weak_warning descr="Member 'None' of 'A | B | None | Any' does not have attribute '__pos__'">+</weak_warning>x)
|
||||
print(x <weak_warning descr="Member 'None' of 'A | B | None | Any' does not have attribute '__add__'">+</weak_warning> 1)
|
||||
print(x<weak_warning descr="Member 'None' of 'A | B | None | Any' does not have attribute '__getitem__'">[</weak_warning>42])
|
||||
|
||||
|
||||
def all_union_members_dont_match_with_any(x: C | None | Any):
|
||||
print(<weak_warning descr="Member 'C' of 'C | None | Any' does not have attribute '__pos__'">+</weak_warning>x)
|
||||
print(x <weak_warning descr="Member 'C' of 'C | None | Any' does not have attribute '__add__'">+</weak_warning> 1)
|
||||
print(x<weak_warning descr="Member 'C' of 'C | None | Any' does not have attribute '__getitem__'">[</weak_warning>42])
|
||||
+3
-3
@@ -5,7 +5,7 @@ def f(x):
|
||||
|
||||
def f(x):
|
||||
try:
|
||||
from <error descr="Unresolved reference 'foo'">foo</error> import <weak_warning descr="Module 'StringIO' not found">StringIO</weak_warning>
|
||||
from <error descr="Unresolved reference 'foo'">foo</error> import <warning descr="Module 'StringIO' not found">StringIO</warning>
|
||||
except Exception:
|
||||
pass
|
||||
return x
|
||||
@@ -28,14 +28,14 @@ def f(x):
|
||||
try:
|
||||
import foo as bar
|
||||
except ImportError:
|
||||
import <weak_warning descr="Module 'bar' not found">bar</weak_warning>
|
||||
import <warning descr="Module 'bar' not found">bar</warning>
|
||||
|
||||
# PY-3678
|
||||
def f():
|
||||
try:
|
||||
from foo import bar #pass
|
||||
except ImportError:
|
||||
import <weak_warning descr="Module 'bar' not found">bar</weak_warning> #fail
|
||||
import <warning descr="Module 'bar' not found">bar</warning> #fail
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ async def foo(x):
|
||||
return y
|
||||
|
||||
|
||||
async def bar(x_new) -> Any:
|
||||
async def bar(x_new) -> int | Any:
|
||||
return await x_new + 1
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ class Test:
|
||||
y = extracted(c)
|
||||
return y
|
||||
|
||||
def extracted(c_new) -> Any:
|
||||
def extracted(c_new) -> int | Any:
|
||||
y = self.a + b * c_new
|
||||
return y
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@ class Test:
|
||||
y = extracted()
|
||||
return y
|
||||
|
||||
def extracted() -> Any:
|
||||
def extracted() -> int | Any:
|
||||
y = x * 2
|
||||
return y
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@ class Test:
|
||||
y = extracted(x)
|
||||
return y
|
||||
|
||||
def extracted(x_new) -> Any:
|
||||
def extracted(x_new) -> int | Any:
|
||||
y = x_new * 2
|
||||
return y
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ def compound_duplicate(p1, p2):
|
||||
print(bar(p2))
|
||||
|
||||
|
||||
def bar(p1_new) -> Any:
|
||||
def bar(p1_new) -> int | Any:
|
||||
return p1_new + 1
|
||||
@@ -14,6 +14,6 @@ def f(p: Person, salutation: str, ageHolder: Ageholder):
|
||||
return <caret>greeting(ageHolder, p, salutation)
|
||||
|
||||
|
||||
def greeting(ageHolder_new: Ageholder, p_new: Person, salutation_new: str) -> str:
|
||||
def greeting(ageHolder_new: Ageholder, p_new: Person, salutation_new: str) -> LiteralString | str | int:
|
||||
return salutation_new + p_new.name + "(" + ageHolder_new.age + ")"
|
||||
|
||||
|
||||
@@ -797,11 +797,11 @@ public class PyTypeTest extends PyTestCase {
|
||||
""";
|
||||
final PyExpression expr = parseExpr(text);
|
||||
assertNotNull(expr);
|
||||
doTest("UnsafeUnion[Union[int, str], Any]", expr, TypeEvalContext.codeCompletion(expr.getProject(), expr.getContainingFile()));
|
||||
doTest("Union[Union[int, str], Any]", expr, TypeEvalContext.codeCompletion(expr.getProject(), expr.getContainingFile()));
|
||||
}
|
||||
|
||||
public void testUpperBoundGeneric() {
|
||||
doTest("UnsafeUnion[Union[int, str], Any]",
|
||||
doTest("Union[Union[int, str], Any]",
|
||||
"""
|
||||
def foo(x):
|
||||
'''
|
||||
@@ -1641,7 +1641,7 @@ public class PyTypeTest extends PyTestCase {
|
||||
|
||||
doTest("List[Union[str, int]]", "expr = ['1', 1, 1]");
|
||||
|
||||
doTest("List[UnsafeUnion[Union[str, int], Any]]", "expr = ['1', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]");
|
||||
doTest("List[Union[Union[str, int], Any]]", "expr = ['1', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]");
|
||||
}
|
||||
|
||||
public void testSetLiteral() {
|
||||
@@ -1649,7 +1649,7 @@ public class PyTypeTest extends PyTestCase {
|
||||
|
||||
doTest("Set[Union[str, int]]", "expr = {'1', 1, 1}");
|
||||
|
||||
doTest("Set[UnsafeUnion[Union[str, int], Any]]", "expr = {'1', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}");
|
||||
doTest("Set[Union[Union[str, int], Any]]", "expr = {'1', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}");
|
||||
}
|
||||
|
||||
public void testDictLiteral() {
|
||||
@@ -2773,23 +2773,23 @@ public class PyTypeTest extends PyTestCase {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.PYTHON35,
|
||||
() -> {
|
||||
doTest("UnsafeUnion[int, Any]",
|
||||
doTest("Union[int, Any]",
|
||||
"""
|
||||
from typing import Any
|
||||
x: Any
|
||||
expr = x * 2""");
|
||||
|
||||
doTest("UnsafeUnion[int, Any]",
|
||||
doTest("Union[int, Any]",
|
||||
"""
|
||||
from typing import Any
|
||||
x: Any
|
||||
expr = 2 * x""");
|
||||
|
||||
doTest("UnsafeUnion[int, Any]",
|
||||
doTest("Union[int, Any]",
|
||||
"def f(x):\n" +
|
||||
" expr = x * 2");
|
||||
|
||||
doTest("UnsafeUnion[int, Any]",
|
||||
doTest("Union[int, Any]",
|
||||
"def f(x):\n" +
|
||||
" expr = 2 * x");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.jetbrains.python;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -248,7 +247,7 @@ public class PyTypingTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testAnyStrForUnknown() {
|
||||
doTest("UnsafeUnion[str | bytes, Any]",
|
||||
doTest("str | bytes | Any",
|
||||
"""
|
||||
from typing import AnyStr
|
||||
|
||||
@@ -3614,52 +3613,6 @@ public class PyTypingTest extends PyTestCase {
|
||||
expr = receiver.get()""");
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
// It works incorrectly due to PY-83119 (the information about unresolved union member attributes
|
||||
// being lost during type inference).
|
||||
public void testGenericUnionMemberMethodCallSomeMembersDoNotOwnIt() {
|
||||
doTest("str", // Should be `str | Any`
|
||||
"""
|
||||
class Box[T]:
|
||||
def get(self) -> T:
|
||||
pass
|
||||
r: int | Box[str] = ...
|
||||
expr = r.get()
|
||||
""");
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
// This version doesn't work now properly because of lacking constraint solving.
|
||||
// We can't match `Box[T]` for `self` with `Box[int] | Box[str]`.
|
||||
public void testGenericUnionMemberCallAllMembersAreSameClassParameterizations() {
|
||||
doTest("Any", // Should be `int | str`
|
||||
"""
|
||||
class Box[T]:
|
||||
def get(self) -> T:
|
||||
pass
|
||||
|
||||
r: Box[int] | Box[str] = ...
|
||||
expr = r.get()
|
||||
""");
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
public void testGenericUnionMemberCallAllMembersOwnIt() {
|
||||
doTest("int | str",
|
||||
"""
|
||||
class Box1[T]:
|
||||
def get(self) -> T:
|
||||
pass
|
||||
|
||||
class Box2[T]:
|
||||
def get(self) -> T:
|
||||
pass
|
||||
|
||||
r: Box1[int] | Box2[str] = ...
|
||||
expr = r.get()
|
||||
""");
|
||||
}
|
||||
|
||||
public void testGenericClassTypeHintedInDocstrings() {
|
||||
doTest("int",
|
||||
"""
|
||||
@@ -6784,26 +6737,6 @@ public class PyTypingTest extends PyTestCase {
|
||||
""");
|
||||
}
|
||||
|
||||
// See com.jetbrains.python.refactoring.PyExtractMethodTest.testTypedStatements
|
||||
//
|
||||
// This scenario changes depending on whether the strict unions are enabled.
|
||||
// Without them, the inferred type is LiteralString | str | int, because due to special handling
|
||||
// of unions containing literal types in PyTypeChecker, none of the candidate methods fully matches:
|
||||
// `LiteralString | str | int` receiver is compatible with neither `LiteralString`, `str` nor `int` for `self`,
|
||||
// so we infer a union of all possible return types.
|
||||
// With strict unions, due to special handling of self in #processSelfParameter, only
|
||||
// `__add__(self: str, other: str) -> str` overload remains.
|
||||
// PY-24834 PY-83313
|
||||
public void testUnionStrConcat() {
|
||||
//Registry.get("python.typing.strict.unions").setValue(false, myFixture.getTestRootDisposable());
|
||||
doTest("str", """
|
||||
from typing import LiteralString
|
||||
|
||||
x: LiteralString | str | int
|
||||
expr = x + "foo"
|
||||
""");
|
||||
}
|
||||
|
||||
private void doTestNoInjectedText(@NotNull String text) {
|
||||
myFixture.configureByText(PythonFileType.INSTANCE, text);
|
||||
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
|
||||
|
||||
@@ -2895,28 +2895,6 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase {
|
||||
""");
|
||||
}
|
||||
|
||||
// PY-74277
|
||||
public void testPassingTypeIsCallable() {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.PYTHON312,
|
||||
() -> doTestByText("""
|
||||
from typing_extensions import TypeIs, Callable
|
||||
|
||||
def takes_narrower(x: int | str, narrower: Callable[[object], TypeIs[int]]):
|
||||
if narrower(x):
|
||||
expr1: int = x
|
||||
# └─ should be of `int` type
|
||||
else:
|
||||
expr2: str = x
|
||||
# └─ should be of `str` type
|
||||
|
||||
def is_bool(x: object) -> TypeIs[bool]:
|
||||
return isinstance(x, bool)
|
||||
|
||||
takes_narrower(42, <warning descr="Expected type '(object) -> TypeIs[int]', got '(x: object) -> TypeIs[bool]' instead">is_bool</warning>)
|
||||
"""));
|
||||
}
|
||||
|
||||
// PY-75556
|
||||
public void testLiteralTypeOnKwargs() {
|
||||
doTestByText("""
|
||||
@@ -3095,11 +3073,6 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase {
|
||||
""");
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
public void testStrictUnionImplicitProtocolMatching() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-76822
|
||||
public void testProtocolWithAssignedPropertyInMethod() {
|
||||
doTestByText("""
|
||||
|
||||
-15
@@ -477,21 +477,6 @@ public class Py3UnresolvedReferencesInspectionTest extends PyInspectionTestCase
|
||||
}
|
||||
|
||||
|
||||
// PY-24834
|
||||
public void testStrictUnionMemberAttributeAccess() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
public void testStrictUnionMemberOperatorAccess() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-24834
|
||||
public void testStrictUnionMemberExtendingAny() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-83529
|
||||
public void testPackageAttributeInPresenceOfBinarySkeleton() {
|
||||
runWithAdditionalClassEntryInSdkRoots(getTestDirectoryPath() + "/site-packages", () -> {
|
||||
|
||||
@@ -1534,10 +1534,10 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
|
||||
title: str
|
||||
year: int
|
||||
|
||||
movies1: list[Movie] = <warning descr="Expected type 'list[Movie]', got 'list[Movie | dict[str, str]]' instead">[
|
||||
movies1: list[Movie] = [
|
||||
{"title": "Blade Runner", "year": 1982}, # OK
|
||||
{"title": "The Matrix"},
|
||||
]</warning>
|
||||
]
|
||||
movies2: list[Movie] = <warning descr="Expected type 'list[Movie]', got 'list[dict[str, str]]' instead">[
|
||||
{"title": "The Matrix"},
|
||||
]</warning>
|
||||
@@ -1609,6 +1609,29 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
// PY-74277
|
||||
public void testPassingTypeIsCallable() {
|
||||
runWithLanguageLevel(
|
||||
LanguageLevel.PYTHON312,
|
||||
() -> doTestByText("""
|
||||
from typing_extensions import TypeIs
|
||||
|
||||
def takes_narrower(x: int | str, narrower: Callable[[object], TypeIs[int]]):
|
||||
if narrower(x):
|
||||
expr1: int = x
|
||||
# └─ should be of `int` type
|
||||
else:
|
||||
expr2: str = x
|
||||
# └─ should be of `str` type
|
||||
|
||||
def is_bool(x: object) -> TypeIs[bool]:
|
||||
return isinstance(x, bool)
|
||||
|
||||
takes_narrower(42, is_bool)
|
||||
"""));
|
||||
}
|
||||
|
||||
|
||||
public void testGeneratorTypeHint() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), this::doTest);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class PyUnusedImportTest extends PyTestCase {
|
||||
myFixture.copyDirectoryToProject(getTestName(true), "");
|
||||
myFixture.configureFromTempProjectFile(filename);
|
||||
myFixture.enableInspections(PyUnusedImportsInspection.class, PyUnresolvedReferencesInspection.class);
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user