| -- Checks for incremental mode (see testcheck.py). | |
| -- Each test is run at least twice, once with a cold cache, once with a warm cache. | |
| -- Before the tests are run again, in step N any *.py.N files are copied to | |
| -- *.py. There are at least two runs; more as long as there are *.py.N files. | |
| -- | |
| -- You can add an empty section like `[delete mod.py.2]` to delete `mod.py` | |
| -- before the second run. | |
| -- | |
| -- Errors expected in the first run should be in the `[out1]` section, and | |
| -- errors expected in the second run should be in the `[out2]` section, and so on. | |
| -- If a section is omitted, it is expected there are no errors on that run. | |
| -- The number of runs is determined by the highest N in all [outN] sections, but | |
| -- there are always at least two runs. (Note that [out] is equivalent to [out1].) | |
| -- | |
| -- The list of modules to be checked can be specified using | |
| -- # cmd: mypy -m mod1 mod2 mod3 | |
| -- To check a different list on the second run, use | |
| -- # cmd2: mypy -m mod1 mod3 | |
| -- (and cmd3 for the third run, and so on). | |
| -- | |
| -- Extra command line flags may be specified using | |
| -- # flags: --some-flag | |
| -- If the second run requires different flags, those can be specified using | |
| -- # flags2: --another-flag | |
| -- (and flags3 for the third run, and so on). | |
| -- | |
| -- Incremental tests involving plugins that get updated are also supported. | |
| -- All plugin files that are updated *must* end in '_plugin', so they will | |
| -- be unloaded from 'sys.modules' between incremental steps. | |
| -- | |
| -- Any files that we expect to be rechecked should be annotated in the [rechecked] | |
| -- annotation, and any files expect to be stale (aka have a modified interface) | |
| -- should be annotated in the [stale] annotation. Note that a file that ends up | |
| -- producing an error has its caches deleted and is marked stale automatically. | |
| -- Such files do not need to be included in [stale ...] list. | |
| -- | |
| -- The test suite will automatically assume that __main__ is stale and rechecked in | |
| -- all cases so we can avoid constantly having to annotate it. The list of | |
| -- rechecked/stale files can be in any arbitrary order, or can be left empty | |
| -- if no files should be rechecked/stale. | |
| -- | |
| -- There are additional incremental mode test cases in check-serialize.test. | |
| [case testIncrementalEmpty] | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalBasics] | |
| import m | |
| [file m.py] | |
| def foo(): | |
| pass | |
| [file m.py.2] | |
| def foo() -> None: | |
| pass | |
| [rechecked m] | |
| [stale m] | |
| [case testIncrementalError] | |
| import m | |
| [file m.py] | |
| def foo() -> None: | |
| pass | |
| [file m.py.2] | |
| def foo() -> None: | |
| bar() | |
| [rechecked m] | |
| [stale] | |
| [out2] | |
| tmp/m.py:2: error: Name "bar" is not defined | |
| [case testIncrementalSimpleImportSequence] | |
| import mod1 | |
| mod1.func1() | |
| [file mod1.py] | |
| import mod2 | |
| def func1() -> None: mod2.func2() | |
| [file mod2.py] | |
| import mod3 | |
| def func2() -> None: mod3.func3() | |
| [file mod3.py] | |
| def func3() -> None: pass | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalInternalChangeOnly] | |
| import mod1 | |
| mod1.func1() | |
| [file mod1.py] | |
| import mod2 | |
| def func1() -> None: mod2.func2() | |
| [file mod2.py] | |
| import mod3 | |
| def func2() -> None: mod3.func3() | |
| [file mod3.py] | |
| def func3() -> None: pass | |
| [file mod3.py.2] | |
| def func3() -> None: 3 + 2 | |
| [rechecked mod3] | |
| [stale] | |
| [case testIncrementalImportGone] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| def func1() -> A: pass | |
| [file mod2.py] | |
| class A: pass | |
| [file mod1.py.2] | |
| def func1() -> A: pass | |
| [rechecked mod1] | |
| [stale mod1] | |
| [out2] | |
| tmp/mod1.py:1: error: Name "A" is not defined | |
| [case testIncrementalCallable] | |
| import mod1 | |
| [file mod1.py] | |
| from typing import Callable | |
| from mypy_extensions import Arg | |
| def func1() -> Callable[[Arg(int, 'x')], int]: pass | |
| [file mod1.py.2] | |
| from typing import Callable | |
| from mypy_extensions import Arg | |
| def func1() -> Callable[[Arg(int, 'x')], int]: ... | |
| [rechecked mod1] | |
| [stale] | |
| [builtins fixtures/dict.pyi] | |
| [case testIncrementalSameNameChange] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| def func1() -> A: pass | |
| [file mod2.py] | |
| class A: pass | |
| [file mod2.py.2] | |
| class Parent: pass | |
| class A(Parent): pass | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [case testIncrementalPartialInterfaceChange] | |
| import mod1 | |
| mod1.func1() | |
| [file mod1.py] | |
| import mod2 | |
| def func1() -> None: mod2.func2() | |
| [file mod2.py] | |
| import mod3 | |
| def func2() -> None: mod3.func3() | |
| [file mod3.py] | |
| def func3() -> None: pass | |
| [file mod3.py.2] | |
| def func3() -> int: return 2 | |
| [rechecked mod2, mod3] | |
| [stale mod3] | |
| [case testIncrementalInternalFunctionDefinitionChange] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accepts_int(a: int) -> int: return a | |
| accepts_int(mod2.foo()) | |
| [file mod2.py] | |
| def foo() -> int: | |
| def inner() -> int: | |
| return 42 | |
| return inner() | |
| [file mod2.py.2] | |
| def foo() -> int: | |
| def inner2() -> str: | |
| return "foo" | |
| return inner2() | |
| [rechecked mod2] | |
| [stale] | |
| [out2] | |
| tmp/mod2.py:4: error: Incompatible return value type (got "str", expected "int") | |
| [case testIncrementalInternalScramble] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| mod2.foo() | |
| [file mod2.py] | |
| def baz() -> int: | |
| return 3 | |
| def bar() -> int: | |
| return baz() | |
| def foo() -> int: | |
| return bar() | |
| [file mod2.py.2] | |
| def foo() -> int: | |
| return baz() | |
| def bar() -> int: | |
| return bar() | |
| def baz() -> int: | |
| return 42 | |
| [rechecked mod2] | |
| [stale] | |
| [case testIncrementalMethodInterfaceChange] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| [file mod2.py] | |
| class Foo: | |
| def bar(self, a: str) -> str: | |
| return "a" | |
| [file mod2.py.2] | |
| class Foo: | |
| def bar(self, a: float) -> str: | |
| return "a" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [case testIncrementalBaseClassChange] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import Child | |
| Child().good_method() | |
| [file mod2.py] | |
| class Good: | |
| def good_method(self) -> int: return 1 | |
| class Bad: pass | |
| class Child(Good): pass | |
| [file mod2.py.2] | |
| class Good: | |
| def good_method(self) -> int: return 1 | |
| class Bad: pass | |
| class Child(Bad): pass | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [out2] | |
| tmp/mod1.py:2: error: "Child" has no attribute "good_method" | |
| [case testIncrementalCascadingChange] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| def accepts_int(a: int) -> None: pass | |
| accepts_int(A) | |
| [file mod2.py] | |
| from mod3 import B | |
| A = B | |
| [file mod3.py] | |
| from mod4 import C | |
| B = C | |
| [file mod4.py] | |
| C = 3 | |
| [file mod4.py.2] | |
| C = "A" | |
| [rechecked mod1, mod2, mod3, mod4] | |
| [stale mod2, mod3, mod4] | |
| [out2] | |
| tmp/mod1.py:3: error: Argument 1 to "accepts_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalBrokenCascade] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accept_int(a: int) -> int: return a | |
| accept_int(mod2.mod3.mod4.const) | |
| [file mod2.py] | |
| import mod3 | |
| [file mod3.py] | |
| import mod4 | |
| [file mod4.py] | |
| const = 3 | |
| [file mod3.py.2] | |
| # Import to mod4 is gone! | |
| [rechecked mod1, mod2, mod3] | |
| [stale mod3] | |
| [builtins fixtures/module.pyi] | |
| [out2] | |
| tmp/mod1.py:3: error: Module has no attribute "mod4" | |
| [case testIncrementalLongBrokenCascade] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accept_int(a: int) -> int: return a | |
| accept_int(mod2.mod3.mod4.mod5.mod6.mod7.const) | |
| [file mod2.py] | |
| import mod3 | |
| [file mod3.py] | |
| import mod4 | |
| [file mod4.py] | |
| import mod5 | |
| [file mod5.py] | |
| import mod6 | |
| [file mod6.py] | |
| import mod7 | |
| [file mod7.py] | |
| const = 3 | |
| [file mod6.py.2] | |
| # Import to mod7 is gone! | |
| [rechecked mod1, mod5, mod6] | |
| [stale mod6] | |
| [builtins fixtures/module.pyi] | |
| [out2] | |
| tmp/mod1.py:3: error: Module has no attribute "mod7" | |
| [case testIncrementalNestedBrokenCascade] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accept_int(a: int) -> int: return a | |
| accept_int(mod2.mod3.mod4.const) | |
| [file mod2/__init__.py] | |
| import mod2.mod3 as mod3 | |
| [file mod2/mod3/__init__.py] | |
| import mod2.mod3.mod4 as mod4 | |
| [file mod2/mod3/__init__.py.2] | |
| # Import is gone! | |
| [file mod2/mod3/mod4.py] | |
| const = 3 | |
| [rechecked mod1, mod2, mod2.mod3] | |
| [stale mod2.mod3] | |
| [builtins fixtures/module.pyi] | |
| [out2] | |
| tmp/mod1.py:3: error: Module has no attribute "mod4" | |
| [case testIncrementalNestedBrokenCascadeWithType1] | |
| import mod1, mod2.mod3.mod5 | |
| [file mod1.py] | |
| import mod2 | |
| def accept_int(x: int) -> None: pass | |
| def produce() -> mod2.CustomType: | |
| return mod2.CustomType() | |
| a = produce() | |
| accept_int(a.foo()) | |
| [file mod2/__init__.py] | |
| from mod2.mod3 import CustomType | |
| [file mod2/mod3/__init__.py] | |
| from mod2.mod3.mod4 import CustomType | |
| [file mod2/mod3/__init__.py.2] | |
| # Import a different class that also happens to be called 'CustomType' | |
| from mod2.mod3.mod5 import CustomType | |
| def produce() -> CustomType: | |
| return CustomType() | |
| [file mod2/mod3/mod4.py] | |
| class CustomType: | |
| def foo(self) -> int: return 1 | |
| [file mod2/mod3/mod5.py] | |
| class CustomType: | |
| def foo(self) -> str: return "a" | |
| [rechecked mod1, mod2, mod2.mod3] | |
| [stale mod1, mod2, mod2.mod3] | |
| [builtins fixtures/module.pyi] | |
| [out1] | |
| [out2] | |
| tmp/mod1.py:6: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalNestedBrokenCascadeWithType2] | |
| import mod1, mod2.mod3.mod5 | |
| [file mod1.py] | |
| from mod2 import produce | |
| def accept_int(x: int) -> None: pass | |
| a = produce() | |
| accept_int(a.foo()) | |
| [file mod2/__init__.py] | |
| from mod2.mod3 import produce | |
| [file mod2/mod3/__init__.py] | |
| from mod2.mod3.mod4 import CustomType | |
| def produce() -> CustomType: | |
| return CustomType() | |
| [file mod2/mod3/__init__.py.2] | |
| # Import a different class that also happens to be called 'CustomType' | |
| from mod2.mod3.mod5 import CustomType | |
| def produce() -> CustomType: | |
| return CustomType() | |
| [file mod2/mod3/mod4.py] | |
| class CustomType: | |
| def foo(self) -> int: return 1 | |
| [file mod2/mod3/mod5.py] | |
| class CustomType: | |
| def foo(self) -> str: return "a" | |
| [rechecked mod1, mod2, mod2.mod3] | |
| [stale mod1, mod2.mod3] | |
| [builtins fixtures/module.pyi] | |
| [out1] | |
| [out2] | |
| tmp/mod1.py:4: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalRemoteChange] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accepts_int(a: int) -> None: pass | |
| accepts_int(mod2.mod3.mod4.const) | |
| [file mod2.py] | |
| import mod3 | |
| [file mod3.py] | |
| import mod4 | |
| [file mod4.py] | |
| const = 3 | |
| [file mod4.py.2] | |
| const = "foo" | |
| [rechecked mod1, mod3, mod4] | |
| [stale mod4] | |
| [out2] | |
| tmp/mod1.py:3: error: Argument 1 to "accepts_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalBadChange] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import func2 | |
| def func1() -> int: | |
| return func2() | |
| [file mod2.py] | |
| def func2() -> int: | |
| return 1 | |
| [file mod2.py.2] | |
| def func2() -> str: | |
| return "foo" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [out2] | |
| tmp/mod1.py:4: error: Incompatible return value type (got "str", expected "int") | |
| [case testIncrementalBadChangeWithSave] | |
| import mod0 | |
| [file mod0.py] | |
| import mod1 | |
| A = mod1.func2() | |
| [file mod1.py] | |
| from mod2 import func2 | |
| def func1() -> int: | |
| return func2() | |
| [file mod2.py] | |
| def func2() -> int: | |
| return 1 | |
| [file mod2.py.2] | |
| def func2() -> str: | |
| return "foo" | |
| [rechecked mod0, mod1, mod2] | |
| [stale mod0, mod2] | |
| [out2] | |
| tmp/mod1.py:4: error: Incompatible return value type (got "str", expected "int") | |
| [case testIncrementalOkChangeWithSave] | |
| import mod0 | |
| [file mod0.py] | |
| import mod1 | |
| A = mod1.func2() | |
| [file mod1.py] | |
| from mod2 import func2 | |
| def func1() -> int: | |
| func2() | |
| return 1 | |
| [file mod2.py] | |
| def func2() -> int: | |
| return 1 | |
| [file mod2.py.2] | |
| def func2() -> str: | |
| return "foo" | |
| [rechecked mod0, mod1, mod2] | |
| [stale mod0, mod2] | |
| [out2] | |
| [case testIncrementalWithComplexDictExpression] | |
| import mod1 | |
| [file mod1.py] | |
| import mod1_private | |
| [file mod1_private.py] | |
| my_dict = { | |
| 'a': [1, 2, 3], | |
| 'b': [4, 5, 6] | |
| } | |
| [file mod1_private.py.2] | |
| my_dict = { | |
| 'a': [1, 2, 3], | |
| 'b': [4, 5, 'a'] | |
| } | |
| [rechecked mod1, mod1_private] | |
| [stale mod1_private] | |
| [builtins fixtures/dict.pyi] | |
| [case testIncrementalWithComplexConstantExpressionNoAnnotation] | |
| import mod1 | |
| [file mod1.py] | |
| import mod1_private | |
| [file mod1_private.py] | |
| def foobar() -> int: return 1 | |
| def baz() -> int: return 2 | |
| const = 1 + foobar() | |
| [file mod1_private.py.2] | |
| def foobar() -> int: return 1 | |
| def baz() -> int: return 2 | |
| const = 1 + baz() | |
| [rechecked mod1_private] | |
| [stale] | |
| [case testIncrementalWithComplexConstantExpressionWithAnnotation] | |
| import mod1 | |
| [file mod1.py] | |
| import mod1_private | |
| [file mod1_private.py] | |
| def foobar() -> int: return 1 | |
| def baz() -> int: return 2 | |
| const = 1 + foobar() # type: int | |
| [file mod1_private.py.2] | |
| def foobar() -> int: return 1 | |
| def baz() -> int: return 2 | |
| const = 1 + baz() # type: int | |
| [rechecked mod1_private] | |
| [stale] | |
| [case testIncrementalSmall] | |
| import mod1 | |
| [file mod1.py] | |
| import mod1_private | |
| def accepts_int(a: int) -> None: pass | |
| accepts_int(mod1_private.some_func(12)) | |
| [file mod1_private.py] | |
| def some_func(a: int) -> int: | |
| return 1 | |
| [file mod1_private.py.2] | |
| def some_func(a: int) -> str: | |
| return "a" | |
| [rechecked mod1, mod1_private] | |
| [stale mod1_private] | |
| [builtins fixtures/ops.pyi] | |
| [out2] | |
| tmp/mod1.py:3: error: Argument 1 to "accepts_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalWithDecorators] | |
| import mod1 | |
| [file mod1.py] | |
| import mod1_private | |
| def accepts_int(a: int) -> None: pass | |
| accepts_int(mod1_private.some_func(12)) | |
| [file mod1_private.py] | |
| from typing import Callable | |
| def multiply(f: Callable[[int], int]) -> Callable[[int], int]: | |
| return lambda a: f(a) * 10 | |
| def stringify(f: Callable[[int], int]) -> Callable[[int], str]: | |
| return lambda a: str(f(a)) | |
| @multiply | |
| def some_func(a: int) -> int: | |
| return a + 2 | |
| [file mod1_private.py.2] | |
| from typing import Callable | |
| def multiply(f: Callable[[int], int]) -> Callable[[int], int]: | |
| return lambda a: f(a) * 10 | |
| def stringify(f: Callable[[int], int]) -> Callable[[int], str]: | |
| return lambda a: str(f(a)) | |
| @stringify | |
| def some_func(a: int) -> int: | |
| return a + 2 | |
| [rechecked mod1, mod1_private] | |
| [stale mod1_private] | |
| [builtins fixtures/ops.pyi] | |
| [out2] | |
| tmp/mod1.py:3: error: Argument 1 to "accepts_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalChangingClassAttributes] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| mod2.Foo.A | |
| [file mod2.py] | |
| class Foo: | |
| A = 3 | |
| [file mod2.py.2] | |
| class Foo: | |
| A = "hello" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [case testIncrementalChangingFields] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| f = mod2.Foo() | |
| f.A | |
| [file mod2.py] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = 3 | |
| [file mod2.py.2] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = "hello" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [out2] | |
| [case testIncrementalChangingFieldsWithAssignment] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| f = mod2.Foo() | |
| B = f.A | |
| [file mod2.py] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = 3 | |
| [file mod2.py.2] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = "hello" | |
| [rechecked mod1, mod2] | |
| [stale mod1, mod2] | |
| [case testIncrementalCheckingChangingFields] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| def accept_int(a: int) -> int: return a | |
| f = mod2.Foo() | |
| accept_int(f.A) | |
| [file mod2.py] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = 3 | |
| [file mod2.py.2] | |
| class Foo: | |
| def __init__(self) -> None: | |
| self.A = "hello" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [out2] | |
| tmp/mod1.py:4: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalNestedClassDefinition] | |
| import mod1 | |
| [file mod1.py] | |
| import mod2 | |
| b = mod2.Foo.Bar() | |
| b.attr | |
| [file mod2.py] | |
| class Foo: | |
| class Bar: | |
| attr = 3 | |
| [file mod2.py.2] | |
| class Foo: | |
| class Bar: | |
| attr = "foo" | |
| [rechecked mod1, mod2] | |
| [stale mod2] | |
| [case testIncrementalSimpleBranchingModules] | |
| import mod1 | |
| import mod2 | |
| [file mod1.py] | |
| def func() -> None: pass | |
| [file mod2.py] | |
| def func() -> None: pass | |
| [file mod1.py.2] | |
| def func() -> int: return 1 | |
| [rechecked mod1] | |
| [stale mod1] | |
| [case testIncrementalSubmoduleImport] | |
| from parent.childA import Foo | |
| def func1() -> Foo: | |
| return Foo() | |
| [file parent/__init__.py] | |
| from parent.childA import Foo | |
| from parent.childB import Bar | |
| __all__ = ['Foo', 'Bar'] | |
| [file parent/childA.py] | |
| import parent | |
| class Foo: | |
| def test(self) -> int: | |
| return parent.Bar().test() | |
| [file parent/childB.py] | |
| class Bar: | |
| def test(self) -> int: return 3 | |
| [builtins fixtures/module_all.pyi] | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalSubmoduleWithAttr] | |
| import mod.child | |
| x = mod.child.Foo() | |
| x.bar() | |
| [file mod/__init__.py] | |
| [file mod/child.py] | |
| class Foo: | |
| def bar(self) -> None: pass | |
| [builtins fixtures/module.pyi] | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalNestedSubmoduleImportFromWithAttr] | |
| from mod1.mod2 import mod3 | |
| def accept_int(a: int) -> None: pass | |
| accept_int(mod3.val3) | |
| [file mod1/__init__.py] | |
| val1 = 1 | |
| [file mod1/mod2/__init__.py] | |
| val2 = 1 | |
| [file mod1/mod2/mod3.py] | |
| val3 = 1 | |
| [builtins fixtures/module.pyi] | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalNestedSubmoduleWithAttr] | |
| import mod1.mod2.mod3 | |
| def accept_int(a: int) -> None: pass | |
| accept_int(mod1.mod2.mod3.val3) | |
| accept_int(mod1.mod2.val2) | |
| accept_int(mod1.val1) | |
| [file mod1/__init__.py] | |
| val1 = 1 | |
| [file mod1/mod2/__init__.py] | |
| val2 = 1 | |
| [file mod1/mod2/mod3.py] | |
| val3 = 1 | |
| [builtins fixtures/module.pyi] | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalSubmoduleParentWithImportFrom] | |
| import parent | |
| [file parent/__init__.py] | |
| from parent import a | |
| [file parent/a.py] | |
| val = 3 | |
| [builtins fixtures/args.pyi] | |
| [stale] | |
| [case testIncrementalSubmoduleParentBackreference] | |
| import parent | |
| [file parent/__init__.py] | |
| from parent import a | |
| [file parent/a.py] | |
| import parent.b | |
| [file parent/b.py] | |
| [builtins fixtures/args.pyi] | |
| [stale] | |
| [case testIncrementalSubmoduleParentBackreferenceComplex] | |
| import parent | |
| [file parent/__init__.py] | |
| import parent.a | |
| [file parent/a.py] | |
| import parent.b | |
| import parent.c | |
| [file parent/b.py] | |
| import parent.a | |
| [file parent/c.py] | |
| import parent.a | |
| [builtins fixtures/args.pyi] | |
| [stale] | |
| [case testIncrementalReferenceNewFileWithImportFrom] | |
| from parent import a | |
| [file parent/__init__.py] | |
| [file parent/a.py] | |
| [file parent/a.py.2] | |
| from parent import b | |
| reveal_type(b.x) | |
| [file parent/b.py.2] | |
| x = 10 | |
| [stale parent.a, parent.b] | |
| [rechecked parent.a, parent.b] | |
| [out2] | |
| tmp/parent/a.py:2: note: Revealed type is "builtins.int" | |
| [case testIncrementalReferenceExistingFileWithImportFrom] | |
| from parent import a, b | |
| [file parent/__init__.py] | |
| [file parent/a.py] | |
| [file parent/b.py] | |
| [file parent/a.py.2] | |
| from parent import b | |
| [stale parent.a] | |
| [case testIncrementalWithTypeIgnoreOnDirectImport] | |
| import a, b | |
| [file a.py] | |
| import b # type: ignore | |
| [file b.py] | |
| import c | |
| [file c.py] | |
| [stale] | |
| [case testIncrementalWithTypeIgnoreOnImportFrom] | |
| import a, b | |
| [file a.py] | |
| from b import something # type: ignore | |
| [file b.py] | |
| import c | |
| something = 3 | |
| [file c.py] | |
| [stale] | |
| [case testIncrementalWithPartialTypeIgnore] | |
| import a # type: ignore | |
| import a.b | |
| [file a/__init__.py] | |
| [file a/b.py] | |
| [stale] | |
| [case testIncrementalAnyIsDifferentFromIgnore] | |
| import b | |
| [file b.py] | |
| from typing import Any | |
| import a.b | |
| [file b.py.2] | |
| from typing import Any | |
| a = 3 # type: Any | |
| import a.b | |
| [file a/__init__.py] | |
| [file a/b.py] | |
| [stale b] | |
| [case testIncrementalSilentImportsAndImportsInClass] | |
| # flags: --ignore-missing-imports | |
| class MyObject(object): | |
| from bar import FooBar | |
| [stale] | |
| [case testIncrementalSameFileSize] | |
| import m | |
| [file m.py] | |
| def foo(a: int) -> None: pass | |
| def bar(a: str) -> None: pass | |
| foo(3) | |
| [file m.py.2] | |
| def foo(a: int) -> None: pass | |
| def bar(a: str) -> None: pass | |
| bar(3) | |
| [rechecked m] | |
| [stale] | |
| [out2] | |
| tmp/m.py:4: error: Argument 1 to "bar" has incompatible type "int"; expected "str" | |
| [case testIncrementalUnsilencingModule] | |
| # cmd: mypy -m main package.subpackage.mod2 | |
| # cmd2: mypy -m main package.subpackage.mod1 | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from package.subpackage.mod1 import Class | |
| def handle(c: Class) -> None: | |
| c.some_attribute | |
| [file package/__init__.py] | |
| # empty | |
| [file package/subpackage/__init__.py] | |
| # empty | |
| [file package/subpackage/mod1.py] | |
| import collections # Any previously unloaded package works here | |
| class Class: pass | |
| [file package/subpackage/mod2.py] | |
| # empty | |
| [builtins fixtures/args.pyi] | |
| [rechecked collections, main, package.subpackage.mod1] | |
| [stale collections, main, package.subpackage.mod1] | |
| [out2] | |
| tmp/main.py:4: error: "Class" has no attribute "some_attribute" | |
| [case testIncrementalWithIgnores] | |
| import foo # type: ignore | |
| [builtins fixtures/module.pyi] | |
| [stale] | |
| [case testIncrementalWithSilentImportsAndIgnore] | |
| # cmd: mypy -m main b | |
| # cmd2: mypy -m main c c.submodule | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| import a # type: ignore | |
| import b | |
| import c | |
| a.A().foo() | |
| b.B().foo() | |
| c.C().foo() | |
| [file b.py] | |
| class B: | |
| def foo(self) -> None: pass | |
| [file b.py.2] | |
| [file c/__init__.py] | |
| class C: pass | |
| [file c/submodule.py] | |
| val = 3 # type: int | |
| if int(): | |
| val = "foo" | |
| [builtins fixtures/module_all.pyi] | |
| [rechecked main, c, c.submodule] | |
| [stale main, c, c.submodule] | |
| [out2] | |
| tmp/c/submodule.py:3: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| tmp/main.py:7: error: "C" has no attribute "foo" | |
| [case testIncrementalRemoteError] | |
| import m | |
| m.C().foo().bar() | |
| [file m.py] | |
| import n | |
| class C: | |
| def foo(self) -> n.A: pass | |
| [file n.py] | |
| class A: | |
| def bar(self): pass | |
| [file n.py.2] | |
| class A: | |
| pass | |
| [rechecked m, n] | |
| [stale n] | |
| [out2] | |
| main:2: error: "A" has no attribute "bar" | |
| [case testIncrementalRemoteErrorFixed] | |
| import m | |
| m.C().foo().bar() | |
| [file m.py] | |
| import n | |
| class C: | |
| def foo(self) -> n.A: pass | |
| [file n.py] | |
| class A: | |
| pass | |
| [file n.py.2] | |
| class A: | |
| def bar(self): pass | |
| [rechecked m, n] | |
| [stale n] | |
| [out1] | |
| main:2: error: "A" has no attribute "bar" | |
| [case testIncrementalChangedError] | |
| import m | |
| [file m.py] | |
| import n | |
| def accept_int(x: int) -> None: pass | |
| accept_int(n.foo) | |
| [file n.py] | |
| foo = "hello" | |
| reveal_type(foo) | |
| [file n.py.2] | |
| foo = 3.14 | |
| reveal_type(foo) | |
| [rechecked m, n] | |
| [stale n] | |
| [out1] | |
| tmp/n.py:2: note: Revealed type is "builtins.str" | |
| tmp/m.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [out2] | |
| tmp/n.py:2: note: Revealed type is "builtins.float" | |
| tmp/m.py:3: error: Argument 1 to "accept_int" has incompatible type "float"; expected "int" | |
| [case testIncrementalReplacingImports] | |
| import good, bad, client | |
| [file good.py] | |
| def foo(a: int) -> None: pass | |
| [file bad.py] | |
| def foo(a: str) -> None: pass | |
| [file client.py] | |
| import good | |
| import bad | |
| from good import foo | |
| foo(3) | |
| [file client.py.2] | |
| import good | |
| import bad | |
| from bad import foo | |
| foo(3) | |
| [rechecked client] | |
| [stale client] | |
| [out2] | |
| tmp/client.py:4: error: Argument 1 to "foo" has incompatible type "int"; expected "str" | |
| [case testIncrementalChangingAlias] | |
| import m1, m2, m3, m4, m5 | |
| [file m1.py] | |
| from m2 import A | |
| def accepts_int(x: int) -> None: pass | |
| accepts_int(A()) | |
| [file m2.py] | |
| from m3 import A | |
| [file m3.py] | |
| from m4 import B | |
| A = B | |
| [file m3.py.2] | |
| from m5 import C | |
| A = C | |
| [file m4.py] | |
| def B() -> int: | |
| return 42 | |
| [file m5.py] | |
| def C() -> str: | |
| return "hello" | |
| [rechecked m1, m2, m3] | |
| [stale m3] | |
| [out2] | |
| tmp/m1.py:3: error: Argument 1 to "accepts_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalStoresAliasTypeVars] | |
| import a | |
| [file mod.py] | |
| from typing import TypeVar, Union | |
| T = TypeVar('T') | |
| Alias = Union[int, T] | |
| x: Alias[str] | |
| [file a.py] | |
| from mod import Alias, x | |
| [file a.py.2] | |
| from mod import Alias, x | |
| reveal_type(x) | |
| y: Alias[int] | |
| reveal_type(y) | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "builtins.int | builtins.str" | |
| tmp/a.py:5: note: Revealed type is "builtins.int | builtins.int" | |
| [case testIncrementalSilentImportsWithBlatantError] | |
| # cmd: mypy -m main | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from evil import Hello | |
| [file main.py.2] | |
| from evil import Hello | |
| reveal_type(Hello()) | |
| [file evil.py] | |
| def accept_int(x: int) -> None: pass | |
| accept_int("not an int") | |
| [rechecked main] | |
| [stale] | |
| [out2] | |
| tmp/main.py:2: note: Revealed type is "Any" | |
| [case testIncrementalImportIsNewlySilenced] | |
| # cmd: mypy -m main foo | |
| # cmd2: mypy -m main | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from foo import bar | |
| def accept_int(x: int) -> None: pass | |
| accept_int(bar) | |
| [file foo.py] | |
| bar = 3 | |
| [file foo.py.2] | |
| # Empty! | |
| [rechecked main] | |
| [stale main] | |
| [case testIncrementalSilencedModuleNoLongerCausesError] | |
| # cmd: mypy -m main evil | |
| # cmd2: mypy -m main | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from evil import bar | |
| def accept_int(x: int) -> None: pass | |
| accept_int(bar) | |
| reveal_type(bar) | |
| [file evil.py] | |
| bar = "str" | |
| [rechecked main] | |
| [stale main] | |
| [out1] | |
| tmp/main.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| tmp/main.py:4: note: Revealed type is "builtins.str" | |
| [out2] | |
| tmp/main.py:4: note: Revealed type is "Any" | |
| [case testIncrementalFixedBugCausesPropagation] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| val = A().makeB().makeC().foo() | |
| reveal_type(val) | |
| [file mod2.py] | |
| from mod3 import B | |
| class A: | |
| def makeB(self) -> B: return B() | |
| [file mod3.py] | |
| from mod4 import C | |
| class B: | |
| def makeC(self) -> C: | |
| val = 3 # type: int | |
| if 1: | |
| val = "str" # deliberately triggering error | |
| return C() | |
| [file mod3.py.2] | |
| from mod4 import C | |
| class B: | |
| def makeC(self) -> C: return C() | |
| [file mod4.py] | |
| class C: | |
| def foo(self) -> int: return 1 | |
| [rechecked mod3] | |
| [stale] | |
| [out1] | |
| tmp/mod3.py:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| tmp/mod1.py:3: note: Revealed type is "builtins.int" | |
| [out2] | |
| tmp/mod1.py:3: note: Revealed type is "builtins.int" | |
| [case testIncrementalIncidentalChangeWithBugCausesPropagation] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| val = A().makeB().makeC().foo() | |
| reveal_type(val) | |
| [file mod2.py] | |
| from mod3 import B | |
| class A: | |
| def makeB(self) -> B: return B() | |
| [file mod3.py] | |
| from mod4 import C | |
| class B: | |
| def makeC(self) -> C: | |
| val = 3 # type: int | |
| if 1: | |
| val = "str" # deliberately triggering error | |
| return C() | |
| [file mod4.py] | |
| class C: | |
| def foo(self) -> int: return 1 | |
| [file mod4.py.2] | |
| class C: | |
| def foo(self) -> str: return 'a' | |
| [rechecked mod4, mod3, mod1] | |
| [stale mod1, mod4] | |
| [out1] | |
| tmp/mod3.py:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| tmp/mod1.py:3: note: Revealed type is "builtins.int" | |
| [out2] | |
| tmp/mod3.py:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| tmp/mod1.py:3: note: Revealed type is "builtins.str" | |
| [case testIncrementalIncidentalChangeWithBugFixCausesPropagation] | |
| import mod1 | |
| [file mod1.py] | |
| from mod2 import A | |
| val = A().makeB().makeC().foo() | |
| reveal_type(val) | |
| [file mod2.py] | |
| from mod3 import B | |
| class A: | |
| def makeB(self) -> B: return B() | |
| [file mod3.py] | |
| from mod4 import C | |
| class B: | |
| def makeC(self) -> C: | |
| val = 3 # type: int | |
| if 1: | |
| val = "str" # deliberately triggering error | |
| return C() | |
| [file mod3.py.2] | |
| from mod4 import C | |
| class B: | |
| def makeC(self) -> C: return C() | |
| [file mod4.py] | |
| class C: | |
| def foo(self) -> int: return 1 | |
| [file mod4.py.2] | |
| class C: | |
| def foo(self) -> str: return 'a' | |
| [rechecked mod4, mod3, mod1] | |
| [stale mod1, mod4] | |
| [out1] | |
| tmp/mod3.py:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| tmp/mod1.py:3: note: Revealed type is "builtins.int" | |
| [out2] | |
| tmp/mod1.py:3: note: Revealed type is "builtins.str" | |
| [case testIncrementalSilentImportsWithInnerImports] | |
| # cmd: mypy -m main foo | |
| # flags: --ignore-missing-imports | |
| [file main.py] | |
| from foo import MyClass | |
| m = MyClass() | |
| [file main.py.2] | |
| from foo import MyClass | |
| m = MyClass() | |
| reveal_type(m.val) | |
| [file foo.py] | |
| class MyClass: | |
| def __init__(self) -> None: | |
| import unrelated | |
| self.val = unrelated.test() | |
| [rechecked main] | |
| [stale] | |
| [out2] | |
| tmp/main.py:3: note: Revealed type is "Any" | |
| [case testIncrementalSilentImportsWithInnerImportsAndNewFile] | |
| # cmd: mypy -m main foo | |
| # cmd2: mypy -m main foo unrelated | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from foo import MyClass | |
| m = MyClass() | |
| [file main.py.2] | |
| from foo import MyClass | |
| m = MyClass() | |
| reveal_type(m.val) | |
| [file foo.py] | |
| class MyClass: | |
| def __init__(self) -> None: | |
| import unrelated | |
| self.val = unrelated.test() | |
| [file unrelated.py] | |
| def test() -> str: return "foo" | |
| [rechecked main, foo, unrelated] | |
| [stale foo, unrelated] | |
| [out2] | |
| tmp/main.py:3: note: Revealed type is "builtins.str" | |
| [case testIncrementalWorksWithNestedClasses] | |
| import foo | |
| [file foo.py] | |
| class MyClass: | |
| class NestedClass: | |
| pass | |
| class_attr = NestedClass() | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalWorksWithBasicProtocols] | |
| import a | |
| [file a.py] | |
| from b import P | |
| x: int | |
| y: P[int] | |
| x = y.meth() | |
| class C: | |
| def meth(self) -> int: | |
| pass | |
| y = C() | |
| [file a.py.2] | |
| from b import P | |
| x: str | |
| y: P[str] | |
| x = y.meth() | |
| class C: | |
| def meth(self) -> str: | |
| pass | |
| y = C() | |
| [file b.py] | |
| from typing import Protocol, TypeVar | |
| T = TypeVar('T', covariant=True) | |
| class P(Protocol[T]): | |
| def meth(self) -> T: | |
| pass | |
| [case testIncrementalSwitchFromNominalToStructural] | |
| import a | |
| [file a.py] | |
| from b import B, fun | |
| class C(B): | |
| def x(self) -> int: pass | |
| def y(self) -> int: pass | |
| fun(C()) | |
| [file b.py] | |
| from typing import Protocol | |
| class B: | |
| def x(self) -> float: pass | |
| def fun(arg: B) -> None: | |
| arg.x() | |
| [file b.py.2] | |
| from typing import Protocol | |
| class B(Protocol): | |
| def x(self) -> float: pass | |
| def fun(arg: B) -> None: | |
| arg.x() | |
| [file a.py.3] | |
| from b import fun | |
| class C: | |
| def x(self) -> int: pass | |
| def y(self) -> int: pass | |
| fun(C()) | |
| [out1] | |
| [out2] | |
| [out3] | |
| [case testIncrementalSwitchFromStructuralToNominal] | |
| import a | |
| [file a.py] | |
| from b import fun | |
| class C: | |
| def x(self) -> int: pass | |
| def y(self) -> int: pass | |
| fun(C()) | |
| [file b.py] | |
| from typing import Protocol | |
| class B(Protocol): | |
| def x(self) -> float: pass | |
| def fun(arg: B) -> None: | |
| arg.x() | |
| [file b.py.2] | |
| from typing import Protocol | |
| class B: | |
| def x(self) -> float: pass | |
| def fun(arg: B) -> None: | |
| arg.x() | |
| [out1] | |
| [out2] | |
| tmp/a.py:5: error: Argument 1 to "fun" has incompatible type "C"; expected "B" | |
| [case testIncrementalWorksWithNamedTuple] | |
| import foo | |
| [file foo.py] | |
| from mid import MyTuple | |
| def accept_int(x: int) -> None: pass | |
| accept_int(MyTuple(1, "b", "c").a) | |
| [file mid.py] | |
| from bar import MyTuple | |
| [file bar.py] | |
| from typing import NamedTuple | |
| MyTuple = NamedTuple('MyTuple', [ | |
| ('a', int), | |
| ('b', str), | |
| ('c', str) | |
| ]) | |
| [file bar.py.2] | |
| from typing import NamedTuple | |
| MyTuple = NamedTuple('MyTuple', [ | |
| ('b', int), # a and b are swapped | |
| ('a', str), | |
| ('c', str) | |
| ]) | |
| [rechecked bar, mid, foo] | |
| [stale bar] | |
| [builtins fixtures/tuple.pyi] | |
| [out2] | |
| tmp/foo.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalWorksWithNestedNamedTuple] | |
| import foo | |
| [file foo.py] | |
| from mid import Outer | |
| def accept_int(x: int) -> None: pass | |
| accept_int(Outer.MyTuple(1, "b", "c").a) | |
| [file mid.py] | |
| from bar import Outer | |
| [file bar.py] | |
| from typing import NamedTuple | |
| class Outer: | |
| MyTuple = NamedTuple('MyTuple', [ | |
| ('a', int), | |
| ('b', str), | |
| ('c', str) | |
| ]) | |
| [file bar.py.2] | |
| from typing import NamedTuple | |
| class Outer: | |
| MyTuple = NamedTuple('MyTuple', [ | |
| ('b', int), # a and b are swapped | |
| ('a', str), | |
| ('c', str) | |
| ]) | |
| [rechecked bar, mid, foo] | |
| [stale bar] | |
| [builtins fixtures/tuple.pyi] | |
| [out2] | |
| tmp/foo.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalPartialSubmoduleUpdate] | |
| # cmd: mypy -m a | |
| # cmd2: mypy -m a a.c | |
| # flags: --follow-imports=skip | |
| [file a/__init__.py] | |
| from .b import B | |
| from .c import C | |
| [file a/b.py] | |
| class B: pass | |
| [file a/c.py] | |
| class C: pass | |
| [file a/c.py.2] | |
| class C: pass | |
| pass | |
| [rechecked a, a.c] | |
| [stale a, a.c] | |
| [out] | |
| [case testIncrementalNestedClassRef] | |
| import top | |
| [file top.py] | |
| from funcs import callee | |
| from classes import Outer | |
| def caller(a: Outer.Inner) -> None: | |
| callee(a) | |
| [file funcs.py] | |
| from classes import Outer | |
| def callee(a: Outer.Inner) -> None: | |
| pass | |
| [file classes.py] | |
| class Outer: | |
| class Inner: | |
| pass | |
| [file top.py.2] | |
| from funcs import callee | |
| from classes import Outer | |
| def caller(a: Outer.Inner) -> int: | |
| callee(a) | |
| return 0 | |
| [case testIncrementalLoadsParentAfterChild] | |
| # cmd: mypy -m r.s | |
| [file r/__init__.py] | |
| from . import s | |
| [file r/m.py] | |
| class R: pass | |
| [file r/s.py] | |
| from . import m | |
| R = m.R | |
| a: R | |
| [file r/s.py.2] | |
| from . import m | |
| R = m.R | |
| a: R | |
| [case testIncrementalBaseClassAttributeConflict] | |
| class A: pass | |
| class B: pass | |
| class X: | |
| attr: A | |
| class Y: | |
| attr: B | |
| class Z(X, Y): pass | |
| [stale] | |
| [out] | |
| main:8: error: Definition of "attr" in base class "X" is incompatible with definition in base class "Y" | |
| [out2] | |
| main:8: error: Definition of "attr" in base class "X" is incompatible with definition in base class "Y" | |
| [case testIncrementalFollowImportsSilent] | |
| # flags: --follow-imports=silent | |
| import a | |
| [file a.py] | |
| x = 0 | |
| [file a.py.2] | |
| x = 0 | |
| x + '' | |
| [case testIncrementalFollowImportsSkip] | |
| # flags: --follow-imports=skip | |
| import a | |
| reveal_type(a.x) | |
| [file a.py] | |
| / | |
| [file a.py.2] | |
| // | |
| [out] | |
| main:3: note: Revealed type is "Any" | |
| [out2] | |
| main:3: note: Revealed type is "Any" | |
| [case testIncrementalFollowImportsError] | |
| # flags: --follow-imports=error | |
| import a | |
| [file a.py] | |
| / | |
| [file a.py.2] | |
| // | |
| [out1] | |
| main:2: error: Import of "a" ignored | |
| main:2: note: (Using --follow-imports=error, module not passed on command line) | |
| [out2] | |
| main:2: error: Import of "a" ignored | |
| main:2: note: (Using --follow-imports=error, module not passed on command line) | |
| [case testIncrementalFollowImportsVariable] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| reveal_type(a.x) | |
| [file a.py] | |
| x = 0 | |
| [file mypy.ini] | |
| \[mypy] | |
| follow_imports = normal | |
| [file mypy.ini.2] | |
| \[mypy] | |
| follow_imports = skip | |
| [out1] | |
| main:3: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:3: note: Revealed type is "Any" | |
| [case testIncrementalFollowImportsVariablePyProjectTOML] | |
| # flags: --config-file tmp/pyproject.toml | |
| import a | |
| reveal_type(a.x) | |
| [file a.py] | |
| x = 0 | |
| [file pyproject.toml] | |
| \[tool.mypy] | |
| follow_imports = 'normal' | |
| [file pyproject.toml.2] | |
| \[tool.mypy] | |
| follow_imports = 'skip' | |
| [out1] | |
| main:3: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:3: note: Revealed type is "Any" | |
| [case testIncrementalIgnoreErrors] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| import module_that_will_be_deleted | |
| [file module_that_will_be_deleted.py] | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-a] | |
| ignore_errors = True | |
| [delete module_that_will_be_deleted.py.2] | |
| [out1] | |
| [out2] | |
| [case testIncrementalNamedTupleInMethod] | |
| from ntcrash import nope | |
| [file ntcrash.py] | |
| from typing import NamedTuple | |
| class C: | |
| def f(self) -> None: | |
| A = NamedTuple('A', [('x', int), ('y', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out1] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [case testIncrementalNamedTupleInMethod2] | |
| from ntcrash import nope | |
| [file ntcrash.py] | |
| from typing import NamedTuple | |
| class C: | |
| class D: | |
| def f(self) -> None: | |
| A = NamedTuple('A', [('x', int), ('y', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out1] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [case testIncrementalNamedTupleInMethod3] | |
| from ntcrash import nope | |
| [file ntcrash.py] | |
| from typing import NamedTuple | |
| class C: | |
| def a(self): | |
| class D: | |
| def f(self) -> None: | |
| A = NamedTuple('A', [('x', int), ('y', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out1] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [case testIncrementalTypedDictInMethod] | |
| from tdcrash import nope | |
| [file tdcrash.py] | |
| from typing import TypedDict | |
| class C: | |
| def f(self) -> None: | |
| A = TypedDict('A', {'x': int, 'y': int}) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out1] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [case testIncrementalTypedDictInMethod2] | |
| from tdcrash import nope | |
| [file tdcrash.py] | |
| from typing import TypedDict | |
| class C: | |
| class D: | |
| def f(self) -> None: | |
| A = TypedDict('A', {'x': int, 'y': int}) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out1] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [case testIncrementalTypedDictInMethod3] | |
| from tdcrash import nope | |
| [file tdcrash.py] | |
| from typing import TypedDict | |
| class C: | |
| def a(self): | |
| class D: | |
| def f(self) -> None: | |
| A = TypedDict('A', {'x': int, 'y': int}) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out1] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "tdcrash" has no attribute "nope" | |
| [case testIncrementalNewTypeInMethod] | |
| from ntcrash import nope | |
| [file ntcrash.py] | |
| from typing import NewType, NamedTuple, TypedDict | |
| class C: | |
| def f(self) -> None: | |
| X = NewType('X', int) | |
| A = TypedDict('A', {'x': X, 'y': int}) | |
| B = NamedTuple('B', [('x', X)]) | |
| def f() -> None: | |
| X = NewType('X', int) | |
| A = TypedDict('A', {'x': X, 'y': int}) | |
| B = NamedTuple('B', [('x', X)]) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out1] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [out2] | |
| main:1: error: Module "ntcrash" has no attribute "nope" | |
| [case testIncrementalInnerClassAttrInMethod] | |
| import crash | |
| nonexisting | |
| [file crash.py] | |
| class C: | |
| def f(self) -> None: | |
| class A: | |
| pass | |
| self.a = A() | |
| [out1] | |
| main:2: error: Name "nonexisting" is not defined | |
| [out2] | |
| main:2: error: Name "nonexisting" is not defined | |
| [case testIncrementalInnerClassAttrInMethodReveal] | |
| import crash | |
| reveal_type(crash.C().a) | |
| reveal_type(crash.D().a) | |
| [file crash.py] | |
| from typing import TypeVar, Generic | |
| T = TypeVar('T') | |
| class C: | |
| def f(self) -> None: | |
| class A: | |
| pass | |
| self.a = A() | |
| reveal_type(C().a) | |
| class D: | |
| def f(self) -> None: | |
| class A: | |
| def g(self) -> None: | |
| class B(Generic[T]): | |
| pass | |
| self.b = B[int]() | |
| self.a = A().b | |
| reveal_type(D().a) | |
| [out1] | |
| tmp/crash.py:8: note: Revealed type is "crash.A@5" | |
| tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int]" | |
| main:2: note: Revealed type is "crash.A@5" | |
| main:3: note: Revealed type is "crash.B@13[builtins.int]" | |
| [out2] | |
| tmp/crash.py:8: note: Revealed type is "crash.A@5" | |
| tmp/crash.py:17: note: Revealed type is "crash.B@13[builtins.int]" | |
| main:2: note: Revealed type is "crash.A@5" | |
| main:3: note: Revealed type is "crash.B@13[builtins.int]" | |
| [case testGenericMethodRestoreMetaLevel] | |
| from typing import Dict | |
| d = {} # type: Dict[str, int] | |
| g = d.get # This should not crash: see https://github.com/python/mypy/issues/2804 | |
| [builtins fixtures/dict.pyi] | |
| [case testGenericMethodRestoreMetaLevel2] | |
| from typing import TypeVar | |
| T = TypeVar('T') | |
| class D: | |
| def m(self, x: T) -> T: | |
| return x | |
| g = D().m # This should not crash: see https://github.com/python/mypy/issues/2804 | |
| [builtins fixtures/dict.pyi] | |
| [case testGenericMethodRestoreMetaLevel3] | |
| from typing import TypeVar | |
| T = TypeVar('T') | |
| class C: | |
| def m(self, x: T) -> T: | |
| return x | |
| class D(C): | |
| def __init__(self) -> None: | |
| self.d = super().m # This should not crash: see https://github.com/python/mypy/issues/2804 | |
| [builtins fixtures/dict.pyi] | |
| [case testIncrementalPerFileFlags] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| pass | |
| [file mypy.ini] | |
| \[mypy] | |
| warn_no_return = False | |
| \[mypy-a] | |
| warn_no_return = True | |
| [rechecked] | |
| [case testIncrementalClassVar] | |
| from typing import ClassVar | |
| class A: | |
| x: ClassVar | |
| A().x = 0 | |
| [out1] | |
| main:4: error: Cannot assign to class variable "x" via instance | |
| [out2] | |
| main:4: error: Cannot assign to class variable "x" via instance | |
| [case testIncrementalClassVarGone] | |
| import m | |
| m.A().x = 0 | |
| [file m.py] | |
| from typing import ClassVar | |
| class A: | |
| x: ClassVar[int] | |
| [file m.py.2] | |
| class A: | |
| x: int | |
| [out1] | |
| main:2: error: Cannot assign to class variable "x" via instance | |
| [case testCachingClassVar] | |
| import b | |
| [file a.py] | |
| from typing import ClassVar | |
| class A: | |
| x: ClassVar[int] | |
| [file b.py] | |
| import a | |
| [file b.py.2] | |
| import a | |
| a.A().x = 0 | |
| [out2] | |
| tmp/b.py:2: error: Cannot assign to class variable "x" via instance | |
| [case testSerializeTypedDict] | |
| import b | |
| reveal_type(b.x) | |
| y: b.A | |
| reveal_type(y) | |
| [file b.py] | |
| from typing import TypedDict | |
| A = TypedDict('A', {'x': int, 'y': str}) | |
| x: A | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out1] | |
| main:2: note: Revealed type is "TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})" | |
| main:4: note: Revealed type is "TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})" | |
| [out2] | |
| main:2: note: Revealed type is "TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})" | |
| main:4: note: Revealed type is "TypedDict('b.A', {'x': builtins.int, 'y': builtins.str})" | |
| [case testSerializeMetaclass] | |
| import b | |
| reveal_type(b.A.f()) | |
| m: b.M = b.A | |
| reveal_type(b.a.f()) | |
| [file b.py] | |
| from typing import Type | |
| class M(type): | |
| def f(cls) -> int: return 0 | |
| class A(metaclass=M): pass | |
| a: Type[A] | |
| [out] | |
| main:2: note: Revealed type is "builtins.int" | |
| main:4: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:2: note: Revealed type is "builtins.int" | |
| main:4: note: Revealed type is "builtins.int" | |
| [case testSerializeMetaclassInImportCycle1] | |
| import b | |
| import c | |
| reveal_type(b.A.f()) | |
| m: c.M = b.A | |
| reveal_type(b.a.f()) | |
| [file b.py] | |
| from typing import Type | |
| from c import M | |
| class A(metaclass=M): pass | |
| a: Type[A] | |
| [file c.py] | |
| class M(type): | |
| def f(cls) -> int: return 0 | |
| [out] | |
| main:3: note: Revealed type is "builtins.int" | |
| main:5: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:3: note: Revealed type is "builtins.int" | |
| main:5: note: Revealed type is "builtins.int" | |
| [case testSerializeMetaclassInImportCycle2] | |
| import b | |
| import c | |
| reveal_type(c.A.f()) | |
| m: b.M = c.A | |
| reveal_type(c.a.f()) | |
| [file b.py] | |
| from c import a | |
| class M(type): | |
| def f(cls) -> int: return 0 | |
| [file c.py] | |
| from typing import Type | |
| import b | |
| class A(metaclass=b.M): pass | |
| a: Type[A] | |
| [out] | |
| main:3: note: Revealed type is "builtins.int" | |
| main:5: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:3: note: Revealed type is "builtins.int" | |
| main:5: note: Revealed type is "builtins.int" | |
| [case testDeleteFile] | |
| import n | |
| [file n.py] | |
| import m | |
| [file m.py] | |
| x = 1 | |
| [delete m.py.2] | |
| [rechecked n] | |
| [stale n] | |
| [out2] | |
| tmp/n.py:1: error: Cannot find implementation or library stub for module named "m" | |
| tmp/n.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testDeleteFileWithinCycle] | |
| import a | |
| [file a.py] | |
| import b | |
| [file b.py] | |
| import c | |
| [file c.py] | |
| import a | |
| [file a.py.2] | |
| import c | |
| [delete b.py.2] | |
| [rechecked a, c] | |
| [stale a] | |
| [out2] | |
| [case testThreePassesBasic] | |
| import m | |
| [file m.py] | |
| def foo(): | |
| pass | |
| [file m.py.2] | |
| def foo() -> None: | |
| pass | |
| [file m.py.3] | |
| def foo(): | |
| pass | |
| [rechecked m] | |
| [stale m] | |
| [rechecked2 m] | |
| [stale2 m] | |
| [out3] | |
| [case testThreePassesErrorInThirdPass] | |
| import m | |
| [file m.py] | |
| def foo(): | |
| pass | |
| [file m.py.2] | |
| def foo() -> None: | |
| pass | |
| [file m.py.3] | |
| def foo() -> int: | |
| return '' | |
| [rechecked m] | |
| [stale m] | |
| [rechecked2 m] | |
| [stale2 m] | |
| [out3] | |
| tmp/m.py:2: error: Incompatible return value type (got "str", expected "int") | |
| [case testThreePassesThirdPassFixesError] | |
| import n | |
| [file n.py] | |
| import m | |
| x = m.foo(1) | |
| [file m.py] | |
| def foo(x): | |
| pass | |
| [file m.py.2] | |
| def foo() -> str: | |
| pass | |
| [file m.py.3] | |
| def foo(x) -> int: | |
| pass | |
| [rechecked m, n] | |
| [stale m, n] | |
| [rechecked2 m, n] | |
| [stale2 m, n] | |
| [out2] | |
| tmp/n.py:2: error: Too many arguments for "foo" | |
| [out3] | |
| [case testCacheDeletedAfterErrorsFound] | |
| import a | |
| [file a.py] | |
| from b import x | |
| [file b.py] | |
| from c import x | |
| [file c.py] | |
| x = 1 | |
| [file c.py.2] | |
| 1 + 1 | |
| [file a.py.3] | |
| from b import x | |
| 1 + 1 | |
| [out] | |
| [out2] | |
| tmp/b.py:1: error: Module "c" has no attribute "x" | |
| [out3] | |
| tmp/b.py:1: error: Module "c" has no attribute "x" | |
| [case testCacheDeletedAfterErrorsFound2] | |
| import a | |
| [file a.py] | |
| from b import x | |
| [file b.py] | |
| from c import C | |
| x: C | |
| [file c.py] | |
| class C: pass | |
| [file c.py.2] | |
| def C(): pass | |
| [file a.py.3] | |
| from b import x | |
| 1 + 1 | |
| [out] | |
| [out2] | |
| tmp/b.py:2: error: Function "c.C" is not valid as a type | |
| tmp/b.py:2: note: Perhaps you need "Callable[...]" or a callback protocol? | |
| [out3] | |
| tmp/b.py:2: error: Function "c.C" is not valid as a type | |
| tmp/b.py:2: note: Perhaps you need "Callable[...]" or a callback protocol? | |
| [case testCacheDeletedAfterErrorsFound3] | |
| import a | |
| [file a.py] | |
| import b | |
| b.f() | |
| [file b.py] | |
| def f() -> None: pass | |
| [file b.py.2] | |
| def f(x) -> None: pass | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Missing positional argument "x" in call to "f" | |
| [out3] | |
| tmp/a.py:2: error: Missing positional argument "x" in call to "f" | |
| [case testCacheDeletedAfterErrorsFound4] | |
| import a | |
| [file a.py] | |
| from b import x | |
| [file b.py] | |
| from c import x | |
| [file c.py] | |
| from d import x | |
| [file d.py] | |
| x = 1 | |
| [file d.py.2] | |
| 1 + 1 | |
| [file a.py.3] | |
| from b import x | |
| 1 + 1 | |
| [out] | |
| [out2] | |
| tmp/c.py:1: error: Module "d" has no attribute "x" | |
| [out3] | |
| tmp/c.py:1: error: Module "d" has no attribute "x" | |
| [case testNoCrashOnDeletedWithCacheOnCmdline] | |
| # cmd: mypy -m nonexistent | |
| # cmd2: mypy -m nonexistent | |
| [file nonexistent.py] | |
| [delete nonexistent.py.2] | |
| [out] | |
| [out2] | |
| tmp/nonexistent.py: error: Cannot read file: No such file or directory | |
| [case testSerializeAbstractPropertyIncremental] | |
| from abc import abstractmethod | |
| import typing | |
| class A: | |
| @property | |
| def f(self) -> int: | |
| return 1 | |
| @f.setter # type: ignore | |
| @abstractmethod | |
| def f(self, x: int) -> None: | |
| pass | |
| a = A() | |
| [builtins fixtures/property.pyi] | |
| [case testSerializeAbstractPropertyDisallowUntypedIncremental] | |
| # flags: --disallow-untyped-defs | |
| from abc import abstractmethod | |
| import typing | |
| class A: | |
| @property | |
| def f(self) -> int: | |
| return 1 | |
| @f.setter # type: ignore | |
| @abstractmethod | |
| def f(self, x: int) -> None: | |
| pass | |
| a = A() | |
| [builtins fixtures/property.pyi] | |
| [case testClassNamesResolutionCrashAccess] | |
| import mod | |
| [file mod.py] | |
| class C: | |
| def __init__(self) -> None: | |
| self.int = '' | |
| def f(self, f: int) -> None: | |
| pass | |
| [file mod.py.2] | |
| class C: | |
| def __init__(self) -> None: | |
| self.int = '' | |
| def f(self, f: int) -> None: | |
| f.x | |
| [out] | |
| [out2] | |
| tmp/mod.py:6: error: "int" has no attribute "x" | |
| [case testClassNamesResolutionCrashReadCache] | |
| import mod | |
| [file mod.py] | |
| import submod | |
| [file mod.py.2] | |
| from submod import C | |
| c = C() | |
| reveal_type(c.int) | |
| reveal_type(c.y) | |
| [file submod.py] | |
| from typing import List | |
| class C: | |
| def __init__(self) -> None: | |
| self.int = [] # type: List[int] | |
| def f(self, f: int) -> None: | |
| self.y = f | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [out2] | |
| tmp/mod.py:4: note: Revealed type is "builtins.list[builtins.int]" | |
| tmp/mod.py:5: note: Revealed type is "builtins.int" | |
| [case testClassNamesResolutionCrashReveal] | |
| import mod | |
| [file mod.py] | |
| class Foo(object): | |
| def __init__(self) -> None: | |
| self.bytes = b"foo" | |
| def bar(self, f: bytes): | |
| pass | |
| foo = Foo() | |
| foo.bar(b"test") | |
| [file mod.py.2] | |
| class Foo(object): | |
| def __init__(self) -> None: | |
| self.bytes = b"foo" | |
| def bar(self, f: bytes): | |
| reveal_type(f) | |
| foo = Foo() | |
| foo.bar(b"test") | |
| [out] | |
| [out2] | |
| tmp/mod.py:7: note: Revealed type is "builtins.bytes" | |
| [case testIncrementalWithSilentImports] | |
| # cmd: mypy -m a | |
| # cmd2: mypy -m b | |
| # flags: --follow-imports=silent | |
| [file a.py] | |
| import b | |
| b.foo(1, 2) | |
| [file b.py] | |
| def foo(a: int, b: int) -> str: | |
| return a + b | |
| [out1] | |
| [out2] | |
| tmp/b.py:2: error: Incompatible return value type (got "int", expected "str") | |
| [case testIncrementalWithSilentImportsReverse] | |
| -- Same commands as previous test, just in reverse order. | |
| -- expected output is also in reverse order | |
| # cmd: mypy -m b | |
| # cmd2: mypy -m a | |
| # flags: --follow-imports=silent | |
| [file a.py] | |
| import b | |
| b.foo(1, 2) | |
| [file b.py] | |
| def foo(a: int, b: int) -> str: | |
| return a + b | |
| [out] | |
| tmp/b.py:2: error: Incompatible return value type (got "int", expected "str") | |
| [out2] | |
| [case testForwardNamedTupleToUnionWithOtherNamedTUple] | |
| from typing import NamedTuple, Union | |
| class Person(NamedTuple): | |
| name: Union[str, "Pair"] | |
| class Pair(NamedTuple): | |
| first: str | |
| last: str | |
| Person(name=Pair(first="John", last="Doe")) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testNoCrashForwardRefToBrokenDoubleNewTypeIncremental] | |
| from typing import Any, List, NewType | |
| Foo = NewType('NotFoo', int) # type: ignore | |
| Foos = NewType('Foos', List[Foo]) # type: ignore | |
| def frob(foos: List[Foos]) -> None: | |
| pass | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testNoCrashForwardRefOverloadIncremental] | |
| from typing import overload, List | |
| @overload | |
| def f(x: int) -> int: ... | |
| @overload | |
| def f(x: F) -> F: ... | |
| def f(x): | |
| pass | |
| F = List[int] | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testNoCrashForwardRefOverloadIncrementalClass] | |
| from typing import overload, Tuple, NamedTuple | |
| x: C | |
| class C: | |
| @overload | |
| def f(self, x: str) -> N: pass | |
| @overload | |
| def f(self, x: int) -> int: pass | |
| def f(self, x): | |
| pass | |
| class N(NamedTuple): | |
| x: A | |
| A = Tuple[int] | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testNewTypeFromForwardNamedTupleIncremental] | |
| from typing import NewType, NamedTuple, Tuple | |
| NT = NewType('NT', 'N') | |
| class N(NamedTuple): | |
| x: int | |
| x: NT = N(1) # type: ignore | |
| x = NT(N(1)) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testNewTypeFromForwardTypedDictIncremental] | |
| from typing import NewType, Tuple, TypedDict, Dict | |
| NT = NewType('NT', N) # type: ignore | |
| class N(TypedDict): | |
| x: A | |
| A = Dict[str, int] | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| -- Some crazy self-referential named tuples, types dicts, and aliases | |
| -- to be sure that everything can be _serialized_ (i.e. ForwardRefs are removed). | |
| -- For this reason errors are silenced (tests with # type: ignore have equivalents in other files) | |
| [case testForwardTypeAliasInBase1] | |
| from typing import List | |
| class C(List['A']): | |
| pass | |
| A = List[int] | |
| x: int = C()[0][0] | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testForwardTypeAliasInBase2] | |
| from typing import List, Generic, TypeVar, NamedTuple | |
| T = TypeVar('T') | |
| class C(A, B): # type: ignore | |
| pass | |
| class G(Generic[T]): pass | |
| A = G[C] # type: ignore | |
| class B(NamedTuple): | |
| x: int | |
| C(1).x | |
| C(1)[0] | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [case testSerializeRecursiveAlias] | |
| from typing import Callable, Union | |
| Node = Union[str, int, Callable[[], "Node"]] | |
| n: Node | |
| [out] | |
| [case testSerializeRecursiveAliases1] | |
| from typing import Type, Callable, Union | |
| A = Union[A, int] # type: ignore | |
| B = Callable[[B], int] # type: ignore | |
| C = Type[C] # type: ignore | |
| [out] | |
| [case testSerializeRecursiveAliases2] | |
| from typing import Type, Callable, Union | |
| A = Union[B, int] # type: ignore | |
| B = Callable[[C], int] # type: ignore | |
| C = Type[A] # type: ignore | |
| [out] | |
| [case testSerializeRecursiveAliases3] | |
| from typing import Type, Callable, Union, NamedTuple | |
| A = Union[B, int] # type: ignore | |
| B = Callable[[C], int] # type: ignore | |
| class C(NamedTuple): # type: ignore | |
| x: A | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testGenericTypeAliasesForwardAnyIncremental1] | |
| from typing import TypeVar, Generic | |
| T = TypeVar('T') | |
| S = TypeVar('S') | |
| IntNode = Node[int, S] # type: ignore[used-before-def] | |
| AnyNode = Node[S, T] # type: ignore[used-before-def] | |
| class Node(Generic[T, S]): | |
| def __init__(self, x: T, y: S) -> None: | |
| self.x = x | |
| self.y = y | |
| def output() -> IntNode[str]: | |
| return Node(1, 'x') | |
| x = output() # type: IntNode | |
| y: IntNode | |
| y.x = 1 | |
| y.y = 1 | |
| y.y = 'x' | |
| z = Node(1, 'x') # type: AnyNode | |
| [out] | |
| [case testGenericTypeAliasesForwardAnyIncremental2] | |
| from typing import TypeVar, Generic | |
| T = TypeVar('T') | |
| S = TypeVar('S') | |
| class Node(Generic[T, S]): | |
| def __init__(self, x: T, y: S) -> None: | |
| self.x = x | |
| self.y = y | |
| def output() -> IntNode[str]: | |
| return Node(1, 'x') | |
| x = output() # type: IntNode | |
| y: IntNode | |
| y.x = 1 | |
| y.y = 1 | |
| y.y = 'x' | |
| z = Node(1, 'x') # type: AnyNode | |
| IntNode = Node[int, S] | |
| AnyNode = Node[S, T] | |
| [out] | |
| [case testNamedTupleForwardAsUpperBoundSerialization] | |
| from typing import NamedTuple, TypeVar, Generic | |
| T = TypeVar('T', bound='M') | |
| class G(Generic[T]): | |
| x: T | |
| yg: G[M] | |
| z: int = G[M]().x.x # type: ignore[used-before-def] | |
| z = G[M]().x[0] # type: ignore[used-before-def] | |
| M = NamedTuple('M', [('x', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [case testSelfRefNTIncremental1] | |
| from typing import Tuple, NamedTuple | |
| Node = NamedTuple('Node', [ | |
| ('name', str), | |
| ('children', Tuple['Node', ...]), # type: ignore | |
| ]) | |
| n: Node | |
| [builtins fixtures/tuple.pyi] | |
| [case testSelfRefNTIncremental2] | |
| from typing import Tuple, NamedTuple | |
| A = NamedTuple('A', [ | |
| ('x', str), | |
| ('y', Tuple['B', ...]), # type: ignore | |
| ]) | |
| class B(NamedTuple): | |
| x: A | |
| y: int | |
| n: A | |
| [builtins fixtures/tuple.pyi] | |
| [case testSelfRefNTIncremental3] | |
| from typing import NamedTuple, Tuple | |
| class B(NamedTuple): | |
| x: Tuple[A, int] # type: ignore | |
| y: int | |
| A = NamedTuple('A', [ | |
| ('x', str), | |
| ('y', 'B'), | |
| ]) | |
| n: B | |
| m: A | |
| lst = [m, n] | |
| [builtins fixtures/tuple.pyi] | |
| [case testSelfRefNTIncremental4] | |
| from typing import NamedTuple | |
| class B(NamedTuple): | |
| x: A # type: ignore | |
| y: int | |
| class A(NamedTuple): | |
| x: str | |
| y: B | |
| n: A | |
| [builtins fixtures/tuple.pyi] | |
| [case testSelfRefNTIncremental5] | |
| from typing import NamedTuple | |
| B = NamedTuple('B', [ | |
| ('x', A), # type: ignore | |
| ('y', int), | |
| ]) | |
| A = NamedTuple('A', [ | |
| ('x', str), | |
| ('y', 'B'), | |
| ]) | |
| n: A | |
| def f(m: B) -> None: pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testCrashWithPartialGlobalAndCycle] | |
| import bar | |
| [file foo.py] | |
| import bar | |
| my_global_dict = {} # type: ignore | |
| def external_func_0() -> None: | |
| global my_global_dict | |
| bar.external_list | |
| my_global_dict[12] = 0 | |
| [file bar.py] | |
| import foo | |
| external_list = [0] | |
| [builtins fixtures/dict.pyi] | |
| [case testIncrementalCrashOnTypeWithFunction] | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| from b import x | |
| [file b.py] | |
| from typing import TypeVar, Type | |
| T = TypeVar('T') | |
| def tp(arg: T) -> Type[T]: | |
| pass | |
| def func(x: int) -> int: | |
| pass | |
| x = tp(func) | |
| [out] | |
| [out2] | |
| [case testReprocessModuleEvenIfInterfaceHashDoesNotChange] | |
| import a | |
| import d | |
| [file a.py] | |
| import b | |
| x: b.c.A | |
| x = b.c.A() | |
| [file b.py] | |
| import c | |
| [file c.py] | |
| class A: | |
| x = 1 | |
| [file d.py] | |
| import a | |
| def f() -> None: pass | |
| [file a.py.2] | |
| import b | |
| x: b.c.A | |
| [file c.py.3] | |
| class A: | |
| x = 2 | |
| [file d.py.4] | |
| import a | |
| def f() -> None: | |
| from c import A | |
| a.x = [A(), a.x][0] | |
| [builtins fixtures/list.pyi] | |
| [stale] | |
| [rechecked a] | |
| [stale2] | |
| [rechecked2 c] | |
| [stale3] | |
| [rechecked3 d] | |
| [out1] | |
| [out2] | |
| [out3] | |
| [out4] | |
| [case testTreeShadowingViaParentPackage] | |
| import m.semanal | |
| [file m/__init__.py] | |
| pass | |
| [file m/nodes.py] | |
| if False: | |
| import m.types | |
| import m.semanal | |
| class Node: | |
| line: int | |
| class FuncBase(Node): | |
| type: m.types.Type | |
| class OverloadedFuncDef(FuncBase): pass | |
| [file m/types.py] | |
| from m.nodes import Node | |
| class Type(Node): pass | |
| class Overloaded(Type): pass | |
| [file m/semanal.py] | |
| from m.nodes import OverloadedFuncDef | |
| from m.types import Overloaded | |
| class C: | |
| def func(self, defn: OverloadedFuncDef): | |
| defn.type = Overloaded() | |
| defn.type.line = 0 | |
| [file m/nodes.py.2] | |
| if False: | |
| import m.types | |
| import m.semanal | |
| class Node: | |
| line: int | |
| class FuncBase(Node): | |
| type: m.types.Type | |
| class OverloadedFuncDef(FuncBase): pass | |
| extra = 1 | |
| [file m/types.py.2] | |
| from m.nodes import Node | |
| class Type(Node): pass | |
| class Overloaded(Type): pass | |
| extra = 1 | |
| [builtins fixtures/list.pyi] | |
| [file m/semanal.py.2] | |
| from m.nodes import OverloadedFuncDef | |
| from m.types import Overloaded | |
| class C: | |
| def func(self, defn: OverloadedFuncDef): | |
| defn.type = Overloaded() | |
| defn.type.line = 0 | |
| extra = 1 | |
| [out1] | |
| [out2] | |
| [case testErrorsAffectDependentsOnly] | |
| # cmd: mypy -m m.a m.b m.c | |
| [file m/__init__.py] | |
| [file m/a.py] | |
| 1 + '' # Deliberate error | |
| [file m/b.py] | |
| import m.a # Depends on module with error | |
| [file m/c.py] | |
| import m # No error here | |
| [rechecked] | |
| [out1] | |
| tmp/m/a.py:1: error: Unsupported operand types for + ("int" and "str") | |
| [out2] | |
| tmp/m/a.py:1: error: Unsupported operand types for + ("int" and "str") | |
| [case testDisallowAnyExprIncremental] | |
| # cmd: mypy -m main | |
| # flags: --disallow-any-expr | |
| [file ns.py] | |
| class Namespace: | |
| def __init__(self): | |
| self.user = 0 | |
| [file main.py] | |
| import ns | |
| user = ns.Namespace().user | |
| [out1] | |
| tmp/main.py:2: error: Expression has type "Any" | |
| [out2] | |
| tmp/main.py:2: error: Expression has type "Any" | |
| [case testIncrementalStrictOptional] | |
| import a | |
| 1 + a.foo() | |
| [file a.py] | |
| def foo() -> int: return 0 | |
| [file a.py.2] | |
| from typing import Optional | |
| def foo() -> Optional[int]: return 0 | |
| [out1] | |
| [out2] | |
| main:2: error: Unsupported operand types for + ("int" and "None") | |
| main:2: note: Right operand is of type "int | None" | |
| [case testAttrsIncrementalSubclassingCached] | |
| from a import A | |
| import attrs | |
| @attrs.define | |
| class B(A): | |
| e: str = 'e' | |
| a = B(5, [5], 'foo') | |
| a.a = 6 | |
| a._b = [2] | |
| a.c = 'yo' | |
| a._d = 22 | |
| a.e = 'hi' | |
| [file a.py] | |
| import attrs | |
| from typing import List, ClassVar | |
| @attrs.define | |
| class A: | |
| a: int | |
| _b: List[int] | |
| c: str = '18' | |
| _d: int = attrs.field(validator=None, default=18) | |
| E = 7 | |
| F: ClassVar[int] = 22 | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| [out2] | |
| [case testAttrsIncrementalSubclassingCachedConverter] | |
| from a import A | |
| import attrs | |
| @attrs.define | |
| class B(A): | |
| pass | |
| reveal_type(B) | |
| [file a.py] | |
| def converter(s:int) -> str: | |
| return 'hello' | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: str = attrs.field(converter=converter) | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:6: note: Revealed type is "def (x: builtins.int) -> __main__.B" | |
| [out2] | |
| main:6: note: Revealed type is "def (x: builtins.int) -> __main__.B" | |
| [case testAttrsIncrementalSubclassingCachedType] | |
| from a import A | |
| import attrs | |
| @attrs.define | |
| class B(A): | |
| pass | |
| reveal_type(B) | |
| [file a.py] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: int | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:6: note: Revealed type is "def (x: builtins.int) -> __main__.B" | |
| [out2] | |
| main:6: note: Revealed type is "def (x: builtins.int) -> __main__.B" | |
| [case testAttrsIncrementalArguments] | |
| from a import Frozen, NoInit, NoCmp | |
| f = Frozen(5) | |
| f.x = 6 | |
| g = NoInit() | |
| Frozen(1) < Frozen(2) | |
| Frozen(1) <= Frozen(2) | |
| Frozen(1) > Frozen(2) | |
| Frozen(1) >= Frozen(2) | |
| NoCmp(1) < NoCmp(2) | |
| NoCmp(1) <= NoCmp(2) | |
| NoCmp(1) > NoCmp(2) | |
| NoCmp(1) >= NoCmp(2) | |
| [file a.py] | |
| import attrs | |
| @attrs.frozen | |
| class Frozen: | |
| x: int | |
| @attrs.define(init=False) | |
| class NoInit: | |
| x: int | |
| @attrs.define(eq=False) | |
| class NoCmp: | |
| x: int | |
| [builtins fixtures/plugin_attrs.pyi] | |
| [rechecked] | |
| [stale] | |
| [out1] | |
| main:3: error: Property "x" defined in "Frozen" is read-only | |
| main:12: error: Unsupported left operand type for < ("NoCmp") | |
| main:13: error: Unsupported left operand type for <= ("NoCmp") | |
| main:14: error: Unsupported left operand type for > ("NoCmp") | |
| main:15: error: Unsupported left operand type for >= ("NoCmp") | |
| [out2] | |
| main:3: error: Property "x" defined in "Frozen" is read-only | |
| main:12: error: Unsupported left operand type for < ("NoCmp") | |
| main:13: error: Unsupported left operand type for <= ("NoCmp") | |
| main:14: error: Unsupported left operand type for > ("NoCmp") | |
| main:15: error: Unsupported left operand type for >= ("NoCmp") | |
| [case testAttrsIncrementalDunder] | |
| from a import A | |
| reveal_type(A) # N: Revealed type is "def (a: builtins.int) -> a.A" | |
| reveal_type(A.__lt__) # N: Revealed type is "def [_AT] (self: _AT`3, other: _AT`3) -> builtins.bool" | |
| reveal_type(A.__le__) # N: Revealed type is "def [_AT] (self: _AT`4, other: _AT`4) -> builtins.bool" | |
| reveal_type(A.__gt__) # N: Revealed type is "def [_AT] (self: _AT`5, other: _AT`5) -> builtins.bool" | |
| reveal_type(A.__ge__) # N: Revealed type is "def [_AT] (self: _AT`6, other: _AT`6) -> builtins.bool" | |
| A(1) < A(2) | |
| A(1) <= A(2) | |
| A(1) > A(2) | |
| A(1) >= A(2) | |
| A(1) == A(2) | |
| A(1) != A(2) | |
| A(1) < 1 # E: Unsupported operand types for < ("A" and "int") | |
| A(1) <= 1 # E: Unsupported operand types for <= ("A" and "int") | |
| A(1) > 1 # E: Unsupported operand types for > ("A" and "int") | |
| A(1) >= 1 # E: Unsupported operand types for >= ("A" and "int") | |
| A(1) == 1 | |
| A(1) != 1 | |
| 1 < A(1) # E: Unsupported operand types for > ("A" and "int") | |
| 1 <= A(1) # E: Unsupported operand types for >= ("A" and "int") | |
| 1 > A(1) # E: Unsupported operand types for < ("A" and "int") | |
| 1 >= A(1) # E: Unsupported operand types for <= ("A" and "int") | |
| 1 == A(1) | |
| 1 != A(1) | |
| [file a.py] | |
| from attr import attrib, attrs | |
| @attrs(auto_attribs=True) | |
| class A: | |
| a: int | |
| [builtins fixtures/plugin_attrs.pyi] | |
| [rechecked] | |
| [stale] | |
| [out2] | |
| main:2: note: Revealed type is "def (a: builtins.int) -> a.A" | |
| main:3: note: Revealed type is "def [_AT] (self: _AT`3, other: _AT`3) -> builtins.bool" | |
| main:4: note: Revealed type is "def [_AT] (self: _AT`4, other: _AT`4) -> builtins.bool" | |
| main:5: note: Revealed type is "def [_AT] (self: _AT`5, other: _AT`5) -> builtins.bool" | |
| main:6: note: Revealed type is "def [_AT] (self: _AT`6, other: _AT`6) -> builtins.bool" | |
| main:15: error: Unsupported operand types for < ("A" and "int") | |
| main:16: error: Unsupported operand types for <= ("A" and "int") | |
| main:17: error: Unsupported operand types for > ("A" and "int") | |
| main:18: error: Unsupported operand types for >= ("A" and "int") | |
| main:22: error: Unsupported operand types for > ("A" and "int") | |
| main:23: error: Unsupported operand types for >= ("A" and "int") | |
| main:24: error: Unsupported operand types for < ("A" and "int") | |
| main:25: error: Unsupported operand types for <= ("A" and "int") | |
| [case testAttrsIncrementalSubclassModified] | |
| from b import B | |
| B(5, 'foo') | |
| [file a.py] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: int | |
| [file b.py] | |
| import attrs | |
| from a import A | |
| @attrs.define | |
| class B(A): | |
| y: str | |
| [file b.py.2] | |
| import attrs | |
| from a import A | |
| @attrs.define | |
| class B(A): | |
| y: int | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| [out2] | |
| main:2: error: Argument 2 to "B" has incompatible type "str"; expected "int" | |
| [rechecked b] | |
| [case testAttrsIncrementalSubclassModifiedErrorFirst] | |
| from b import B | |
| B(5, 'foo') | |
| [file a.py] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: int | |
| [file b.py] | |
| import attrs | |
| from a import A | |
| @attrs.define | |
| class B(A): | |
| y: int | |
| [file b.py.2] | |
| import attrs | |
| from a import A | |
| @attrs.define | |
| class B(A): | |
| y: str | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:2: error: Argument 2 to "B" has incompatible type "str"; expected "int" | |
| [out2] | |
| [rechecked b] | |
| [case testAttrsIncrementalThreeFiles] | |
| from c import C | |
| C(5, 'foo', True) | |
| [file a.py] | |
| import attrs | |
| @attrs.define(slots=False) | |
| class A: | |
| a: int | |
| [file b.py] | |
| import attrs | |
| @attrs.define(slots=False) | |
| class B: | |
| b: str | |
| [file c.py] | |
| from a import A | |
| from b import B | |
| import attrs | |
| @attrs.define(slots=False) | |
| class C(A, B): | |
| c: bool | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| [out2] | |
| [case testAttrsIncrementalConverterInSubmodule] | |
| from a.a import A | |
| reveal_type(A) | |
| [file a/__init__.py] | |
| [file a/a.py] | |
| from typing import Optional | |
| def converter(s:Optional[int]) -> int: | |
| ... | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: int = attrs.field(converter=converter) | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:2: note: Revealed type is "def (x: builtins.int | None) -> a.a.A" | |
| [out2] | |
| main:2: note: Revealed type is "def (x: builtins.int | None) -> a.a.A" | |
| [case testAttrsIncrementalConverterManyStyles] | |
| import a | |
| [file a.py] | |
| from base import Base | |
| Base(1, 'str', True) | |
| Base(None, None, None) | |
| from subclass import A, B | |
| A(1, 'str', True) | |
| A(None, None, None) | |
| B(1, 'str', True, 1, 'str', True) | |
| B(None, None, None, None, None, None) | |
| from submodule.base import SubBase | |
| SubBase(1, 'str', True) | |
| SubBase(None, None, None) | |
| from submodule.subclass import AA, BB | |
| AA(1, 'str', True) | |
| AA(None, None, None) | |
| BB(1, 'str', True, 1, 'str', True) | |
| BB(None, None, None, None, None, None) | |
| from submodule.subsubclass import SubAA, SubBB | |
| SubAA(1, 'str', True) | |
| SubAA(None, None, None) | |
| SubBB(1, 'str', True, 1, 'str', True) | |
| SubBB(None, None, None, None, None, None) | |
| [file a.py.2] | |
| # Now with errors. | |
| from base import Base | |
| Base(1, 1, True) | |
| from subclass import A, B | |
| A(1, 1, True) | |
| B(1, 'str', True, 1, 1, True) | |
| from submodule.base import SubBase | |
| SubBase(1, 1, True) | |
| from submodule.subclass import AA, BB | |
| AA(1, 1, True) | |
| BB(1, 'str', True, 1, 1, True) | |
| from submodule.subsubclass import SubAA, SubBB | |
| SubAA(1, 1, True) | |
| SubBB(1, 'str', True, 1, 1, True) | |
| [file foo.py] | |
| from typing import Optional | |
| def maybe_int(x: Optional[int]) -> int: | |
| ... | |
| [file bar.py] | |
| from typing import Optional | |
| def maybe_bool(x: Optional[bool]) -> bool: | |
| ... | |
| [file base.py] | |
| from typing import Optional | |
| import attrs | |
| import bar | |
| from foo import maybe_int | |
| def maybe_str(x: Optional[str]) -> str: | |
| ... | |
| @attrs.define | |
| class Base: | |
| x: int = attrs.field(converter=maybe_int) | |
| y: str = attrs.field(converter=maybe_str) | |
| z: bool = attrs.field(converter=bar.maybe_bool) | |
| [file subclass.py] | |
| from typing import Optional | |
| import attrs | |
| from base import Base | |
| @attrs.define | |
| class A(Base): pass | |
| import bar | |
| from foo import maybe_int | |
| def maybe_str(x: Optional[str]) -> str: | |
| ... | |
| @attrs.define | |
| class B(Base): | |
| xx: int = attrs.field(converter=maybe_int) | |
| yy: str = attrs.field(converter=maybe_str) | |
| zz: bool = attrs.field(converter=bar.maybe_bool) | |
| [file submodule/__init__.py] | |
| [file submodule/base.py] | |
| from typing import Optional | |
| import attrs | |
| import bar | |
| from foo import maybe_int | |
| def maybe_str(x: Optional[str]) -> str: | |
| ... | |
| @attrs.define | |
| class SubBase: | |
| x: int = attrs.field(converter=maybe_int) | |
| y: str = attrs.field(converter=maybe_str) | |
| z: bool = attrs.field(converter=bar.maybe_bool) | |
| [file submodule/subclass.py] | |
| from typing import Optional | |
| import attrs | |
| from base import Base | |
| @attrs.define | |
| class AA(Base): pass | |
| import bar | |
| from foo import maybe_int | |
| def maybe_str(x: Optional[str]) -> str: | |
| ... | |
| @attrs.define | |
| class BB(Base): | |
| xx: int = attrs.field(converter=maybe_int) | |
| yy: str = attrs.field(converter=maybe_str) | |
| zz: bool = attrs.field(converter=bar.maybe_bool) | |
| [file submodule/subsubclass.py] | |
| from typing import Optional | |
| import attrs | |
| from .base import SubBase | |
| @attrs.define | |
| class SubAA(SubBase): pass | |
| import bar | |
| from foo import maybe_int | |
| def maybe_str(x: Optional[str]) -> str: | |
| ... | |
| @attrs.define | |
| class SubBB(SubBase): | |
| xx: int = attrs.field(converter=maybe_int) | |
| yy: str = attrs.field(converter=maybe_str) | |
| zz: bool = attrs.field(converter=bar.maybe_bool) | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| [out2] | |
| tmp/a.py:3: error: Argument 2 to "Base" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:6: error: Argument 2 to "A" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:7: error: Argument 5 to "B" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:10: error: Argument 2 to "SubBase" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:13: error: Argument 2 to "AA" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:14: error: Argument 5 to "BB" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:17: error: Argument 2 to "SubAA" has incompatible type "int"; expected "str | None" | |
| tmp/a.py:18: error: Argument 5 to "SubBB" has incompatible type "int"; expected "str | None" | |
| [case testAttrsIncrementalConverterInFunction] | |
| import attrs | |
| def foo() -> None: | |
| def foo(x: str) -> int: | |
| ... | |
| @attrs.define | |
| class A: | |
| x: int = attrs.field(converter=foo) | |
| reveal_type(A) | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:8: note: Revealed type is "def (x: builtins.str) -> __main__.A@6" | |
| [out2] | |
| main:8: note: Revealed type is "def (x: builtins.str) -> __main__.A@6" | |
| -- FIXME: new analyzer busted | |
| [case testAttrsIncrementalConverterInSubmoduleForwardRef-skip] | |
| from a.a import A | |
| reveal_type(A) | |
| [file a/__init__.py] | |
| [file a/a.py] | |
| from typing import List | |
| def converter(s:F) -> int: | |
| ... | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: int = attrs.field(converter=converter) | |
| F = List[int] | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| main:3: note: Revealed type is "def (x: builtins.list[builtins.int]) -> a.a.A" | |
| [out2] | |
| main:3: note: Revealed type is "def (x: builtins.list[builtins.int]) -> a.a.A" | |
| -- FIXME: new analyzer busted | |
| [case testAttrsIncrementalConverterType-skip] | |
| from a import C | |
| import attrs | |
| o = C("1", "2", "3", "4") | |
| o = C(1, 2, "3", 4) | |
| reveal_type(C) | |
| @attrs.define | |
| class D(C): | |
| x: str | |
| reveal_type(D) | |
| [file a.py] | |
| from typing import overload | |
| import attrs | |
| @attrs.define | |
| class A: | |
| x: str | |
| @overload | |
| def parse(x: int) -> int: | |
| ... | |
| @overload | |
| def parse(x: str, y: str = '') -> int: | |
| ... | |
| def parse(x, y): ... | |
| @attrs.define | |
| class C: | |
| a: complex = attrs.field(converter=complex) | |
| b: int = attrs.field(converter=int) | |
| c: A = attrs.field(converter=A) | |
| d: int = attrs.field(converter=parse) | |
| [builtins fixtures/plugin_attrs.pyi] | |
| [out1] | |
| main:6: note: Revealed type is "def (a: Union[builtins.float, builtins.str], b: Union[builtins.str, builtins.bytes, builtins.int], c: builtins.str, d: Union[builtins.int, builtins.str]) -> a.C" | |
| main:10: note: Revealed type is "def (a: Union[builtins.float, builtins.str], b: Union[builtins.str, builtins.bytes, builtins.int], c: builtins.str, d: Union[builtins.int, builtins.str], x: builtins.str) -> __main__.D" | |
| [out2] | |
| main:6: note: Revealed type is "def (a: Union[builtins.float, builtins.str], b: Union[builtins.str, builtins.bytes, builtins.int], c: builtins.str, d: Union[builtins.int, builtins.str]) -> a.C" | |
| main:10: note: Revealed type is "def (a: Union[builtins.float, builtins.str], b: Union[builtins.str, builtins.bytes, builtins.int], c: builtins.str, d: Union[builtins.int, builtins.str], x: builtins.str) -> __main__.D" | |
| [case testAttrsIncrementalThreeRuns] | |
| from a import A | |
| A(5) | |
| [file a.py] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| a: int | |
| [file a.py.2] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| a: str | |
| [file a.py.3] | |
| import attrs | |
| @attrs.define | |
| class A: | |
| a: int = 6 | |
| [builtins fixtures/list.pyi] | |
| [out1] | |
| [out2] | |
| main:2: error: Argument 1 to "A" has incompatible type "int"; expected "str" | |
| [out3] | |
| [case testDeletedDepLineNumber] | |
| # The import is not on line 1 and that data should be preserved | |
| import a | |
| [file a.py] | |
| [delete a.py.2] | |
| [out1] | |
| [out2] | |
| main:2: error: Cannot find implementation or library stub for module named "a" | |
| main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testIncrementalInheritanceAddAnnotation] | |
| import a | |
| [file a.py] | |
| import b | |
| def foo() -> None: | |
| 1 + b.Bar().get() | |
| [file b.py] | |
| from c import Baz | |
| class Bar(Baz): pass | |
| [file c.py] | |
| class Baz: | |
| def get(self): | |
| return 1 | |
| [file c.py.2] | |
| from typing import Optional | |
| class Baz: | |
| def get(self) -> Optional[int]: | |
| return 1 | |
| [out] | |
| [out2] | |
| tmp/a.py:3: error: Unsupported operand types for + ("int" and "None") | |
| tmp/a.py:3: note: Right operand is of type "int | None" | |
| [case testIncrementalMetaclassUpdate] | |
| import a | |
| [file a.py] | |
| from b import B | |
| B.x | |
| [file b.py] | |
| import c | |
| class B(metaclass=c.M): pass | |
| [file c.py] | |
| class M(type): | |
| x: int | |
| [file c.py.2] | |
| class M(type): | |
| y: int | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: "type[B]" has no attribute "x" | |
| [case testIncrementalLotsOfInheritance] | |
| import a | |
| [file a.py] | |
| from b import B | |
| from d import D | |
| def take(d: D) -> None: pass | |
| def foo() -> None: | |
| take(B()) | |
| [file b.py] | |
| from c import C | |
| class B(C): pass | |
| [file c.py] | |
| from d import D | |
| class C(D): pass | |
| [file c.py.2] | |
| from d import D | |
| class C: pass | |
| [file d.py] | |
| class D: pass | |
| [out] | |
| [out2] | |
| tmp/a.py:5: error: Argument 1 to "take" has incompatible type "B"; expected "D" | |
| [case testIncrementalInheritanceProperty] | |
| import a | |
| [file a.py] | |
| import b | |
| def foo() -> None: | |
| 1 + b.Bar().x | |
| [file b.py] | |
| from c import Baz | |
| class Bar(Baz): pass | |
| [file c.py] | |
| class Baz: | |
| def __init__(self) -> None: | |
| self.x = 12 # type: int | |
| [file c.py.2] | |
| class Baz: | |
| def __init__(self) -> None: | |
| self.x = 'lol' # type: str | |
| [out] | |
| [out2] | |
| tmp/a.py:3: error: Unsupported operand types for + ("int" and "str") | |
| [case testIncrementalWithIgnoresTwice] | |
| import a | |
| [file a.py] | |
| import b | |
| import foo # type: ignore | |
| [file b.py] | |
| x = 1 | |
| [file b.py.2] | |
| x = 'hi' | |
| [file b.py.3] | |
| x = 1 | |
| [builtins fixtures/module.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testIgnoredImport2] | |
| import x | |
| [file y.py] | |
| import xyz # type: ignore | |
| B = 0 | |
| from x import A | |
| [file x.py] | |
| A = 0 | |
| from y import B | |
| [file x.py.2] | |
| A = 1 | |
| from y import B | |
| [file x.py.3] | |
| A = 2 | |
| from y import B | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testDeletionOfSubmoduleTriggersImportFrom2] | |
| from p.q import f | |
| f() | |
| [file p/__init__.py] | |
| [file p/q.py] | |
| def f() -> None: pass | |
| [delete p/q.py.2] | |
| [file p/q.py.3] | |
| def f(x: int) -> None: pass | |
| [out] | |
| [out2] | |
| main:1: error: Cannot find implementation or library stub for module named "p.q" | |
| main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [out3] | |
| main:2: error: Missing positional argument "x" in call to "f" | |
| [case testDeleteIndirectDependency] | |
| import b | |
| b.x.foo() | |
| [file b.py] | |
| import c | |
| x = c.Foo() | |
| [file c.py] | |
| class Foo: | |
| def foo(self) -> None: pass | |
| [delete c.py.2] | |
| [file b.py.2] | |
| class Foo: | |
| def foo(self) -> None: pass | |
| x = Foo() | |
| [out] | |
| [out2] | |
| [case testImportReExportInCycle] | |
| from m import One | |
| [file m/__init__.py] | |
| from .one import One | |
| from .two import Two | |
| [file m/one.py] | |
| class One: | |
| pass | |
| [file m/two.py] | |
| import m | |
| class Two: | |
| pass | |
| [file m/one.py.2] | |
| class One: | |
| name: str | |
| [file m/two.py.2] | |
| import m | |
| reveal_type(m.One.name) | |
| class Two: | |
| pass | |
| [out2] | |
| tmp/m/two.py:2: note: Revealed type is "builtins.str" | |
| [case testImportUnusedIgnore1] | |
| # flags: --warn-unused-ignores | |
| import a | |
| [file a.py] | |
| import b | |
| import foo # type: ignore | |
| [file b.py] | |
| x = 1 | |
| [file b.py.2] | |
| x = '2' | |
| [case testImportUnusedIgnore2] | |
| # flags: --warn-unused-ignores | |
| import a | |
| [file a.py] | |
| import b | |
| import c # type: ignore | |
| [file b.py] | |
| x = 1 | |
| [file b.py.2] | |
| x = 'hi' | |
| [file c.py.3] | |
| pass | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/a.py:2: error: Unused "type: ignore" comment | |
| -- Test that a non cache_fine_grained run can use a fine-grained cache | |
| [case testRegularUsesFgCache] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| x = 0 | |
| [file mypy.ini] | |
| \[mypy] | |
| cache_fine_grained = True | |
| local_partial_types = True | |
| [file mypy.ini.2] | |
| \[mypy] | |
| cache_fine_grained = False | |
| local_partial_types = True | |
| -- Nothing should get rechecked | |
| [rechecked] | |
| [stale] | |
| [case testFgCacheNeedsFgCache] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| x = 0 | |
| [file mypy.ini] | |
| \[mypy] | |
| cache_fine_grained = False | |
| [file mypy.ini.2] | |
| \[mypy] | |
| cache_fine_grained = True | |
| [rechecked _typeshed, a, builtins, types, typing] | |
| [stale _typeshed, a, builtins, types, typing] | |
| [builtins fixtures/tuple.pyi] | |
| [case testIncrementalPackageNameOverload] | |
| # cmd: mypy -m main a | |
| # flags: --follow-imports=skip | |
| [file main.py] | |
| from a import x | |
| x.foo() | |
| [file a/__init__.py] | |
| pass | |
| [file a/__init__.py.2] | |
| x = 10 | |
| [file a/x.py] | |
| def foo() -> None: | |
| pass | |
| [out] | |
| [out2] | |
| tmp/main.py:2: error: "int" has no attribute "foo" | |
| [case testIncrementalFineGrainedCacheError1] | |
| # flags: --cache-fine-grained --no-sqlite-cache | |
| import a | |
| [file a.py] | |
| [file b.py] | |
| x = 0 | |
| [file a.py.2] | |
| from b import x | |
| 1 + 'lol' | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Unsupported operand types for + ("int" and "str") | |
| [case testIncrementalBustedFineGrainedCache1] | |
| # flags: --cache-fine-grained --no-sqlite-cache | |
| import a | |
| import b | |
| [file a.py] | |
| [file b.py] | |
| -- This is a heinous hack, but we simulate having a invalid cache by clobbering | |
| -- the proto deps file with something with mtime mismatches. | |
| [file ../.mypy_cache/3.10/@deps.meta.json.2] | |
| {"snapshot": {"__main__": "a7c958b001a45bd6a2a320f4e53c4c16", "a": "d41d8cd98f00b204e9800998ecf8427e", "b": "d41d8cd98f00b204e9800998ecf8427e", "builtins": "c532c89da517a4b779bcf7a964478d67"}, "deps_meta": {"@root": {"path": "@root.deps.json", "mtime": 0}, "__main__": {"path": "__main__.deps.json", "mtime": 0}, "a": {"path": "a.deps.json", "mtime": 0}, "b": {"path": "b.deps.json", "mtime": 0}, "builtins": {"path": "builtins.deps.json", "mtime": 0}}} | |
| [file ../.mypy_cache/.gitignore] | |
| # Another hack to not trigger a .gitignore creation failure "false positive" | |
| [file ../.mypy_cache/CACHEDIR.TAG] | |
| Signature: 8a477f597d28d172789f06886806bc55 | |
| # Another another hack to not trigger a CACHEDIR.TAG creation failure "false positive" | |
| [file b.py.2] | |
| # uh | |
| -- Every file should get reloaded, since the cache was invalidated | |
| [stale _typeshed, a, b, builtins, types, typing] | |
| [rechecked _typeshed, a, b, builtins, types, typing] | |
| [builtins fixtures/tuple.pyi] | |
| [case testIncrementalBustedFineGrainedCache2] | |
| # flags2: --cache-fine-grained | |
| import a | |
| import b | |
| [file a.py] | |
| [file b.py] | |
| [file b.py.2] | |
| # uh | |
| -- Every file should get reloaded, since the settings changed | |
| [stale _typeshed, a, b, builtins, types, typing] | |
| [rechecked _typeshed, a, b, builtins, types, typing] | |
| [builtins fixtures/tuple.pyi] | |
| [case testIncrementalBustedFineGrainedCache3] | |
| # flags: --cache-fine-grained --no-sqlite-cache | |
| import a | |
| import b | |
| [file a.py] | |
| [file b.py] | |
| -- This is a heinous hack, but we simulate having a invalid cache by deleting | |
| -- the proto deps file. | |
| [delete ../.mypy_cache/3.10/@deps.meta.json.2] | |
| [file b.py.2] | |
| # uh | |
| -- Every file should get reloaded, since the cache was invalidated | |
| [stale _typeshed, a, b, builtins, types, typing] | |
| [rechecked _typeshed, a, b, builtins, types, typing] | |
| [builtins fixtures/tuple.pyi] | |
| [case testIncrementalWorkingFineGrainedCache] | |
| # flags: --cache-fine-grained | |
| # flags2: --cache-fine-grained | |
| import a | |
| import b | |
| [file a.py] | |
| [file b.py] | |
| [file b.py.2] | |
| # uh | |
| -- b gets rechecked because it changed, but nothing is stale | |
| -- since the interface did not change | |
| [stale] | |
| [rechecked b] | |
| [case testIncrementalDataclassesSubclassingCached] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| e: str = 'e' | |
| a = B(5, [5], 'foo') | |
| a.a = 6 | |
| a._b = [2] | |
| a.c = 'yo' | |
| a._d = 22 | |
| a.e = 'hi' | |
| [file a.py] | |
| from dataclasses import dataclass, field | |
| from typing import ClassVar, List | |
| @dataclass | |
| class A: | |
| a: int | |
| _b: List[int] | |
| c: str = '18' | |
| _d: int = field(default=False) | |
| E = 7 | |
| F: ClassVar[int] = 22 | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| [case testIncrementalDataclassesSubclassingCachedType] | |
| import b | |
| [file b.py] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| pass | |
| [file b.py.2] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| pass | |
| reveal_type(B) | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| x: int | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| tmp/b.py:8: note: Revealed type is "def (x: builtins.int) -> b.B" | |
| [case testIncrementalDataclassesArguments] | |
| import b | |
| [file b.py] | |
| from a import Frozen, NoInit, NoCmp | |
| [file b.py.2] | |
| from a import Frozen, NoInit, NoCmp | |
| f = Frozen(5) | |
| f.x = 6 | |
| g = NoInit() | |
| Frozen(1) < Frozen(2) | |
| Frozen(1) <= Frozen(2) | |
| Frozen(1) > Frozen(2) | |
| Frozen(1) >= Frozen(2) | |
| NoCmp(1) < NoCmp(2) | |
| NoCmp(1) <= NoCmp(2) | |
| NoCmp(1) > NoCmp(2) | |
| NoCmp(1) >= NoCmp(2) | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass(frozen=True, order=True) | |
| class Frozen: | |
| x: int | |
| @dataclass(init=False) | |
| class NoInit: | |
| x: int | |
| @dataclass(order=False) | |
| class NoCmp: | |
| x: int | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| tmp/b.py:4: error: Property "x" defined in "Frozen" is read-only | |
| tmp/b.py:13: error: Unsupported left operand type for < ("NoCmp") | |
| tmp/b.py:14: error: Unsupported left operand type for <= ("NoCmp") | |
| tmp/b.py:15: error: Unsupported left operand type for > ("NoCmp") | |
| tmp/b.py:16: error: Unsupported left operand type for >= ("NoCmp") | |
| [case testIncrementalDataclassesDunder] | |
| import b | |
| [file b.py] | |
| from a import A | |
| [file b.py.2] | |
| from a import A | |
| reveal_type(A) | |
| reveal_type(A.__eq__) | |
| reveal_type(A.__ne__) | |
| reveal_type(A.__lt__) | |
| reveal_type(A.__le__) | |
| reveal_type(A.__gt__) | |
| reveal_type(A.__ge__) | |
| A(1) < A(2) | |
| A(1) <= A(2) | |
| A(1) > A(2) | |
| A(1) >= A(2) | |
| A(1) == A(2) | |
| A(1) != A(2) | |
| A(1) < 1 | |
| A(1) <= 1 | |
| A(1) > 1 | |
| A(1) >= 1 | |
| A(1) == 1 | |
| A(1) != 1 | |
| 1 < A(1) | |
| 1 <= A(1) | |
| 1 > A(1) | |
| 1 >= A(1) | |
| 1 == A(1) | |
| 1 != A(1) | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass(order=True) | |
| class A: | |
| a: int | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| tmp/b.py:3: note: Revealed type is "def (a: builtins.int) -> a.A" | |
| tmp/b.py:4: note: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" | |
| tmp/b.py:5: note: Revealed type is "def (builtins.object, builtins.object) -> builtins.bool" | |
| tmp/b.py:6: note: Revealed type is "def [_DT] (self: _DT`1, other: _DT`1) -> builtins.bool" | |
| tmp/b.py:7: note: Revealed type is "def [_DT] (self: _DT`2, other: _DT`2) -> builtins.bool" | |
| tmp/b.py:8: note: Revealed type is "def [_DT] (self: _DT`3, other: _DT`3) -> builtins.bool" | |
| tmp/b.py:9: note: Revealed type is "def [_DT] (self: _DT`4, other: _DT`4) -> builtins.bool" | |
| tmp/b.py:18: error: Unsupported operand types for < ("A" and "int") | |
| tmp/b.py:19: error: Unsupported operand types for <= ("A" and "int") | |
| tmp/b.py:20: error: Unsupported operand types for > ("A" and "int") | |
| tmp/b.py:21: error: Unsupported operand types for >= ("A" and "int") | |
| tmp/b.py:25: error: Unsupported operand types for > ("A" and "int") | |
| tmp/b.py:26: error: Unsupported operand types for >= ("A" and "int") | |
| tmp/b.py:27: error: Unsupported operand types for < ("A" and "int") | |
| tmp/b.py:28: error: Unsupported operand types for <= ("A" and "int") | |
| [case testIncrementalDataclassesSubclassModified] | |
| from b import B | |
| B(5, 'foo') | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| x: int | |
| [file b.py] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| y: str | |
| [file b.py.2] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| y: int | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| main:2: error: Argument 2 to "B" has incompatible type "str"; expected "int" | |
| [rechecked b] | |
| [case testIncrementalDataclassesSubclassModifiedErrorFirst] | |
| from b import B | |
| B(5, 'foo') | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| x: int | |
| [file b.py] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| y: int | |
| [file b.py.2] | |
| from a import A | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B(A): | |
| y: str | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| main:2: error: Argument 2 to "B" has incompatible type "str"; expected "int" | |
| [out2] | |
| [rechecked b] | |
| [case testIncrementalDataclassesThreeFiles] | |
| from c import C | |
| C('foo', 5, True) | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| a: int | |
| [file b.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B: | |
| b: str | |
| [file b.py.2] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class B: | |
| b: str | |
| c: str | |
| [file c.py] | |
| from a import A | |
| from b import B | |
| from dataclasses import dataclass | |
| @dataclass | |
| class C(A, B): | |
| c: bool | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| tmp/c.py:7: error: Incompatible types in assignment (expression has type "bool", base class "B" defined the type as "str") | |
| main:2: error: Argument 2 to "C" has incompatible type "int"; expected "bool" | |
| [case testIncrementalDataclassesThreeRuns] | |
| from a import A | |
| A(5) | |
| [file a.py] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| a: int | |
| [file a.py.2] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| a: str | |
| [file a.py.3] | |
| from dataclasses import dataclass | |
| @dataclass | |
| class A: | |
| a: int = 6 | |
| [builtins fixtures/dataclasses.pyi] | |
| [out1] | |
| [out2] | |
| main:2: error: Argument 1 to "A" has incompatible type "int"; expected "str" | |
| [out3] | |
| [case testParentPatchingMess] | |
| # flags: --ignore-missing-imports --follow-imports=skip | |
| # cmd: mypy -m d d.k d.k.a d.k.v t | |
| [file d/__init__.py] | |
| [file d/k/__init__.py] | |
| from d.k.a import x | |
| [file d/k/a.py] | |
| x = 10 | |
| [file d/k/v.py] | |
| from d.k.e import x | |
| [file t.py] | |
| from d import k | |
| [file t.py.2] | |
| from d import k | |
| # dummy change | |
| [case testCachedBadProtocolNote] | |
| import b | |
| [file a.py] | |
| from typing import TypedDict | |
| Point = TypedDict('Point', {'x': int, 'y': int}) | |
| [file b.py] | |
| from typing import Iterable | |
| from a import Point | |
| p: Point | |
| it: Iterable[int] = p | |
| [file b.py.2] | |
| from typing import Iterable | |
| from a import Point | |
| p: Point | |
| it: Iterable[int] = p # change | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [out] | |
| tmp/b.py:4: error: Incompatible types in assignment (expression has type "Point", variable has type "Iterable[int]") | |
| tmp/b.py:4: note: Following member(s) of "Point" have conflicts: | |
| tmp/b.py:4: note: Expected: | |
| tmp/b.py:4: note: def __iter__(self) -> Iterator[int] | |
| tmp/b.py:4: note: Got: | |
| tmp/b.py:4: note: def __iter__(self) -> Iterator[str] | |
| [out2] | |
| tmp/b.py:4: error: Incompatible types in assignment (expression has type "Point", variable has type "Iterable[int]") | |
| tmp/b.py:4: note: Following member(s) of "Point" have conflicts: | |
| tmp/b.py:4: note: Expected: | |
| tmp/b.py:4: note: def __iter__(self) -> Iterator[int] | |
| tmp/b.py:4: note: Got: | |
| tmp/b.py:4: note: def __iter__(self) -> Iterator[str] | |
| [case testIndirectDepsAlwaysPatched-writescache] | |
| # flags: --no-incremental | |
| # flags2: --incremental | |
| from b import C | |
| def f() -> None: | |
| x: int = C().x | |
| [file b.py] | |
| from c import C | |
| [file c.pyi] | |
| class C: | |
| x: int | |
| [file c.pyi.2] | |
| class C: | |
| x: str | |
| [out] | |
| [out2] | |
| main:5: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testBazelFlagIgnoresFileChanges-skip] | |
| -- This test fails on windows, when the mypy source in on a different drive than | |
| -- the run-directory. In this case os.path.relpath(...) fails with an exception | |
| -- Since the initial run wrote a cache file, the second run ignores the source | |
| # flags: --bazel | |
| from a import f | |
| f() | |
| [file a.py] | |
| def f(): pass | |
| [file a.py.2] | |
| [out] | |
| [out2] | |
| [case testModuleGetattrInitIncremental] | |
| import c | |
| [file c.py] | |
| import a.b | |
| x = a.b.f() | |
| [file c.py.2] | |
| import a.b | |
| x = a.b.f() | |
| # touch | |
| [file a/__init__.pyi] | |
| from typing import Any | |
| def __getattr__(attr: str) -> Any: ... | |
| [builtins fixtures/module.pyi] | |
| [out] | |
| [out2] | |
| [case testModuleGetattrInitIncremental2] | |
| import c | |
| [file c.py] | |
| import a.b.c | |
| [file c.py.2] | |
| import a.b.c | |
| # touch | |
| [file a/__init__.pyi] | |
| from typing import Any | |
| def __getattr__(attr: str) -> Any: ... | |
| [file a/b.pyi] | |
| # empty | |
| [builtins fixtures/module.pyi] | |
| [out] | |
| tmp/c.py:1: error: Cannot find implementation or library stub for module named "a.b.c" | |
| tmp/c.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [out2] | |
| tmp/c.py:1: error: Cannot find implementation or library stub for module named "a.b.c" | |
| tmp/c.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testModuleGetattrIncrementalSerializeVarFlag] | |
| import main | |
| [file main.py] | |
| from b import A, f | |
| f() | |
| [file main.py.3] | |
| from b import A, f # foo | |
| f() | |
| [file b.py] | |
| from c import A | |
| def f() -> A: ... | |
| [file b.py.2] | |
| from c import A # foo | |
| def f() -> A: ... | |
| [file c.py] | |
| from d import A | |
| [file d.pyi] | |
| def __getattr__(n): ... | |
| [out1] | |
| [out2] | |
| [out3] | |
| [case testAddedMissingStubs] | |
| # flags: --ignore-missing-imports | |
| from missing import f | |
| f(int()) | |
| [file missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsPackage] | |
| # flags: --ignore-missing-imports | |
| import package.missing | |
| package.missing.f(int()) | |
| [file package/__init__.pyi.2] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsPackageFrom] | |
| # flags: --ignore-missing-imports | |
| from package import missing | |
| missing.f(int()) | |
| [file package/__init__.pyi.2] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsPackagePartial] | |
| # flags: --ignore-missing-imports | |
| import package.missing | |
| package.missing.f(int()) | |
| [file package/__init__.pyi] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:3: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsPackagePartialGetAttr] | |
| import package.missing | |
| package.missing.f(int()) | |
| [file package/__init__.pyi] | |
| from typing import Any | |
| def __getattr__(attr: str) -> Any: ... | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsIgnore] | |
| from missing import f # type: ignore | |
| f(int()) | |
| [file missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsIgnorePackage] | |
| import package.missing # type: ignore | |
| package.missing.f(int()) | |
| [file package/__init__.pyi.2] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsIgnorePackageFrom] | |
| from package import missing # type: ignore | |
| missing.f(int()) | |
| [file package/__init__.pyi.2] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testAddedMissingStubsIgnorePackagePartial] | |
| import package.missing # type: ignore | |
| package.missing.f(int()) | |
| [file package/__init__.pyi] | |
| [file package/missing.pyi.2] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| main:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| -- Test cases for final qualifier | |
| [case testFinalAddFinalVarAssign] | |
| import mod | |
| from a import D | |
| from mod import x | |
| mod.x = 2 # This an all below are errors. | |
| x = 2 | |
| d: D | |
| d.y = 2 | |
| d.z = 2 | |
| D.y = 2 | |
| [file a.py] | |
| import mod | |
| class D(mod.C): | |
| pass | |
| [file mod.py] | |
| x = 1 | |
| class C: | |
| y = 1 | |
| def __init__(self) -> None: | |
| self.z = 1 | |
| [file mod.py.2] | |
| from typing import Final | |
| x: Final = 1 | |
| class C: | |
| y: Final = 1 | |
| def __init__(self) -> None: | |
| self.z: Final = 1 | |
| [out] | |
| [out2] | |
| main:5: error: Cannot assign to final name "x" | |
| main:6: error: Cannot assign to final name "x" | |
| main:8: error: Cannot assign to final attribute "y" | |
| main:9: error: Cannot assign to final attribute "z" | |
| main:10: error: Cannot assign to final attribute "y" | |
| [case testFinalAddFinalVarOverride] | |
| from mod import C | |
| class D(C): | |
| x = 2 | |
| def __init__(self) -> None: | |
| self.y = 2 | |
| class E(C): | |
| y = 2 | |
| def __init__(self) -> None: | |
| self.x = 2 | |
| [file mod.py] | |
| class C: | |
| x = 1 | |
| def __init__(self) -> None: | |
| self.y = 1 | |
| [file mod.py.2] | |
| from typing import Final | |
| class C: | |
| x: Final = 1 | |
| def __init__(self) -> None: | |
| self.y: Final = 1 | |
| [out] | |
| [out2] | |
| main:4: error: Cannot assign to final name "x" | |
| main:6: error: Cannot assign to final attribute "y" | |
| main:8: error: Cannot assign to final name "y" | |
| main:10: error: Cannot assign to final attribute "x" | |
| [case testFinalAddFinalMethodOverride] | |
| from mod import C | |
| class D(C): | |
| def meth(self) -> int: ... | |
| [file mod.py] | |
| class C: | |
| def meth(self) -> int: ... | |
| [file mod.py.2] | |
| from typing import final | |
| class C: | |
| @final | |
| def meth(self) -> int: ... | |
| [out] | |
| [out2] | |
| main:4: error: Cannot override final attribute "meth" (previously declared in base class "C") | |
| -- These tests should just not crash | |
| [case testOverrideByBadVar] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class Slow: | |
| pass | |
| s: Slow | |
| from cext import Slow # type: ignore | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarAlias] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class Slow: | |
| pass | |
| A = Slow | |
| from cext import Slow # type: ignore | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarClass] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class C: | |
| class Slow: | |
| pass | |
| s: Slow | |
| from cext import Slow # type: ignore | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarClassAlias] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class C: | |
| class Slow: | |
| pass | |
| A = Slow | |
| from cext import Slow # type: ignore | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarExisting] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class Slow: | |
| pass | |
| s: Slow | |
| from cext import Slow # type: ignore | |
| [file cext.py] | |
| Slow = 1 | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarAliasExisting] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class Slow: | |
| pass | |
| A = Slow | |
| from cext import Slow # type: ignore | |
| [file cext.py] | |
| Slow = 1 | |
| [out] | |
| [out2] | |
| [case testOverrideByBadFunction] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class C: | |
| class Slow: | |
| pass | |
| s: Slow | |
| def Slow() -> None: ... # type: ignore | |
| [out] | |
| [out2] | |
| [case testOverrideByBadVarLocal] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| def outer() -> None: | |
| class Slow: | |
| pass | |
| s: Slow | |
| from cext import Slow # type: ignore | |
| [out] | |
| [out2] | |
| [case testRecursiveAliasImported] | |
| import a | |
| [file a.py] | |
| import lib | |
| x: int | |
| [file a.py.2] | |
| import lib | |
| x: lib.A | |
| reveal_type(x) | |
| [file lib.pyi] | |
| from typing import List | |
| MYPY = False | |
| if MYPY: # Force processing order | |
| from other import B | |
| A = List[B] # type: ignore | |
| [file other.pyi] | |
| from typing import List | |
| from lib import A | |
| B = List[A] | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "builtins.list[builtins.list[...]]" | |
| [case testRecursiveNamedTupleTypedDict] | |
| import a | |
| [file a.py] | |
| import lib | |
| x: int | |
| [file a.py.2] | |
| import lib | |
| x: lib.A | |
| reveal_type(x.x['x']) | |
| [file lib.pyi] | |
| from typing import NamedTuple | |
| from other import B | |
| A = NamedTuple('A', [('x', B)]) | |
| [file other.pyi] | |
| from typing import TypedDict | |
| from lib import A | |
| B = TypedDict('B', {'x': A}) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "tuple[TypedDict('other.B', {'x': tuple[..., fallback=lib.A]}), fallback=lib.A]" | |
| [case testFollowImportSkipNotInvalidatedOnPresent] | |
| # flags: --follow-imports=skip | |
| # cmd: mypy -m main | |
| [file main.py] | |
| import other | |
| [file other.py] | |
| x = 1 | |
| [file other.py.2] | |
| x = 'hi' | |
| [stale] | |
| [rechecked] | |
| [case testFollowImportSkipNotInvalidatedOnPresentPackage] | |
| # flags: --follow-imports=skip | |
| # cmd: mypy -m main | |
| [file main.py] | |
| import other | |
| [file other/__init__.py] | |
| x = 1 | |
| [file other/__init__.py.2] | |
| x = 'hi' | |
| [stale] | |
| [rechecked] | |
| [case testFollowImportSkipNotInvalidatedOnAdded] | |
| # flags: --follow-imports=skip --ignore-missing-imports | |
| # cmd: mypy -m main | |
| [file main.py] | |
| import other | |
| [file other.py.2] | |
| x = 1 | |
| [stale] | |
| [rechecked] | |
| [case testFollowImportSkipInvalidatedOnAddedStub] | |
| # flags: --follow-imports=skip --ignore-missing-imports | |
| # cmd: mypy -m main | |
| [file main.py] | |
| import other | |
| [file other.pyi.2] | |
| x = 1 | |
| [stale main, other] | |
| [rechecked main, other] | |
| [case testFollowImportSkipNotInvalidatedOnAddedStubOnFollowForStubs] | |
| # flags: --follow-imports=skip --ignore-missing-imports --config-file=tmp/mypy.ini | |
| # cmd: mypy -m main | |
| [file main.py] | |
| import other | |
| [file other.pyi.2] | |
| x = 1 | |
| [file mypy.ini] | |
| \[mypy] | |
| follow_imports_for_stubs = True | |
| [stale] | |
| [rechecked] | |
| [case testAddedSkippedStubsPackageFrom] | |
| # flags: --follow-imports=skip --ignore-missing-imports | |
| # cmd: mypy -m main | |
| # cmd2: mypy -m main package package.missing | |
| [file main.py] | |
| from package import missing | |
| missing.f(int()) | |
| [file package/__init__.py] | |
| [file package/missing.py] | |
| def f(x: str) -> None: pass | |
| [out] | |
| [out2] | |
| tmp/main.py:2: error: Argument 1 to "f" has incompatible type "int"; expected "str" | |
| [case testOverrideByIdemAlias] | |
| # https://github.com/python/mypy/issues/6404 | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| C = C # type: ignore | |
| class C: # type: ignore | |
| pass | |
| [out] | |
| [out2] | |
| [case testOverrideByIdemAliasReversed] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| class C: | |
| pass | |
| C = C # type: ignore | |
| x: C | |
| [out] | |
| [out2] | |
| [case testOverrideByIdemAliasGeneric] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| from typing import Generic, TypeVar | |
| T = TypeVar('T') | |
| class C(Generic[T]): | |
| pass | |
| C = C[int] # type: ignore | |
| x: C | |
| [out] | |
| [out2] | |
| [case testOverrideByIdemAliasImported] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| from other import C | |
| C = C # type: ignore | |
| x: C | |
| [file other.py] | |
| class C: | |
| pass | |
| [out] | |
| [out2] | |
| [case testOverrideByIdemAliasImportedReversed] | |
| import a | |
| [file a.py] | |
| import lib | |
| x = 1 | |
| [file a.py.2] | |
| import lib | |
| x = 2 | |
| [file lib.py] | |
| C = C # type: ignore | |
| from other import C | |
| [file other.py] | |
| class C: | |
| pass | |
| [out] | |
| [out2] | |
| [case testConditionalExceptionAliasOverride] | |
| import a | |
| [file a.py] | |
| import lib | |
| try: | |
| x = 1 | |
| except lib.Exception as e: | |
| pass | |
| [file a.py.2] | |
| import lib | |
| try: | |
| x = 2 | |
| except lib.Exception as e: | |
| pass | |
| [file lib.py] | |
| try: | |
| Exception = Exception | |
| except BaseException: | |
| class Exception(BaseException): pass # type: ignore | |
| try: | |
| pass | |
| except Exception as e: | |
| pass | |
| [builtins fixtures/exception.pyi] | |
| [out] | |
| [out2] | |
| [case testBadEnumLoading] | |
| import a | |
| [file a.py] | |
| from b import E | |
| x: E | |
| y = 1 | |
| [file a.py.2] | |
| from b import E | |
| x: E | |
| y = 2 | |
| [file b.py] | |
| from typing import List | |
| from enum import Enum | |
| def f() -> List[str]: ... | |
| E = Enum('E', f()) # type: ignore | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [out2] | |
| [case testChangedPluginsInvalidateCache] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| from b import x | |
| y: int = x | |
| [file a.py.2] | |
| from b import x | |
| y: int = x | |
| touch = 1 | |
| [file b.py] | |
| class C: ... | |
| def f() -> C: ... | |
| x = f() | |
| [file basic_plugin.py] | |
| from mypy.plugin import Plugin | |
| class MyPlugin(Plugin): | |
| def get_function_hook(self, fullname): | |
| if fullname.endswith('.f'): | |
| return my_hook | |
| assert fullname is not None | |
| return None | |
| def my_hook(ctx): | |
| return ctx.api.named_generic_type('builtins.int', []) | |
| def plugin(version): | |
| return MyPlugin | |
| [file basic_plugin.py.2] | |
| from mypy.plugin import Plugin | |
| class MyPlugin(Plugin): | |
| def get_function_hook(self, fullname): | |
| if fullname.endswith('.f'): | |
| return my_hook | |
| assert fullname is not None | |
| return None | |
| def my_hook(ctx): | |
| return ctx.api.named_generic_type('builtins.str', []) | |
| def plugin(version): | |
| return MyPlugin | |
| [file mypy.ini] | |
| \[mypy] | |
| plugins=basic_plugin.py | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testChangedPluginsInvalidateCache2] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| from b import x | |
| y: int = x | |
| [file a.py.2] | |
| from b import x | |
| y: int = x | |
| touch = 1 | |
| [file b.py] | |
| class C: ... | |
| def f() -> C: ... | |
| x = f() | |
| [file basic_plugin.py] | |
| from mypy.plugin import Plugin | |
| from version_plugin import __version__, choice | |
| class MyPlugin(Plugin): | |
| def get_function_hook(self, fullname): | |
| if fullname.endswith('.f'): | |
| return my_hook | |
| assert fullname is not None | |
| return None | |
| def my_hook(ctx): | |
| if choice: | |
| return ctx.api.named_generic_type('builtins.int', []) | |
| else: | |
| return ctx.api.named_generic_type('builtins.str', []) | |
| def plugin(version): | |
| return MyPlugin | |
| [file version_plugin.py] | |
| __version__ = 0.1 | |
| choice = True | |
| [file version_plugin.py.2] | |
| __version__ = 0.2 | |
| choice = False | |
| [file mypy.ini] | |
| \[mypy] | |
| plugins=basic_plugin.py | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testAddedPluginsInvalidateCache] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| from b import x | |
| y: int = x | |
| [file a.py.2] | |
| from b import x | |
| y: int = x | |
| touch = 1 | |
| [file b.py] | |
| def f() -> int: ... | |
| x = f() | |
| [file basic_plugin.py] | |
| from mypy.plugin import Plugin | |
| class MyPlugin(Plugin): | |
| def get_function_hook(self, fullname): | |
| if fullname.endswith('.f'): | |
| return my_hook | |
| assert fullname is not None | |
| return None | |
| def my_hook(ctx): | |
| return ctx.api.named_generic_type('builtins.str', []) | |
| def plugin(version): | |
| return MyPlugin | |
| [file mypy.ini] | |
| \[mypy] | |
| python_version=3.6 | |
| [file mypy.ini.2] | |
| \[mypy] | |
| python_version=3.6 | |
| plugins=basic_plugin.py | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testRemovedPluginsInvalidateCache] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| [file a.py] | |
| from b import x | |
| y: str = x | |
| [file a.py.2] | |
| from b import x | |
| y: str = x | |
| touch = 1 | |
| [file b.py] | |
| def f() -> int: ... | |
| x = f() | |
| [file basic_plugin.py] | |
| from mypy.plugin import Plugin | |
| class MyPlugin(Plugin): | |
| def get_function_hook(self, fullname): | |
| if fullname.endswith('.f'): | |
| return my_hook | |
| assert fullname is not None | |
| return None | |
| def my_hook(ctx): | |
| return ctx.api.named_generic_type('builtins.str', []) | |
| def plugin(version): | |
| return MyPlugin | |
| [file mypy.ini] | |
| \[mypy] | |
| python_version=3.6 | |
| plugins=basic_plugin.py | |
| [file mypy.ini.2] | |
| \[mypy] | |
| python_version=3.6 | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| [case testPluginConfigData] | |
| # flags: --config-file tmp/mypy.ini | |
| import a | |
| import b | |
| [file a.py] | |
| [file b.py] | |
| [file test.json] | |
| {"a": false, "b": false} | |
| [file test.json.2] | |
| {"a": true, "b": false} | |
| [file mypy.ini] | |
| \[mypy] | |
| plugins=<ROOT>/test-data/unit/plugins/config_data.py | |
| # The config change will force a to be rechecked but not b. | |
| [rechecked a] | |
| [case testLiteralIncrementalTurningIntoLiteral] | |
| import mod | |
| reveal_type(mod.a) | |
| [file mod.py] | |
| from typing import Literal | |
| a = 1 | |
| [file mod.py.2] | |
| from typing import Literal | |
| a: Literal[2] = 2 | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| main:2: note: Revealed type is "builtins.int" | |
| [out2] | |
| main:2: note: Revealed type is "Literal[2]" | |
| [case testAddedSubStarImport] | |
| # cmd: mypy -m a pack pack.mod b | |
| # cmd2: mypy -m other | |
| [file a.py] | |
| from pack import * | |
| [file pack/__init__.py] | |
| [file pack/mod.py] | |
| [file b.py] | |
| import pack.mod | |
| [file other.py] | |
| import a | |
| [out] | |
| [out2] | |
| [case testNewAnalyzerIncrementalBrokenNamedTuple] | |
| import a | |
| [file a.py] | |
| from b import NT | |
| x: NT | |
| [file a.py.2] | |
| from b import NT | |
| x: NT | |
| reveal_type(x) | |
| [file b.py] | |
| from typing import NamedTuple | |
| NT = NamedTuple('BadName', [('x', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| tmp/b.py:2: error: First argument to namedtuple() should be "NT", not "BadName" | |
| [out2] | |
| tmp/b.py:2: error: First argument to namedtuple() should be "NT", not "BadName" | |
| tmp/a.py:3: note: Revealed type is "tuple[builtins.int, fallback=b.NT]" | |
| [case testNewAnalyzerIncrementalBrokenNamedTupleNested] | |
| import a | |
| [file a.py] | |
| from b import C | |
| x: C | |
| [file a.py.2] | |
| from b import C | |
| x: C | |
| # touch | |
| [file b.py] | |
| class C: ... | |
| from collections import namedtuple | |
| def test() -> None: | |
| NT = namedtuple('BadName', ['x', 'y']) | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| tmp/b.py:4: error: First argument to namedtuple() should be "NT", not "BadName" | |
| [out2] | |
| tmp/b.py:4: error: First argument to namedtuple() should be "NT", not "BadName" | |
| [case testNewAnalyzerIncrementalMethodNamedTuple] | |
| import a | |
| [file a.py] | |
| from b import C | |
| x: C | |
| [file a.py.2] | |
| from b import C | |
| x: C | |
| reveal_type(x.h) | |
| [file b.py] | |
| from typing import NamedTuple | |
| class C: | |
| def __init__(self) -> None: | |
| self.h: Hidden | |
| Hidden = NamedTuple('Hidden', [('x', int)]) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "tuple[builtins.int, fallback=b.Hidden@5]" | |
| [case testIncrementalNodeCreatedFromGetattr] | |
| import a | |
| [file a.py] | |
| from b import C | |
| c: C | |
| [file b.py] | |
| from c import C | |
| [file c.pyi] | |
| def __getattr__(s): ... | |
| [file a.py.2] | |
| from b import C | |
| c: C | |
| reveal_type(c) | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "Any" | |
| [case testNewAnalyzerIncrementalNestedEnum] | |
| import a | |
| [file a.py] | |
| from b import C | |
| x: C | |
| [file a.py.2] | |
| from b import C | |
| x: C | |
| # touch | |
| [file b.py] | |
| class C: ... | |
| from enum import Enum | |
| def test() -> None: | |
| Color = Enum('Color', 'RED BLACK') | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [out2] | |
| [case testCannotDetermineTypeFromOtherModule] | |
| import aa | |
| [file aa.py] | |
| import a | |
| [file aa.py.2] | |
| import a # dummy | |
| [file a.py] | |
| from b import Sub | |
| Sub().foo | |
| Sub().foo | |
| [file b.py] | |
| from typing import Any | |
| class desc: | |
| def __get__(self, _: Any, __: Any = None) -> int: | |
| return 42 | |
| class Base: | |
| @property | |
| def foo(self) -> int: ... | |
| class Sub(Base): | |
| foo = desc(42) # type: ignore | |
| [builtins fixtures/property.pyi] | |
| [out] | |
| [out2] | |
| [case testRedefinitionClass] | |
| import b | |
| [file a.py] | |
| from whatever import Foo # type: ignore | |
| class Foo: # type: ignore | |
| def f(self) -> None: | |
| pass | |
| [file b.py] | |
| import a | |
| [file b.py.2] | |
| import a # a change | |
| [case testIsInstanceAdHocIntersectionIncrementalNoChange] | |
| import b | |
| [file a.py] | |
| class A: pass | |
| class B: pass | |
| class Foo: | |
| def __init__(self) -> None: | |
| x: A | |
| assert isinstance(x, B) | |
| self.x = x | |
| [file b.py] | |
| from a import Foo | |
| [file b.py.2] | |
| from a import Foo | |
| reveal_type(Foo().x) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.B">" | |
| [case testIsInstanceAdHocIntersectionIncrementalNoChangeSameName] | |
| import b | |
| [file c.py] | |
| class B: pass | |
| [file a.py] | |
| import c | |
| class B: pass | |
| class Foo: | |
| def __init__(self) -> None: | |
| x: c.B | |
| assert isinstance(x, B) | |
| self.x = x | |
| [file b.py] | |
| from a import Foo | |
| [file b.py.2] | |
| from a import Foo | |
| reveal_type(Foo().x) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:2: note: Revealed type is "a.<subclass of "c.B" and "a.B">" | |
| [case testIsInstanceAdHocIntersectionIncrementalNoChangeTuple] | |
| import b | |
| [file a.py] | |
| from typing import Tuple | |
| class B: pass | |
| class Foo: | |
| def __init__(self) -> None: | |
| x: Tuple[int, ...] | |
| assert isinstance(x, B) | |
| self.x = x | |
| [file b.py] | |
| from a import Foo | |
| [file b.py.2] | |
| from a import Foo | |
| reveal_type(Foo().x) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:2: note: Revealed type is "a.<subclass of "tuple[builtins.int, ...]" and "a.B">" | |
| [case testIsInstanceAdHocIntersectionIncrementalIsInstanceChange] | |
| import c | |
| [file a.py] | |
| class A: pass | |
| class B: pass | |
| class C: pass | |
| class Foo: | |
| def __init__(self) -> None: | |
| x: A | |
| assert isinstance(x, B) | |
| self.x = x | |
| [file a.py.2] | |
| class A: pass | |
| class B: pass | |
| class C: pass | |
| class Foo: | |
| def __init__(self) -> None: | |
| x: A | |
| assert isinstance(x, C) | |
| self.x = x | |
| [file b.py] | |
| from a import Foo | |
| y = Foo().x | |
| [file c.py] | |
| from b import y | |
| reveal_type(y) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.B">" | |
| [out2] | |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.C">" | |
| [case testIsInstanceAdHocIntersectionIncrementalUnderlyingObjChang] | |
| import c | |
| [file a.py] | |
| class A: pass | |
| class B: pass | |
| class C: pass | |
| Extra = B | |
| [file a.py.2] | |
| class A: pass | |
| class B: pass | |
| class C: pass | |
| Extra = C | |
| [file b.py] | |
| from a import A, Extra | |
| x: A | |
| if isinstance(x, Extra): | |
| y = x | |
| [file c.py] | |
| from b import y | |
| reveal_type(y) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| tmp/c.py:2: note: Revealed type is "b.<subclass of "a.A" and "a.B">" | |
| [out2] | |
| tmp/c.py:2: note: Revealed type is "b.<subclass of "a.A" and "a.C">" | |
| [case testIsInstanceAdHocIntersectionIncrementalIntersectionToUnreachable] | |
| import c | |
| [file a.py] | |
| class A: | |
| x: int | |
| class B: | |
| x: int | |
| x: A | |
| assert isinstance(x, B) | |
| y = x | |
| [file a.py.2] | |
| class A: | |
| x: int | |
| class B: | |
| x: str | |
| x: A | |
| assert isinstance(x, B) | |
| y = x | |
| [file b.py] | |
| from a import y | |
| z = y | |
| [file c.py] | |
| from b import z | |
| reveal_type(z) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.B">" | |
| [out2] | |
| tmp/b.py:2: error: Cannot determine type of "y" | |
| tmp/c.py:2: note: Revealed type is "Any" | |
| [case testIsInstanceAdHocIntersectionIncrementalUnreachaableToIntersection] | |
| import c | |
| [file a.py] | |
| class A: | |
| x: int | |
| class B: | |
| x: str | |
| x: A | |
| assert isinstance(x, B) | |
| y = x | |
| [file a.py.2] | |
| class A: | |
| x: int | |
| class B: | |
| x: int | |
| x: A | |
| assert isinstance(x, B) | |
| y = x | |
| [file b.py] | |
| from a import y | |
| z = y | |
| [file c.py] | |
| from b import z | |
| reveal_type(z) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| tmp/b.py:2: error: Cannot determine type of "y" | |
| tmp/c.py:2: note: Revealed type is "Any" | |
| [out2] | |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.B">" | |
| [case testIsInstanceAdHocIntersectionIncrementalNestedClass] | |
| import b | |
| [file a.py] | |
| class A: | |
| class B: ... | |
| class C: ... | |
| class D: | |
| def __init__(self) -> None: | |
| x: A.B | |
| assert isinstance(x, A.C) | |
| self.x = x | |
| [file b.py] | |
| from a import A | |
| [file b.py.2] | |
| from a import A | |
| reveal_type(A.D().x) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:2: note: Revealed type is "a.<subclass of "a.A.B" and "a.A.C">" | |
| [case testIsInstanceAdHocIntersectionIncrementalUnions] | |
| import c | |
| [file a.py] | |
| import b | |
| class A: | |
| p: b.D | |
| class B: | |
| p: b.D | |
| class C: | |
| p: b.D | |
| c: str | |
| x: A | |
| assert isinstance(x, (B, C)) | |
| y = x | |
| [file b.py] | |
| class D: | |
| p: int | |
| [file c.py] | |
| from a import y | |
| [file c.py.2] | |
| from a import y, C | |
| reveal_type(y) | |
| reveal_type(y.p.p) | |
| assert isinstance(y, C) | |
| reveal_type(y.c) | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| [out2] | |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "a.A" and "a.B"> | a.<subclass of "a.A" and "a.C">" | |
| tmp/c.py:3: note: Revealed type is "builtins.int" | |
| tmp/c.py:5: note: Revealed type is "builtins.str" | |
| [case testStubFixupIssues] | |
| import a | |
| [file a.py] | |
| import p | |
| [file a.py.2] | |
| import p | |
| p.N | |
| [file p/__init__.pyi] | |
| from p.util import * | |
| [file p/util.pyi] | |
| from p.params import N | |
| class Test: ... | |
| x: N | |
| [file p/params.pyi] | |
| import p.util | |
| class N(p.util.Test): | |
| ... | |
| [out2] | |
| tmp/a.py:2: error: Module has no attribute "N" | |
| [case testIncrementalIndirectSkipWarnUnused] | |
| # flags: --follow-imports=skip --warn-unused-ignores | |
| # cmd: mypy -m main a b c1 | |
| # cmd2: mypy -m main a b c2 | |
| [file main.py] | |
| import a | |
| a.foo.bar() | |
| [file a.py] | |
| import b | |
| foo = b.Foo() | |
| [file b.py] | |
| from c1 import C | |
| class Foo: | |
| def bar(self) -> C: | |
| return C() | |
| [file c1.py] | |
| class C: pass | |
| [file b.py.2] | |
| from c2 import C | |
| class Foo: | |
| def bar(self) -> C: | |
| return C() | |
| [file c2.py] | |
| [delete c1.py.2] | |
| [file c2.py.2] | |
| class C: pass | |
| [case testIncrementalNestedNamedTuple] | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| import b # foo | |
| [file b.py] | |
| from typing import NamedTuple | |
| def f() -> None: | |
| class NT(NamedTuple): | |
| x: int | |
| n: NT = NT(x=2) | |
| def g() -> None: | |
| NT = NamedTuple('NT', [('y', str)]) | |
| n: NT = NT(y='x') | |
| [builtins fixtures/tuple.pyi] | |
| [case testIncrementalNestedTypeAlias] | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| import b | |
| reveal_type(b.C().x) | |
| reveal_type(b.D().x) | |
| [file b.py] | |
| from typing import List | |
| class C: | |
| def __init__(self) -> None: | |
| Alias = List[int] | |
| self.x = [] # type: Alias | |
| class D: | |
| def __init__(self) -> None: | |
| Alias = List[str] | |
| self.x = [] # type: Alias | |
| [builtins fixtures/list.pyi] | |
| [out2] | |
| tmp/a.py:2: note: Revealed type is "builtins.list[builtins.int]" | |
| tmp/a.py:3: note: Revealed type is "builtins.list[builtins.str]" | |
| [case testIncrementalNamespacePackage1] | |
| # flags: --namespace-packages | |
| import m | |
| [file m.py] | |
| from foo.bar import x | |
| x + 0 | |
| [file foo/bar.py] | |
| x = 0 | |
| [rechecked] | |
| [stale] | |
| [case testIncrementalNamespacePackage2] | |
| # flags: --namespace-packages | |
| import m | |
| [file m.py] | |
| from foo import bar | |
| bar.x + 0 | |
| [file foo/bar.py] | |
| x = 0 | |
| [rechecked] | |
| [stale] | |
| [case testExplicitReexportImportCycleWildcard] | |
| # flags: --no-implicit-reexport | |
| import pkg.a | |
| [file pkg/__init__.pyi] | |
| [file pkg/a.pyi] | |
| MYPY = False | |
| if MYPY: | |
| from pkg.b import B | |
| [file pkg/b.pyi] | |
| import pkg.a | |
| MYPY = False | |
| if MYPY: | |
| from pkg.c import C | |
| class B: | |
| pass | |
| [file pkg/c.pyi] | |
| from pkg.a import * | |
| class C: | |
| pass | |
| [rechecked] | |
| [stale] | |
| [case testEnumAreStillFinalAfterCache] | |
| import a | |
| class Ok(a.RegularEnum): | |
| x = 1 | |
| class NotOk(a.FinalEnum): | |
| x = 1 | |
| [file a.py] | |
| from enum import Enum | |
| class RegularEnum(Enum): | |
| x: int | |
| class FinalEnum(Enum): | |
| x = 1 | |
| [builtins fixtures/isinstance.pyi] | |
| [out] | |
| main:3: error: Cannot override writable attribute "x" with a final one | |
| main:3: error: Incompatible types in assignment (expression has type "Ok", base class "RegularEnum" defined the type as "int") | |
| main:4: error: Cannot extend enum with existing members: "FinalEnum" | |
| main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") | |
| [out2] | |
| main:3: error: Cannot override writable attribute "x" with a final one | |
| main:3: error: Incompatible types in assignment (expression has type "Ok", base class "RegularEnum" defined the type as "int") | |
| main:4: error: Cannot extend enum with existing members: "FinalEnum" | |
| main:5: error: Cannot override final attribute "x" (previously declared in base class "FinalEnum") | |
| [case testSlotsSerialization] | |
| import a | |
| [file a.py] | |
| from b import C | |
| class D(C): | |
| pass | |
| [file b.py] | |
| class C: | |
| __slots__ = ('x',) | |
| [file a.py.2] | |
| from b import C | |
| class D(C): | |
| __slots__ = ('y',) | |
| def __init__(self) -> None: | |
| self.x = 1 | |
| self.y = 2 | |
| self.z = 3 | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:9: error: Trying to assign name "z" that is not in "__slots__" of type "a.D" | |
| [case testMethodAliasIncremental] | |
| import b | |
| [file a.py] | |
| class A: | |
| def f(self) -> None: pass | |
| g = f | |
| [file b.py] | |
| from a import A | |
| A().g() | |
| [file b.py.2] | |
| # trivial change | |
| from a import A | |
| A().g() | |
| [out] | |
| [out2] | |
| [case testIncrementalWithDifferentKindsOfNestedTypesWithinMethod] | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| import b | |
| b.xyz | |
| [file b.py] | |
| from typing import NamedTuple, NewType, TypedDict | |
| from typing_extensions import TypeAlias | |
| from enum import Enum | |
| from dataclasses import dataclass | |
| class C: | |
| def f(self) -> None: | |
| class C: | |
| c: int | |
| class NT1(NamedTuple): | |
| c: int | |
| NT2 = NamedTuple("NT2", [("c", int)]) | |
| class NT3(NT1): | |
| pass | |
| class TD(TypedDict): | |
| c: int | |
| TD2 = TypedDict("TD2", {"c": int}) | |
| class E(Enum): | |
| X = 1 | |
| @dataclass | |
| class DC: | |
| c: int | |
| Alias: TypeAlias = NT1 | |
| N = NewType("N", NT1) | |
| c: C = C() | |
| nt1: NT1 = NT1(c=1) | |
| nt2: NT2 = NT2(c=1) | |
| nt3: NT3 = NT3(c=1) | |
| td: TD = TD(c=1) | |
| td2: TD2 = TD2(c=1) | |
| e: E = E.X | |
| dc: DC = DC(c=1) | |
| al: Alias = Alias(c=1) | |
| n: N = N(NT1(c=1)) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out2] | |
| tmp/a.py:2: error: Module has no attribute "xyz" | |
| [case testIncrementalInvalidNamedTupleInUnannotatedFunction] | |
| # flags: --disable-error-code=annotation-unchecked | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| import b # f | |
| [file b.py] | |
| from typing import NamedTuple | |
| def toplevel(fields): | |
| TupleType = NamedTuple("TupleType", fields) | |
| class InheritFromTuple(TupleType): | |
| pass | |
| NT2 = NamedTuple("bad", [('x', int)]) | |
| nt2: NT2 = NT2(x=1) | |
| class C: | |
| def method(self, fields): | |
| TupleType = NamedTuple("TupleType", fields) | |
| class InheritFromTuple(TupleType): | |
| pass | |
| NT2 = NamedTuple("bad", [('x', int)]) | |
| nt2: NT2 = NT2(x=1) | |
| [builtins fixtures/tuple.pyi] | |
| [case testNamedTupleUpdateNonRecursiveToRecursiveCoarse] | |
| import c | |
| [file a.py] | |
| from b import M | |
| from typing import NamedTuple, Optional | |
| class N(NamedTuple): | |
| r: Optional[M] | |
| x: int | |
| n: N | |
| [file b.py] | |
| from a import N | |
| from typing import NamedTuple | |
| class M(NamedTuple): | |
| r: None | |
| x: int | |
| [file b.py.2] | |
| from a import N | |
| from typing import NamedTuple, Optional | |
| class M(NamedTuple): | |
| r: Optional[N] | |
| x: int | |
| [file c.py] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x.r is not None: | |
| s: int = x.r.x | |
| [file c.py.3] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x.r is not None and x.r.r is not None and x.r.r.r is not None: | |
| reveal_type(x) | |
| s: int = x.r.r.r.r | |
| f(a.n) | |
| reveal_type(a.n) | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/c.py:4: note: Revealed type is "tuple[tuple[... | None, builtins.int, fallback=b.M] | None, builtins.int, fallback=a.N]" | |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "N | None", variable has type "int") | |
| tmp/c.py:7: note: Revealed type is "tuple[tuple[... | None, builtins.int, fallback=b.M] | None, builtins.int, fallback=a.N]" | |
| [case testTupleTypeUpdateNonRecursiveToRecursiveCoarse] | |
| import c | |
| [file a.py] | |
| from b import M | |
| from typing import Tuple, Optional | |
| class N(Tuple[Optional[M], int]): ... | |
| [file b.py] | |
| from a import N | |
| from typing import Tuple | |
| class M(Tuple[None, int]): ... | |
| [file b.py.2] | |
| from a import N | |
| from typing import Tuple, Optional | |
| class M(Tuple[Optional[N], int]): ... | |
| [file c.py] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x[0] is not None: | |
| s: int = x[0][1] | |
| [file c.py.3] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x[0] is not None and x[0][0] is not None and x[0][0][0] is not None: | |
| reveal_type(x) | |
| s: int = x[0][0][0][0] | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/c.py:4: note: Revealed type is "tuple[tuple[... | None, builtins.int, fallback=b.M] | None, builtins.int, fallback=a.N]" | |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "N | None", variable has type "int") | |
| [case testTypeAliasUpdateNonRecursiveToRecursiveCoarse] | |
| import c | |
| [file a.py] | |
| from b import M | |
| from typing import Tuple, Optional | |
| N = Tuple[Optional[M], int] | |
| [file b.py] | |
| from a import N | |
| from typing import Tuple | |
| M = Tuple[None, int] | |
| [file b.py.2] | |
| from a import N | |
| from typing import Tuple, Optional | |
| M = Tuple[Optional[N], int] | |
| [file c.py] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x[0] is not None: | |
| s: int = x[0][1] | |
| [file c.py.3] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x[0] is not None and x[0][0] is not None and x[0][0][0] is not None: | |
| reveal_type(x) | |
| s: int = x[0][0][0][0] | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/c.py:4: note: Revealed type is "tuple[tuple[... | None, builtins.int] | None, builtins.int]" | |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "N | None", variable has type "int") | |
| [case testTypedDictUpdateNonRecursiveToRecursiveCoarse] | |
| import c | |
| [file a.py] | |
| from b import M | |
| from typing import TypedDict, Optional | |
| class N(TypedDict): | |
| r: Optional[M] | |
| x: int | |
| n: N | |
| [file b.py] | |
| from a import N | |
| from typing import TypedDict | |
| class M(TypedDict): | |
| r: None | |
| x: int | |
| [file b.py.2] | |
| from a import N | |
| from typing import TypedDict, Optional | |
| class M(TypedDict): | |
| r: Optional[N] | |
| x: int | |
| [file c.py] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x["r"] is not None: | |
| s: int = x["r"]["x"] | |
| [file c.py.3] | |
| import a | |
| def f(x: a.N) -> None: | |
| if x["r"] is not None and x["r"]["r"] is not None and x["r"]["r"]["r"] is not None: | |
| reveal_type(x) | |
| s: int = x["r"]["r"]["r"]["r"] | |
| f(a.n) | |
| reveal_type(a.n) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/c.py:4: note: Revealed type is "TypedDict('a.N', {'r': TypedDict('b.M', {'r': ... | None, 'x': builtins.int}) | None, 'x': builtins.int})" | |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "N | None", variable has type "int") | |
| tmp/c.py:7: note: Revealed type is "TypedDict('a.N', {'r': TypedDict('b.M', {'r': ... | None, 'x': builtins.int}) | None, 'x': builtins.int})" | |
| [case testIncrementalAddClassMethodPlugin] | |
| # flags: --config-file tmp/mypy.ini | |
| import b | |
| [file mypy.ini] | |
| \[mypy] | |
| plugins=<ROOT>/test-data/unit/plugins/add_classmethod.py | |
| [file a.py] | |
| class BaseAddMethod: pass | |
| class MyClass(BaseAddMethod): | |
| pass | |
| [file b.py] | |
| import a | |
| [file b.py.2] | |
| import a | |
| my_class = a.MyClass() | |
| reveal_type(a.MyClass.foo_classmethod) | |
| reveal_type(a.MyClass.foo_staticmethod) | |
| reveal_type(my_class.foo_classmethod) | |
| reveal_type(my_class.foo_staticmethod) | |
| [rechecked b] | |
| [out2] | |
| tmp/b.py:4: note: Revealed type is "def ()" | |
| tmp/b.py:5: note: Revealed type is "def (builtins.int) -> builtins.str" | |
| tmp/b.py:6: note: Revealed type is "def ()" | |
| tmp/b.py:7: note: Revealed type is "def (builtins.int) -> builtins.str" | |
| [case testIncrementalAddOverloadedMethodPlugin] | |
| # flags: --config-file tmp/mypy.ini | |
| import b | |
| [file mypy.ini] | |
| \[mypy] | |
| plugins=<ROOT>/test-data/unit/plugins/add_overloaded_method.py | |
| [file a.py] | |
| class AddOverloadedMethod: pass | |
| class MyClass(AddOverloadedMethod): | |
| pass | |
| [file b.py] | |
| import a | |
| [file b.py.2] | |
| import a | |
| reveal_type(a.MyClass.method) | |
| reveal_type(a.MyClass.clsmethod) | |
| reveal_type(a.MyClass.stmethod) | |
| my_class = a.MyClass() | |
| reveal_type(my_class.method) | |
| reveal_type(my_class.clsmethod) | |
| reveal_type(my_class.stmethod) | |
| [rechecked b] | |
| [out2] | |
| tmp/b.py:3: note: Revealed type is "Overload(def (self: a.MyClass, arg: builtins.int) -> builtins.str, def (self: a.MyClass, arg: builtins.str) -> builtins.int)" | |
| tmp/b.py:4: note: Revealed type is "Overload(def (arg: builtins.int) -> builtins.str, def (arg: builtins.str) -> builtins.int)" | |
| tmp/b.py:5: note: Revealed type is "Overload(def (arg: builtins.int) -> builtins.str, def (arg: builtins.str) -> builtins.int)" | |
| tmp/b.py:8: note: Revealed type is "Overload(def (arg: builtins.int) -> builtins.str, def (arg: builtins.str) -> builtins.int)" | |
| tmp/b.py:9: note: Revealed type is "Overload(def (arg: builtins.int) -> builtins.str, def (arg: builtins.str) -> builtins.int)" | |
| tmp/b.py:10: note: Revealed type is "Overload(def (arg: builtins.int) -> builtins.str, def (arg: builtins.str) -> builtins.int)" | |
| [case testGenericNamedTupleSerialization] | |
| import b | |
| [file a.py] | |
| from typing import NamedTuple, Generic, TypeVar | |
| T = TypeVar("T") | |
| class NT(NamedTuple, Generic[T]): | |
| key: int | |
| value: T | |
| [file b.py] | |
| from a import NT | |
| nt = NT(key=0, value="yes") | |
| s: str = nt.value | |
| [file b.py.2] | |
| from a import NT | |
| nt = NT(key=0, value=42) | |
| s: str = nt.value | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:3: error: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| [case testGenericTypedDictSerialization] | |
| import b | |
| [file a.py] | |
| from typing import TypedDict, Generic, TypeVar | |
| T = TypeVar("T") | |
| class TD(TypedDict, Generic[T]): | |
| key: int | |
| value: T | |
| [file b.py] | |
| from a import TD | |
| td = TD(key=0, value="yes") | |
| s: str = td["value"] | |
| [file b.py.2] | |
| from a import TD | |
| td = TD(key=0, value=42) | |
| s: str = td["value"] | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:3: error: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| [case testUnpackKwargsSerialize] | |
| import m | |
| [file lib.py] | |
| from typing import TypedDict | |
| from typing_extensions import Unpack | |
| class Person(TypedDict): | |
| name: str | |
| age: int | |
| def foo(**kwargs: Unpack[Person]): | |
| ... | |
| [file m.py] | |
| from lib import foo | |
| foo(name='Jennifer', age=38) | |
| [file m.py.2] | |
| from lib import foo | |
| foo(name='Jennifer', age="38") | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/m.py:2: error: Argument "age" to "foo" has incompatible type "str"; expected "int" | |
| [case testDisableEnableErrorCodesIncremental] | |
| # flags: --disable-error-code truthy-bool | |
| # flags2: --enable-error-code truthy-bool | |
| class Foo: | |
| pass | |
| foo = Foo() | |
| if foo: | |
| ... | |
| [out] | |
| [out2] | |
| main:7: error: "__main__.foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context | |
| [case testModuleAsProtocolImplementationSerialize] | |
| import m | |
| [file m.py] | |
| from typing import Protocol | |
| from lib import C | |
| class Options(Protocol): | |
| timeout: int | |
| def update(self) -> bool: ... | |
| def setup(options: Options) -> None: ... | |
| setup(C().config) | |
| [file lib.py] | |
| import default_config | |
| class C: | |
| config = default_config | |
| [file default_config.py] | |
| timeout = 100 | |
| def update() -> bool: ... | |
| [file default_config.py.2] | |
| timeout = 100 | |
| def update() -> str: ... | |
| [builtins fixtures/module.pyi] | |
| [out] | |
| [out2] | |
| tmp/m.py:9: error: Argument 1 to "setup" has incompatible type Module; expected "Options" | |
| tmp/m.py:9: note: Following member(s) of Module "default_config" have conflicts: | |
| tmp/m.py:9: note: Expected: | |
| tmp/m.py:9: note: def update() -> bool | |
| tmp/m.py:9: note: Got: | |
| tmp/m.py:9: note: def update() -> str | |
| [case testAbstractBodyTurnsEmptyCoarse] | |
| from b import Base | |
| class Sub(Base): | |
| def meth(self) -> int: | |
| return super().meth() | |
| [file b.py] | |
| from abc import abstractmethod | |
| class Base: | |
| @abstractmethod | |
| def meth(self) -> int: return 0 | |
| [file b.py.2] | |
| from abc import abstractmethod | |
| class Base: | |
| @abstractmethod | |
| def meth(self) -> int: ... | |
| [out] | |
| [out2] | |
| main:5: error: Call to abstract method "meth" of "Base" with trivial body via super() is unsafe | |
| [case testLiteralCoarseGrainedChainedAliases] | |
| from mod1 import Alias1 | |
| from typing import Literal | |
| x: Alias1 | |
| def expect_int(x: int) -> None: pass | |
| expect_int(x) | |
| [file mod1.py] | |
| from mod2 import Alias2 | |
| Alias1 = Alias2 | |
| [file mod2.py] | |
| from mod3 import Alias3 | |
| Alias2 = Alias3 | |
| [file mod3.py] | |
| from typing import Literal | |
| Alias3 = int | |
| [file mod3.py.2] | |
| from typing import Literal | |
| Alias3 = str | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| main:5: error: Argument 1 to "expect_int" has incompatible type "str"; expected "int" | |
| [case testLiteralCoarseGrainedChainedAliases2] | |
| from mod1 import Alias1 | |
| from typing import Literal | |
| x: Alias1 | |
| def expect_3(x: Literal[3]) -> None: pass | |
| expect_3(x) | |
| [file mod1.py] | |
| from mod2 import Alias2 | |
| Alias1 = Alias2 | |
| [file mod2.py] | |
| from mod3 import Alias3 | |
| Alias2 = Alias3 | |
| [file mod3.py] | |
| from typing import Literal | |
| Alias3 = Literal[3] | |
| [file mod3.py.2] | |
| from typing import Literal | |
| Alias3 = Literal[4] | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| main:5: error: Argument 1 to "expect_3" has incompatible type "Literal[4]"; expected "Literal[3]" | |
| [case testDoubleReexportFunctionUpdated] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| reveal_type(f.foo) | |
| [file f.py] | |
| import c | |
| def foo(arg: c.C) -> None: pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py] | |
| class C: ... | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/m.py:2: note: Revealed type is "def (arg: pb2.C)" | |
| [case testDoubleReexportGenericUpdated] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| x: f.F | |
| reveal_type(x[0]) | |
| [file f.py] | |
| import c | |
| class FB(list[c.C]): ... | |
| class F(FB): ... | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py] | |
| class C: ... | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/m.py:3: note: Revealed type is "pb2.C" | |
| [case testNoCrashDoubleReexportFunctionEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| def foo(arg: c.C) -> None: pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportAliasEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| D = list[c.C] | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportBaseEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| class D(c.C): pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportBaseEmpty2] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| class D(c.C): pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testDoubleReexportMetaUpdated] | |
| import m | |
| class C(metaclass=m.M): ... | |
| [file m.py] | |
| from types import M | |
| [file types.py] | |
| class M(type): ... | |
| [file types.py.2] | |
| class M: ... | |
| [out] | |
| [out2] | |
| main:2: error: Metaclasses not inheriting from "type" are not supported | |
| [case testIncrementalOkChangeWithSave2] | |
| import mod1 | |
| x: int = mod1.x | |
| [file mod1.py] | |
| from mod2 import x | |
| [file mod2.py] | |
| x = 1 | |
| [file mod2.py.2] | |
| x = "no way" | |
| [out] | |
| [out2] | |
| main:2: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testNoCrashDoubleReexportMetaEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| class D(metaclass=c.C): pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C(type): ... | |
| [file pb2.py.2] | |
| class C(type): ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportMetaEmpty2] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| import c | |
| class D(metaclass=c.C): pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C(type): ... | |
| [file pb2.py.2] | |
| class C(type): ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportTypedDictEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| from typing import TypedDict | |
| import c | |
| class D(TypedDict): | |
| x: c.C | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportTupleEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| from typing import Tuple | |
| import c | |
| class D(Tuple[c.C, int]): pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashDoubleReexportOverloadEmpty] | |
| import m | |
| [file m.py] | |
| import f | |
| [file m.py.3] | |
| import f | |
| # modify | |
| [file f.py] | |
| from typing import Any, overload | |
| import c | |
| @overload | |
| def foo(arg: int) -> None: ... | |
| @overload | |
| def foo(arg: c.C) -> None: ... | |
| def foo(arg: Any) -> None: | |
| pass | |
| [file c.py] | |
| from types import C | |
| [file types.py] | |
| import pb1 | |
| C = pb1.C | |
| [file types.py.2] | |
| import pb1, pb2 | |
| C = pb2.C | |
| [file pb1.py] | |
| class C: ... | |
| [file pb2.py.2] | |
| class C: ... | |
| [file pb1.py.2] | |
| [out] | |
| [out2] | |
| [out3] | |
| [case testNoCrashOnPartialLambdaInference_no_parallel] | |
| # flags: --no-local-partial-types | |
| import m | |
| [file m.py] | |
| from typing import TypeVar, Callable | |
| V = TypeVar("V") | |
| def apply(val: V, func: Callable[[V], None]) -> None: | |
| return func(val) | |
| xs = [] | |
| apply(0, lambda a: xs.append(a)) | |
| [file m.py.2] | |
| from typing import TypeVar, Callable | |
| V = TypeVar("V") | |
| def apply(val: V, func: Callable[[V], None]) -> None: | |
| return func(val) | |
| xs = [] | |
| apply(0, lambda a: xs.append(a)) | |
| reveal_type(xs) | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| [out2] | |
| tmp/m.py:9: note: Revealed type is "builtins.list[builtins.int]" | |
| [case testNoCrashOnPartialLambdaInference_parallel_only] | |
| # flags: --local-partial-types | |
| import m | |
| [file m.py] | |
| from typing import TypeVar, Callable | |
| V = TypeVar("V") | |
| def apply(val: V, func: Callable[[V], None]) -> None: | |
| return func(val) | |
| xs = [] | |
| apply(0, lambda a: xs.append(a)) | |
| [file m.py.2] | |
| from typing import TypeVar, Callable | |
| V = TypeVar("V") | |
| def apply(val: V, func: Callable[[V], None]) -> None: | |
| return func(val) | |
| xs = [] | |
| apply(0, lambda a: xs.append(a)) | |
| reveal_type(xs) | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| tmp/m.py:7: error: Need type annotation for "xs" (hint: "xs: list[<type>] = ...") | |
| tmp/m.py:8: error: Cannot determine type of "xs" | |
| [out2] | |
| tmp/m.py:7: error: Need type annotation for "xs" (hint: "xs: list[<type>] = ...") | |
| tmp/m.py:8: error: Cannot determine type of "xs" | |
| tmp/m.py:9: note: Revealed type is "builtins.list[Any]" | |
| [case testTypingSelfCoarse] | |
| import m | |
| [file lib.py] | |
| from typing import Self | |
| class C: | |
| def meth(self, other: Self) -> Self: ... | |
| [file m.py] | |
| import lib | |
| class D: ... | |
| [file m.py.2] | |
| import lib | |
| class D(lib.C): ... | |
| reveal_type(D.meth) | |
| reveal_type(D().meth) | |
| [out] | |
| [out2] | |
| tmp/m.py:4: note: Revealed type is "def [Self <: lib.C] (self: Self`1, other: Self`1) -> Self`1" | |
| tmp/m.py:5: note: Revealed type is "def (other: m.D) -> m.D" | |
| [case testIncrementalNestedGenericCallableCrash] | |
| from typing import TypeVar, Callable | |
| T = TypeVar("T") | |
| class B: | |
| def foo(self) -> Callable[[T], T]: ... | |
| class C(B): | |
| def __init__(self) -> None: | |
| self.x = self.foo() | |
| [out] | |
| [out2] | |
| [case testNoCrashIncrementalMetaAny] | |
| import a | |
| [file a.py] | |
| from m import Foo | |
| [file a.py.2] | |
| from m import Foo | |
| # touch | |
| [file m.py] | |
| from missing_module import Meta # type: ignore[import] | |
| class Foo(metaclass=Meta): ... | |
| [case testIncrementalNativeInt] | |
| import a | |
| [file a.py] | |
| from mypy_extensions import i64 | |
| x: i64 = 0 | |
| [file a.py.2] | |
| from mypy_extensions import i64 | |
| x: i64 = 0 | |
| y: int = x | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [case testGenericTypedDictWithError] | |
| import b | |
| [file a.py] | |
| from typing import Generic, TypeVar, TypedDict | |
| TValue = TypeVar("TValue") | |
| class Dict(TypedDict, Generic[TValue]): | |
| value: TValue | |
| [file b.py] | |
| from a import Dict, TValue | |
| def f(d: Dict[TValue]) -> TValue: | |
| return d["value"] | |
| def g(d: Dict[TValue]) -> TValue: | |
| return d["x"] | |
| [file b.py.2] | |
| from a import Dict, TValue | |
| def f(d: Dict[TValue]) -> TValue: | |
| return d["value"] | |
| def g(d: Dict[TValue]) -> TValue: | |
| return d["y"] | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "x" | |
| [out2] | |
| tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "y" | |
| [case testParamSpecNoCrash] | |
| import m | |
| [file m.py] | |
| from typing import Callable, TypeVar | |
| from lib import C | |
| T = TypeVar("T") | |
| def test(x: Callable[..., T]) -> T: ... | |
| test(C) # type: ignore | |
| [file m.py.2] | |
| from typing import Callable, TypeVar | |
| from lib import C | |
| T = TypeVar("T") | |
| def test(x: Callable[..., T]) -> T: ... | |
| test(C) # type: ignore | |
| # touch | |
| [file lib.py] | |
| from typing import ParamSpec, Generic, Callable | |
| P = ParamSpec("P") | |
| class C(Generic[P]): | |
| def __init__(self, fn: Callable[P, int]) -> None: ... | |
| [builtins fixtures/dict.pyi] | |
| [case testVariadicClassIncrementalUpdateRegularToVariadic] | |
| from typing import Any | |
| from lib import C | |
| x: C[int, str] | |
| [file lib.py] | |
| from typing import Generic, TypeVar | |
| T = TypeVar("T") | |
| S = TypeVar("S") | |
| class C(Generic[T, S]): ... | |
| [file lib.py.2] | |
| from typing import Generic | |
| from typing_extensions import TypeVarTuple, Unpack | |
| Ts = TypeVarTuple("Ts") | |
| class C(Generic[Unpack[Ts]]): ... | |
| [builtins fixtures/tuple.pyi] | |
| [case testVariadicClassIncrementalUpdateVariadicToRegular] | |
| from typing import Any | |
| from lib import C | |
| x: C[int, str, int] | |
| [file lib.py] | |
| from typing import Generic | |
| from typing_extensions import TypeVarTuple, Unpack | |
| Ts = TypeVarTuple("Ts") | |
| class C(Generic[Unpack[Ts]]): ... | |
| [file lib.py.2] | |
| from typing import Generic, TypeVar | |
| T = TypeVar("T") | |
| S = TypeVar("S") | |
| class C(Generic[T, S]): ... | |
| [builtins fixtures/tuple.pyi] | |
| [out2] | |
| main:4: error: "C" expects 2 type arguments, but 3 given | |
| [case testVariadicTupleIncrementalUpdateNoCrash] | |
| import m | |
| [file m.py] | |
| from typing import Any | |
| from lib import C | |
| x: C[Any] | |
| [file m.py.2] | |
| from lib import C | |
| x: C[int] | |
| [file lib.py] | |
| from typing import Generic, Tuple, TypeVar | |
| from typing_extensions import TypeVarTuple, Unpack | |
| Ts = TypeVarTuple("Ts") | |
| class C(Tuple[Unpack[Ts]]): ... | |
| [builtins fixtures/tuple.pyi] | |
| [case testNoIncrementalCrashOnInvalidTypedDict] | |
| import m | |
| [file m.py] | |
| import counts | |
| [file m.py.2] | |
| import counts | |
| # touch | |
| [file counts.py] | |
| from typing import TypedDict | |
| Counts = TypedDict("Counts", {k: int for k in "abc"}) # type: ignore | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [case testNoIncrementalCrashOnInvalidTypedDictFunc] | |
| import m | |
| [file m.py] | |
| import counts | |
| [file m.py.2] | |
| import counts | |
| # touch | |
| [file counts.py] | |
| from typing import TypedDict | |
| def test() -> None: | |
| Counts = TypedDict("Counts", {k: int for k in "abc"}) # type: ignore | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [case testNoIncrementalCrashOnTypedDictMethod] | |
| import a | |
| [file a.py] | |
| from b import C | |
| x: C | |
| [file a.py.2] | |
| from b import C | |
| x: C | |
| reveal_type(x.h) | |
| [file b.py] | |
| from typing import TypedDict | |
| class C: | |
| def __init__(self) -> None: | |
| self.h: Hidden | |
| class Hidden(TypedDict): | |
| x: int | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "TypedDict('b.Hidden@5', {'x': builtins.int})" | |
| [case testNoIncrementalCrashOnInvalidEnumMethod] | |
| import a | |
| [file a.py] | |
| from lib import TheClass | |
| [file a.py.2] | |
| from lib import TheClass | |
| x: TheClass | |
| reveal_type(x.enum_type) | |
| [file lib.py] | |
| import enum | |
| class TheClass: | |
| def __init__(self) -> None: | |
| names = ["foo"] | |
| pyenum = enum.Enum('Blah', { # type: ignore[misc] | |
| x.upper(): x | |
| for x in names | |
| }) | |
| self.enum_type = pyenum | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| tmp/a.py:3: note: Revealed type is "def (value: builtins.object) -> lib.pyenum@6" | |
| -- Note: do not use _no_parallel unless really needed! | |
| [case testIncrementalFunctoolsPartial_no_parallel] | |
| import a | |
| [file a.py] | |
| from typing import Callable | |
| from partial import p1, p2 | |
| p1(1, "a", 3) # OK | |
| p1(1, "a", c=3) # OK | |
| p1(1, b="a", c=3) # OK | |
| reveal_type(p1) | |
| def takes_callable_int(f: Callable[..., int]) -> None: ... | |
| def takes_callable_str(f: Callable[..., str]) -> None: ... | |
| takes_callable_int(p1) | |
| takes_callable_str(p1) | |
| p2("a") # OK | |
| p2("a", 3) # OK | |
| p2("a", c=3) # OK | |
| p2(1, 3) | |
| p2(1, "a", 3) | |
| p2(a=1, b="a", c=3) | |
| [file a.py.2] | |
| from typing import Callable | |
| from partial import p3 | |
| p3(1) # OK | |
| p3(1, c=3) # OK | |
| p3(a=1) # OK | |
| p3(1, b="a", c=3) # OK, keywords can be clobbered | |
| p3(1, 3) | |
| [file partial.py] | |
| from typing import Callable | |
| import functools | |
| def foo(a: int, b: str, c: int = 5) -> int: ... | |
| p1 = functools.partial(foo) | |
| p2 = functools.partial(foo, 1) | |
| p3 = functools.partial(foo, b="a") | |
| [builtins fixtures/dict.pyi] | |
| [out] | |
| tmp/a.py:8: note: Revealed type is "functools.partial[builtins.int]" | |
| tmp/a.py:13: error: Argument 1 to "takes_callable_str" has incompatible type "partial[int]"; expected "Callable[..., str]" | |
| tmp/a.py:13: note: "partial[int].__call__" has type "def __call__(__self, *args: Any, **kwargs: Any) -> int" | |
| tmp/a.py:18: error: Argument 1 to "foo" has incompatible type "int"; expected "str" | |
| tmp/a.py:19: error: Too many arguments for "foo" | |
| tmp/a.py:19: error: Argument 1 to "foo" has incompatible type "int"; expected "str" | |
| tmp/a.py:19: error: Argument 2 to "foo" has incompatible type "str"; expected "int" | |
| tmp/a.py:20: error: Unexpected keyword argument "a" for "foo" | |
| tmp/a.py:20: note: "foo" defined in "partial" | |
| [out2] | |
| tmp/a.py:8: error: Too many positional arguments for "foo" | |
| tmp/a.py:8: error: Argument 2 to "foo" has incompatible type "int"; expected "str" | |
| [case testStartUsingTypeGuard] | |
| import a | |
| [file a.py] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| [file a.py.2] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| if guard(x): | |
| assert_type(x, int) | |
| else: | |
| assert_type(x, Union[int, str]) | |
| [file lib.py] | |
| from typing_extensions import TypeGuard | |
| def guard(x: object) -> TypeGuard[int]: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testStartUsingTypeIs] | |
| import a | |
| [file a.py] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| [file a.py.2] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| if guard(x): | |
| assert_type(x, int) | |
| else: | |
| assert_type(x, str) | |
| [file lib.py] | |
| from typing_extensions import TypeIs | |
| def guard(x: object) -> TypeIs[int]: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testTypeGuardToTypeIs] | |
| import a | |
| [file a.py] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| if guard(x): | |
| assert_type(x, int) | |
| else: | |
| assert_type(x, Union[int, str]) | |
| [file a.py.2] | |
| from lib import guard | |
| from typing import Union | |
| from typing_extensions import assert_type | |
| x: Union[int, str] | |
| if guard(x): | |
| assert_type(x, int) | |
| else: | |
| assert_type(x, str) | |
| [file lib.py] | |
| from typing_extensions import TypeGuard | |
| def guard(x: object) -> TypeGuard[int]: | |
| pass | |
| [file lib.py.2] | |
| from typing_extensions import TypeIs | |
| def guard(x: object) -> TypeIs[int]: | |
| pass | |
| [builtins fixtures/tuple.pyi] | |
| [case testStartUsingPEP604Union] | |
| import a | |
| [file a.py] | |
| import lib | |
| [file a.py.2] | |
| from lib import IntOrStr | |
| assert isinstance(1, IntOrStr) | |
| [file lib.py] | |
| from typing_extensions import TypeAlias | |
| IntOrStr: TypeAlias = int | str | |
| assert isinstance(1, IntOrStr) | |
| [builtins fixtures/type.pyi] | |
| [case testPropertySetterTypeIncremental] | |
| import b | |
| [file a.py] | |
| class A: | |
| @property | |
| def f(self) -> int: | |
| return 1 | |
| @f.setter | |
| def f(self, x: str) -> None: | |
| pass | |
| [file b.py] | |
| from a import A | |
| [file b.py.2] | |
| from a import A | |
| a = A() | |
| a.f = '' # OK | |
| reveal_type(a.f) | |
| a.f = 1 | |
| reveal_type(a.f) | |
| [builtins fixtures/property.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:4: note: Revealed type is "builtins.int" | |
| tmp/b.py:5: error: Incompatible types in assignment (expression has type "int", variable has type "str") | |
| tmp/b.py:6: note: Revealed type is "builtins.int" | |
| [case testSerializeDeferredGenericNamedTuple] | |
| import pkg | |
| [file pkg/__init__.py] | |
| from .lib import NT | |
| [file pkg/lib.py] | |
| from typing import Generic, NamedTuple, TypeVar | |
| from pkg import does_not_exist # type: ignore | |
| from pkg.missing import also_missing # type: ignore | |
| T = TypeVar("T", bound=does_not_exist) | |
| class NT(NamedTuple, Generic[T]): | |
| values: also_missing[T] | |
| [file pkg/__init__.py.2] | |
| # touch | |
| from .lib import NT | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| [out2] | |
| [case testNewRedefineAffectsCache] | |
| # flags: --local-partial-types --allow-redefinition | |
| # flags2: --local-partial-types | |
| # flags3: --local-partial-types --allow-redefinition | |
| x = 0 | |
| if int(): | |
| x = "" | |
| [out] | |
| [out2] | |
| main:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testUntypedCallsExcludeAffectsCache] | |
| # flags: --disallow-untyped-calls --untyped-calls-exclude=mod.Super | |
| # flags2: --disallow-untyped-calls --untyped-calls-exclude=mod | |
| # flags3: --disallow-untyped-calls --untyped-calls-exclude=mod.Super | |
| import mod | |
| [file mod.py] | |
| class Super: | |
| def draw(self): | |
| ... | |
| class Class(Super): | |
| ... | |
| Class().draw() | |
| [out] | |
| tmp/mod.py:6: error: Call to untyped function "draw" in typed context | |
| [out2] | |
| [out3] | |
| tmp/mod.py:6: error: Call to untyped function "draw" in typed context | |
| [case testMethodMakeBoundIncremental] | |
| from a import A | |
| a = A() | |
| a.f() | |
| [file a.py] | |
| class B: | |
| def f(self, s: A) -> int: ... | |
| def f(s: A) -> int: ... | |
| class A: | |
| f = f | |
| [file a.py.2] | |
| class B: | |
| def f(self, s: A) -> int: ... | |
| def f(s: A) -> int: ... | |
| class A: | |
| f = B().f | |
| [out] | |
| [out2] | |
| main:3: error: Too few arguments | |
| [case testUnreachableAfterToplevelAssertImportThirdParty] | |
| # flags: --platform unknown | |
| import sys | |
| assert sys.platform == 'linux' | |
| import does_not_exist | |
| [builtins fixtures/ops.pyi] | |
| [out] | |
| [out2] | |
| [case testIncrementalNoCrashOnParamSpecPrefixUpdateMethod] | |
| import impl | |
| [file impl.py] | |
| from typing_extensions import ParamSpec | |
| from lib import Sub | |
| P = ParamSpec("P") | |
| class Impl(Sub[P]): | |
| def test(self, *args: P.args, **kwargs: P.kwargs) -> None: | |
| self.meth(1, *args, **kwargs) | |
| [file impl.py.2] | |
| from typing_extensions import ParamSpec | |
| from lib import Sub | |
| P = ParamSpec("P") | |
| class Impl(Sub[P]): | |
| def test(self, *args: P.args, **kwargs: P.kwargs) -> None: | |
| self.meth("no", *args, **kwargs) | |
| [file lib.py] | |
| from typing import Generic | |
| from typing_extensions import ParamSpec, Concatenate | |
| P = ParamSpec("P") | |
| class Base(Generic[P]): | |
| def meth(self, *args: P.args, **kwargs: P.kwargs) -> None: ... | |
| class Sub(Base[Concatenate[int, P]]): ... | |
| [builtins fixtures/paramspec.pyi] | |
| [out] | |
| [out2] | |
| tmp/impl.py:7: error: Argument 1 to "meth" of "Base" has incompatible type "str"; expected "int" | |
| [case testIncrementalNoCrashOnParamSpecPrefixUpdateMethodAlias] | |
| import impl | |
| [file impl.py] | |
| from typing_extensions import ParamSpec | |
| from lib import Sub | |
| P = ParamSpec("P") | |
| class Impl(Sub[P]): | |
| def test(self, *args: P.args, **kwargs: P.kwargs) -> None: | |
| self.alias(1, *args, **kwargs) | |
| [file impl.py.2] | |
| from typing_extensions import ParamSpec | |
| from lib import Sub | |
| P = ParamSpec("P") | |
| class Impl(Sub[P]): | |
| def test(self, *args: P.args, **kwargs: P.kwargs) -> None: | |
| self.alias("no", *args, **kwargs) | |
| [file lib.py] | |
| from typing import Generic | |
| from typing_extensions import ParamSpec, Concatenate | |
| P = ParamSpec("P") | |
| class Base(Generic[P]): | |
| def meth(self, *args: P.args, **kwargs: P.kwargs) -> None: ... | |
| alias = meth | |
| class Sub(Base[Concatenate[int, P]]): ... | |
| [builtins fixtures/paramspec.pyi] | |
| [out] | |
| [out2] | |
| tmp/impl.py:7: error: Argument 1 has incompatible type "str"; expected "int" | |
| [case testIncrementalDifferentSourcesFreshnessCorrect] | |
| # cmd: mypy -m foo bar | |
| # cmd2: mypy -m foo | |
| # cmd3: mypy -m foo bar | |
| [file foo.py] | |
| foo = 5 | |
| [file foo.py.2] | |
| foo = "foo" | |
| [file bar.py] | |
| from foo import foo | |
| bar: int = foo | |
| [out] | |
| [out2] | |
| [out3] | |
| tmp/bar.py:2: error: Incompatible types in assignment (expression has type "str", variable has type "int") | |
| [case testIncrementalBlockingErrorRepeatAndUndo] | |
| import m | |
| [file m.py] | |
| import f | |
| reveal_type(f.x) | |
| [file m.py.3] | |
| import f | |
| reveal_type(f.x) | |
| # touch | |
| [file f.py] | |
| x = 1 | |
| [file f.py.2] | |
| no way | |
| [file f.py.4] | |
| x = 1 | |
| [out] | |
| tmp/m.py:2: note: Revealed type is "builtins.int" | |
| [out2] | |
| tmp/f.py:1: error: Simple statements must be separated by newlines or semicolons | |
| [out3] | |
| tmp/f.py:1: error: Simple statements must be separated by newlines or semicolons | |
| [out4] | |
| tmp/m.py:2: note: Revealed type is "builtins.int" | |
| [case testIncrementalSameErrorOrder] | |
| import m | |
| [file m.py] | |
| import n | |
| def accept_int(x: int) -> None: pass | |
| accept_int(n.foo) | |
| [file n.py] | |
| import other | |
| foo = "hello" | |
| reveal_type(foo) | |
| [file other.py] | |
| [file other.py.2] | |
| # touch | |
| [rechecked other] | |
| [stale] | |
| [out] | |
| tmp/n.py:3: note: Revealed type is "builtins.str" | |
| tmp/m.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [out2] | |
| tmp/n.py:3: note: Revealed type is "builtins.str" | |
| tmp/m.py:3: error: Argument 1 to "accept_int" has incompatible type "str"; expected "int" | |
| [case testIncrementalNoIndirectDepFromLocal] | |
| import foo | |
| import bar | |
| [file foo.py] | |
| # Having a local named 'bar' shouldn't generate a dependency on module 'bar' | |
| def f(bar: int) -> int: | |
| return bar | |
| [file bar.py] | |
| import foo | |
| x = 1 | |
| [file bar.py.2] | |
| import foo | |
| x = 2 | |
| [out] | |
| [rechecked bar] | |
| [stale] | |
| [case testIncrementalTypedDictGetMethodTotalFalse] | |
| import impl | |
| [file lib.py] | |
| from typing import TypedDict | |
| class Unrelated: pass | |
| D = TypedDict('D', {'x': int, 'y': str}, total=False) | |
| [file impl.py] | |
| pass | |
| [file impl.py.2] | |
| from typing import Literal | |
| from lib import D, Unrelated | |
| d: D | |
| u: Unrelated | |
| x: Literal['x'] | |
| y: Literal['y'] | |
| z: Literal['z'] | |
| x_or_y: Literal['x', 'y'] | |
| x_or_z: Literal['x', 'z'] | |
| x_or_y_or_z: Literal['x', 'y', 'z'] | |
| # test with literal expression | |
| reveal_type(d.get('x')) | |
| reveal_type(d.get('y')) | |
| reveal_type(d.get('z')) | |
| reveal_type(d.get('x', u)) | |
| reveal_type(d.get('x', 1)) | |
| reveal_type(d.get('y', None)) | |
| # test with literal type / union of literal types with implicit default | |
| reveal_type(d.get(x)) | |
| reveal_type(d.get(y)) | |
| reveal_type(d.get(z)) | |
| reveal_type(d.get(x_or_y)) | |
| reveal_type(d.get(x_or_z)) | |
| reveal_type(d.get(x_or_y_or_z)) | |
| # test with literal type / union of literal types with explicit default | |
| reveal_type(d.get(x, u)) | |
| reveal_type(d.get(y, u)) | |
| reveal_type(d.get(z, u)) | |
| reveal_type(d.get(x_or_y, u)) | |
| reveal_type(d.get(x_or_z, u)) | |
| reveal_type(d.get(x_or_y_or_z, u)) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/impl.py:13: note: Revealed type is "builtins.int | None" | |
| tmp/impl.py:14: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:15: note: Revealed type is "builtins.object" | |
| tmp/impl.py:16: note: Revealed type is "builtins.int | lib.Unrelated" | |
| tmp/impl.py:17: note: Revealed type is "builtins.int" | |
| tmp/impl.py:18: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:21: note: Revealed type is "builtins.int | None" | |
| tmp/impl.py:22: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:23: note: Revealed type is "builtins.object" | |
| tmp/impl.py:24: note: Revealed type is "builtins.int | builtins.str | None" | |
| tmp/impl.py:25: note: Revealed type is "builtins.object" | |
| tmp/impl.py:26: note: Revealed type is "builtins.object" | |
| tmp/impl.py:29: note: Revealed type is "builtins.int | lib.Unrelated" | |
| tmp/impl.py:30: note: Revealed type is "builtins.str | lib.Unrelated" | |
| tmp/impl.py:31: note: Revealed type is "builtins.object" | |
| tmp/impl.py:32: note: Revealed type is "builtins.int | builtins.str | lib.Unrelated" | |
| tmp/impl.py:33: note: Revealed type is "builtins.object" | |
| tmp/impl.py:34: note: Revealed type is "builtins.object" | |
| [case testIncrementalTypedDictGetMethodTotalTrue] | |
| import impl | |
| [file lib.py] | |
| from typing import TypedDict | |
| class Unrelated: pass | |
| D = TypedDict('D', {'x': int, 'y': str}, total=True) | |
| [file impl.py] | |
| pass | |
| [file impl.py.2] | |
| from typing import Literal | |
| from lib import D, Unrelated | |
| d: D | |
| u: Unrelated | |
| x: Literal['x'] | |
| y: Literal['y'] | |
| z: Literal['z'] | |
| x_or_y: Literal['x', 'y'] | |
| x_or_z: Literal['x', 'z'] | |
| x_or_y_or_z: Literal['x', 'y', 'z'] | |
| # test with literal expression | |
| reveal_type(d.get('x')) | |
| reveal_type(d.get('y')) | |
| reveal_type(d.get('z')) | |
| reveal_type(d.get('x', u)) | |
| reveal_type(d.get('x', 1)) | |
| reveal_type(d.get('y', None)) | |
| # test with literal type / union of literal types with implicit default | |
| reveal_type(d.get(x)) | |
| reveal_type(d.get(y)) | |
| reveal_type(d.get(z)) | |
| reveal_type(d.get(x_or_y)) | |
| reveal_type(d.get(x_or_z)) | |
| reveal_type(d.get(x_or_y_or_z)) | |
| # test with literal type / union of literal types with explicit default | |
| reveal_type(d.get(x, u)) | |
| reveal_type(d.get(y, u)) | |
| reveal_type(d.get(z, u)) | |
| reveal_type(d.get(x_or_y, u)) | |
| reveal_type(d.get(x_or_z, u)) | |
| reveal_type(d.get(x_or_y_or_z, u)) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/impl.py:13: note: Revealed type is "builtins.int" | |
| tmp/impl.py:14: note: Revealed type is "builtins.str" | |
| tmp/impl.py:15: note: Revealed type is "builtins.object" | |
| tmp/impl.py:16: note: Revealed type is "builtins.int" | |
| tmp/impl.py:17: note: Revealed type is "builtins.int" | |
| tmp/impl.py:18: note: Revealed type is "builtins.str" | |
| tmp/impl.py:21: note: Revealed type is "builtins.int" | |
| tmp/impl.py:22: note: Revealed type is "builtins.str" | |
| tmp/impl.py:23: note: Revealed type is "builtins.object" | |
| tmp/impl.py:24: note: Revealed type is "builtins.int | builtins.str" | |
| tmp/impl.py:25: note: Revealed type is "builtins.object" | |
| tmp/impl.py:26: note: Revealed type is "builtins.object" | |
| tmp/impl.py:29: note: Revealed type is "builtins.int" | |
| tmp/impl.py:30: note: Revealed type is "builtins.str" | |
| tmp/impl.py:31: note: Revealed type is "builtins.object" | |
| tmp/impl.py:32: note: Revealed type is "builtins.int | builtins.str" | |
| tmp/impl.py:33: note: Revealed type is "builtins.object" | |
| tmp/impl.py:34: note: Revealed type is "builtins.object" | |
| [case testIncrementalTypedDictGetMethodTotalMixed] | |
| import impl | |
| [file lib.py] | |
| from typing import TypedDict | |
| from typing_extensions import Required, NotRequired | |
| class Unrelated: pass | |
| D = TypedDict('D', {'x': Required[int], 'y': NotRequired[str]}) | |
| [file impl.py] | |
| pass | |
| [file impl.py.2] | |
| from typing import Literal | |
| from lib import D, Unrelated | |
| d: D | |
| u: Unrelated | |
| x: Literal['x'] | |
| y: Literal['y'] | |
| z: Literal['z'] | |
| x_or_y: Literal['x', 'y'] | |
| x_or_z: Literal['x', 'z'] | |
| x_or_y_or_z: Literal['x', 'y', 'z'] | |
| # test with literal expression | |
| reveal_type(d.get('x')) | |
| reveal_type(d.get('y')) | |
| reveal_type(d.get('z')) | |
| reveal_type(d.get('x', u)) | |
| reveal_type(d.get('x', 1)) | |
| reveal_type(d.get('y', None)) | |
| # test with literal type / union of literal types with implicit default | |
| reveal_type(d.get(x)) | |
| reveal_type(d.get(y)) | |
| reveal_type(d.get(z)) | |
| reveal_type(d.get(x_or_y)) | |
| reveal_type(d.get(x_or_z)) | |
| reveal_type(d.get(x_or_y_or_z)) | |
| # test with literal type / union of literal types with explicit default | |
| reveal_type(d.get(x, u)) | |
| reveal_type(d.get(y, u)) | |
| reveal_type(d.get(z, u)) | |
| reveal_type(d.get(x_or_y, u)) | |
| reveal_type(d.get(x_or_z, u)) | |
| reveal_type(d.get(x_or_y_or_z, u)) | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| [out2] | |
| tmp/impl.py:13: note: Revealed type is "builtins.int" | |
| tmp/impl.py:14: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:15: note: Revealed type is "builtins.object" | |
| tmp/impl.py:16: note: Revealed type is "builtins.int" | |
| tmp/impl.py:17: note: Revealed type is "builtins.int" | |
| tmp/impl.py:18: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:21: note: Revealed type is "builtins.int" | |
| tmp/impl.py:22: note: Revealed type is "builtins.str | None" | |
| tmp/impl.py:23: note: Revealed type is "builtins.object" | |
| tmp/impl.py:24: note: Revealed type is "builtins.int | builtins.str | None" | |
| tmp/impl.py:25: note: Revealed type is "builtins.object" | |
| tmp/impl.py:26: note: Revealed type is "builtins.object" | |
| tmp/impl.py:29: note: Revealed type is "builtins.int" | |
| tmp/impl.py:30: note: Revealed type is "builtins.str | lib.Unrelated" | |
| tmp/impl.py:31: note: Revealed type is "builtins.object" | |
| tmp/impl.py:32: note: Revealed type is "builtins.int | builtins.str | lib.Unrelated" | |
| tmp/impl.py:33: note: Revealed type is "builtins.object" | |
| tmp/impl.py:34: note: Revealed type is "builtins.object" | |
| [case testIncrementalAccessSubmoduleWithoutExplicitImport] | |
| import b | |
| import a | |
| [file a.py] | |
| import pkg | |
| pkg.submod.foo() | |
| [file a.py.2] | |
| import pkg | |
| pkg.submod.foo() | |
| x = 1 | |
| [file b.py] | |
| import c | |
| [file c.py] | |
| from pkg import submod | |
| [file pkg/__init__.pyi] | |
| [file pkg/submod.pyi] | |
| def foo() -> None: pass | |
| [out] | |
| tmp/a.py:3: error: Module has no attribute "submod" | |
| [out2] | |
| tmp/a.py:3: error: Module has no attribute "submod" | |
| [case testIncrementalAccessSubmoduleWithoutExplicitImportNested] | |
| import a | |
| [file a.py] | |
| import pandas | |
| pandas.core.dtypes | |
| [file a.py.2] | |
| import pandas | |
| pandas.core.dtypes | |
| # touch | |
| [file pandas/__init__.py] | |
| import pandas.core.api | |
| [file pandas/core/__init__.py] | |
| [file pandas/core/api.py] | |
| import pandas.core.dtypes.dtypes | |
| [file pandas/core/dtypes/__init__.py] | |
| [file pandas/core/dtypes/dtypes.py] | |
| X = 0 | |
| [out] | |
| [out2] | |
| [case testIncrementalAccessSubmoduleWithoutExplicitImportNestedFrom] | |
| import a | |
| [file a.py] | |
| import pandas | |
| # Although this actually works at runtime, we do not support this, since | |
| # this would cause major slowdown for a rare edge case. This test verifies | |
| # that we fail consistently on cold and warm runs. | |
| pandas.core.dtypes | |
| [file a.py.2] | |
| import pandas | |
| pandas.core.dtypes | |
| [file pandas/__init__.py] | |
| import pandas.core.api | |
| [file pandas/core/__init__.py] | |
| [file pandas/core/api.py] | |
| from pandas.core.dtypes.dtypes import X | |
| [file pandas/core/dtypes/__init__.py] | |
| [file pandas/core/dtypes/dtypes.py] | |
| X = 0 | |
| [out] | |
| tmp/a.py:6: error: Module has no attribute "dtypes" | |
| [out2] | |
| tmp/a.py:2: error: Module has no attribute "dtypes" | |
| [case testStarImportCycleRedefinition] | |
| import m | |
| [file m.py] | |
| import a | |
| [file m.py.2] | |
| import a | |
| reveal_type(a.C) | |
| [file a/__init__.py] | |
| from a.b import * | |
| from a.c import * | |
| x = 1 | |
| [file a/b.py] | |
| from other import C | |
| from a.c import y | |
| class C: ... # type: ignore | |
| [file a/c.py] | |
| from other import C | |
| from a import x | |
| y = 1 | |
| [file other.py] | |
| class C: ... | |
| [out2] | |
| tmp/m.py:2: note: Revealed type is "def () -> other.C" | |
| [case testOutputFormatterIncremental] | |
| # flags2: --output json | |
| def wrong() -> int: | |
| if wrong(): | |
| return 0 | |
| [out] | |
| main:2: error: Missing return statement | |
| [out2] | |
| {"file": "main", "line": 2, "column": 0, "end_line": 4, "end_column": 16, "message": "Missing return statement", "hint": null, "code": "return", "severity": "error"} | |
| [case testReExportAllInStubIncremental] | |
| from m1 import C | |
| from m1 import D | |
| C() | |
| C(1) | |
| [file m1.pyi] | |
| from m2 import * | |
| [file m2.pyi] | |
| from m3 import * | |
| from m3 import __all__ as __all__ | |
| class D: pass | |
| [file m2.pyi.2] | |
| from m3 import * | |
| from m3 import __all__ as __all__ | |
| class D: | |
| x = 1 | |
| [file m3.pyi] | |
| from m4 import C as C | |
| __all__ = ['C'] | |
| [file m4.pyi] | |
| class C: pass | |
| [builtins fixtures/list.pyi] | |
| [out] | |
| main:2: error: Module "m1" has no attribute "D" | |
| main:4: error: Too many arguments for "C" | |
| [out2] | |
| main:2: error: Module "m1" has no attribute "D" | |
| main:4: error: Too many arguments for "C" | |
| [case testCyclicUndefinedImportWithStarIncremental] | |
| import m | |
| [file m.py] | |
| import a | |
| [file m.py.2] | |
| import a | |
| reveal_type(a.no_such_export) | |
| [file a.py] | |
| from b import no_such_export | |
| [file b.py] | |
| from a import * | |
| [out] | |
| tmp/b.py:1: error: Cannot resolve name "no_such_export" (possible cyclic definition) | |
| [out2] | |
| tmp/b.py:1: error: Cannot resolve name "no_such_export" (possible cyclic definition) | |
| tmp/m.py:2: note: Revealed type is "Any" | |
| [case testCachedUnexpectedKeywordArgument] | |
| import m | |
| [file m.py] | |
| import a | |
| [file a.py] | |
| import b | |
| b.lol(uhhhh=12) # tweak | |
| [file a.py.2] | |
| import b | |
| b.lol(uhhhh=12) | |
| [file b.py] | |
| def lol() -> None: pass | |
| [file b.py.3] | |
| # space | |
| def lol() -> None: pass | |
| [file m.py.4] | |
| import a # touch | |
| [out] | |
| tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" | |
| tmp/a.py:2: note: "lol" defined in "b" | |
| [out2] | |
| tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" | |
| tmp/a.py:2: note: "lol" defined in "b" | |
| [out3] | |
| tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" | |
| tmp/a.py:2: note: "lol" defined in "b" | |
| [out4] | |
| tmp/a.py:2: error: Unexpected keyword argument "uhhhh" for "lol" | |
| tmp/a.py:2: note: "lol" defined in "b" | |
| [case testMissingImportUnIgnoredInConfig] | |
| # flags: --config-file tmp/mypy.ini | |
| from foo import bar | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = True | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = False | |
| [out] | |
| [out2] | |
| main:2: error: Cannot find implementation or library stub for module named "foo" | |
| main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testMissingImportUnIgnoredInConfig2] | |
| # flags: --config-file tmp/mypy.ini | |
| from foo import bar | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = False | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = True | |
| [out] | |
| main:2: error: Cannot find implementation or library stub for module named "foo" | |
| main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [out2] | |
| [case testMissingImportUnIgnoredInConfig3] | |
| # flags: --config-file tmp/mypy.ini | |
| from foo import bar | |
| [file foo.py] | |
| bar = 1 | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| follow_imports = skip | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| follow_imports = error | |
| [out] | |
| [out2] | |
| main:2: error: Import of "foo" ignored | |
| main:2: note: (Using --follow-imports=error, module not passed on command line) | |
| [case testMissingImportUnIgnoredInConfig4] | |
| # flags: --config-file tmp/mypy.ini | |
| from foo import bar | |
| [file foo.py] | |
| bar = 1 | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| follow_imports = error | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| follow_imports = skip | |
| [out] | |
| main:2: error: Import of "foo" ignored | |
| main:2: note: (Using --follow-imports=error, module not passed on command line) | |
| [out2] | |
| [case testMissingImportUnIgnoredInConfig5] | |
| # flags: --config-file tmp/mypy.ini --warn-unused-ignores | |
| from foo import bar # type: ignore[import-not-found] | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = True | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = False | |
| [out] | |
| main:2: error: Unused "type: ignore" comment | |
| [out2] | |
| [case testMissingImportUnIgnoredInConfig6] | |
| # flags: --config-file tmp/mypy.ini --warn-unused-ignores | |
| from foo import bar # type: ignore[import-not-found] | |
| [file mypy.ini] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = False | |
| [file mypy.ini.2] | |
| \[mypy] | |
| \[mypy-foo] | |
| ignore_missing_imports = True | |
| [out] | |
| [out2] | |
| main:2: error: Unused "type: ignore" comment | |
| [case testIndirectDependencyReorderModulesNoCrash] | |
| import a | |
| [file a.py] | |
| import b | |
| [file a.py.2] | |
| import pkg.mod | |
| import b | |
| [file b.py] | |
| import foo | |
| import pkg | |
| x: pkg.mod.C | |
| [file pkg/__init__.py] | |
| [file pkg/mod.py] | |
| import c | |
| class C: ... | |
| # The chain of trivial stale modules is to force late load of pkg.mod, | |
| # otherwise the test can pass accidentally. | |
| [file c.py] | |
| import d | |
| [file c.py.2] | |
| import d # touch | |
| [file d.py] | |
| import e | |
| [file d.py.2] | |
| import e # touch | |
| [file e.py] | |
| [file foo.py] | |
| import bar | |
| [file bar.py] | |
| import pkg.mod | |
| [file bar.py.2] | |
| [out] | |
| [out2] | |
| tmp/b.py:3: error: Name "pkg.mod.C" is not defined | |
| [case testIndirectDependencyReorderModulesNoCrash2] | |
| import m | |
| [file m.py] | |
| import a | |
| [file m.py.2] | |
| import a | |
| import d | |
| [file a.py] | |
| import b | |
| x: b.c.d.C | |
| [file b.py] | |
| import c | |
| [file c.py] | |
| import d | |
| [file c.py.2] | |
| [file d.py] | |
| import n1 | |
| class C: ... | |
| # The chain of trivial stale modules is to force late load of d, | |
| # otherwise the test can pass accidentally. | |
| [file n1.py] | |
| import n2 | |
| [file n1.py.2] | |
| import n2 # touch | |
| [file n2.py] | |
| import n3 | |
| [file n2.py.2] | |
| import n3 # touch | |
| [file n3.py] | |
| [out] | |
| [out2] | |
| tmp/a.py:2: error: Name "b.c.d.C" is not defined | |
| [case testDeletedModuleFromImport] | |
| # flags: --ignore-missing-imports | |
| from a import b | |
| [file a/__init__.py] | |
| [file a/b.py] | |
| [delete a/b.py.2] | |
| [out] | |
| [out2] | |
| main:2: error: Module "a" has no attribute "b" | |
| [case testDeletedModuleFromImport2] | |
| # flags: --ignore-missing-imports | |
| import a | |
| import a.b | |
| from a import b # no error here | |
| [file a/__init__.py] | |
| [file a/b.py] | |
| [delete a/b.py.2] | |
| [out] | |
| [out2] | |
| [case testDeletedModuleFromImport3] | |
| # flags: --warn-unused-ignores | |
| from a import b # type: ignore[attr-defined] | |
| [file a/__init__.py] | |
| [file a/b.py] | |
| [delete a/b.py.2] | |
| [out] | |
| main:2: error: Unused "type: ignore" comment | |
| [out2] | |
| [case testConfigWarnUnusedSectionIncremental] | |
| # flags: --config-file=tmp/mypy.ini | |
| import m | |
| [file m.py] | |
| import a | |
| [file m.py.2] | |
| import a # touch | |
| [file a.py] | |
| import foo # type: ignore | |
| [file mypy.ini] | |
| \[mypy] | |
| warn_unused_configs = true | |
| \[mypy-bar] | |
| \[mypy-foo] | |
| [file mypy.ini.3] | |
| \[mypy] | |
| warn_unused_configs = true | |
| \[mypy-foo] | |
| [out] | |
| tmp/mypy.ini: note: unused section(s): [mypy-bar] | |
| [out2] | |
| tmp/mypy.ini: note: unused section(s): [mypy-bar] | |
| [out3] | |
| [case testConfigWarnUnusedSectionIncrementalTOML] | |
| # flags: --config-file tmp/pyproject.toml | |
| import m | |
| [file m.py] | |
| import a | |
| [file m.py.2] | |
| import a # touch | |
| [file a.py] | |
| import foo # type: ignore | |
| [file pyproject.toml] | |
| \[tool.mypy] | |
| warn_unused_configs = true | |
| \[[tool.mypy.overrides]] | |
| module = "bar" | |
| \[[tool.mypy.overrides]] | |
| module = "foo" | |
| warn_unreachable = true | |
| [file pyproject.toml.3] | |
| \[tool.mypy] | |
| warn_unused_configs = true | |
| \[[tool.mypy.overrides]] | |
| module = "foo" | |
| [out] | |
| tmp/pyproject.toml: note: unused section(s): module = ['bar'] | |
| [out2] | |
| tmp/pyproject.toml: note: unused section(s): module = ['bar'] | |
| [out3] | |
| [case testAddedMissingModuleSkip] | |
| # flags: --follow-imports=skip | |
| import mod | |
| [file mod.py.2] | |
| [out] | |
| main:2: error: Cannot find implementation or library stub for module named "mod" | |
| main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [out2] | |
| [case testDeletedModuleSkip] | |
| # flags: --follow-imports=skip | |
| import mod | |
| [file mod.py] | |
| [delete mod.py.2] | |
| [out] | |
| [out2] | |
| main:2: error: Cannot find implementation or library stub for module named "mod" | |
| main:2: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports | |
| [case testIncrementalFileConfigCommentsStale] | |
| -- When a dependency changes, the importing module becomes stale and is | |
| -- reprocessed via process_stale_scc. As inline config comments are not cached | |
| -- (by design), moving the order of processing the stale SCC can accidentally | |
| -- break file config comments on subsequent runs. | |
| # mypy: disable-error-code="import-not-found" | |
| import nonexistent | |
| import b | |
| [file b.py] | |
| x = 1 | |
| [file b.py.2] | |
| x = "hello" | |
| [builtins fixtures/module.pyi] | |
| [stale b] | |
| [rechecked b] | |
| [case testNamedTupleInlineBaseClassNoNameCollision] | |
| import m | |
| [file m.py] | |
| from lib import A, B | |
| a: A | |
| b: B | |
| reveal_type(a) | |
| reveal_type(b) | |
| [file m.py.2] | |
| from lib import A, B | |
| a: A | |
| b: B | |
| reveal_type(a) # touch | |
| reveal_type(b) | |
| [file lib.py] | |
| from typing import NamedTuple | |
| class A(NamedTuple("Same", [('x', int)])): pass | |
| class B(NamedTuple("Same", [('x', str)])): pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| tmp/m.py:4: note: Revealed type is "tuple[builtins.int, fallback=lib.A]" | |
| tmp/m.py:5: note: Revealed type is "tuple[builtins.str, fallback=lib.B]" | |
| [out2] | |
| tmp/m.py:4: note: Revealed type is "tuple[builtins.int, fallback=lib.A]" | |
| tmp/m.py:5: note: Revealed type is "tuple[builtins.str, fallback=lib.B]" | |
| [case testNamedTupleInlineBaseClassRedefined] | |
| import m | |
| [file m.py] | |
| from lib import A | |
| a: A | |
| reveal_type(a) | |
| [file m.py.2] | |
| from lib import A | |
| a: A # touch | |
| reveal_type(a) | |
| [file lib.py] | |
| from typing import NamedTuple | |
| class A(NamedTuple("N", [('x', int)])): pass | |
| class A(NamedTuple("N", [('x', str)])): pass | |
| [builtins fixtures/tuple.pyi] | |
| [out] | |
| tmp/lib.py:3: error: Name "A" already defined on line 2 | |
| tmp/m.py:3: note: Revealed type is "tuple[builtins.int, fallback=lib.A]" | |
| [out2] | |
| tmp/lib.py:3: error: Name "A" already defined on line 2 | |
| tmp/m.py:3: note: Revealed type is "tuple[builtins.int, fallback=lib.A]" | |
| [case testTypedDictInlineBaseClassRedefined] | |
| import m | |
| [file m.py] | |
| from lib import A | |
| a: A | |
| reveal_type(a) | |
| [file m.py.2] | |
| from lib import A | |
| a: A # touch | |
| reveal_type(a) | |
| [file lib.py] | |
| from typing import TypedDict | |
| class A(TypedDict("TD", {'x': int})): | |
| pass | |
| class A(TypedDict("TD", {'x': str})): | |
| pass | |
| [builtins fixtures/dict.pyi] | |
| [typing fixtures/typing-typeddict.pyi] | |
| [out] | |
| tmp/lib.py:4: error: Name "A" already defined (possibly by an import) | |
| tmp/m.py:3: note: Revealed type is "TypedDict('lib.A', {'x': builtins.int})" | |
| [out2] | |
| tmp/lib.py:4: error: Name "A" already defined (possibly by an import) | |
| tmp/m.py:3: note: Revealed type is "TypedDict('lib.A', {'x': builtins.int})" | |
| [case testNewReturnTypeIncremental] | |
| import m | |
| [file m.py] | |
| from lib import C | |
| reveal_type(C().ta) | |
| x: int = C().ta | |
| reveal_type(C().ta.x) | |
| [file m.py.2] | |
| from lib import C | |
| # touch | |
| reveal_type(C().ta) | |
| x: int = C().ta | |
| reveal_type(C().ta.x) | |
| [file lib.py] | |
| class A: | |
| x = "test" | |
| def __new__(cls) -> int: ... # type: ignore | |
| class C: | |
| def __init__(self) -> None: | |
| self.ta = A | |
| [out] | |
| tmp/m.py:3: note: Revealed type is "def () -> builtins.int" | |
| tmp/m.py:4: error: Incompatible types in assignment (expression has type "type[A]", variable has type "int") | |
| tmp/m.py:5: note: Revealed type is "builtins.str" | |
| [out2] | |
| tmp/m.py:4: note: Revealed type is "def () -> builtins.int" | |
| tmp/m.py:5: error: Incompatible types in assignment (expression has type "type[A]", variable has type "int") | |
| tmp/m.py:6: note: Revealed type is "builtins.str" | |
| [case testTypeFormWorksInIncrementalMode] | |
| import b | |
| [file a.py] | |
| from typing import TypeVar | |
| from typing_extensions import TypeForm | |
| T = TypeVar("T") | |
| def test(arg: TypeForm[T]) -> T: ... | |
| [file b.py] | |
| from a import test | |
| test("int") | |
| [file b.py.2] | |
| from a import test | |
| reveal_type(test("int")) | |
| [builtins fixtures/primitives.pyi] | |
| [typing fixtures/typing-full.pyi] | |
| [out] | |
| [out2] | |
| tmp/b.py:2: note: Revealed type is "builtins.int" | |
| [case testIncrementalNativeParserShadowFile] | |
| # flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py | |
| import a | |
| import b | |
| -- a and b don't depend on each other, so they can be checked in parallel. | |
| [file a.py] | |
| x: int = 1 | |
| reveal_type(x) | |
| [file b.py] | |
| y: int = 2 | |
| [file a_shadow.py] | |
| x: str = "y" | |
| reveal_type(x) | |
| [rechecked] | |
| [stale] | |
| [out1] | |
| tmp/a.py:2: note: Revealed type is "builtins.str" | |
| [out2] | |
| tmp/a.py:2: note: Revealed type is "builtins.str" | |
| [case testIncrementalNativeParserShadowFileChanged] | |
| # flags: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py | |
| import a | |
| import b | |
| -- a and b don't depend on each other, so they can be checked in parallel. | |
| [file a.py] | |
| x: int = 1 | |
| reveal_type(x) | |
| [file b.py] | |
| y: int = 2 | |
| [file a_shadow.py] | |
| x: str = "y" | |
| reveal_type(x) | |
| [file a_shadow.py.2] | |
| x: bytes = b"y" | |
| reveal_type(x) | |
| [rechecked a] | |
| [stale a] | |
| [out1] | |
| tmp/a.py:2: note: Revealed type is "builtins.str" | |
| [out2] | |
| tmp/a.py:2: note: Revealed type is "builtins.bytes" | |
| [case testIncrementalNativeParserShadowFileIntroduced] | |
| # flags: --native-parser | |
| # flags2: --native-parser --shadow-file tmp/a.py tmp/a_shadow.py | |
| import a | |
| import b | |
| -- a and b don't depend on each other, so they can be checked in parallel. | |
| -- The first run has no shadow file; the second run introduces one for a.py. | |
| [file a.py] | |
| x: int = 1 | |
| reveal_type(x) | |
| [file b.py] | |
| y: int = 2 | |
| [file a_shadow.py.2] | |
| x: str = "y" | |
| reveal_type(x) | |
| [rechecked a] | |
| [stale a] | |
| [out1] | |
| tmp/a.py:2: note: Revealed type is "builtins.int" | |
| [out2] | |
| tmp/a.py:2: note: Revealed type is "builtins.str" | |
| [case testIncrementalFollowImportsSkipStubWithSkippedRuntimeDependency] | |
| # flags: --follow-imports=skip | |
| import pkg.foo | |
| [file pkg/__init__.py] | |
| [file pkg/foo.pyi] | |
| from pkg import helper | |
| x = 1 | |
| [file pkg/helper.py] | |
| y = 2 | |
| [rechecked] | |
| [stale] | |
| [out2] | |
| [out3] | |
| [case testNoLocalPartialTypesInlineRespectedIncremental_no_parallel] | |
| import a | |
| [file a.py] | |
| # mypy: no-local-partial-types | |
| import dep | |
| items = [] | |
| def add() -> None: | |
| items.append(1) | |
| reveal_type(items) | |
| [file dep.py] | |
| value: int = 1 | |
| [file dep.py.2] | |
| value: str = "x" | |
| [builtins fixtures/list.pyi] | |
| [rechecked a, dep] | |
| [stale dep] | |
| [out] | |
| tmp/a.py:9: note: Revealed type is "builtins.list[builtins.int]" | |
| [out2] | |
| tmp/a.py:9: note: Revealed type is "builtins.list[builtins.int]" | |
| [case testIncrementalWorksCorrectlyWithNonUtf8] | |
| import a | |
| [file a.py] | |
| import b_latin1 | |
| [file a.py.2] | |
| import b_latin1 | |
| # touch | |
| [file b_latin1.py] | |
| # coding: latin-1 | |
| Jérôme = False | |
| [file b_latin1.py.2] | |
| # coding: latin-1 | |
| Jérôme = False | |
| [rechecked a] | |
| [stale] | |
| [out] | |
| [out2] |