blob: ebe2e9caed02646817c679b29af716ed39d88754 [file] [log] [blame] [edit]
-- Test cases for generating fine-grained dependencies for classes.
--
-- The dependencies are used for fined-grained incremental checking.
--
-- See the comment at the top of deps.test for more documentation.
-- TODO: Move class related test cases from deps.test to here
[case testNamedTuple]
from typing import NamedTuple, Any
from a import A
N = NamedTuple('N', [('a', 'A')])
def f(a: Any) -> None:
n = N(a)
n.a
[file a.py]
class A: pass
[builtins fixtures/tuple.pyi]
[out]
<m.N.__init__> -> m.f
<m.N.__new__> -> m.f
<m.N.a> -> m.f
<m.N> -> m.f
<a.A> -> <m.N.a>, <m.N>, m
<a> -> m
[case testNamedTuple2]
from typing import NamedTuple, Any, Tuple
from a import A, B
N = NamedTuple('N', [('a', 'Tuple[A, B]')])
def f(a: Any) -> None:
n = N(a)
n.a
[file a.py]
class A: pass
class B: pass
[builtins fixtures/tuple.pyi]
[out]
<m.N.__init__> -> m.f
<m.N.__new__> -> m.f
<m.N.a> -> m.f
<m.N> -> m.f
<a.A> -> <m.N.a>, <m.N>, m
<a.B> -> <m.N.a>, <m.N>, m
<a> -> m
[case testNamedTuple3]
from typing import NamedTuple
N = NamedTuple('N', [('x', int)])
x = N(1)
M = NamedTuple('M', [('z', 'N')])
y = M(x)
[builtins fixtures/tuple.pyi]
[out]
<m.M.__init__> -> m
<m.M.__new__> -> m
<m.M> -> <m.y>, m
<m.N.__init__> -> m
<m.N.__new__> -> m
<m.N> -> <m.M.z>, <m.M>, <m.x>, <m.y>, m
<m.x> -> m
<m.y> -> m
[case testNamedTuple4]
from typing import NamedTuple, Any
from a import A
class N(NamedTuple):
a: A
def f(a: Any) -> None:
n = N(a)
n.a
[file a.py]
class A: pass
[builtins fixtures/tuple.pyi]
[out]
<m.N.__init__> -> m.f
<m.N.__new__> -> m.f
<m.N.a> -> m.f
<m.N> -> m.N, m.f
<a.A> -> <m.N.a>, <m.N>, m, m.N
<a> -> m
[case testIfFalseInClassBody]
class A:
if False:
x = None # type: str
x.foo()
[builtins fixtures/bool.pyi]
[out]
<m.A> -> m.A
[case testAlwaysFalseIsinstanceInClassBody]
class A:
x: int
if isinstance(x, str):
y: str = None
y.foo()
[builtins fixtures/isinstance.pyi]
[out]
<m.A> -> m.A
[case testDoubleAttributeInitializationToNone]
class C:
def __init__(self) -> None:
self.x = None
self.x = None
[out]
<m.C.x> -> m.C.__init__
<m.C> -> m.C
[case testClassNestedWithinFunction]
class C: pass
def f() -> None:
class S1(C): pass
class D:
def g(self) -> None:
class S2(C): pass
[out]
-- TODO: Is it okay to have targets like m.S1@4.__init__?
<m.C.(abstract)> -> <m.S1@4.__init__>, <m.S2@8.__init__>, m.D.g, m.f
<m.C.__init__> -> <m.S1@4.__init__>, <m.S2@8.__init__>
<m.C.__new__> -> <m.S1@4.__new__>, <m.S2@8.__new__>
<m.C> -> m.C, m.D.g, m.f
<m.D.g> -> m.D.g
<m.D> -> m.D
<m.f> -> m.f
[case testClassSuper]
class C:
def __init__(self, x: int) -> None: pass
def foo(self) -> None: pass
class D(C):
def __init__(self, x: int) -> None:
super().__init__(x)
super().foo()
[out]
<m.C.(abstract)> -> <m.D.__init__>, m
<m.C.__init__> -> <m.D.__init__>, m.D.__init__
<m.C.__new__> -> <m.D.__new__>
<m.C.foo> -> <m.D.foo>, m.D.__init__
<m.C> -> m, m.C, m.D
<m.D> -> m.D
[case testClassMissingInit]
class C:
def __init__(self, x: int) -> None: pass
class D(C):
pass
def foo() -> None:
D(6)
[out]
<m.C.(abstract)> -> <m.D.__init__>, m
<m.C.__init__> -> <m.D.__init__>
<m.C.__new__> -> <m.D.__new__>
<m.C> -> m, m.C, m.D
<m.D.__init__> -> m.foo
<m.D.__new__> -> m.foo
<m.D> -> m.D, m.foo
[case testClassBasedEnum]
from enum import Enum
from m import B
class A(Enum):
X = B()
def f(a: A) -> None:
pass
def g() -> None:
A.X
[file m.py]
class B: pass
[out]
<m.A.X> -> m.g
<m.A> -> <m.f>, m.A, m.f, m.g
<m.B.__init__> -> m
<m.B.__new__> -> m
-- The <m.A.X> dependency target is superfluous but benign
<m.B> -> <m.A.X>, m
<m> -> m
[case testClassAttribute]
class C:
x = 0
def f() -> None:
C.x
def g() -> None:
C.x = 1
[out]
<m.C.x> -> m.f, m.g
<m.C> -> m.C, m.f, m.g
[case testStaticAndClassMethods]
class C:
@staticmethod
def foo() -> None:
h()
@classmethod
def bar(cls) -> None:
h()
def fstatic() -> None:
C.foo()
def fclass() -> None:
C.bar()
cc = C()
def gstatic() -> None:
cc.foo()
def gclass() -> None:
cc.bar()
def h() -> None: pass
[builtins fixtures/classmethod.pyi]
[out]
<m.C.__init__> -> m
<m.C.__new__> -> m
<m.C.bar> -> m, m.fclass, m.gclass
<m.C.foo> -> m, m.fstatic, m.gstatic
<m.C> -> <m.cc>, m, m.C, m.fclass, m.fstatic
<m.cc> -> m, m.gclass, m.gstatic
<m.h> -> m.C.bar, m.C.foo
[case testClassAttributeWithMetaclass]
class M(type):
x = 1
class C(metaclass=M):
pass
def f() -> None:
C.x
[out]
<m.C.x> -> m.f
<m.C> -> m.C, m.f
<m.M.x> -> m.f
<m.M> -> <m.C>, m, m.M