| -- 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] |
| [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 mod1, 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 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 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 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.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, 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 c] |
| [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] |
| [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] |
| [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 "Union[builtins.int, builtins.str]" |
| tmp/a.py:5: note: Revealed type is "Union[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] |
| [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, mod2, mod1] |
| [stale mod3, mod2] |
| [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, mod2, mod1] |
| [stale 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, mod2, mod1] |
| [stale mod4, mod3, mod2] |
| [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 = None # type: A |
| class Y: |
| attr = None # type: 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 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 mypy_extensions import TypedDict |
| class C: |
| def f(self) -> None: |
| A = TypedDict('A', {'x': int, 'y': int}) |
| [builtins fixtures/dict.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 mypy_extensions import TypedDict |
| class C: |
| class D: |
| def f(self) -> None: |
| A = TypedDict('A', {'x': int, 'y': int}) |
| [builtins fixtures/dict.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 mypy_extensions import TypedDict |
| class C: |
| def a(self): |
| class D: |
| def f(self) -> None: |
| A = TypedDict('A', {'x': int, 'y': int}) |
| [builtins fixtures/dict.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 mypy_extensions import TypedDict |
| from typing import NewType, NamedTuple |
| 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] |
| [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 = None # type: 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 = None # type: ClassVar[int] |
| [file m.py.2] |
| class A: |
| x = None # type: 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 = None # type: 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 mypy_extensions import TypedDict |
| A = TypedDict('A', {'x': int, 'y': str}) |
| x: A |
| [builtins fixtures/dict.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] |
| [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] |
| [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] |
| [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] |
| mypy: can't read file 'tmp/nonexistent.py': 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 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, Dict |
| from mypy_extensions import TypedDict |
| |
| NT = NewType('NT', N) # type: ignore |
| class N(TypedDict): |
| x: A |
| A = Dict[str, int] |
| [builtins fixtures/dict.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 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 m.a, m.b] |
| [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 "Optional[int]" |
| |
| [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/list.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`1, other: _AT`1) -> builtins.bool" |
| main:4: note: Revealed type is "def [_AT] (self: _AT`2, other: _AT`2) -> builtins.bool" |
| main:5: note: Revealed type is "def [_AT] (self: _AT`3, other: _AT`3) -> builtins.bool" |
| main:6: note: Revealed type is "def [_AT] (self: _AT`4, other: _AT`4) -> 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 |
| class A: |
| a: int |
| |
| [file b.py] |
| import attrs |
| @attrs.define |
| class B: |
| b: str |
| |
| [file c.py] |
| from a import A |
| from b import B |
| import attrs |
| @attrs.define |
| 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: Union[builtins.int, None]) -> a.a.A" |
| [out2] |
| main:2: note: Revealed type is "def (x: Union[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 "Optional[str]" |
| tmp/a.py:6: error: Argument 2 to "A" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:7: error: Argument 5 to "B" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:10: error: Argument 2 to "SubBase" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:13: error: Argument 2 to "AA" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:14: error: Argument 5 to "BB" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:17: error: Argument 2 to "SubAA" has incompatible type "int"; expected "Optional[str]" |
| tmp/a.py:18: error: Argument 5 to "SubBB" has incompatible type "int"; expected "Optional[str]" |
| |
| [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 "Optional[int]" |
| |
| [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, typing] |
| [stale _typeshed, a, builtins, 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.8/@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, typing] |
| [rechecked _typeshed, a, b, builtins, 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, typing] |
| [rechecked _typeshed, a, b, builtins, 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.8/@deps.meta.json.2] |
| [file b.py.2] |
| # uh |
| -- Every file should get reloaded, since the cache was invalidated |
| [stale _typeshed, a, b, builtins, typing] |
| [rechecked _typeshed, a, b, builtins, 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] |
| # flags: --python-version 3.7 |
| 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] |
| # flags: --python-version 3.7 |
| 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] |
| # flags: --python-version 3.7 |
| 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] |
| # flags: --python-version 3.7 |
| 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] |
| # flags: --python-version 3.7 |
| 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:3: error: Argument 2 to "B" has incompatible type "str"; expected "int" |
| [rechecked b] |
| |
| [case testIncrementalDataclassesSubclassModifiedErrorFirst] |
| # flags: --python-version 3.7 |
| 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:3: error: Argument 2 to "B" has incompatible type "str"; expected "int" |
| |
| [out2] |
| [rechecked b] |
| |
| [case testIncrementalDataclassesThreeFiles] |
| # flags: --python-version 3.7 |
| 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:3: error: Argument 2 to "C" has incompatible type "int"; expected "bool" |
| |
| [case testIncrementalDataclassesThreeRuns] |
| # flags: --python-version 3.7 |
| 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:3: 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 mypy_extensions 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 |
| [typing fixtures/typing-medium.pyi] |
| [builtins fixtures/dict.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] |
| # flags: --disable-recursive-aliases |
| 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] |
| tmp/lib.pyi:4: error: Module "other" has no attribute "B" |
| tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) |
| [out2] |
| tmp/lib.pyi:4: error: Module "other" has no attribute "B" |
| tmp/other.pyi:3: error: Cannot resolve name "B" (possible cyclic definition) |
| tmp/a.py:3: note: Revealed type is "builtins.list[Any]" |
| |
| [case testRecursiveNamedTupleTypedDict-skip] |
| # https://github.com/python/mypy/issues/7125 |
| |
| 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)]) # type: ignore |
| [file other.pyi] |
| from mypy_extensions import TypedDict |
| from lib import A |
| B = TypedDict('B', {'x': A}) |
| [builtins fixtures/dict.pyi] |
| [out] |
| [out2] |
| tmp/a.py:3: note: Revealed type is "Tuple[TypedDict('other.B', {'x': Any}), 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_extensions import Literal |
| a = 1 |
| [file mod.py.2] |
| from typing_extensions 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.C.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] |
| tmp/a.py:3: error: Cannot determine type of "foo" |
| tmp/a.py:4: error: Cannot determine type of "foo" |
| [out2] |
| tmp/a.py:3: error: Cannot determine type of "foo" |
| tmp/a.py:4: error: Cannot determine type of "foo" |
| |
| [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" and "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 "B" and "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" and "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" and "B">" |
| [out2] |
| tmp/c.py:2: note: Revealed type is "a.<subclass of "A" and "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" and "B">" |
| [out2] |
| tmp/c.py:2: note: Revealed type is "b.<subclass of "A" and "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" and "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" and "B">" |
| |
| [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: "object" 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: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: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] |
| # flags: --python-version 3.7 |
| |
| import a |
| |
| [file a.py] |
| import b |
| |
| [file a.py.2] |
| import b |
| b.xyz |
| |
| [file b.py] |
| from typing import NamedTuple, NewType |
| from typing_extensions import TypedDict, 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] |
| [out2] |
| tmp/a.py:2: error: "object" 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[Union[Tuple[Union[..., None], builtins.int, fallback=b.M], None], builtins.int, fallback=a.N]" |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "Optional[N]", variable has type "int") |
| tmp/c.py:7: note: Revealed type is "Tuple[Union[Tuple[Union[..., 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[Union[Tuple[Union[..., None], builtins.int, fallback=b.M], None], builtins.int, fallback=a.N]" |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "Optional[N]", 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[Union[Tuple[Union[..., None], builtins.int], None], builtins.int]" |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "Optional[N]", 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': Union[TypedDict('b.M', {'r': Union[..., None], 'x': builtins.int}), None], 'x': builtins.int})" |
| tmp/c.py:5: error: Incompatible types in assignment (expression has type "Optional[N]", variable has type "int") |
| tmp/c.py:7: note: Revealed type is "TypedDict('a.N', {'r': Union[TypedDict('b.M', {'r': Union[..., 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 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_extensions import Unpack, TypedDict |
| |
| 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] |
| [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 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 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 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 testNoCrashDoubleReexportTypedDictEmpty] |
| import m |
| |
| [file m.py] |
| import f |
| [file m.py.3] |
| import f |
| # modify |
| |
| [file f.py] |
| from typing_extensions 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] |
| [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] |
| 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 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 |
| from typing_extensions import 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] |
| [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] |