-- Test cases for generating dependencies between ASTs nodes.
--
-- The dependencies are used for fined-grained incremental checking and
-- the daemon mode.
--
-- The output of each test case includes the dependency map for whitelisted
-- modules (includes the main module and the modules 'pkg' and 'pkg.mod' at
-- least).
--
-- Dependencies are formatted as "<trigger> -> affected locations".
--
-- Look at the docstring of mypy.server.deps for an explanation of
-- how fine-grained dependencies are represented.

[case testCallFunction]
def f() -> None:
    g()
def g() -> None:
    pass
[out]
<m.g> -> m.f

[case testCallMethod]
def f(a: A) -> None:
    a.g()
class A:
    def g(self) -> None: pass
[out]
<m.A.g> -> m.f
<m.A> -> <m.f>, m.A, m.f

[case testAccessAttribute]
def f(a: A) -> None:
    a.x
class A:
    def g(self) -> None:
        self.x = 1
[out]
<m.A.x> -> m.A.g, m.f
<m.A> -> <m.f>, m.A, m.f

[case testConstructInstance]
def f() -> None:
    A()
class A: pass
[out]
<m.A.__init__> -> m.f
<m.A.__new__> -> m.f
<m.A> -> m.A, m.f

[case testAccessModuleAttribute]
class A: pass
x = A()
def f() -> None:
    x
[out]
<m.A.__init__> -> m
<m.A.__new__> -> m
<m.A> -> <m.x>, m, m.A
<m.x> -> m, m.f

[case testAccessModuleAttribute2]
import n
def f() -> None:
    n.x
[file n.py]
x = 1
[out]
<n.x> -> m.f
<n> -> m, m.f

[case testImport]
import n
[file n.py]
x = 1
[out]
<n> -> m

[case testCallImportedFunction]
import n
n.f()
[file n.py]
def f() -> None: pass
[out]
<n.f> -> m
<n> -> m

[case testImportModuleAs]
import n as x
x.f()
[file n.py]
def f() -> None: pass
[out]
<n.f> -> m
<n> -> m

[case testCallImportedFunctionInFunction]
import n
def g() -> None:
    n.f()
[file n.py]
def f() -> None: pass
[out]
<n.f> -> m.g
<n> -> m, m.g

[case testInheritanceSimple]
class A:
    pass
class B(A):
    pass
[out]
<m.A.(abstract)> -> <m.B.__init__>, m
<m.A.__init__> -> <m.B.__init__>
<m.A.__new__> -> <m.B.__new__>
<m.A> -> m, m.A, m.B
<m.B> -> m.B

[case testInheritanceWithMethodAndAttribute]
class A:
    pass
class B(A):
    def f(self) -> None:
        self.x = 1
[out]
<m.A.(abstract)> -> <m.B.__init__>, m
<m.A.__init__> -> <m.B.__init__>
<m.A.__new__> -> <m.B.__new__>
<m.A.f> -> m.B.f
<m.A.x> -> <m.B.x>
<m.A> -> m, m.A, m.B
<m.B.x> -> m.B.f
<m.B> -> m.B

[case testInheritanceWithMethodAndAttributeAndDeepHierarchy]
class A:
    pass
class B(A):
    pass
class C(B):
    def f(self) -> None:
        self.x = 1
[out]
<m.A.(abstract)> -> <m.B.__init__>, <m.C.__init__>, m
<m.A.__init__> -> <m.B.__init__>, <m.C.__init__>
<m.A.__new__> -> <m.B.__new__>, <m.C.__new__>
<m.A.f> -> m.C.f
<m.A.x> -> <m.C.x>
<m.A> -> m, m.A, m.B
<m.B.(abstract)> -> <m.C.__init__>, m
<m.B.__init__> -> <m.C.__init__>
<m.B.__new__> -> <m.C.__new__>
<m.B.f> -> m.C.f
<m.B.x> -> <m.C.x>
<m.B> -> m, m.B, m.C
<m.C.x> -> m.C.f
<m.C> -> m.C

[case testInheritAttribute]
import n
class B(n.A):
    def f(self) -> None:
        a = 1
        a = self.x
[file n.py]
class A:
    def g(self) -> None:
        self.x = 1
[out]
<m.B.x> -> m.B.f
<m.B> -> m.B
<n.A.(abstract)> -> <m.B.__init__>, m
<n.A.__init__> -> <m.B.__init__>
<n.A.__new__> -> <m.B.__new__>
<n.A.f> -> m.B.f
<n.A.g> -> <m.B.g>
<n.A.x> -> <m.B.x>
<n.A> -> m, m.B
<n> -> m

[case testInheritMethod]
class A:
    def g(self) -> None: pass
class B(A):
    def f(self) -> None:
        self.g()
[out]
<m.A.(abstract)> -> <m.B.__init__>, m
<m.A.__init__> -> <m.B.__init__>
<m.A.__new__> -> <m.B.__new__>
<m.A.f> -> m.B.f
<m.A.g> -> <m.B.g>
<m.A> -> m, m.A, m.B
<m.B.g> -> m.B.f
<m.B> -> m.B

[case testPackage]
import a.b
def f() -> None:
    a.b.g()
[file a/__init__.py]
[file a/b.py]
def g() -> None: pass
[out]
<a.b.g> -> m.f
<a.b> -> m, m.f
<a> -> m.f

[case testClassInPackage]
import a.b
def f(x: a.b.A) -> None:
    x.g()
    x.y
[file a/__init__.py]
[file a/b.py]
class A:
    def g(self) -> None:
        self.y = 1
[out]
<a.b.A.g> -> m.f
<a.b.A.y> -> m.f
<a.b.A> -> <m.f>, m.f
<a.b> -> m

[case testPackage__init__]
import a
def f() -> None:
    a.g()
[file a/__init__.py]
def g() -> None: pass
[out]
<a.g> -> m.f
<a> -> m, m.f

[case testClassInPackage__init__]
import a
def f(x: a.A) -> None:
    x.g()
    x.y
[file a/__init__.py]
class A:
    def g(self) -> None:
        self.y = 1
[out]
<a.A.g> -> m.f
<a.A.y> -> m.f
<a.A> -> <m.f>, m.f
<a> -> m

[case testConstructor]
class A:
    def __init__(self, x: C) -> None: pass
class C: pass
def f() -> None:
    A(C())
[out]
<m.A.__init__> -> m.f
<m.A.__new__> -> m.f
<m.A> -> m.A, m.f
<m.C.__init__> -> m.f
<m.C.__new__> -> m.f
<m.C> -> <m.A.__init__>, m.A.__init__, m.C, m.f

[case testNonTrivialConstructor]
class C:
    def __init__(self) -> None:
        self.x = 1
[out]
<m.C.x> -> m.C.__init__
<m.C> -> m.C

[case testImportFrom]
from n import f

def g() -> None:
    f()
[file n.py]
def f() -> None: pass
[out]
<n.f> -> m, m.g

[case testImportFromAs]
from n import f as ff

def g() -> None:
    ff()
[file n.py]
def f() -> None: pass
[out]
<n.f> -> m, m.g

[case testNestedClass]
def f() -> None:
    b = A.B()
    b.f()
class A:
    class B:
        def f(self) -> None: pass
[out]
<m.A.B.__init__> -> m.f
<m.A.B.__new__> -> m.f
<m.A.B.f> -> m.f
<m.A.B> -> m.A.B, m.f
<m.A> -> m.A, m.f

[case testNestedClassAttribute]
def f() -> None:
    b = A.B()
    b.x
class A:
    class B:
        def f(self) -> None:
            self.x = 1
[out]
<m.A.B.__init__> -> m.f
<m.A.B.__new__> -> m.f
<m.A.B.x> -> m.A.B.f, m.f
<m.A.B> -> m.A.B, m.f
<m.A> -> m.A, m.f

[case testNestedClassInAnnotation]
def f(x: A.B) -> None:
    pass
class A:
    class B: pass
[out]
<m.A.B> -> <m.f>, m.A.B, m.f
<m.A> -> m.A

[case testNestedClassInAnnotation2]
def f(x: A.B) -> None:
    x.f()
class A:
    class B:
        def f(self) -> None: pass
[out]
<m.A.B.f> -> m.f
<m.A.B> -> <m.f>, m.A.B, m.f
<m.A> -> m.A

[case NestedFunctionType]
from mod import A, B, C, D
def outer() -> None:
    def inner(x: A, *args: B, **kwds: C) -> D:
        pass
[file mod.py]
class A: pass
class B: pass
class C: pass
class D: pass
[builtins fixtures/dict.pyi]
[out]
<mod.A> -> <m.outer>, m, m.outer
<mod.B> -> <m.outer>, m, m.outer
<mod.C> -> <m.outer>, m, m.outer
<mod.D> -> <m.outer>, m, m.outer

[case NestedFunctionBody]
from mod import A, B, C
def outer() -> None:
    def inner() -> None:
        A()
        x: B
        y: C
        y.x
[file mod.py]
class A: pass
class B: pass
class C:
    x: int
[builtins fixtures/dict.pyi]
[out]
<mod.A.__init__> -> m.outer
<mod.A.__new__> -> m.outer
<mod.A> -> m, m.outer
<mod.B> -> m, m.outer
<mod.C.x> -> m.outer
<mod.C> -> m, m.outer

[case testDefaultArgValue]
def f1(x: int) -> int: pass
def f2() -> int: pass
def g(x: int = f1(f2())) -> None: pass
[out]
<m.f1> -> m.g
<m.f2> -> m.g

[case testIsInstance]
class A:
    def g(self) -> None: pass

def f(x: object) -> None:
    if isinstance(x, A):
        x.g()
[builtins fixtures/isinstancelist.pyi]
[out]
-- The dependencies on the ctor are basically spurious but not a problem
<m.A.__init__> -> m.f
<m.A.__new__> -> m.f
<m.A.g> -> m.f
<m.A> -> m.A, m.f

[case testUnreachableIsInstance]
class A:
    x: int

class B:
    y: int

def f(x: A) -> None:
    if isinstance(x, B):
        x.y
[builtins fixtures/isinstancelist.pyi]
[out]
<m.A> -> <m.f>, m.A, m.f
-- The dependencies on the ctor are basically spurious but not a problem
<m.B.__init__> -> m.f
<m.B.__new__> -> m.f
<m.B> -> m.B, m.f

[case testAttributeWithClassType1]
from n import A

class B:
    def h(self, z: A) -> None:
        self.z = z
[file n.py]
class A: pass
[out]
<m.B.z> -> m.B.h
<m.B> -> m.B
<n.A> -> <m.B.h>, <m.B.z>, m, m.B.h

[case testAttributeWithClassType2]
from m import A

class B:
    def f(self) -> None:
        self.x = A()
[file m.py]
class A: pass
[out]
<m.B.x> -> m.B.f
<m.B> -> m.B
<m.A.__init__> -> m.B.f
<m.A.__new__> -> m.B.f
<m.A> -> <m.B.x>, m, m.B.f

[case testAttributeWithClassType3]
from n import A, x

class B:
    def g(self) -> None:
        self.x = x
[file n.py]
class A: pass

x = A()
[out]
<m.B.x> -> m.B.g
<m.B> -> m.B
<n.A> -> <m.B.x>, m
<n.x> -> m, m.B.g

[case testAttributeWithClassType4]
from n import A

class B:
    def g(self) -> None:
        self.x: A
[file n.py]
class A: pass
[out]
<m.B.x> -> m.B.g
<m.B> -> m.B
<n.A> -> <m.B.x>, m, m.B.g

[case testClassBody]
def f() -> int: pass
def g() -> int: pass
def h() -> int: pass

class A:
    h()
    if f():
        g()
[out]
<m.A> -> m.A
<m.f> -> m
<m.g> -> m
<m.h> -> m

[case testVariableInitializedInClass]
from n import A

class B:
    x = None  # type: A
[file n.py]
class A: pass
[out]
<m.B> -> m.B
<n.A> -> <m.B.x>, m

[case testVariableAnnotationInClass]
from n import A

class B:
    x: A

    def f(self) -> None:
        y = self.x
[file n.py]
class A: pass
[out]
<m.B.x> -> m.B.f
<m.B> -> m.B
<n.A> -> <m.B.x>, m

[case testGlobalVariableInitialized]
from n import A

x = A()
[file n.py]
class A: pass
[out]
<m.x> -> m
<n.A.__init__> -> m
<n.A.__new__> -> m
<n.A> -> <m.x>, m

[case testGlobalVariableAnnotation]
from n import A

x: A
[file n.py]
class A: pass
[out]
<m.x> -> m
<n.A> -> <m.x>, m

[case testProperty]
class B: pass

class A:
    @property
    def x(self) -> B: pass

def f(a: A) -> None:
    b = a.x
[builtins fixtures/property.pyi]
[out]
<m.A.x> -> m, m.f
<m.A> -> <m.f>, m.A, m.f
<m.B> -> <m.A.x>, m.A.x, m.B

[case testUnreachableAssignment]
from typing import List, Tuple

def f() -> None: pass

class C:
    def __init__(self, x: int) -> None:
        if isinstance(x, int):
            self.y = 1
        else:
            self.y = f()
[builtins fixtures/isinstancelist.pyi]
[out]
<m.C.y> -> m.C.__init__
<m.C> -> m.C
<m.f> -> m.C.__init__

[case testPartialNoneTypeAttributeCrash1]
class C: pass

class A:
    x = None

    def f(self) -> None:
        self.x = C()
[out]
<m.A.x> -> m.A.f
<m.A> -> m.A
<m.C.__init__> -> m.A.f
<m.C.__new__> -> m.A.f
<m.C> -> <m.A.x>, m.A.f, m.C

[case testPartialNoneTypeAttributeCrash2]
# flags: --strict-optional
class C: pass

class A:
    x = None

    def f(self) -> None:
        self.x = C()
[out]
<m.A.x> -> m.A.f
<m.A> -> m.A
<m.C.__init__> -> m.A.f
<m.C.__new__> -> m.A.f
<m.C> -> <m.A.x>, m.A.f, m.C

[case testRelativeImport]
import pkg  # Magic package name in test runner
[file pkg/__init__.py]
from . import mod
from .a import x
[file pkg/mod.py]
from . import a
[file pkg/a.py]
x = 1
[out]
<pkg.a.x> -> pkg
<pkg.a> -> pkg.mod
<pkg.mod> -> pkg
<pkg> -> m

[case testTypedDict]
from mypy_extensions import TypedDict
Point = TypedDict('Point', {'x': int, 'y': int})
p = Point(dict(x=42, y=1337))
def foo(x: Point) -> int:
    return x['x'] + x['y']
[builtins fixtures/dict.pyi]
[out]
<m.Point> -> <m.foo>, <m.p>, m, m.foo
<m.p> -> m
<mypy_extensions.TypedDict> -> m

[case testTypedDict2]
from mypy_extensions import TypedDict
class A: pass
Point = TypedDict('Point', {'x': int, 'y': A})
p = Point(dict(x=42, y=A()))
def foo(x: Point) -> int:
    return x['x']
[builtins fixtures/dict.pyi]
[out]
<m.A.__init__> -> m
<m.A.__new__> -> m
<m.A> -> <m.Point>, <m.foo>, <m.p>, m, m.A, m.foo
<m.Point> -> <m.foo>, <m.p>, m, m.foo
<m.p> -> m
<mypy_extensions.TypedDict> -> m

[case testTypedDict3]
from mypy_extensions import TypedDict
class A: pass
class Point(TypedDict):
    x: int
    y: A
p = Point(dict(x=42, y=A()))
def foo(x: Point) -> int:
    return x['x']
[builtins fixtures/dict.pyi]
[out]
<m.A.__init__> -> m
<m.A.__new__> -> m
<m.A> -> <m.Point>, <m.foo>, <m.p>, m, m.A, m.foo
<m.Point> -> <m.foo>, <m.p>, m, m.Point, m.foo
<m.p> -> m
<mypy_extensions.TypedDict> -> m

[case testImportStar]
from a import *
[file a.py]
x = 0
[out]
<a[wildcard]> -> m

[case testDecoratorDepsMod]
import mod

@mod.deca
@mod.decb(mod.C())
def func(x: int) -> int:
    pass
[file mod.py]
from typing import Callable, TypeVar
F = TypeVar('F', bound=Callable)

def deca(func: Callable[[int], int]) -> Callable[[str], str]:
    pass
def decb(arg: C) -> Callable[[F], F]:
    pass
class C:
    pass
[out]
<m.func> -> m
<mod.C.__init__> -> m
<mod.C.__new__> -> m
<mod.C> -> m
<mod.deca> -> m
<mod.decb> -> m
<mod> -> m

[case testDecoratorDepsFunc]
import mod

def outer() -> None:
    @mod.deca
    @mod.decb(mod.C())
    def func(x: int) -> int:
        pass
[file mod.py]
from typing import Callable, TypeVar
F = TypeVar('F', bound=Callable)

def deca(func: Callable[[int], int]) -> Callable[[str], str]:
    pass
def decb(arg: C) -> Callable[[F], F]:
    pass
class C:
    pass
[out]
<mod.C.__init__> -> m.outer
<mod.C.__new__> -> m.outer
<mod.C> -> m.outer
<mod.deca> -> m.outer
<mod.decb> -> m.outer
<mod> -> m, m.outer

[case testDecoratorDepsDeeepNested]
import mod

def outer() -> None:
    def inner() -> None:
        @mod.dec
        def func(x: int) -> int:
            pass
[file mod.py]
from typing import Callable
def dec(func: Callable[[int], int]) -> Callable[[str], str]:
    pass
[out]
<mod.dec> -> m.outer
<mod> -> m, m.outer

[case testDecoratorDepsNestedClass]
import mod

class Outer:
    class Inner:
        c = mod.C()
        @c.dec
        def func(self, x: int) -> int:
            pass
[file mod.py]
from typing import Callable
class C:
    def dec(self, func: Callable[..., int]) -> Callable[..., str]:
        pass
[out]
<m.Outer.Inner.func> -> m
<m.Outer.Inner> -> m.Outer.Inner
<m.Outer> -> m.Outer
<mod.C.__init__> -> m
<mod.C.__new__> -> m
<mod.C.dec> -> m
<mod.C> -> <m.Outer.Inner.c>, m
<mod> -> m

[case testDecoratorDepsClassInFunction]
import mod

def outer() -> None:
    class Inner:
        c = mod.C()
        @c.dec
        def func(self, x: int) -> int:
            pass
[file mod.py]
from typing import Callable
class C:
    def dec(self, func: Callable[..., int]) -> Callable[..., str]:
        pass
[out]
<m.outer> -> m.outer
<mod.C.__init__> -> m.outer
<mod.C.__new__> -> m.outer
<mod.C.dec> -> m.outer
<mod.C> -> <m.outer.c>, m.outer
<mod> -> m, m.outer

[case DecoratorDepsMethod]
import mod

class D:
    @mod.deca
    @mod.decb(mod.C())
    def func(self, x: int) -> int:
        pass
[file mod.py]
from typing import Callable, TypeVar
F = TypeVar('F', bound=Callable)

def deca(func: Callable[..., int]) -> Callable[..., str]:
    pass
def decb(arg: C) -> Callable[[F], F]:
    pass
class C:
    pass
[out]
<m.D.func> -> m
<m.D> -> m.D
<mod.C.__init__> -> m
<mod.C.__new__> -> m
<mod.C> -> m
<mod.deca> -> m
<mod.decb> -> m
<mod> -> m

[case testMissingModuleClass1]
from b import A  # type: ignore
def f(x: A) -> None:
    x.foo()
[out]
<m.A> -> <m.f>, m.f
<b.A> -> m

[case testMissingModuleClass2]
from p.b import A  # type: ignore
def f(x: A) -> None:
    x.foo()
[out]
<m.A> -> <m.f>, m.f
<p.b.A> -> m

[case testDepsFromOverloadMod]
# __dump_all__
import mod
x = mod.f
[file mod.py]
from typing import overload, Any
import submod
@overload
def f(x: int) -> submod.A: pass
@overload
def f(x: str) -> submod.B: pass
def f(x) -> Any:
    y: submod.C
    y.x
[file submod.py]
class A: pass
class B: pass
class C:
    x: D
class D: pass
[out]
<m.x> -> m
<mod.f> -> m
<mod> -> m
<submod.A> -> <m.x>, <mod.f>, mod.f, submod.A
<submod.B> -> <m.x>, <mod.f>, mod.f, submod.B
<submod.C.x> -> mod.f
<submod.C> -> mod.f, submod.C
<submod.D> -> <submod.C.x>, submod, submod.D
<submod> -> mod

[case testDepsFromOverloadFunc]
import mod
def f() -> None:
    x = mod.f
[file mod.py]
from typing import overload
@overload
def f(x: int) -> None: pass
@overload
def f(x: str) -> str: pass
def f(x):
    pass
[out]
<mod.f> -> m.f
<mod> -> m, m.f

[case testDepsToOverloadMod]
from typing import overload, Any
import mod
@overload
def f(x: int) -> None: pass
@overload
def f(x: str) -> str: pass
def f(x: Any) -> Any:
    mod.g()
[file mod.py]
def g() -> int:
    pass
[out]
<mod.g> -> m.f
<mod> -> m, m.f

[case testDepsToOverloadFunc]
from typing import overload, Any
import mod
def outer() -> None:
    @overload
    def f(x: int) -> mod.A: pass
    @overload
    def f(x: str) -> mod.B: pass
    def f(x: Any) -> Any:
        mod.g()
[file mod.py]
def g() -> int:
    pass
class A: pass
class B: pass
[out]
<mod.A> -> <m.outer>, m.outer
<mod.B> -> <m.outer>, m.outer
<mod.g> -> m.outer
<mod> -> m, m.outer

[case testDepsFromOverloadToOverload]
from typing import overload, Any
import mod
def outer() -> None:
    @overload
    def f(x: int) -> None: pass
    @overload
    def f(x: str) -> str: pass
    def f(x: Any) -> Any:
        mod.g(str())
[file mod.py]
from typing import overload
@overload
def g(x: int) -> None: pass
@overload
def g(x: str) -> str: pass
def g(x):
    pass
[out]
<mod.g> -> m.outer
<mod> -> m, m.outer

[case testDepsFromOverloadToOverloadDefaultClass]
from typing import overload, Any
import mod
class Outer:
    @overload
    def f(self, x: int) -> None: pass
    @overload
    def f(self, x: str, cb=mod.g) -> str: pass
    def f(self, *args: Any, **kwargs: Any) -> Any:
        pass
[file mod.py]
from typing import overload
@overload
def g(x: int) -> None: pass
@overload
def g(x: str) -> str: pass
def g(x):
    pass
[builtins fixtures/dict.pyi]
[out]
<m.Outer> -> m.Outer
<mod.g> -> m.Outer.f
<mod> -> m, m.Outer.f

[case testDepsFromOverloadToOverloadDefaultNested]
from typing import overload, Any
import mod
def outer() -> None:
    @overload
    def f(x: int) -> None: pass
    @overload
    def f(x: str, cb=mod.g) -> str: pass
    def f(*args: Any, **kwargs: Any) -> Any:
        pass
[file mod.py]
from typing import overload
@overload
def g(x: int) -> None: pass
@overload
def g(x: str) -> str: pass
def g(x):
    pass
[builtins fixtures/dict.pyi]
[out]
<mod.g> -> m.outer
<mod> -> m, m.outer

[case testDepsToOverloadGeneric]
# __dump_all__
import mod
from typing import overload, Any
@overload
def f(x: mod.TA) -> mod.TA: pass
@overload
def f(x: mod.TB, y: int) -> mod.TB: pass
def f(*args: Any, **kwargs: Any) -> Any:
    pass
[file mod.py]
from typing import TypeVar
import submod
TA = TypeVar('TA', submod.A, submod.B)
TB = TypeVar('TB', bound=submod.C)
[file submod.py]
class A: pass
class B: pass
class C: pass
[builtins fixtures/dict.pyi]
[out]
<mod.TA> -> <m.f>, m.f
<mod.TB> -> <m.f>, m.f
<mod> -> m
<submod.A> -> <m.f>, <mod.TA>, m.f, mod, submod.A
<submod.B> -> <m.f>, <mod.TA>, m.f, mod, submod.B
<submod.C> -> <m.f>, <mod.TB>, m.f, mod, submod.C
<submod> -> mod

[case testDepsOverloadBothExternalAndImplementationType]
import mod
from typing import overload
@overload
def f(x: mod.A) -> mod.A: pass
@overload
def f(x: mod.B) -> mod.B: pass
def f(x: mod.Base) -> mod.Base:
    pass
[file mod.py]
class Base:
    pass
class A(Base):
    pass
class B(Base):
    pass
[out]
<mod.A> -> <m.f>, m.f
<mod.B> -> <m.f>, m.f
<mod.Base> -> <m.f>, m.f
<mod> -> m

[case testCustomIterator]
class A:
    def __iter__(self) -> B: pass
class B:
    def __iter__(self) -> B: pass
    def __next__(self) -> C: pass
class C:
    pass
def f() -> None:
    for x in A(): pass
[out]
<m.A.__getitem__> -> m.f
<m.A.__init__> -> m.f
<m.A.__iter__> -> m.f
<m.A.__new__> -> m.f
<m.A> -> m.A, m.f
<m.B.__next__> -> m.f
<m.B> -> <m.A.__iter__>, <m.B.__iter__>, m.A.__iter__, m.B, m.B.__iter__
<m.C> -> <m.B.__next__>, m.B.__next__, m.C

[case testCustomIterator_python2]
class A:
    def __iter__(self): # type: () -> B
        pass
class B:
    def __iter__(self): # type: () -> B
        pass
    def next(self): # type: () -> C
        pass
class C:
    pass
def f(): # type: () -> None
    for x in A(): pass
[out]
<m.A.__getitem__> -> m.f
<m.A.__init__> -> m.f
<m.A.__iter__> -> m.f
<m.A.__new__> -> m.f
<m.A> -> m.A, m.f
<m.B.next> -> m.f
<m.B> -> <m.A.__iter__>, <m.B.__iter__>, m.A.__iter__, m.B, m.B.__iter__
<m.C> -> <m.B.next>, m.B.next, m.C

[case testDepsLiskovClass]
from mod import A, C
class D(C):
    x: A
[file mod.py]
class C:
    x: B
class B:
    pass
class A(B):
    pass
[out]
<m.D.x> -> m
<m.D> -> m.D
<mod.A> -> <m.D.x>, m
<mod.C.(abstract)> -> <m.D.__init__>, m
<mod.C.__init__> -> <m.D.__init__>
<mod.C.__new__> -> <m.D.__new__>
<mod.C.x> -> <m.D.x>
<mod.C> -> m, m.D

[case testDepsLiskovMethod]
from mod import A, C
class D(C):
    def __init__(self) -> None:
        self.x: A
[file mod.py]
class C:
    def __init__(self) -> None:
        self.x: B
class B:
    pass
class A(B):
    pass
[out]
<m.D.x> -> m.D.__init__
<m.D> -> m.D
<mod.A> -> <m.D.x>, m, m.D.__init__
<mod.C.(abstract)> -> <m.D.__init__>, m
<mod.C.__init__> -> <m.D.__init__>, m.D.__init__
<mod.C.__new__> -> <m.D.__new__>
<mod.C.x> -> <m.D.x>
<mod.C> -> m, m.D

[case testIndexedStarLvalue]
from typing import List, Tuple

class B:
    def __setitem__(self, i: int, v: List[str]) -> None: pass

def g() -> Tuple[int, str, str]: pass

def f(b: B) -> None:
    a, *b[0] = g()
[builtins fixtures/list.pyi]
[out]
<m.B.__getitem__> -> m.f
<m.B.__setitem__> -> m.f
<m.B> -> <m.f>, m.B, m.f
<m.g> -> m.f

[case testLogicalDecorator]
# flags: --logical-deps
from mod import dec
@dec
def f() -> None:
    pass
[file mod.py]
from typing import Callable
def dec(f: Callable[[], None]) -> Callable[[], None]:
    pass
[out]
<m.f> -> m
<mod.dec> -> <m.f>, m

[case testLogicalDecoratorWithArgs]
# flags: --logical-deps
from mod import dec
@dec(str())
def f() -> None:
    pass
[file mod.py]
from typing import Callable
def dec(arg: str) -> Callable[[Callable[[], None]], Callable[[], None]]:
    pass
[out]
<m.f> -> m
<mod.dec> -> <m.f>, m

[case testLogicalDecoratorMember]
# flags: --logical-deps
import mod
@mod.dec
def f() -> None:
    pass
[file mod.py]
from typing import Callable
def dec(f: Callable[[], None]) -> Callable[[], None]:
    pass
[out]
<m.f> -> m
<mod.dec> -> <m.f>, m
<mod> -> m

[case testLogicalDefinition]
# flags: --logical-deps
from mod import func
b = func()
[file mod.py]
def func() -> int:
    pass
[out]
<m.b> -> m
<mod.func> -> <m.b>, m

[case testLogicalDefinitionIrrelevant]
# flags: --logical-deps
from mod import func
def outer() -> None:
    a = func()
b: int = func()
c = int()
c = func()
[file mod.py]
def func() -> int:
    pass
[out]
<m.b> -> m
<m.c> -> m
<mod.func> -> m, m.outer

[case testLogicalDefinitionMember]
# flags: --logical-deps
import mod
b = mod.func()
[file mod.py]
def func() -> int:
    pass
[out]
<m.b> -> m
<mod.func> -> <m.b>, m
<mod> -> m

[case testLogicalDefinitionClass]
# flags: --logical-deps
from mod import Cls
b = Cls()
[file mod.py]
class Base:
    def __init__(self) -> None: pass
class Cls(Base): pass
[out]
<m.b> -> m
<mod.Base.__init__> -> <m.b>
<mod.Cls.__init__> -> m
<mod.Cls.__new__> -> m
<mod.Cls> -> <m.b>, m

[case testLogicalBaseAttribute]
# flags: --logical-deps
from mod import C
class D(C):
    x: int
[file mod.py]
class C:
    x: int
    y: int
[out]
<m.D.x> -> m
<m.D> -> m.D
<mod.C.(abstract)> -> <m.D.__init__>, m
<mod.C.__init__> -> <m.D.__init__>
<mod.C.__new__> -> <m.D.__new__>
<mod.C.x> -> <m.D.x>
<mod.C> -> m, m.D

[case testLogicalIgnoredImport1]
# flags: --logical-deps --ignore-missing-imports
import foo
def f() -> None:
    foo.x
[out]
<foo.x> -> m.f
<foo> -> m, m.f

[case testLogicalIgnoredImport2]
# flags: --logical-deps --ignore-missing-imports
import foo.bar
import a.b.c.d
def f() -> None:
    foo.bar.x
    foo.bar.x.y
    a.b.c.d.e
[out]
<a.b.c.d.e> -> m.f
<a.b.c.d> -> m, m.f
<a.b.c> -> m.f
<a.b> -> m.f
<a> -> m.f
<foo.bar.x.y> -> m.f
<foo.bar.x> -> m.f
<foo.bar> -> m, m.f
<foo> -> m.f

[case testLogicalIgnoredFromImport]
# flags: --logical-deps --ignore-missing-imports
from foo.bar import f, C
def g() -> None:
    f()
    C.ff()
def gg(x: C) -> None:
    z = x.y
    z.zz
[out]
<foo.bar.C.ff> -> m.g
<foo.bar.C.y> -> m.gg
<foo.bar.C> -> <m.gg>, m, m.g, m.gg
<foo.bar.f> -> m, m.g
