gtn/.venv/Lib/site-packages/mypyc/test-data/alwaysdefined.test

733 lines
15 KiB
Plaintext
Raw Normal View History

-- Test cases for always defined attributes.
--
-- If class C has attributes x and y that are always defined, the output will
-- have a line like this:
--
-- C: [x, y]
[case testAlwaysDefinedSimple]
class C:
def __init__(self, x: int) -> None:
self.x = x
[out]
C: [x]
[case testAlwaysDefinedFail]
class MethodCall:
def __init__(self, x: int) -> None:
self.f()
self.x = x
def f(self) -> None:
pass
class FuncCall:
def __init__(self, x: int) -> None:
f(x)
self.x = x
f(self)
self.y = x
class GetAttr:
x: int
def __init__(self, x: int) -> None:
a = self.x
self.x = x
class _Base:
def __init__(self) -> None:
f(self)
class CallSuper(_Base):
def __init__(self, x: int) -> None:
super().__init__()
self.x = x
class Lambda:
def __init__(self, x: int) -> None:
f = lambda x: x + 1
self.x = x
g = lambda x: self
self.y = x
class If:
def __init__(self, x: int) -> None:
self.a = 1
if x:
self.x = x
else:
self.y = 1
class Deletable:
__deletable__ = ('x', 'y')
def __init__(self) -> None:
self.x = 0
self.y = 1
self.z = 2
class PrimitiveWithSelf:
def __init__(self, s: str) -> None:
self.x = getattr(self, s)
def f(a) -> None: pass
[out]
MethodCall: []
FuncCall: [x]
GetAttr: []
CallSuper: []
Lambda: []
If: [a]
Deletable: [z]
PrimitiveWithSelf: []
[case testAlwaysDefinedConditional]
class IfAlways:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
self.y = y
elif y:
self.x = y
self.y = x
else:
self.x = 0
self.y = 0
self.z = 0
class IfSometimes1:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
self.y = y
elif y:
self.z = y
self.y = x
else:
self.y = 0
self.a = 0
class IfSometimes2:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
self.y = y
class IfStopAnalysis1:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
f(self)
else:
self.x = x
self.y = y
class IfStopAnalysis2:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
else:
self.x = x
f(self)
self.y = y
class IfStopAnalysis3:
def __init__(self, x: int, y: int) -> None:
if x:
self.x = x
else:
f(self)
self.x = x
self.y = y
class IfConditionalAndNonConditional1:
def __init__(self, x: int) -> None:
self.x = 0
if x:
self.x = x
class IfConditionalAndNonConditional2:
def __init__(self, x: int) -> None:
# x is not considered always defined, since the second assignment may
# either initialize or update.
if x:
self.x = x
self.x = 0
def f(a) -> None: pass
[out]
IfAlways: [x, y, z]
IfSometimes1: [y]
IfSometimes2: [y]
IfStopAnalysis1: [x]
IfStopAnalysis2: [x]
IfStopAnalysis3: []
IfConditionalAndNonConditional1: [x]
IfConditionalAndNonConditional2: []
[case testAlwaysDefinedExpressions]
from typing import Dict, List, Set, Optional, cast
from typing_extensions import Final
import other
class C: pass
class Collections:
def __init__(self, x: int) -> None:
self.l = [x]
self.d: Dict[str, str] = {}
self.s: Set[int] = set()
self.d2 = {'x': x}
self.s2 = {x}
self.l2 = [f(), None] * x
self.t = tuple(self.l2)
class Comparisons:
def __init__(self, y: int, c: C, s: str, o: Optional[str]) -> None:
self.n1 = y < 5
self.n2 = y == 5
self.c1 = y is c
self.c2 = y is not c
self.o1 = o is None
self.o2 = o is not None
self.s = s < 'x'
class BinaryOps:
def __init__(self, x: int, s: str) -> None:
self.a = x + 2
self.b = x & 2
self.c = x * 2
self.d = -x
self.e = 'x' + s
self.f = x << x
g = 2
class LocalsAndGlobals:
def __init__(self, x: int) -> None:
t = x + 1
self.a = t - t
self.g = g
class Booleans:
def __init__(self, x: int, b: bool) -> None:
self.a = True
self.b = False
self.c = not b
self.d = b or b
self.e = b and b
F: Final = 3
class ModuleFinal:
def __init__(self) -> None:
self.a = F
self.b = other.Y
class ClassFinal:
F: Final = 3
def __init__(self) -> None:
self.a = ClassFinal.F
class Literals:
def __init__(self) -> None:
self.a = 'x'
self.b = b'x'
self.c = 2.2
class ListComprehension:
def __init__(self, x: List[int]) -> None:
self.a = [i + 1 for i in x]
class Helper:
def __init__(self, arg) -> None:
self.x = 0
def foo(self, arg) -> int:
return 1
class AttrAccess:
def __init__(self, o: Helper) -> None:
self.x = o.x
o.x = o.x + 1
self.y = o.foo(self.x)
o.foo(self)
self.z = 1
class Construct:
def __init__(self) -> None:
self.x = Helper(1)
self.y = Helper(self)
class IsInstance:
def __init__(self, x: object) -> None:
if isinstance(x, str):
self.x = 0
elif isinstance(x, Helper):
self.x = 1
elif isinstance(x, (list, tuple)):
self.x = 2
else:
self.x = 3
class Cast:
def __init__(self, x: object) -> None:
self.x = cast(int, x)
self.s = cast(str, x)
self.c = cast(Cast, x)
class PropertyAccessGetter:
def __init__(self, other: PropertyAccessGetter) -> None:
self.x = other.p
self.y = 1
self.z = self.p
@property
def p(self) -> int:
return 0
class PropertyAccessSetter:
def __init__(self, other: PropertyAccessSetter) -> None:
other.p = 1
self.y = 1
self.z = self.p
@property
def p(self) -> int:
return 0
@p.setter
def p(self, x: int) -> None:
pass
def f() -> int:
return 0
[file other.py]
# Not compiled
from typing_extensions import Final
Y: Final = 3
[out]
C: []
Collections: [d, d2, l, l2, s, s2, t]
Comparisons: [c1, c2, n1, n2, o1, o2, s]
BinaryOps: [a, b, c, d, e, f]
LocalsAndGlobals: [a, g]
Booleans: [a, b, c, d, e]
ModuleFinal: [a, b]
ClassFinal: [F, a]
Literals: [a, b, c]
ListComprehension: [a]
Helper: [x]
AttrAccess: [x, y]
Construct: [x]
IsInstance: [x]
Cast: [c, s, x]
PropertyAccessGetter: [x, y]
PropertyAccessSetter: [y]
[case testAlwaysDefinedExpressions2]
from typing import List, Tuple
class C:
def __init__(self) -> None:
self.x = 0
class AttributeRef:
def __init__(self, c: C) -> None:
self.aa = c.x
self.bb = self.aa
if c is not None:
self.z = 0
self.cc = 0
self.dd = self.z
class ListOps:
def __init__(self, x: List[int], n: int) -> None:
self.a = len(x)
self.b = x[n]
self.c = [y + 1 for y in x]
class TupleOps:
def __init__(self, t: Tuple[int, str]) -> None:
x, y = t
self.x = x
self.y = t[0]
s = x, y
self.z = s
class IfExpr:
def __init__(self, x: int) -> None:
self.a = 1 if x < 5 else 2
class Base:
def __init__(self, x: int) -> None:
self.x = x
class Derived1(Base):
def __init__(self, y: int) -> None:
self.aa = y
super().__init__(y)
self.bb = y
class Derived2(Base):
pass
class Conditionals:
def __init__(self, b: bool, n: int) -> None:
if not (n == 5 or n >= n + 1):
self.a = b
else:
self.a = not b
if b:
self.b = 2
else:
self.b = 4
[out]
C: [x]
AttributeRef: [aa, bb, cc, dd]
ListOps: [a, b, c]
TupleOps: [x, y, z]
IfExpr: [a]
Base: [x]
Derived1: [aa, bb, x]
Derived2: [x]
Conditionals: [a, b]
[case testAlwaysDefinedStatements]
from typing import Any, List, Optional, Iterable
class Return:
def __init__(self, x: int) -> None:
self.x = x
if x > 5:
self.y = 1
return
self.y = 2
self.z = x
class While:
def __init__(self, x: int) -> None:
n = 2
while x > 0:
n *=2
x -= 1
self.a = n
while x < 5:
self.b = 1
self.b += 1
class Try:
def __init__(self, x: List[int]) -> None:
self.a = 0
try:
self.b = x[0]
except:
self.c = x
self.d = 0
try:
self.e = x[0]
except:
self.e = 1
class TryFinally:
def __init__(self, x: List[int]) -> None:
self.a = 0
try:
self.b = x[0]
finally:
self.c = x
self.d = 0
try:
self.e = x[0]
finally:
self.e = 1
class Assert:
def __init__(self, x: Optional[str], y: int) -> None:
assert x is not None
assert y < 5
self.a = x
class For:
def __init__(self, it: Iterable[int]) -> None:
self.x = 0
for x in it:
self.x += x
for x in it:
self.y = x
class Assignment1:
def __init__(self, other: Assignment1) -> None:
self.x = 0
self = other # Give up after assignment to self
self.y = 1
class Assignment2:
def __init__(self) -> None:
self.x = 0
other = self # Give up after self is aliased
self.y = other.x
class With:
def __init__(self, x: Any) -> None:
self.a = 0
with x:
self.b = 1
self.c = 2
def f() -> None:
pass
[out]
Return: [x, y]
While: [a]
-- We could infer 'e' as always defined, but this is tricky, since always defined attribute
-- analysis must be performed earlier than exception handling transform. This would be
-- easy to infer *after* exception handling transform.
Try: [a, d]
-- Again, 'e' could be always defined, but it would be a bit tricky to do it.
TryFinally: [a, c, d]
Assert: [a]
For: [x]
Assignment1: [x]
Assignment2: [x]
-- TODO: Why is not 'b' included?
With: [a, c]
[case testAlwaysDefinedAttributeDefaults]
class Basic:
x = 0
class ClassBodyAndInit:
x = 0
s = 'x'
def __init__(self, n: int) -> None:
self.n = 0
class AttrWithDefaultAndInit:
x = 0
def __init__(self, x: int) -> None:
self.x = x
class Base:
x = 0
y = 1
class Derived(Base):
y = 2
z = 3
[out]
Basic: [x]
ClassBodyAndInit: [n, s, x]
AttrWithDefaultAndInit: [x]
Base: [x, y]
Derived: [x, y, z]
[case testAlwaysDefinedWithInheritance]
class Base:
def __init__(self, x: int) -> None:
self.x = x
class Deriv1(Base):
def __init__(self, x: int, y: str) -> None:
super().__init__(x)
self.y = y
class Deriv2(Base):
def __init__(self, x: int, y: str) -> None:
self.y = y
super().__init__(x)
class Deriv22(Deriv2):
def __init__(self, x: int, y: str, z: bool) -> None:
super().__init__(x, y)
self.z = False
class Deriv3(Base):
def __init__(self) -> None:
super().__init__(1)
class Deriv4(Base):
def __init__(self) -> None:
self.y = 1
self.x = 2
def f(a): pass
class BaseUnsafe:
def __init__(self, x: int, y: int) -> None:
self.x = x
f(self) # Unknown function
self.y = y
class DerivUnsafe(BaseUnsafe):
def __init__(self, z: int, zz: int) -> None:
self.z = z
super().__init__(1, 2) # Calls unknown function
self.zz = zz
class BaseWithDefault:
x = 1
def __init__(self) -> None:
self.y = 1
class DerivedWithDefault(BaseWithDefault):
def __init__(self) -> None:
super().__init__()
self.z = 1
class AlwaysDefinedInBase:
def __init__(self) -> None:
self.x = 1
self.y = 1
class UndefinedInDerived(AlwaysDefinedInBase):
def __init__(self, x: bool) -> None:
self.x = 1
if x:
self.y = 2
class UndefinedInDerived2(UndefinedInDerived):
def __init__(self, x: bool):
if x:
self.y = 2
[out]
Base: [x]
Deriv1: [x, y]
Deriv2: [x, y]
Deriv22: [x, y, z]
Deriv3: [x]
Deriv4: [x, y]
BaseUnsafe: [x]
DerivUnsafe: [x, z]
BaseWithDefault: [x, y]
DerivedWithDefault: [x, y, z]
AlwaysDefinedInBase: []
UndefinedInDerived: []
UndefinedInDerived2: []
[case testAlwaysDefinedWithInheritance2]
from mypy_extensions import trait, mypyc_attr
from interpreted import PythonBase
class BasePartiallyDefined:
def __init__(self, x: int) -> None:
self.a = 0
if x:
self.x = x
class Derived1(BasePartiallyDefined):
def __init__(self, x: int) -> None:
super().__init__(x)
self.y = x
class BaseUndefined:
x: int
class DerivedAlwaysDefined(BaseUndefined):
def __init__(self) -> None:
super().__init__()
self.z = 0
self.x = 2
@trait
class MyTrait:
def f(self) -> None: pass
class SimpleTraitImpl(MyTrait):
def __init__(self) -> None:
super().__init__()
self.x = 0
@trait
class TraitWithAttr:
x: int
y: str
class TraitWithAttrImpl(TraitWithAttr):
def __init__(self) -> None:
self.y = 'x'
@trait
class TraitWithAttr2:
z: int
class TraitWithAttrImpl2(TraitWithAttr, TraitWithAttr2):
def __init__(self) -> None:
self.y = 'x'
self.z = 2
@mypyc_attr(allow_interpreted_subclasses=True)
class BaseWithGeneralSubclassing:
x = 0
y: int
def __init__(self, s: str) -> None:
self.s = s
class Derived2(BaseWithGeneralSubclassing):
def __init__(self) -> None:
super().__init__('x')
self.z = 0
class SubclassPythonclass(PythonBase):
def __init__(self) -> None:
self.y = 1
class BaseWithSometimesDefined:
def __init__(self, b: bool) -> None:
if b:
self.x = 0
class Derived3(BaseWithSometimesDefined):
def __init__(self, b: bool) -> None:
super().__init__(b)
self.x = 1
[file interpreted.py]
class PythonBase:
def __init__(self) -> None:
self.x = 0
[out]
BasePartiallyDefined: [a]
Derived1: [a, y]
BaseUndefined: []
DerivedAlwaysDefined: [x, z]
MyTrait: []
SimpleTraitImpl: [x]
TraitWithAttr: []
TraitWithAttrImpl: [y]
TraitWithAttr2: []
TraitWithAttrImpl2: [y, z]
BaseWithGeneralSubclassing: []
-- TODO: 's' could also be always defined
Derived2: [x, z]
-- Always defined attribute analysis is turned off when inheriting a non-native class.
SubclassPythonclass: []
BaseWithSometimesDefined: []
-- TODO: 'x' could also be always defined, but it is a bit tricky to support
Derived3: []
[case testAlwaysDefinedWithNesting]
class NestedFunc:
def __init__(self) -> None:
self.x = 0
def f() -> None:
self.y = 0
f()
self.z = 1
[out]
-- TODO: Support nested functions.
NestedFunc: []
f___init___NestedFunc_obj: []