Major fixes and new features
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-09-25 15:51:48 +09:00
parent dd7349bb4c
commit ddce9f5125
5586 changed files with 1470941 additions and 0 deletions

View File

@@ -0,0 +1,732 @@
-- 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: []

View File

@@ -0,0 +1,603 @@
-- Test cases for data flow analysis.
[case testSimple_MaybeDefined]
def f(a: int) -> None:
x = 1
if x == a:
y = 1
else:
z = 1
[out]
def f(a):
a, x :: int
r0 :: native_int
r1, r2, r3 :: bit
y, z :: int
L0:
x = 2
r0 = x & 1
r1 = r0 != 0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = CPyTagged_IsEq_(x, a)
if r2 goto L3 else goto L4 :: bool
L2:
r3 = x == a
if r3 goto L3 else goto L4 :: bool
L3:
y = 2
goto L5
L4:
z = 2
L5:
return 1
(0, 0) {a} {a, x}
(0, 1) {a, x} {a, x}
(0, 2) {a, x} {a, x}
(0, 3) {a, x} {a, x}
(1, 0) {a, x} {a, x}
(1, 1) {a, x} {a, x}
(2, 0) {a, x} {a, x}
(2, 1) {a, x} {a, x}
(3, 0) {a, x} {a, x, y}
(3, 1) {a, x, y} {a, x, y}
(4, 0) {a, x} {a, x, z}
(4, 1) {a, x, z} {a, x, z}
(5, 0) {a, x, y, z} {a, x, y, z}
[case testSimple_Liveness]
def f(a: int) -> int:
x = 1
if x == 1:
return a
else:
return x
[out]
def f(a):
a, x :: int
r0 :: bit
L0:
x = 2
r0 = x == 2
if r0 goto L1 else goto L2 :: bool
L1:
return a
L2:
return x
L3:
unreachable
(0, 0) {a} {a, x}
(0, 1) {a, x} {a, r0, x}
(0, 2) {a, r0, x} {a, x}
(1, 0) {a} {}
(2, 0) {x} {}
(3, 0) {} {}
[case testSpecial_Liveness]
def f() -> int:
x = 1
y = 1
x = 2
return x
[out]
def f():
x, y :: int
L0:
x = 2
y = 2
x = 4
return x
(0, 0) {} {}
(0, 1) {} {}
(0, 2) {} {x}
(0, 3) {x} {}
[case testSpecial2_Liveness]
def f(a: int) -> int:
a = 1
a = 2
a = 3
return a
[out]
def f(a):
a :: int
L0:
a = 2
a = 4
a = 6
return a
(0, 0) {} {}
(0, 1) {} {}
(0, 2) {} {a}
(0, 3) {a} {}
[case testSimple_MustDefined]
def f(a: int) -> None:
if a == 1:
y = 1
x = 2
else:
x = 2
[out]
def f(a):
a :: int
r0 :: bit
y, x :: int
L0:
r0 = a == 2
if r0 goto L1 else goto L2 :: bool
L1:
y = 2
x = 4
goto L3
L2:
x = 4
L3:
return 1
(0, 0) {a} {a}
(0, 1) {a} {a}
(1, 0) {a} {a, y}
(1, 1) {a, y} {a, x, y}
(1, 2) {a, x, y} {a, x, y}
(2, 0) {a} {a, x}
(2, 1) {a, x} {a, x}
(3, 0) {a, x} {a, x}
[case testTwoArgs_MustDefined]
def f(x: int, y: int) -> int:
return x
[out]
def f(x, y):
x, y :: int
L0:
return x
(0, 0) {x, y} {x, y}
[case testLoop_MustDefined]
def f(n: int) -> None:
while n < 5:
n = n + 1
m = n
[out]
def f(n):
n :: int
r0 :: native_int
r1, r2, r3 :: bit
r4, m :: int
L0:
L1:
r0 = n & 1
r1 = r0 != 0
if r1 goto L2 else goto L3 :: bool
L2:
r2 = CPyTagged_IsLt_(n, 10)
if r2 goto L4 else goto L5 :: bool
L3:
r3 = n < 10 :: signed
if r3 goto L4 else goto L5 :: bool
L4:
r4 = CPyTagged_Add(n, 2)
n = r4
m = n
goto L1
L5:
return 1
(0, 0) {n} {n}
(1, 0) {n} {n}
(1, 1) {n} {n}
(1, 2) {n} {n}
(2, 0) {n} {n}
(2, 1) {n} {n}
(3, 0) {n} {n}
(3, 1) {n} {n}
(4, 0) {n} {n}
(4, 1) {n} {n}
(4, 2) {n} {m, n}
(4, 3) {m, n} {m, n}
(5, 0) {n} {n}
[case testMultiPass_Liveness]
def f(n: int) -> None:
x = 1
y = 1
while n < 1:
n = y
while n < 2:
n = 1
n = x
[out]
def f(n):
n, x, y :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6, r7 :: bit
L0:
x = 2
y = 2
L1:
r0 = n & 1
r1 = r0 != 0
if r1 goto L2 else goto L3 :: bool
L2:
r2 = CPyTagged_IsLt_(n, 2)
if r2 goto L4 else goto L10 :: bool
L3:
r3 = n < 2 :: signed
if r3 goto L4 else goto L10 :: bool
L4:
n = y
L5:
r4 = n & 1
r5 = r4 != 0
if r5 goto L6 else goto L7 :: bool
L6:
r6 = CPyTagged_IsLt_(n, 4)
if r6 goto L8 else goto L9 :: bool
L7:
r7 = n < 4 :: signed
if r7 goto L8 else goto L9 :: bool
L8:
n = 2
n = x
goto L5
L9:
goto L1
L10:
return 1
(0, 0) {n} {n, x}
(0, 1) {n, x} {n, x, y}
(0, 2) {n, x, y} {n, x, y}
(1, 0) {n, x, y} {n, r0, x, y}
(1, 1) {n, r0, x, y} {n, r1, x, y}
(1, 2) {n, r1, x, y} {n, x, y}
(2, 0) {n, x, y} {r2, x, y}
(2, 1) {r2, x, y} {x, y}
(3, 0) {n, x, y} {r3, x, y}
(3, 1) {r3, x, y} {x, y}
(4, 0) {x, y} {n, x, y}
(4, 1) {n, x, y} {n, x, y}
(5, 0) {n, x, y} {n, r4, x, y}
(5, 1) {n, r4, x, y} {n, r5, x, y}
(5, 2) {n, r5, x, y} {n, x, y}
(6, 0) {n, x, y} {n, r6, x, y}
(6, 1) {n, r6, x, y} {n, x, y}
(7, 0) {n, x, y} {n, r7, x, y}
(7, 1) {n, r7, x, y} {n, x, y}
(8, 0) {x, y} {x, y}
(8, 1) {x, y} {n, x, y}
(8, 2) {n, x, y} {n, x, y}
(9, 0) {n, x, y} {n, x, y}
(10, 0) {} {}
[case testCall_Liveness]
def f(x: int) -> int:
a = f(1)
return f(a) + a
[out]
def f(x):
x, r0, a, r1, r2, r3 :: int
L0:
r0 = f(2)
if is_error(r0) goto L3 (error at f:2) else goto L1
L1:
a = r0
r1 = f(a)
if is_error(r1) goto L3 (error at f:3) else goto L2
L2:
r2 = CPyTagged_Add(r1, a)
return r2
L3:
r3 = <error> :: int
return r3
(0, 0) {} {r0}
(0, 1) {r0} {r0}
(1, 0) {r0} {a}
(1, 1) {a} {a, r1}
(1, 2) {a, r1} {a, r1}
(2, 0) {a, r1} {r2}
(2, 1) {r2} {}
(3, 0) {} {r3}
(3, 1) {r3} {}
[case testLoop_MaybeDefined]
def f(a: int) -> None:
while a < a:
while a < a:
y = a
x = a
[out]
def f(a):
a :: int
r0 :: native_int
r1 :: bit
r2 :: native_int
r3, r4, r5 :: bit
r6 :: native_int
r7 :: bit
r8 :: native_int
r9, r10, r11 :: bit
y, x :: int
L0:
L1:
r0 = a & 1
r1 = r0 != 0
if r1 goto L3 else goto L2 :: bool
L2:
r2 = a & 1
r3 = r2 != 0
if r3 goto L3 else goto L4 :: bool
L3:
r4 = CPyTagged_IsLt_(a, a)
if r4 goto L5 else goto L12 :: bool
L4:
r5 = a < a :: signed
if r5 goto L5 else goto L12 :: bool
L5:
L6:
r6 = a & 1
r7 = r6 != 0
if r7 goto L8 else goto L7 :: bool
L7:
r8 = a & 1
r9 = r8 != 0
if r9 goto L8 else goto L9 :: bool
L8:
r10 = CPyTagged_IsLt_(a, a)
if r10 goto L10 else goto L11 :: bool
L9:
r11 = a < a :: signed
if r11 goto L10 else goto L11 :: bool
L10:
y = a
goto L6
L11:
x = a
goto L1
L12:
return 1
(0, 0) {a} {a}
(1, 0) {a, x, y} {a, x, y}
(1, 1) {a, x, y} {a, x, y}
(1, 2) {a, x, y} {a, x, y}
(2, 0) {a, x, y} {a, x, y}
(2, 1) {a, x, y} {a, x, y}
(2, 2) {a, x, y} {a, x, y}
(3, 0) {a, x, y} {a, x, y}
(3, 1) {a, x, y} {a, x, y}
(4, 0) {a, x, y} {a, x, y}
(4, 1) {a, x, y} {a, x, y}
(5, 0) {a, x, y} {a, x, y}
(6, 0) {a, x, y} {a, x, y}
(6, 1) {a, x, y} {a, x, y}
(6, 2) {a, x, y} {a, x, y}
(7, 0) {a, x, y} {a, x, y}
(7, 1) {a, x, y} {a, x, y}
(7, 2) {a, x, y} {a, x, y}
(8, 0) {a, x, y} {a, x, y}
(8, 1) {a, x, y} {a, x, y}
(9, 0) {a, x, y} {a, x, y}
(9, 1) {a, x, y} {a, x, y}
(10, 0) {a, x, y} {a, x, y}
(10, 1) {a, x, y} {a, x, y}
(11, 0) {a, x, y} {a, x, y}
(11, 1) {a, x, y} {a, x, y}
(12, 0) {a, x, y} {a, x, y}
[case testTrivial_BorrowedArgument]
def f(a: int, b: int) -> int:
return b
[out]
def f(a, b):
a, b :: int
L0:
return b
(0, 0) {a, b} {a, b}
[case testSimple_BorrowedArgument]
def f(a: int) -> int:
b = a
a = 1
return a
[out]
def f(a):
a, b :: int
L0:
b = a
a = 2
return a
(0, 0) {a} {a}
(0, 1) {a} {}
(0, 2) {} {}
[case testConditional_BorrowedArgument]
def f(a: int) -> int:
if a == a:
x = 2
a = 1
else:
x = 1
return x
[out]
def f(a):
a :: int
r0 :: native_int
r1, r2, r3 :: bit
x :: int
L0:
r0 = a & 1
r1 = r0 != 0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = CPyTagged_IsEq_(a, a)
if r2 goto L3 else goto L4 :: bool
L2:
r3 = a == a
if r3 goto L3 else goto L4 :: bool
L3:
x = 4
a = 2
goto L5
L4:
x = 2
L5:
return x
(0, 0) {a} {a}
(0, 1) {a} {a}
(0, 2) {a} {a}
(1, 0) {a} {a}
(1, 1) {a} {a}
(2, 0) {a} {a}
(2, 1) {a} {a}
(3, 0) {a} {a}
(3, 1) {a} {}
(3, 2) {} {}
(4, 0) {a} {a}
(4, 1) {a} {a}
(5, 0) {} {}
[case testLoop_BorrowedArgument]
def f(a: int) -> int:
sum = 0
i = 0
while i <= a:
sum = sum + i
i = i + 1
return sum
[out]
def f(a):
a, sum, i :: int
r0 :: native_int
r1 :: bit
r2 :: native_int
r3, r4, r5 :: bit
r6, r7 :: int
L0:
sum = 0
i = 0
L1:
r0 = i & 1
r1 = r0 != 0
if r1 goto L3 else goto L2 :: bool
L2:
r2 = a & 1
r3 = r2 != 0
if r3 goto L3 else goto L4 :: bool
L3:
r4 = CPyTagged_IsLt_(a, i)
if r4 goto L6 else goto L5 :: bool
L4:
r5 = i <= a :: signed
if r5 goto L5 else goto L6 :: bool
L5:
r6 = CPyTagged_Add(sum, i)
sum = r6
r7 = CPyTagged_Add(i, 2)
i = r7
goto L1
L6:
return sum
(0, 0) {a} {a}
(0, 1) {a} {a}
(0, 2) {a} {a}
(1, 0) {a} {a}
(1, 1) {a} {a}
(1, 2) {a} {a}
(2, 0) {a} {a}
(2, 1) {a} {a}
(2, 2) {a} {a}
(3, 0) {a} {a}
(3, 1) {a} {a}
(4, 0) {a} {a}
(4, 1) {a} {a}
(5, 0) {a} {a}
(5, 1) {a} {a}
(5, 2) {a} {a}
(5, 3) {a} {a}
(5, 4) {a} {a}
(6, 0) {a} {a}
[case testError]
def f(x: List[int]) -> None: pass # E: Name "List" is not defined \
# N: Did you forget to import it from "typing"? (Suggestion: "from typing import List")
[case testExceptUndefined_Liveness]
def lol(x: object) -> int:
try:
st = id(x)
except Exception:
return -1
return st + 1
[out]
def lol(x):
x :: object
r0, st :: int
r1 :: tuple[object, object, object]
r2 :: object
r3 :: str
r4 :: object
r5, r6 :: bit
r7, r8 :: int
L0:
L1:
r0 = CPyTagged_Id(x)
st = r0
goto L10
L2:
r1 = CPy_CatchError()
r2 = builtins :: module
r3 = 'Exception'
r4 = CPyObject_GetAttr(r2, r3)
if is_error(r4) goto L8 (error at lol:4) else goto L3
L3:
r5 = CPy_ExceptionMatches(r4)
if r5 goto L4 else goto L5 :: bool
L4:
CPy_RestoreExcInfo(r1)
return -2
L5:
CPy_Reraise()
if not 0 goto L8 else goto L6 :: bool
L6:
unreachable
L7:
CPy_RestoreExcInfo(r1)
goto L10
L8:
CPy_RestoreExcInfo(r1)
r6 = CPy_KeepPropagating()
if not r6 goto L11 else goto L9 :: bool
L9:
unreachable
L10:
r7 = CPyTagged_Add(st, 2)
return r7
L11:
r8 = <error> :: int
return r8
(0, 0) {x} {x}
(1, 0) {x} {r0}
(1, 1) {r0} {st}
(1, 2) {st} {st}
(2, 0) {} {r1}
(2, 1) {r1} {r1, r2}
(2, 2) {r1, r2} {r1, r2, r3}
(2, 3) {r1, r2, r3} {r1, r4}
(2, 4) {r1, r4} {r1, r4}
(3, 0) {r1, r4} {r1, r5}
(3, 1) {r1, r5} {r1}
(4, 0) {r1} {}
(4, 1) {} {}
(5, 0) {r1} {r1}
(5, 1) {r1} {r1}
(6, 0) {} {}
(7, 0) {r1, st} {st}
(7, 1) {st} {st}
(8, 0) {r1} {}
(8, 1) {} {r6}
(8, 2) {r6} {}
(9, 0) {} {}
(10, 0) {st} {r7}
(10, 1) {r7} {}
(11, 0) {} {r8}
(11, 1) {r8} {}

View File

@@ -0,0 +1,245 @@
-- Test cases for invoking mypyc on the command line
--
-- These are slow -- do not add test cases unless you have a very good reason to do so.
[case testCompileMypyc]
# cmd: a.py b.py p/__init__.py p/q.py
import os.path
import p
import p.q
import a
import b
print('<main>', b.g(a.A()))
try:
a.f('')
except TypeError:
pass
else:
assert False
for x in [a, b, p, p.q]:
assert os.path.splitext(x.__file__)[1] != '.py'
[file z.py]
[file a.py]
import b
import c
from p import s
from typing import NamedTuple
print('<a>', ord('A') == 65) # Test full builtins
class A:
def __init__(self) -> None:
self.x = 4
def f(x: int) -> b.B:
return b.B(x)
class B:
def __init__(self, x: int, y: str) -> None:
self.x = x
print('<a>', f(5).x)
print('<c>', c.foo())
assert s.bar(10) == 20
class NT(NamedTuple):
x: int
print(NT(2))
[file b.py]
import a
import p.q
class B:
def __init__(self, x: int) -> None:
self.x = x
def g(z: 'a.A') -> int:
return p.q.foo(z.x)
print('<b>', 'here')
[file c.py]
def foo() -> int:
return 10
[file p/__init__.py]
[file p/q.py]
import p.r
def foo(x: int) -> int:
return x*p.r.foo(x)
[file p/r.py]
def foo(x: int) -> int:
return x
[file p/s.py]
def bar(x: int) -> int:
return x*2
[out]
<b> here
<a> True
<a> 5
<c> 10
NT(x=2)
<main> 16
-- This test is here so we can turn it on when we get nervous about
-- this case, but is disabled for speed reasons.
[case testCompileMypycOne-skip]
# cmd: a.py
import os.path
import a
assert os.path.splitext(a.__file__)[1] != '.py'
assert a.f(10) == 100
[file a.py]
def f(x: int) -> int:
return x*x
[case testErrorOutput]
# cmd: test.py
[file test.py]
from typing import List, Any, AsyncIterable
from typing_extensions import Final
from mypy_extensions import trait, mypyc_attr
from functools import singledispatch
def busted(b: bool) -> None:
for i in range(1, 10, 0): # E: range() step can't be zero
try:
if i == 5:
break # E: break inside try/finally block is unimplemented
elif i == 4:
continue # E: continue inside try/finally block is unimplemented
finally:
print('oops')
print(sum([1,2,3]))
x = [1,2]
class Foo:
a, b = (10, 20) # E: Only assignment to variables is supported in class bodies
x[0] = 10 # E: Only assignment to variables is supported in class bodies
lol = 20
l = [10] # W: Unsupported default attribute value
c = d = 50 # E: Multiple assignment in class bodies not supported
if 1+1 == 2: # E: Unsupported statement in class body
x = 10
Foo.lol = 50 # E: Only class variables defined as ClassVar can be assigned to
def decorator(x: Any) -> Any:
return x
class NeverMetaclass(type): # E: Inheriting from most builtin types is unimplemented
pass
class Concrete1:
pass
@trait
class PureTrait:
pass
@trait
class Trait1:
pass
class Concrete2:
pass
@trait
class Trait2(Concrete2):
pass
@decorator
class NonExt(Concrete1): # E: Non-extension classes may not inherit from extension classes
pass
class NopeMultipleInheritance(Concrete1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
pass
class NopeMultipleInheritanceAndBadOrder(Concrete1, Trait1, Concrete2): # E: Multiple inheritance is not supported (except for traits)
pass
class NopeMultipleInheritanceAndBadOrder2(Concrete1, Concrete2, Trait1): # E: Multiple inheritance is not supported (except for traits)
pass
class NopeMultipleInheritanceAndBadOrder3(Trait1, Concrete1, Concrete2): # E: Non-trait base must appear first in parent list # E: Multiple inheritance is not supported (except for traits)
pass
class NopeBadOrder(Trait1, Concrete2): # E: Non-trait base must appear first in parent list
pass
@decorator
class NonExt2:
@property # E: Property setters not supported in non-extension classes
def test(self) -> int:
return 0
@test.setter
def test(self, x: int) -> None:
pass
iterator_warning = (i+1 for i in range(10)) # W: Treating generator comprehension as list
# But we don't want warnings for these cases:
tup = tuple(i+1 for i in range(10))
a_str = " ".join(str(i) for i in range(10))
wtvr = next(i for i in range(10) if i == 5)
d1 = {1: 2}
# Make sure we can produce an error when we hit the awful None case
def f(l: List[object]) -> None:
x = None # E: Local variable "x" has inferred type None; add an annotation
for i in l:
if x is None:
x = i
@mypyc_attr(allow_interpreted_subclasses=True)
class AllowInterp1(Concrete1): # E: Base class "test.Concrete1" does not allow interpreted subclasses
pass
@mypyc_attr(allow_interpreted_subclasses=True)
class AllowInterp2(PureTrait): # E: Base class "test.PureTrait" does not allow interpreted subclasses
pass
async def async_generators() -> AsyncIterable[int]:
yield 1 # E: async generators are unimplemented
@singledispatch
def a(arg) -> None:
pass
@decorator # E: Calling decorator after registering function not supported
@a.register
def g(arg: int) -> None:
pass
@a.register
@decorator
def h(arg: str) -> None:
pass
@decorator
@decorator # E: Calling decorator after registering function not supported
@a.register
def i(arg: Foo) -> None:
pass
[case testOnlyWarningOutput]
# cmd: test.py
[file test.py]
names = (str(v) for v in [1, 2, 3]) # W: Treating generator comprehension as list

View File

@@ -0,0 +1,48 @@
"""Default driver for run tests (run-*.test).
This imports the 'native' module (containing the compiled test cases)
and calls each function starting with test_, and reports any
exceptions as failures.
Test cases can provide a custom driver.py that overrides this file.
"""
import sys
import native
failures = []
for name in dir(native):
if name.startswith('test_'):
test_func = getattr(native, name)
try:
test_func()
except Exception as e:
failures.append((name, sys.exc_info()))
if failures:
from traceback import print_exception, format_tb
import re
def extract_line(tb):
formatted = '\n'.join(format_tb(tb))
m = re.search('File "(native|driver).py", line ([0-9]+), in (test_|<module>)', formatted)
if m is None:
return "0"
return m.group(1)
# Sort failures by line number of test function.
failures = sorted(failures, key=lambda e: extract_line(e[1][2]))
# If there are multiple failures, print stack traces of all but the final failure.
for name, e in failures[:-1]:
print(f'<< {name} >>')
sys.stdout.flush()
print_exception(*e)
print()
sys.stdout.flush()
# Raise exception for the last failure. Test runner will show the traceback.
print(f'<< {failures[-1][0]} >>')
sys.stdout.flush()
raise failures[-1][1][1]

View File

@@ -0,0 +1,125 @@
-- Test cases for basic block execution frequency analysis.
--
-- These test cases are using exception transform test machinery for convenience.
--
-- NOTE: These must all have the _freq suffix
[case testSimpleError_freq]
from typing import List
def f(x: List[int]) -> int:
return x[0]
[out]
def f(x):
x :: list
r0 :: object
r1, r2 :: int
L0:
r0 = CPyList_GetItemShort(x, 0)
if is_error(r0) goto L3 (error at f:3) else goto L1
L1:
r1 = unbox(int, r0)
dec_ref r0
if is_error(r1) goto L3 (error at f:3) else goto L2
L2:
return r1
L3:
r2 = <error> :: int
return r2
hot blocks: [0, 1, 2]
[case testHotBranch_freq]
from typing import List
def f(x: bool) -> None:
if x:
y = 1
else:
y = 2
[out]
def f(x):
x :: bool
y :: int
L0:
if x goto L1 else goto L2 :: bool
L1:
y = 2
dec_ref y :: int
goto L3
L2:
y = 4
dec_ref y :: int
L3:
return 1
hot blocks: [0, 1, 2, 3]
[case testGoto_freq]
from typing import List
def f(x: bool) -> int:
if x:
y = 1
else:
return 2
return y
[out]
def f(x):
x :: bool
y :: int
L0:
if x goto L1 else goto L2 :: bool
L1:
y = 2
goto L3
L2:
return 4
L3:
return y
hot blocks: [0, 1, 2, 3]
[case testFalseOnError_freq]
from typing import List
def f(x: List[int]) -> None:
x[0] = 1
[out]
def f(x):
x :: list
r0 :: object
r1 :: bit
r2 :: None
L0:
r0 = object 1
inc_ref r0
r1 = CPyList_SetItem(x, 0, r0)
if not r1 goto L2 (error at f:3) else goto L1 :: bool
L1:
return 1
L2:
r2 = <error> :: None
return r2
hot blocks: [0, 1]
[case testRareBranch_freq]
from typing_extensions import Final
x: Final = str()
def f() -> str:
return x
[out]
def f():
r0 :: str
r1 :: bool
r2 :: str
L0:
r0 = __main__.x :: static
if is_error(r0) goto L1 else goto L3
L1:
r1 = raise NameError('value for final name "x" was not set')
if not r1 goto L4 (error at f:6) else goto L2 :: bool
L2:
unreachable
L3:
inc_ref r0
return r0
L4:
r2 = <error> :: str
return r2
hot blocks: [0, 3]

View File

@@ -0,0 +1,713 @@
-- Test cases for exception handling insertion transform.
--
-- The result includes refcount handling since these two transforms interact.
[case testListGetAndUnboxError]
from typing import List
def f(x: List[int]) -> int:
return x[0]
[out]
def f(x):
x :: list
r0 :: object
r1, r2 :: int
L0:
r0 = CPyList_GetItemShort(x, 0)
if is_error(r0) goto L3 (error at f:3) else goto L1
L1:
r1 = unbox(int, r0)
dec_ref r0
if is_error(r1) goto L3 (error at f:3) else goto L2
L2:
return r1
L3:
r2 = <error> :: int
return r2
[case testListAppendAndSetItemError]
from typing import List
def f(x: List[int], y: int, z: int) -> None:
x.append(y)
x[y] = z
[out]
def f(x, y, z):
x :: list
y, z :: int
r0 :: object
r1 :: i32
r2 :: bit
r3 :: object
r4 :: bit
r5 :: None
L0:
inc_ref y :: int
r0 = box(int, y)
r1 = PyList_Append(x, r0)
dec_ref r0
r2 = r1 >= 0 :: signed
if not r2 goto L3 (error at f:3) else goto L1 :: bool
L1:
inc_ref z :: int
r3 = box(int, z)
r4 = CPyList_SetItem(x, y, r3)
if not r4 goto L3 (error at f:4) else goto L2 :: bool
L2:
return 1
L3:
r5 = <error> :: None
return r5
[case testOptionalHandling]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> int:
if x is None:
return 1
if x is not None:
return 2
return 3
[out]
def f(x):
x :: union[__main__.A, None]
r0 :: object
r1 :: bit
r2 :: __main__.A
r3 :: object
r4 :: bit
r5 :: int
L0:
r0 = load_address _Py_NoneStruct
r1 = x == r0
if r1 goto L1 else goto L2 :: bool
L1:
return 2
L2:
r2 = borrow cast(__main__.A, x)
if is_error(r2) goto L6 (error at f:8) else goto L3
L3:
r3 = load_address _Py_NoneStruct
r4 = r2 != r3
if r4 goto L4 else goto L5 :: bool
L4:
return 4
L5:
return 6
L6:
r5 = <error> :: int
return r5
[case testListSum]
from typing import List
def sum(a: List[int], l: int) -> int:
sum = 0
i = 0
while i < l:
sum = sum + a[i]
i = i + 1
return sum
[out]
def sum(a, l):
a :: list
l, sum, i :: int
r0 :: native_int
r1 :: bit
r2 :: native_int
r3, r4, r5 :: bit
r6 :: object
r7, r8, r9, r10 :: int
L0:
sum = 0
i = 0
L1:
r0 = i & 1
r1 = r0 != 0
if r1 goto L3 else goto L2 :: bool
L2:
r2 = l & 1
r3 = r2 != 0
if r3 goto L3 else goto L4 :: bool
L3:
r4 = CPyTagged_IsLt_(i, l)
if r4 goto L5 else goto L10 :: bool
L4:
r5 = i < l :: signed
if r5 goto L5 else goto L10 :: bool
L5:
r6 = CPyList_GetItemBorrow(a, i)
if is_error(r6) goto L11 (error at sum:6) else goto L6
L6:
r7 = unbox(int, r6)
if is_error(r7) goto L11 (error at sum:6) else goto L7
L7:
r8 = CPyTagged_Add(sum, r7)
dec_ref sum :: int
dec_ref r7 :: int
sum = r8
r9 = CPyTagged_Add(i, 2)
dec_ref i :: int
i = r9
goto L1
L8:
return sum
L9:
r10 = <error> :: int
return r10
L10:
dec_ref i :: int
goto L8
L11:
dec_ref sum :: int
dec_ref i :: int
goto L9
[case testTryExcept]
def g() -> None:
try:
object()
except:
print("weeee")
[out]
def g():
r0 :: object
r1 :: str
r2, r3 :: object
r4 :: tuple[object, object, object]
r5 :: str
r6 :: object
r7 :: str
r8, r9 :: object
r10 :: bit
r11 :: None
L0:
L1:
r0 = builtins :: module
r1 = 'object'
r2 = CPyObject_GetAttr(r0, r1)
if is_error(r2) goto L3 (error at g:3) else goto L2
L2:
r3 = PyObject_CallFunctionObjArgs(r2, 0)
dec_ref r2
if is_error(r3) goto L3 (error at g:3) else goto L10
L3:
r4 = CPy_CatchError()
r5 = 'weeee'
r6 = builtins :: module
r7 = 'print'
r8 = CPyObject_GetAttr(r6, r7)
if is_error(r8) goto L6 (error at g:5) else goto L4
L4:
r9 = PyObject_CallFunctionObjArgs(r8, r5, 0)
dec_ref r8
if is_error(r9) goto L6 (error at g:5) else goto L11
L5:
CPy_RestoreExcInfo(r4)
dec_ref r4
goto L8
L6:
CPy_RestoreExcInfo(r4)
dec_ref r4
r10 = CPy_KeepPropagating()
if not r10 goto L9 else goto L7 :: bool
L7:
unreachable
L8:
return 1
L9:
r11 = <error> :: None
return r11
L10:
dec_ref r3
goto L8
L11:
dec_ref r9
goto L5
[case testGenopsTryFinally]
def a() -> str:
try:
print()
return 'hi'
finally:
print('goodbye!')
[out]
def a():
r0 :: object
r1 :: str
r2, r3 :: object
r4, r5 :: str
r6, r7 :: tuple[object, object, object]
r8 :: str
r9 :: tuple[object, object, object]
r10 :: str
r11 :: object
r12 :: str
r13, r14 :: object
r15 :: bit
r16 :: str
L0:
L1:
r0 = builtins :: module
r1 = 'print'
r2 = CPyObject_GetAttr(r0, r1)
if is_error(r2) goto L5 (error at a:3) else goto L2
L2:
r3 = PyObject_CallFunctionObjArgs(r2, 0)
dec_ref r2
if is_error(r3) goto L5 (error at a:3) else goto L19
L3:
r4 = 'hi'
inc_ref r4
r5 = r4
L4:
r6 = <error> :: tuple[object, object, object]
r7 = r6
goto L6
L5:
r8 = <error> :: str
r5 = r8
r9 = CPy_CatchError()
r7 = r9
L6:
r10 = 'goodbye!'
r11 = builtins :: module
r12 = 'print'
r13 = CPyObject_GetAttr(r11, r12)
if is_error(r13) goto L20 (error at a:6) else goto L7
L7:
r14 = PyObject_CallFunctionObjArgs(r13, r10, 0)
dec_ref r13
if is_error(r14) goto L20 (error at a:6) else goto L21
L8:
if is_error(r7) goto L11 else goto L22
L9:
CPy_Reraise()
if not 0 goto L13 else goto L23 :: bool
L10:
unreachable
L11:
if is_error(r5) goto L17 else goto L12
L12:
return r5
L13:
if is_error(r7) goto L15 else goto L14
L14:
CPy_RestoreExcInfo(r7)
xdec_ref r7
L15:
r15 = CPy_KeepPropagating()
if not r15 goto L18 else goto L16 :: bool
L16:
unreachable
L17:
unreachable
L18:
r16 = <error> :: str
return r16
L19:
dec_ref r3
goto L3
L20:
xdec_ref r5
goto L13
L21:
dec_ref r14
goto L8
L22:
xdec_ref r5
goto L9
L23:
xdec_ref r7
goto L10
[case testDocstring1]
def lol() -> None:
"""Hello"""
pass
[out]
def lol():
L0:
return 1
[case testExceptUndefined1]
from typing import Any
def lol(x: Any) -> object:
try:
st = x.foo
except:
return ''
# No uninit check should be generated, since the exception branch always returns
return st
[out]
def lol(x):
x :: object
r0 :: str
r1, st :: object
r2 :: tuple[object, object, object]
r3 :: str
L0:
L1:
r0 = 'foo'
r1 = CPyObject_GetAttr(x, r0)
if is_error(r1) goto L3 (error at lol:4) else goto L2
L2:
st = r1
goto L4
L3:
r2 = CPy_CatchError()
r3 = ''
CPy_RestoreExcInfo(r2)
dec_ref r2
inc_ref r3
return r3
L4:
return st
[case testExceptUndefined2]
from typing import Any
def lol(x: Any) -> object:
try:
a = x.foo
b = x.bar
except:
pass
# uninit checks are needed, since the exception can skip initializing the vars
return a + b
[out]
def lol(x):
x, r0, a, r1, b :: object
r2 :: str
r3 :: object
r4 :: str
r5 :: object
r6 :: tuple[object, object, object]
r7, r8 :: bool
r9, r10 :: object
L0:
r0 = <error> :: object
a = r0
r1 = <error> :: object
b = r1
L1:
r2 = 'foo'
r3 = CPyObject_GetAttr(x, r2)
if is_error(r3) goto L4 (error at lol:4) else goto L15
L2:
a = r3
r4 = 'bar'
r5 = CPyObject_GetAttr(x, r4)
if is_error(r5) goto L4 (error at lol:5) else goto L16
L3:
b = r5
goto L6
L4:
r6 = CPy_CatchError()
L5:
CPy_RestoreExcInfo(r6)
dec_ref r6
L6:
if is_error(a) goto L17 else goto L9
L7:
r7 = raise UnboundLocalError('local variable "a" referenced before assignment')
if not r7 goto L14 (error at lol:9) else goto L8 :: bool
L8:
unreachable
L9:
if is_error(b) goto L18 else goto L12
L10:
r8 = raise UnboundLocalError('local variable "b" referenced before assignment')
if not r8 goto L14 (error at lol:9) else goto L11 :: bool
L11:
unreachable
L12:
r9 = PyNumber_Add(a, b)
xdec_ref a
xdec_ref b
if is_error(r9) goto L14 (error at lol:9) else goto L13
L13:
return r9
L14:
r10 = <error> :: object
return r10
L15:
xdec_ref a
goto L2
L16:
xdec_ref b
goto L3
L17:
xdec_ref b
goto L7
L18:
xdec_ref a
goto L10
[case testMaybeUninitVarExc]
def f(b: bool) -> None:
u = 'a'
while b:
v = 'b'
if v is not u:
break
print(v)
[out]
def f(b):
b :: bool
r0, v, r1, u, r2 :: str
r3, r4 :: bit
r5 :: object
r6 :: str
r7 :: object
r8 :: bool
r9 :: object
r10 :: None
L0:
r0 = <error> :: str
v = r0
r1 = 'a'
inc_ref r1
u = r1
L1:
if b goto L10 else goto L11 :: bool
L2:
r2 = 'b'
inc_ref r2
v = r2
r3 = v == u
r4 = r3 ^ 1
if r4 goto L11 else goto L1 :: bool
L3:
r5 = builtins :: module
r6 = 'print'
r7 = CPyObject_GetAttr(r5, r6)
if is_error(r7) goto L12 (error at f:7) else goto L4
L4:
if is_error(v) goto L13 else goto L7
L5:
r8 = raise UnboundLocalError('local variable "v" referenced before assignment')
if not r8 goto L9 (error at f:7) else goto L6 :: bool
L6:
unreachable
L7:
r9 = PyObject_CallFunctionObjArgs(r7, v, 0)
dec_ref r7
xdec_ref v
if is_error(r9) goto L9 (error at f:7) else goto L14
L8:
return 1
L9:
r10 = <error> :: None
return r10
L10:
xdec_ref v
goto L2
L11:
dec_ref u
goto L3
L12:
xdec_ref v
goto L9
L13:
dec_ref r7
goto L5
L14:
dec_ref r9
goto L8
[case testExceptionWithOverlappingErrorValue]
from mypy_extensions import i64
def f() -> i64:
return 0
def g() -> i64:
return f()
[out]
def f():
L0:
return 0
def g():
r0 :: i64
r1 :: bit
r2 :: object
r3 :: i64
L0:
r0 = f()
r1 = r0 == -113
if r1 goto L2 else goto L1 :: bool
L1:
return r0
L2:
r2 = PyErr_Occurred()
if not is_error(r2) goto L3 (error at g:7) else goto L1
L3:
r3 = <error> :: i64
return r3
[case testExceptionWithNativeAttributeGetAndSet]
class C:
def __init__(self, x: int) -> None:
self.x = x
def foo(c: C, x: int) -> None:
c.x = x - c.x
[out]
def C.__init__(self, x):
self :: __main__.C
x :: int
L0:
inc_ref x :: int
self.x = x
return 1
def foo(c, x):
c :: __main__.C
x, r0, r1 :: int
r2 :: bool
L0:
r0 = borrow c.x
r1 = CPyTagged_Subtract(x, r0)
c.x = r1
return 1
[case testExceptionWithOverlappingFloatErrorValue]
def f() -> float:
return 0.0
def g() -> float:
return f()
[out]
def f():
L0:
return 0.0
def g():
r0 :: float
r1 :: bit
r2 :: object
r3 :: float
L0:
r0 = f()
r1 = r0 == -113.0
if r1 goto L2 else goto L1 :: bool
L1:
return r0
L2:
r2 = PyErr_Occurred()
if not is_error(r2) goto L3 (error at g:5) else goto L1
L3:
r3 = <error> :: float
return r3
[case testExceptionWithLowLevelIntAttribute]
from mypy_extensions import i32, i64
class C:
def __init__(self, x: i32, y: i64) -> None:
self.x = x
self.y = y
def f(c: C) -> None:
c.x
c.y
[out]
def C.__init__(self, x, y):
self :: __main__.C
x :: i32
y :: i64
L0:
self.x = x
self.y = y
return 1
def f(c):
c :: __main__.C
r0 :: i32
r1 :: i64
L0:
r0 = c.x
r1 = c.y
return 1
[case testConditionallyUndefinedI64]
from mypy_extensions import i64
def f(x: i64) -> i64:
if x:
y: i64 = 2
return y
[out]
def f(x):
x, r0, y :: i64
__locals_bitmap0 :: u32
r1 :: bit
r2, r3 :: u32
r4 :: bit
r5 :: bool
r6 :: i64
L0:
r0 = <error> :: i64
y = r0
__locals_bitmap0 = 0
r1 = x != 0
if r1 goto L1 else goto L2 :: bool
L1:
y = 2
r2 = __locals_bitmap0 | 1
__locals_bitmap0 = r2
L2:
r3 = __locals_bitmap0 & 1
r4 = r3 == 0
if r4 goto L3 else goto L5 :: bool
L3:
r5 = raise UnboundLocalError('local variable "y" referenced before assignment')
if not r5 goto L6 (error at f:-1) else goto L4 :: bool
L4:
unreachable
L5:
return y
L6:
r6 = <error> :: i64
return r6
[case testExceptionWithFloatAttribute]
class C:
def __init__(self, x: float, y: float) -> None:
self.x = x
if x:
self.y = y
def f(c: C) -> float:
return c.x + c.y
[out]
def C.__init__(self, x, y):
self :: __main__.C
x, y :: float
r0 :: bit
L0:
self.x = x
r0 = x != 0.0
if r0 goto L1 else goto L2 :: bool
L1:
self.y = y
L2:
return 1
def f(c):
c :: __main__.C
r0, r1 :: float
r2 :: bit
r3 :: float
r4 :: object
r5 :: float
L0:
r0 = c.x
r1 = c.y
r2 = r1 == -113.0
if r2 goto L2 else goto L1 :: bool
L1:
r3 = r0 + r1
return r3
L2:
r4 = PyErr_Occurred()
if not is_error(r4) goto L3 (error at f:8) else goto L1
L3:
r5 = <error> :: float
return r5

View File

@@ -0,0 +1,373 @@
# These builtins stubs are used implicitly in AST to IR generation
# test cases.
import _typeshed
from typing import (
TypeVar, Generic, List, Iterator, Iterable, Dict, Optional, Tuple, Any, Set,
overload, Mapping, Union, Callable, Sequence, FrozenSet, Protocol
)
T = TypeVar('T')
T_co = TypeVar('T_co', covariant=True)
T_contra = TypeVar('T_contra', contravariant=True)
S = TypeVar('S')
K = TypeVar('K') # for keys in mapping
V = TypeVar('V') # for values in mapping
class __SupportsAbs(Protocol[T_co]):
def __abs__(self) -> T_co: pass
class __SupportsDivMod(Protocol[T_contra, T_co]):
def __divmod__(self, other: T_contra) -> T_co: ...
class __SupportsRDivMod(Protocol[T_contra, T_co]):
def __rdivmod__(self, other: T_contra) -> T_co: ...
_M = TypeVar("_M", contravariant=True)
class __SupportsPow2(Protocol[T_contra, T_co]):
def __pow__(self, other: T_contra) -> T_co: ...
class __SupportsPow3NoneOnly(Protocol[T_contra, T_co]):
def __pow__(self, other: T_contra, modulo: None = ...) -> T_co: ...
class __SupportsPow3(Protocol[T_contra, _M, T_co]):
def __pow__(self, other: T_contra, modulo: _M) -> T_co: ...
__SupportsSomeKindOfPow = Union[
__SupportsPow2[Any, Any], __SupportsPow3NoneOnly[Any, Any] | __SupportsPow3[Any, Any, Any]
]
class object:
def __init__(self) -> None: pass
def __eq__(self, x: object) -> bool: pass
def __ne__(self, x: object) -> bool: pass
class type:
def __init__(self, o: object) -> None: ...
__name__ : str
__annotations__: Dict[str, Any]
class ellipsis: pass
# Primitive types are special in generated code.
class int:
@overload
def __init__(self) -> None: pass
@overload
def __init__(self, x: object, base: int = 10) -> None: pass
def __add__(self, n: int) -> int: pass
def __sub__(self, n: int) -> int: pass
def __mul__(self, n: int) -> int: pass
def __pow__(self, n: int, modulo: Optional[int] = None) -> int: pass
def __floordiv__(self, x: int) -> int: pass
def __truediv__(self, x: float) -> float: pass
def __mod__(self, x: int) -> int: pass
def __divmod__(self, x: float) -> Tuple[float, float]: pass
def __neg__(self) -> int: pass
def __pos__(self) -> int: pass
def __abs__(self) -> int: pass
def __invert__(self) -> int: pass
def __and__(self, n: int) -> int: pass
def __or__(self, n: int) -> int: pass
def __xor__(self, n: int) -> int: pass
def __lshift__(self, x: int) -> int: pass
def __rshift__(self, x: int) -> int: pass
def __eq__(self, n: object) -> bool: pass
def __ne__(self, n: object) -> bool: pass
def __lt__(self, n: int) -> bool: pass
def __gt__(self, n: int) -> bool: pass
def __le__(self, n: int) -> bool: pass
def __ge__(self, n: int) -> bool: pass
class str:
@overload
def __init__(self) -> None: pass
@overload
def __init__(self, x: object) -> None: pass
def __add__(self, x: str) -> str: pass
def __mul__(self, x: int) -> str: pass
def __rmul__(self, x: int) -> str: pass
def __eq__(self, x: object) -> bool: pass
def __ne__(self, x: object) -> bool: pass
def __lt__(self, x: str) -> bool: ...
def __le__(self, x: str) -> bool: ...
def __gt__(self, x: str) -> bool: ...
def __ge__(self, x: str) -> bool: ...
@overload
def __getitem__(self, i: int) -> str: pass
@overload
def __getitem__(self, i: slice) -> str: pass
def __contains__(self, item: str) -> bool: pass
def __iter__(self) -> Iterator[str]: ...
def split(self, sep: Optional[str] = None, max: Optional[int] = None) -> List[str]: pass
def strip (self, item: str) -> str: pass
def join(self, x: Iterable[str]) -> str: pass
def format(self, *args: Any, **kwargs: Any) -> str: ...
def upper(self) -> str: ...
def startswith(self, x: str, start: int=..., end: int=...) -> bool: ...
def endswith(self, x: str, start: int=..., end: int=...) -> bool: ...
def replace(self, old: str, new: str, maxcount: int=...) -> str: ...
def encode(self, x: str=..., y: str=...) -> bytes: ...
class float:
def __init__(self, x: object) -> None: pass
def __add__(self, n: float) -> float: pass
def __radd__(self, n: float) -> float: pass
def __sub__(self, n: float) -> float: pass
def __rsub__(self, n: float) -> float: pass
def __mul__(self, n: float) -> float: pass
def __truediv__(self, n: float) -> float: pass
def __floordiv__(self, n: float) -> float: pass
def __mod__(self, n: float) -> float: pass
def __pow__(self, n: float) -> float: pass
def __neg__(self) -> float: pass
def __pos__(self) -> float: pass
def __abs__(self) -> float: pass
def __invert__(self) -> float: pass
def __eq__(self, x: object) -> bool: pass
def __ne__(self, x: object) -> bool: pass
def __lt__(self, x: float) -> bool: ...
def __le__(self, x: float) -> bool: ...
def __gt__(self, x: float) -> bool: ...
def __ge__(self, x: float) -> bool: ...
class complex:
def __init__(self, x: object, y: object = None) -> None: pass
def __add__(self, n: complex) -> complex: pass
def __radd__(self, n: float) -> complex: pass
def __sub__(self, n: complex) -> complex: pass
def __rsub__(self, n: float) -> complex: pass
def __mul__(self, n: complex) -> complex: pass
def __truediv__(self, n: complex) -> complex: pass
def __neg__(self) -> complex: pass
class bytes:
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, x: object) -> None: ...
def __add__(self, x: bytes) -> bytes: ...
def __mul__(self, x: int) -> bytes: ...
def __rmul__(self, x: int) -> bytes: ...
def __eq__(self, x: object) -> bool: ...
def __ne__(self, x: object) -> bool: ...
@overload
def __getitem__(self, i: int) -> int: ...
@overload
def __getitem__(self, i: slice) -> bytes: ...
def join(self, x: Iterable[object]) -> bytes: ...
def decode(self, x: str=..., y: str=...) -> str: ...
class bytearray:
@overload
def __init__(self) -> None: pass
@overload
def __init__(self, x: object) -> None: pass
@overload
def __init__(self, string: str, encoding: str, err: str = ...) -> None: pass
def __add__(self, s: bytes) -> bytearray: ...
def __setitem__(self, i: int, o: int) -> None: ...
def __getitem__(self, i: int) -> int: ...
def decode(self, x: str = ..., y: str = ...) -> str: ...
class bool(int):
def __init__(self, o: object = ...) -> None: ...
@overload
def __and__(self, n: bool) -> bool: ...
@overload
def __and__(self, n: int) -> int: ...
@overload
def __or__(self, n: bool) -> bool: ...
@overload
def __or__(self, n: int) -> int: ...
@overload
def __xor__(self, n: bool) -> bool: ...
@overload
def __xor__(self, n: int) -> int: ...
class tuple(Generic[T_co], Sequence[T_co], Iterable[T_co]):
def __init__(self, i: Iterable[T_co]) -> None: pass
@overload
def __getitem__(self, i: int) -> T_co: pass
@overload
def __getitem__(self, i: slice) -> Tuple[T_co, ...]: pass
def __len__(self) -> int: pass
def __iter__(self) -> Iterator[T_co]: ...
def __contains__(self, item: object) -> int: ...
class function: pass
class list(Generic[T], Sequence[T], Iterable[T]):
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
@overload
def __getitem__(self, i: int) -> T: ...
@overload
def __getitem__(self, s: slice) -> List[T]: ...
def __setitem__(self, i: int, o: T) -> None: pass
def __delitem__(self, i: int) -> None: pass
def __mul__(self, i: int) -> List[T]: pass
def __rmul__(self, i: int) -> List[T]: pass
def __iter__(self) -> Iterator[T]: pass
def __len__(self) -> int: pass
def __contains__(self, item: object) -> int: ...
def __add__(self, x: List[T]) -> List[T]: ...
def append(self, x: T) -> None: pass
def pop(self, i: int = -1) -> T: pass
def count(self, T) -> int: pass
def extend(self, l: Iterable[T]) -> None: pass
def insert(self, i: int, x: T) -> None: pass
def sort(self) -> None: pass
def reverse(self) -> None: pass
def remove(self, o: T) -> None: pass
def index(self, o: T) -> int: pass
class dict(Mapping[K, V]):
@overload
def __init__(self, **kwargs: K) -> None: ...
@overload
def __init__(self, map: Mapping[K, V], **kwargs: V) -> None: ...
@overload
def __init__(self, iterable: Iterable[Tuple[K, V]], **kwargs: V) -> None: ...
def __getitem__(self, key: K) -> V: pass
def __setitem__(self, k: K, v: V) -> None: pass
def __delitem__(self, k: K) -> None: pass
def __contains__(self, item: object) -> int: pass
def __iter__(self) -> Iterator[K]: pass
def __len__(self) -> int: pass
@overload
def update(self, __m: Mapping[K, V], **kwargs: V) -> None: pass
@overload
def update(self, __m: Iterable[Tuple[K, V]], **kwargs: V) -> None: ...
@overload
def update(self, **kwargs: V) -> None: ...
def pop(self, x: int) -> K: pass
def keys(self) -> Iterable[K]: pass
def values(self) -> Iterable[V]: pass
def items(self) -> Iterable[Tuple[K, V]]: pass
def clear(self) -> None: pass
def copy(self) -> Dict[K, V]: pass
def setdefault(self, key: K, val: V = ...) -> V: pass
class set(Generic[T]):
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
def __iter__(self) -> Iterator[T]: pass
def __len__(self) -> int: pass
def add(self, x: T) -> None: pass
def remove(self, x: T) -> None: pass
def discard(self, x: T) -> None: pass
def clear(self) -> None: pass
def pop(self) -> T: pass
def update(self, x: Iterable[S]) -> None: pass
def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> Set[Union[T, S]]: ...
def __xor__(self, s: Union[Set[S], FrozenSet[S]]) -> Set[Union[T, S]]: ...
class frozenset(Generic[T]):
def __init__(self, i: Optional[Iterable[T]] = None) -> None: pass
def __iter__(self) -> Iterator[T]: pass
def __len__(self) -> int: pass
def __or__(self, s: Union[Set[S], FrozenSet[S]]) -> FrozenSet[Union[T, S]]: ...
def __xor__(self, s: Union[Set[S], FrozenSet[S]]) -> FrozenSet[Union[T, S]]: ...
class slice: pass
class range(Iterable[int]):
def __init__(self, x: int, y: int = ..., z: int = ...) -> None: pass
def __iter__(self) -> Iterator[int]: pass
def __len__(self) -> int: pass
def __next__(self) -> int: pass
class property:
def __init__(self, fget: Optional[Callable[[Any], Any]] = ...,
fset: Optional[Callable[[Any, Any], None]] = ...,
fdel: Optional[Callable[[Any], None]] = ...,
doc: Optional[str] = ...) -> None: ...
def getter(self, fget: Callable[[Any], Any]) -> property: ...
def setter(self, fset: Callable[[Any, Any], None]) -> property: ...
def deleter(self, fdel: Callable[[Any], None]) -> property: ...
def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ...
def __set__(self, obj: Any, value: Any) -> None: ...
def __delete__(self, obj: Any) -> None: ...
def fget(self) -> Any: ...
def fset(self, value: Any) -> None: ...
def fdel(self) -> None: ...
class BaseException: pass
class Exception(BaseException):
def __init__(self, message: Optional[str] = None) -> None: pass
class Warning(Exception): pass
class UserWarning(Warning): pass
class TypeError(Exception): pass
class ValueError(Exception): pass
class AttributeError(Exception): pass
class ImportError(Exception): pass
class NameError(Exception): pass
class UnboundLocalError(NameError): pass
class LookupError(Exception): pass
class KeyError(LookupError): pass
class IndexError(LookupError): pass
class RuntimeError(Exception): pass
class UnicodeEncodeError(RuntimeError): pass
class UnicodeDecodeError(RuntimeError): pass
class NotImplementedError(RuntimeError): pass
class StopIteration(Exception):
value: Any
class ArithmeticError(Exception): pass
class ZeroDivisionError(ArithmeticError): pass
class OverflowError(ArithmeticError): pass
class GeneratorExit(BaseException): pass
def any(i: Iterable[T]) -> bool: pass
def all(i: Iterable[T]) -> bool: pass
def sum(i: Iterable[T]) -> int: pass
def reversed(object: Sequence[T]) -> Iterator[T]: ...
def id(o: object) -> int: pass
# This type is obviously wrong but the test stubs don't have Sized anymore
def len(o: object) -> int: pass
def print(*object) -> None: pass
def isinstance(x: object, t: object) -> bool: pass
def iter(i: Iterable[T]) -> Iterator[T]: pass
@overload
def next(i: Iterator[T]) -> T: pass
@overload
def next(i: Iterator[T], default: T) -> T: pass
def hash(o: object) -> int: ...
def globals() -> Dict[str, Any]: ...
def getattr(obj: object, name: str, default: Any = None) -> Any: ...
def setattr(obj: object, name: str, value: Any) -> None: ...
def enumerate(x: Iterable[T]) -> Iterator[Tuple[int, T]]: ...
@overload
def zip(x: Iterable[T], y: Iterable[S]) -> Iterator[Tuple[T, S]]: ...
@overload
def zip(x: Iterable[T], y: Iterable[S], z: Iterable[V]) -> Iterator[Tuple[T, S, V]]: ...
def eval(e: str) -> Any: ...
def abs(x: __SupportsAbs[T]) -> T: ...
@overload
def divmod(x: __SupportsDivMod[T_contra, T_co], y: T_contra) -> T_co: ...
@overload
def divmod(x: T_contra, y: __SupportsRDivMod[T_contra, T_co]) -> T_co: ...
@overload
def pow(base: __SupportsPow2[T_contra, T_co], exp: T_contra, mod: None = None) -> T_co: ...
@overload
def pow(base: __SupportsPow3NoneOnly[T_contra, T_co], exp: T_contra, mod: None = None) -> T_co: ...
@overload
def pow(base: __SupportsPow3[T_contra, _M, T_co], exp: T_contra, mod: _M) -> T_co: ...
def exit() -> None: ...
def min(x: T, y: T) -> T: ...
def max(x: T, y: T) -> T: ...
def repr(o: object) -> str: ...
def ascii(o: object) -> str: ...
def ord(o: object) -> int: ...
def chr(i: int) -> str: ...
# Dummy definitions.
class classmethod: pass
class staticmethod: pass
NotImplemented: Any = ...

View File

@@ -0,0 +1,103 @@
# Simple support library for our run tests.
from contextlib import contextmanager
from collections.abc import Iterator
import math
from typing import (
Any, Iterator, TypeVar, Generator, Optional, List, Tuple, Sequence,
Union, Callable, Awaitable,
)
from typing import Final
FLOAT_MAGIC: Final = -113.0
# Various different float values
float_vals = [
float(n) * 0.25 for n in range(-10, 10)
] + [
-0.0,
1.0/3.0,
math.sqrt(2.0),
1.23e200,
-2.34e200,
5.43e-100,
-6.532e-200,
float('inf'),
-float('inf'),
float('nan'),
FLOAT_MAGIC,
math.pi,
2.0 * math.pi,
math.pi / 2.0,
-math.pi / 2.0,
-1.7976931348623158e+308, # Smallest finite value
-2.2250738585072014e-308, # Closest to zero negative normal value
-7.5491e-312, # Arbitrary negative subnormal value
-5e-324, # Closest to zero negative subnormal value
1.7976931348623158e+308, # Largest finite value
2.2250738585072014e-308, # Closest to zero positive normal value
-6.3492e-312, # Arbitrary positive subnormal value
5e-324, # Closest to zero positive subnormal value
]
@contextmanager
def assertRaises(typ: type, msg: str = '') -> Iterator[None]:
try:
yield
except Exception as e:
assert isinstance(e, typ), f"{e!r} is not a {typ.__name__}"
assert msg in str(e), f'Message "{e}" does not match "{msg}"'
else:
assert False, f"Expected {typ.__name__} but got no exception"
def assertDomainError() -> Any:
return assertRaises(ValueError, "math domain error")
def assertMathRangeError() -> Any:
return assertRaises(OverflowError, "math range error")
T = TypeVar('T')
U = TypeVar('U')
V = TypeVar('V')
def run_generator(gen: Generator[T, V, U],
inputs: Optional[List[V]] = None,
p: bool = False) -> Tuple[Sequence[T], Union[U, str]]:
res: List[T] = []
i = -1
while True:
try:
if i >= 0 and inputs:
# ... fixtures don't have send
val = gen.send(inputs[i]) # type: ignore
elif not hasattr(gen, '__next__'): # type: ignore
val = gen.send(None) # type: ignore
else:
val = next(gen)
except StopIteration as e:
return (tuple(res), e.value)
except Exception as e:
return (tuple(res), str(e))
if p:
print(val)
res.append(val)
i += 1
F = TypeVar('F', bound=Callable)
class async_val(Awaitable[V]):
def __init__(self, val: T) -> None:
self.val = val
def __await__(self) -> Generator[T, V, V]:
z = yield self.val
return z
# Wrap a mypyc-generated function in a real python function, to allow it to be
# stuck into classes and the like.
def make_python_function(f: F) -> F:
def g(*args: Any, **kwargs: Any) -> Any:
return f(*args, **kwargs)
return g # type: ignore

View File

@@ -0,0 +1,169 @@
# More complete stub for typing module.
#
# Use [typing fixtures/typing-full.pyi] to use this instead of lib-stub/typing.pyi
# in a particular test case.
#
# Many of the definitions have special handling in the type checker, so they
# can just be initialized to anything.
from abc import abstractmethod, ABCMeta
class GenericMeta(type): pass
cast = 0
overload = 0
Any = 0
Union = 0
Optional = 0
TypeVar = 0
Generic = 0
Protocol = 0
Tuple = 0
Callable = 0
_promote = 0
NamedTuple = 0
Type = 0
no_type_check = 0
ClassVar = 0
Final = 0
Literal = 0
TypedDict = 0
NoReturn = 0
NewType = 0
T = TypeVar('T')
T_co = TypeVar('T_co', covariant=True)
T_contra = TypeVar('T_contra', contravariant=True)
U = TypeVar('U')
V = TypeVar('V')
S = TypeVar('S')
# Note: definitions below are different from typeshed, variances are declared
# to silence the protocol variance checks. Maybe it is better to use type: ignore?
@runtime_checkable
class Container(Protocol[T_co]):
@abstractmethod
# Use int because bool isn't in the default test builtins
def __contains__(self, arg: object) -> int: pass
@runtime_checkable
class Sized(Protocol):
@abstractmethod
def __len__(self) -> int: pass
@runtime_checkable
class Iterable(Protocol[T_co]):
@abstractmethod
def __iter__(self) -> 'Iterator[T_co]': pass
@runtime_checkable
class Iterator(Iterable[T_co], Protocol):
@abstractmethod
def __next__(self) -> T_co: pass
class Generator(Iterator[T], Generic[T, U, V]):
@abstractmethod
def send(self, value: U) -> T: pass
@abstractmethod
def throw(self, typ: Any, val: Any=None, tb: Any=None) -> None: pass
@abstractmethod
def close(self) -> None: pass
@abstractmethod
def __iter__(self) -> 'Generator[T, U, V]': pass
class AsyncGenerator(AsyncIterator[T], Generic[T, U]):
@abstractmethod
def __anext__(self) -> Awaitable[T]: pass
@abstractmethod
def asend(self, value: U) -> Awaitable[T]: pass
@abstractmethod
def athrow(self, typ: Any, val: Any=None, tb: Any=None) -> Awaitable[T]: pass
@abstractmethod
def aclose(self) -> Awaitable[T]: pass
@abstractmethod
def __aiter__(self) -> 'AsyncGenerator[T, U]': pass
@runtime_checkable
class Awaitable(Protocol[T]):
@abstractmethod
def __await__(self) -> Generator[Any, Any, T]: pass
class AwaitableGenerator(Generator[T, U, V], Awaitable[V], Generic[T, U, V, S], metaclass=ABCMeta):
pass
class Coroutine(Awaitable[V], Generic[T, U, V]):
@abstractmethod
def send(self, value: U) -> T: pass
@abstractmethod
def throw(self, typ: Any, val: Any=None, tb: Any=None) -> None: pass
@abstractmethod
def close(self) -> None: pass
@runtime_checkable
class AsyncIterable(Protocol[T]):
@abstractmethod
def __aiter__(self) -> 'AsyncIterator[T]': pass
@runtime_checkable
class AsyncIterator(AsyncIterable[T], Protocol):
def __aiter__(self) -> 'AsyncIterator[T]': return self
@abstractmethod
def __anext__(self) -> Awaitable[T]: pass
class Sequence(Iterable[T_co], Container[T_co]):
@abstractmethod
def __getitem__(self, n: Any) -> T_co: pass
class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta):
def keys(self) -> Iterable[T]: pass # Approximate return type
def __getitem__(self, key: T) -> T_co: pass
@overload
def get(self, k: T) -> Optional[T_co]: pass
@overload
def get(self, k: T, default: Union[T_co, V]) -> Union[T_co, V]: pass
def values(self) -> Iterable[T_co]: pass # Approximate return type
def items(self) -> Iterable[Tuple[T, T_co]]: pass # Approximate return type
def __len__(self) -> int: ...
def __contains__(self, arg: object) -> int: pass
class MutableMapping(Mapping[T, U], metaclass=ABCMeta):
def __setitem__(self, k: T, v: U) -> None: pass
class SupportsInt(Protocol):
def __int__(self) -> int: pass
class SupportsFloat(Protocol):
def __float__(self) -> float: pass
def runtime_checkable(cls: T) -> T:
return cls
class ContextManager(Generic[T]):
def __enter__(self) -> T: pass
# Use Any because not all the precise types are in the fixtures.
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any: pass
TYPE_CHECKING = 1
# Fallback type for all typed dicts (does not exist at runtime).
class _TypedDict(Mapping[str, object]):
# Needed to make this class non-abstract. It is explicitly declared abstract in
# typeshed, but we don't want to import abc here, as it would slow down the tests.
def __iter__(self) -> Iterator[str]: ...
def copy(self: T) -> T: ...
# Using NoReturn so that only calls using the plugin hook can go through.
def setdefault(self, k: NoReturn, default: object) -> object: ...
# Mypy expects that 'default' has a type variable type.
def pop(self, k: NoReturn, default: T = ...) -> object: ...
def update(self: T, __m: T) -> None: ...
def __delitem__(self, k: NoReturn) -> None: ...

View File

@@ -0,0 +1,238 @@
-- Generate ops related to Any types
[case testCoerceAnyInCallsAndReturn]
from typing import Any
def f(x: Any) -> Any:
return g(x)
def g(x: int) -> int:
return f(x)
[out]
def f(x):
x :: object
r0, r1 :: int
r2 :: object
L0:
r0 = unbox(int, x)
r1 = g(r0)
r2 = box(int, r1)
return r2
def g(x):
x :: int
r0, r1 :: object
r2 :: int
L0:
r0 = box(int, x)
r1 = f(r0)
r2 = unbox(int, r1)
return r2
[case testCoerceAnyInAssignment]
from typing import Any, Tuple
class C:
a: Any
n: int
def f(a: Any, n: int, c: C) -> None:
c.a = n
c.n = a
a = n
n = a
a.a = n
[out]
def f(a, n, c):
a :: object
n :: int
c :: __main__.C
r0 :: object
r1 :: bool
r2 :: int
r3 :: bool
r4 :: object
r5 :: int
r6 :: str
r7 :: object
r8 :: i32
r9 :: bit
L0:
r0 = box(int, n)
c.a = r0; r1 = is_error
r2 = unbox(int, a)
c.n = r2; r3 = is_error
r4 = box(int, n)
a = r4
r5 = unbox(int, a)
n = r5
r6 = 'a'
r7 = box(int, n)
r8 = PyObject_SetAttr(a, r6, r7)
r9 = r8 >= 0 :: signed
return 1
[case testCoerceAnyInOps]
from typing import Any, List
def f1(a: Any, n: int) -> None:
a + n
n + a
def f2(a: Any, n: int, l: List[int]) -> None:
a[n]
l[a]
a[n] = n
l[a] = n
l[n] = a
[a, n]
def f3(a: Any, n: int) -> None:
a += n
n += a
[out]
def f1(a, n):
a :: object
n :: int
r0, r1, r2, r3 :: object
L0:
r0 = box(int, n)
r1 = PyNumber_Add(a, r0)
r2 = box(int, n)
r3 = PyNumber_Add(r2, a)
return 1
def f2(a, n, l):
a :: object
n :: int
l :: list
r0, r1, r2, r3, r4 :: object
r5 :: i32
r6 :: bit
r7 :: object
r8 :: i32
r9, r10 :: bit
r11 :: list
r12 :: object
r13, r14, r15 :: ptr
L0:
r0 = box(int, n)
r1 = PyObject_GetItem(a, r0)
r2 = PyObject_GetItem(l, a)
r3 = box(int, n)
r4 = box(int, n)
r5 = PyObject_SetItem(a, r3, r4)
r6 = r5 >= 0 :: signed
r7 = box(int, n)
r8 = PyObject_SetItem(l, a, r7)
r9 = r8 >= 0 :: signed
r10 = CPyList_SetItem(l, n, a)
r11 = PyList_New(2)
r12 = box(int, n)
r13 = get_element_ptr r11 ob_item :: PyListObject
r14 = load_mem r13 :: ptr*
set_mem r14, a :: builtins.object*
r15 = r14 + WORD_SIZE*1
set_mem r15, r12 :: builtins.object*
keep_alive r11
return 1
def f3(a, n):
a :: object
n :: int
r0, r1, r2, r3 :: object
r4 :: int
L0:
r0 = box(int, n)
r1 = PyNumber_InPlaceAdd(a, r0)
a = r1
r2 = box(int, n)
r3 = PyNumber_InPlaceAdd(r2, a)
r4 = unbox(int, r3)
n = r4
return 1
[case testCoerceAnyInConditionalExpr]
from typing import Any
def f4(a: Any, n: int, b: bool) -> None:
a = a if b else n
n = n if b else a
[out]
def f4(a, n, b):
a :: object
n :: int
b :: bool
r0, r1, r2, r3 :: object
r4 :: int
L0:
if b goto L1 else goto L2 :: bool
L1:
r0 = a
goto L3
L2:
r1 = box(int, n)
r0 = r1
L3:
a = r0
if b goto L4 else goto L5 :: bool
L4:
r2 = box(int, n)
r3 = r2
goto L6
L5:
r3 = a
L6:
r4 = unbox(int, r3)
n = r4
return 1
[case testAbsSpecialization]
# Specialization of native classes that implement __abs__ is checked in
# irbuild-dunders.test
def f() -> None:
a = abs(1)
b = abs(1.1)
[out]
def f():
r0, r1 :: object
r2, a :: int
r3, b :: float
L0:
r0 = object 1
r1 = PyNumber_Absolute(r0)
r2 = unbox(int, r1)
a = r2
r3 = fabs(1.1)
b = r3
return 1
[case testFunctionBasedOps]
def f() -> None:
a = divmod(5, 2)
def f2() -> int:
return pow(2, 5)
def f3() -> float:
return pow(2, 5, 3)
[out]
def f():
r0, r1, r2 :: object
r3, a :: tuple[float, float]
L0:
r0 = object 5
r1 = object 2
r2 = PyNumber_Divmod(r0, r1)
r3 = unbox(tuple[float, float], r2)
a = r3
return 1
def f2():
r0, r1, r2 :: object
r3 :: int
L0:
r0 = object 2
r1 = object 5
r2 = CPyNumber_Power(r0, r1)
r3 = unbox(int, r2)
return r3
def f3():
r0, r1, r2, r3 :: object
r4 :: int
r5 :: float
L0:
r0 = object 2
r1 = object 5
r2 = object 3
r3 = PyNumber_Power(r0, r1, r2)
r4 = unbox(int, r3)
r5 = CPyFloat_FromTagged(r4)
return r5

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,463 @@
[case testBoolToAndFromInt]
from mypy_extensions import i64
def bool_to_int(b: bool) -> int:
return b
def int_to_bool(n: int) -> bool:
return bool(n)
def bool_to_i64(b: bool) -> i64:
return b
def i64_to_bool(n: i64) -> bool:
return bool(n)
def bit_to_int(n1: i64, n2: i64) -> int:
return bool(n1 == n2)
def bit_to_i64(n1: i64, n2: i64) -> i64:
return bool(n1 == n2)
[out]
def bool_to_int(b):
b, r0 :: bool
r1 :: int
L0:
r0 = b << 1
r1 = extend r0: builtins.bool to builtins.int
return r1
def int_to_bool(n):
n :: int
r0 :: bit
L0:
r0 = n != 0
return r0
def bool_to_i64(b):
b :: bool
r0 :: i64
L0:
r0 = extend b: builtins.bool to i64
return r0
def i64_to_bool(n):
n :: i64
r0 :: bit
L0:
r0 = n != 0
return r0
def bit_to_int(n1, n2):
n1, n2 :: i64
r0 :: bit
r1 :: bool
r2 :: int
L0:
r0 = n1 == n2
r1 = r0 << 1
r2 = extend r1: builtins.bool to builtins.int
return r2
def bit_to_i64(n1, n2):
n1, n2 :: i64
r0 :: bit
r1 :: i64
L0:
r0 = n1 == n2
r1 = extend r0: bit to i64
return r1
[case testConversionToBool]
from typing import List, Optional
class C: pass
class D:
def __bool__(self) -> bool:
return True
def list_to_bool(l: List[str]) -> bool:
return bool(l)
def always_truthy_instance_to_bool(o: C) -> bool:
return bool(o)
def instance_to_bool(o: D) -> bool:
return bool(o)
def optional_truthy_to_bool(o: Optional[C]) -> bool:
return bool(o)
def optional_maybe_falsey_to_bool(o: Optional[D]) -> bool:
return bool(o)
[out]
def D.__bool__(self):
self :: __main__.D
L0:
return 1
def list_to_bool(l):
l :: list
r0 :: ptr
r1 :: native_int
r2 :: short_int
r3 :: bit
L0:
r0 = get_element_ptr l ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive l
r2 = r1 << 1
r3 = r2 != 0
return r3
def always_truthy_instance_to_bool(o):
o :: __main__.C
r0 :: i32
r1 :: bit
r2 :: bool
L0:
r0 = PyObject_IsTrue(o)
r1 = r0 >= 0 :: signed
r2 = truncate r0: i32 to builtins.bool
return r2
def instance_to_bool(o):
o :: __main__.D
r0 :: bool
L0:
r0 = o.__bool__()
return r0
def optional_truthy_to_bool(o):
o :: union[__main__.C, None]
r0 :: object
r1 :: bit
L0:
r0 = load_address _Py_NoneStruct
r1 = o != r0
return r1
def optional_maybe_falsey_to_bool(o):
o :: union[__main__.D, None]
r0 :: object
r1 :: bit
r2 :: __main__.D
r3 :: bool
r4 :: bit
L0:
r0 = load_address _Py_NoneStruct
r1 = o != r0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = cast(__main__.D, o)
r3 = r2.__bool__()
r4 = r3
goto L3
L2:
r4 = 0
L3:
return r4
[case testBoolComparisons]
def eq(x: bool, y: bool) -> bool:
return x == y
def neq(x: bool, y: bool) -> bool:
return x != y
def lt(x: bool, y: bool) -> bool:
return x < y
def le(x: bool, y: bool) -> bool:
return x <= y
def gt(x: bool, y: bool) -> bool:
return x > y
def ge(x: bool, y: bool) -> bool:
return x >= y
[out]
def eq(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x == y
return r0
def neq(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x != y
return r0
def lt(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x < y :: signed
return r0
def le(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x <= y :: signed
return r0
def gt(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x > y :: signed
return r0
def ge(x, y):
x, y :: bool
r0 :: bit
L0:
r0 = x >= y :: signed
return r0
[case testBoolMixedComparisons1]
from mypy_extensions import i64
def eq1(x: int, y: bool) -> bool:
return x == y
def eq2(x: bool, y: int) -> bool:
return x == y
def neq1(x: i64, y: bool) -> bool:
return x != y
def neq2(x: bool, y: i64) -> bool:
return x != y
[out]
def eq1(x, y):
x :: int
y, r0 :: bool
r1 :: int
r2 :: bit
L0:
r0 = y << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = x == r1
return r2
def eq2(x, y):
x :: bool
y :: int
r0 :: bool
r1 :: int
r2 :: bit
L0:
r0 = x << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = r1 == y
return r2
def neq1(x, y):
x :: i64
y :: bool
r0 :: i64
r1 :: bit
L0:
r0 = extend y: builtins.bool to i64
r1 = x != r0
return r1
def neq2(x, y):
x :: bool
y, r0 :: i64
r1 :: bit
L0:
r0 = extend x: builtins.bool to i64
r1 = r0 != y
return r1
[case testBoolMixedComparisons2]
from mypy_extensions import i64
def lt1(x: bool, y: int) -> bool:
return x < y
def lt2(x: int, y: bool) -> bool:
return x < y
def gt1(x: bool, y: i64) -> bool:
return x < y
def gt2(x: i64, y: bool) -> bool:
return x < y
[out]
def lt1(x, y):
x :: bool
y :: int
r0 :: bool
r1 :: short_int
r2 :: native_int
r3 :: bit
r4 :: native_int
r5, r6, r7 :: bit
r8 :: bool
r9 :: bit
L0:
r0 = x << 1
r1 = extend r0: builtins.bool to short_int
r2 = r1 & 1
r3 = r2 == 0
r4 = y & 1
r5 = r4 == 0
r6 = r3 & r5
if r6 goto L1 else goto L2 :: bool
L1:
r7 = r1 < y :: signed
r8 = r7
goto L3
L2:
r9 = CPyTagged_IsLt_(r1, y)
r8 = r9
L3:
return r8
def lt2(x, y):
x :: int
y, r0 :: bool
r1 :: short_int
r2 :: native_int
r3 :: bit
r4 :: native_int
r5, r6, r7 :: bit
r8 :: bool
r9 :: bit
L0:
r0 = y << 1
r1 = extend r0: builtins.bool to short_int
r2 = x & 1
r3 = r2 == 0
r4 = r1 & 1
r5 = r4 == 0
r6 = r3 & r5
if r6 goto L1 else goto L2 :: bool
L1:
r7 = x < r1 :: signed
r8 = r7
goto L3
L2:
r9 = CPyTagged_IsLt_(x, r1)
r8 = r9
L3:
return r8
def gt1(x, y):
x :: bool
y, r0 :: i64
r1 :: bit
L0:
r0 = extend x: builtins.bool to i64
r1 = r0 < y :: signed
return r1
def gt2(x, y):
x :: i64
y :: bool
r0 :: i64
r1 :: bit
L0:
r0 = extend y: builtins.bool to i64
r1 = x < r0 :: signed
return r1
[case testBoolBitwise]
from mypy_extensions import i64
def bitand(x: bool, y: bool) -> bool:
b = x & y
return b
def bitor(x: bool, y: bool) -> bool:
b = x | y
return b
def bitxor(x: bool, y: bool) -> bool:
b = x ^ y
return b
def invert(x: bool) -> int:
return ~x
def mixed_bitand(x: i64, y: bool) -> i64:
return x & y
[out]
def bitand(x, y):
x, y, r0, b :: bool
L0:
r0 = x & y
b = r0
return b
def bitor(x, y):
x, y, r0, b :: bool
L0:
r0 = x | y
b = r0
return b
def bitxor(x, y):
x, y, r0, b :: bool
L0:
r0 = x ^ y
b = r0
return b
def invert(x):
x, r0 :: bool
r1, r2 :: int
L0:
r0 = x << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = CPyTagged_Invert(r1)
return r2
def mixed_bitand(x, y):
x :: i64
y :: bool
r0, r1 :: i64
L0:
r0 = extend y: builtins.bool to i64
r1 = x & r0
return r1
[case testBoolArithmetic]
def add(x: bool, y: bool) -> int:
z = x + y
return z
def mixed(b: bool, n: int) -> int:
z = b + n
z -= b
z = z * b
return z
def negate(b: bool) -> int:
return -b
def unary_plus(b: bool) -> int:
x = +b
return x
[out]
def add(x, y):
x, y, r0 :: bool
r1 :: int
r2 :: bool
r3, r4, z :: int
L0:
r0 = x << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = y << 1
r3 = extend r2: builtins.bool to builtins.int
r4 = CPyTagged_Add(r1, r3)
z = r4
return z
def mixed(b, n):
b :: bool
n :: int
r0 :: bool
r1, r2, z :: int
r3 :: bool
r4, r5 :: int
r6 :: bool
r7, r8 :: int
L0:
r0 = b << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = CPyTagged_Add(r1, n)
z = r2
r3 = b << 1
r4 = extend r3: builtins.bool to builtins.int
r5 = CPyTagged_Subtract(z, r4)
z = r5
r6 = b << 1
r7 = extend r6: builtins.bool to builtins.int
r8 = CPyTagged_Multiply(z, r7)
z = r8
return z
def negate(b):
b, r0 :: bool
r1, r2 :: int
L0:
r0 = b << 1
r1 = extend r0: builtins.bool to builtins.int
r2 = CPyTagged_Negate(r1)
return r2
def unary_plus(b):
b, r0 :: bool
r1, x :: int
L0:
r0 = b << 1
r1 = extend r0: builtins.bool to builtins.int
x = r1
return x

View File

@@ -0,0 +1,184 @@
[case testBytesBasics]
def f(num: int, l: list, d: dict, s: str) -> None:
b1 = bytes()
b2 = bytes(num)
b3 = bytes(l)
b4 = bytes(d)
b5 = bytes(s)
[out]
def f(num, l, d, s):
num :: int
l :: list
d :: dict
s :: str
r0, r1 :: object
r2, b1 :: bytes
r3, r4, r5 :: object
r6, b2, r7, b3, r8, b4, r9, b5 :: bytes
L0:
r0 = load_address PyBytes_Type
r1 = PyObject_CallFunctionObjArgs(r0, 0)
r2 = cast(bytes, r1)
b1 = r2
r3 = load_address PyBytes_Type
r4 = box(int, num)
r5 = PyObject_CallFunctionObjArgs(r3, r4, 0)
r6 = cast(bytes, r5)
b2 = r6
r7 = PyBytes_FromObject(l)
b3 = r7
r8 = PyBytes_FromObject(d)
b4 = r8
r9 = PyBytes_FromObject(s)
b5 = r9
return 1
[case testBytearrayBasics]
def f(s: str, num: int) -> None:
a = bytearray()
b = bytearray(s)
c = bytearray(num)
[out]
def f(s, num):
s :: str
num :: int
r0 :: object
r1 :: str
r2, r3, a :: object
r4 :: bytes
b, r5 :: object
r6 :: bytes
c :: object
L0:
r0 = builtins :: module
r1 = 'bytearray'
r2 = CPyObject_GetAttr(r0, r1)
r3 = PyObject_CallFunctionObjArgs(r2, 0)
a = r3
r4 = PyByteArray_FromObject(s)
b = r4
r5 = box(int, num)
r6 = PyByteArray_FromObject(r5)
c = r6
return 1
[case testBytesEquality]
def eq(x: bytes, y: bytes) -> bool:
return x == y
def neq(x: bytes, y: bytes) -> bool:
return x != y
[out]
def eq(x, y):
x, y :: bytes
r0 :: i32
r1, r2 :: bit
L0:
r0 = CPyBytes_Compare(x, y)
r1 = r0 >= 0 :: signed
r2 = r0 == 1
return r2
def neq(x, y):
x, y :: bytes
r0 :: i32
r1, r2 :: bit
L0:
r0 = CPyBytes_Compare(x, y)
r1 = r0 >= 0 :: signed
r2 = r0 != 1
return r2
[case testBytesSlicing]
def f(a: bytes, start: int, end: int) -> bytes:
return a[start:end]
[out]
def f(a, start, end):
a :: bytes
start, end :: int
r0 :: bytes
L0:
r0 = CPyBytes_GetSlice(a, start, end)
return r0
[case testBytesIndex]
def f(a: bytes, i: int) -> int:
return a[i]
[out]
def f(a, i):
a :: bytes
i, r0 :: int
L0:
r0 = CPyBytes_GetItem(a, i)
return r0
[case testBytesConcat]
def f(a: bytes, b: bytes) -> bytes:
return a + b
[out]
def f(a, b):
a, b, r0 :: bytes
L0:
r0 = CPyBytes_Concat(a, b)
return r0
[case testBytesJoin]
from typing import List
def f(b: List[bytes]) -> bytes:
return b" ".join(b)
[out]
def f(b):
b :: list
r0, r1 :: bytes
L0:
r0 = b' '
r1 = CPyBytes_Join(r0, b)
return r1
[case testBytesLen]
def f(b: bytes) -> int:
return len(b)
[out]
def f(b):
b :: bytes
r0 :: ptr
r1 :: native_int
r2 :: short_int
L0:
r0 = get_element_ptr b ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive b
r2 = r1 << 1
return r2
[case testBytesFormatting]
def f(var: bytes, num: int) -> None:
b1 = b'aaaa%bbbbb%s' % (var, var)
b2 = b'aaaa%bbbbb%s%d' % (var, var, num)
b3 = b'%b' % var
b4 = b'%ssss' % var
[typing fixtures/typing-full.pyi]
[out]
def f(var, num):
var :: bytes
num :: int
r0, r1, r2, b1, r3 :: bytes
r4 :: tuple[bytes, bytes, int]
r5, r6 :: object
r7, b2, r8, b3, r9, r10, b4 :: bytes
L0:
r0 = b'aaaa'
r1 = b'bbbb'
r2 = CPyBytes_Build(4, r0, var, r1, var)
b1 = r2
r3 = b'aaaa%bbbbb%s%d'
r4 = (var, var, num)
r5 = box(tuple[bytes, bytes, int], r4)
r6 = PyNumber_Remainder(r3, r5)
r7 = cast(bytes, r6)
b2 = r7
r8 = CPyBytes_Build(1, var)
b3 = r8
r9 = b'sss'
r10 = CPyBytes_Build(2, var, r9)
b4 = r10
return 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,480 @@
[case testIntConstantFolding]
def bin_ops() -> None:
add = 15 + 47
add_mul = (2 + 3) * 5
sub = 7 - 11
div = 3 / 2
bit_and = 6 & 10
bit_or = 6 | 10
bit_xor = 6 ^ 10
lshift = 5 << 2
rshift = 13 >> 2
lshift0 = 5 << 0
rshift0 = 13 >> 0
def unary_ops() -> None:
neg1 = -5
neg2 = --1
neg3 = -0
pos = +5
inverted1 = ~0
inverted2 = ~5
inverted3 = ~3
def pow() -> None:
p0 = 3**0
p1 = 3**5
p2 = (-5)**3
p3 = 0**0
[out]
def bin_ops():
add, add_mul, sub :: int
div :: float
bit_and, bit_or, bit_xor, lshift, rshift, lshift0, rshift0 :: int
L0:
add = 124
add_mul = 50
sub = -8
div = 1.5
bit_and = 4
bit_or = 28
bit_xor = 24
lshift = 40
rshift = 6
lshift0 = 10
rshift0 = 26
return 1
def unary_ops():
neg1, neg2, neg3, pos, inverted1, inverted2, inverted3 :: int
L0:
neg1 = -10
neg2 = 2
neg3 = 0
pos = 10
inverted1 = -2
inverted2 = -12
inverted3 = -8
return 1
def pow():
p0, p1, p2, p3 :: int
L0:
p0 = 2
p1 = 486
p2 = -250
p3 = 2
return 1
[case testIntConstantFoldingDivMod]
def div() -> None:
div1 = 25 // 5
div2 = 24 // 5
div3 = 29 // 5
div4 = 30 // 5
div_zero = 0 // 5
neg1 = -1 // 3
neg2 = -2 // 3
neg3 = -3 // 3
neg4 = -4 // 3
neg_neg = -765467 // -234
pos_neg = 983745 // -7864
def mod() -> None:
mod1 = 25 % 5
mod2 = 24 % 5
mod3 = 29 % 5
mod4 = 30 % 5
mod_zero = 0 % 5
neg1 = -4 % 3
neg2 = -5 % 3
neg3 = -6 % 3
neg4 = -7 % 3
neg_neg = -765467 % -234
pos_neg = 983745 % -7864
[out]
def div():
div1, div2, div3, div4, div_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int
L0:
div1 = 10
div2 = 8
div3 = 10
div4 = 12
div_zero = 0
neg1 = -2
neg2 = -2
neg3 = -2
neg4 = -4
neg_neg = 6542
pos_neg = -252
return 1
def mod():
mod1, mod2, mod3, mod4, mod_zero, neg1, neg2, neg3, neg4, neg_neg, pos_neg :: int
L0:
mod1 = 0
mod2 = 8
mod3 = 8
mod4 = 0
mod_zero = 0
neg1 = 4
neg2 = 2
neg3 = 0
neg4 = 4
neg_neg = -106
pos_neg = -14238
return 1
[case testIntConstantFoldingUnsupportedCases]
def error_cases() -> None:
div_by_zero = 5 / 0
floor_div_by_zero = 5 // 0
mod_by_zero = 5 % 0
lshift_neg = 6 << -1
rshift_neg = 7 >> -1
def unsupported_pow() -> None:
p = 3 ** (-1)
[out]
def error_cases():
r0, div_by_zero :: float
r1, floor_div_by_zero, r2, mod_by_zero, r3, lshift_neg, r4, rshift_neg :: int
L0:
r0 = CPyTagged_TrueDivide(10, 0)
div_by_zero = r0
r1 = CPyTagged_FloorDivide(10, 0)
floor_div_by_zero = r1
r2 = CPyTagged_Remainder(10, 0)
mod_by_zero = r2
r3 = CPyTagged_Lshift(12, -2)
lshift_neg = r3
r4 = CPyTagged_Rshift(14, -2)
rshift_neg = r4
return 1
def unsupported_pow():
r0, r1, r2 :: object
r3, p :: float
L0:
r0 = object 3
r1 = object -1
r2 = CPyNumber_Power(r0, r1)
r3 = unbox(float, r2)
p = r3
return 1
[case testIntConstantFoldingBigIntResult_64bit]
def long_and_short() -> None:
# The smallest and largest representable short integers
short1 = 0x3ffffffffffffff0 + 0xf # (1 << 62) - 1
short2 = -0x3fffffffffffffff - 1 # -(1 << 62)
short3 = -0x4000000000000000
# Smallest big integers by absolute value
big1 = 1 << 62
big2 = 0x4000000000000000 # 1 << 62
big3 = -(1 << 62) - 1
big4 = -0x4000000000000001 # -(1 << 62) - 1
big5 = 123**41
[out]
def long_and_short():
short1, short2, short3, r0, big1, r1, big2, r2, big3, r3, big4, r4, big5 :: int
L0:
short1 = 9223372036854775806
short2 = -9223372036854775808
short3 = -9223372036854775808
r0 = object 4611686018427387904
big1 = r0
r1 = object 4611686018427387904
big2 = r1
r2 = object -4611686018427387905
big3 = r2
r3 = object -4611686018427387905
big4 = r3
r4 = object 48541095000524544750127162673405880068636916264012200797813591925035550682238127143323
big5 = r4
return 1
[case testIntConstantFoldingFinal]
from typing_extensions import Final
X: Final = 5
Y: Final = 2 + 4
def f() -> None:
a = X + 1
a = Y + 1
[out]
def f():
a :: int
L0:
a = 12
a = 14
return 1
[case testIntConstantFoldingClassFinal]
from typing_extensions import Final
class C:
X: Final = 5
def f() -> None:
a = C.X + 1
[out]
def C.__mypyc_defaults_setup(__mypyc_self__):
__mypyc_self__ :: __main__.C
L0:
__mypyc_self__.X = 10
return 1
def f():
a :: int
L0:
a = 12
return 1
[case testFloatConstantFolding]
from typing_extensions import Final
N: Final = 1.5
N2: Final = 1.5 * 2
def bin_ops() -> None:
add = 0.5 + 0.5
add_mul = (1.5 + 3.5) * 5.0
sub = 7.0 - 7.5
div = 3.0 / 2.0
floor_div = 3.0 // 2.0
def bin_ops_neg() -> None:
add = 0.5 + -0.5
add_mul = (-1.5 + 3.5) * -5.0
add_mul2 = (1.5 + -3.5) * -5.0
sub = 7.0 - -7.5
div = 3.0 / -2.0
floor_div = 3.0 // -2.0
def unary_ops() -> None:
neg1 = -5.5
neg2 = --1.5
neg3 = -0.0
pos = +5.5
def pow() -> None:
p0 = 16.0**0
p1 = 16.0**0.5
p2 = (-5.0)**3
p3 = 16.0**(-0)
p4 = 16.0**(-0.5)
p5 = (-2.0)**(-1)
def error_cases() -> None:
div = 2.0 / 0.0
floor_div = 2.0 // 0.0
power_imag = (-2.0)**0.5
power_imag2 = (-2.0)**(-0.5)
power_overflow = 2.0**10000.0
def final_floats() -> None:
add1 = N + 1.2
add2 = N + N2
add3 = -1.2 + N2
[out]
def bin_ops():
add, add_mul, sub, div, floor_div :: float
L0:
add = 1.0
add_mul = 25.0
sub = -0.5
div = 1.5
floor_div = 1.0
return 1
def bin_ops_neg():
add, add_mul, add_mul2, sub, div, floor_div :: float
L0:
add = 0.0
add_mul = -10.0
add_mul2 = 10.0
sub = 14.5
div = -1.5
floor_div = -2.0
return 1
def unary_ops():
neg1, neg2, neg3, pos :: float
L0:
neg1 = -5.5
neg2 = 1.5
neg3 = -0.0
pos = 5.5
return 1
def pow():
p0, p1, p2, p3, p4, p5 :: float
L0:
p0 = 1.0
p1 = 4.0
p2 = -125.0
p3 = 1.0
p4 = 0.25
p5 = -0.5
return 1
def error_cases():
r0 :: bit
r1 :: bool
r2, div, r3, floor_div :: float
r4, r5, r6 :: object
r7, power_imag :: float
r8, r9, r10 :: object
r11, power_imag2 :: float
r12, r13, r14 :: object
r15, power_overflow :: float
L0:
r0 = 0.0 == 0.0
if r0 goto L1 else goto L2 :: bool
L1:
r1 = raise ZeroDivisionError('float division by zero')
unreachable
L2:
r2 = 2.0 / 0.0
div = r2
r3 = CPyFloat_FloorDivide(2.0, 0.0)
floor_div = r3
r4 = box(float, -2.0)
r5 = box(float, 0.5)
r6 = CPyNumber_Power(r4, r5)
r7 = unbox(float, r6)
power_imag = r7
r8 = box(float, -2.0)
r9 = box(float, -0.5)
r10 = CPyNumber_Power(r8, r9)
r11 = unbox(float, r10)
power_imag2 = r11
r12 = box(float, 2.0)
r13 = box(float, 10000.0)
r14 = CPyNumber_Power(r12, r13)
r15 = unbox(float, r14)
power_overflow = r15
return 1
def final_floats():
add1, add2, add3 :: float
L0:
add1 = 2.7
add2 = 4.5
add3 = 1.8
return 1
[case testMixedFloatIntConstantFolding]
def bin_ops() -> None:
add = 1 + 0.5
sub = 1 - 0.5
mul = 0.5 * 5
div = 5 / 0.5
floor_div = 9.5 // 5
def error_cases() -> None:
div = 2.0 / 0
floor_div = 2.0 // 0
power_overflow = 2.0**10000
[out]
def bin_ops():
add, sub, mul, div, floor_div :: float
L0:
add = 1.5
sub = 0.5
mul = 2.5
div = 10.0
floor_div = 1.0
return 1
def error_cases():
r0 :: bit
r1 :: bool
r2, div, r3, floor_div :: float
r4, r5, r6 :: object
r7, power_overflow :: float
L0:
r0 = 0.0 == 0.0
if r0 goto L1 else goto L2 :: bool
L1:
r1 = raise ZeroDivisionError('float division by zero')
unreachable
L2:
r2 = 2.0 / 0.0
div = r2
r3 = CPyFloat_FloorDivide(2.0, 0.0)
floor_div = r3
r4 = box(float, 2.0)
r5 = box(float, 10000.0)
r6 = CPyNumber_Power(r4, r5)
r7 = unbox(float, r6)
power_overflow = r7
return 1
[case testStrConstantFolding]
from typing_extensions import Final
S: Final = 'z'
N: Final = 2
def f() -> None:
x = 'foo' + 'bar'
y = 'x' + 'y' + S
mul = "foobar" * 2
mul2 = N * "foobar"
[out]
def f():
r0, x, r1, y, r2, mul, r3, mul2 :: str
L0:
r0 = 'foobar'
x = r0
r1 = 'xyz'
y = r1
r2 = 'foobarfoobar'
mul = r2
r3 = 'foobarfoobar'
mul2 = r3
return 1
[case testBytesConstantFolding]
from typing_extensions import Final
N: Final = 2
def f() -> None:
# Unfortunately, mypy doesn't store the bytes value of final refs.
x = b'foo' + b'bar'
mul = b"foobar" * 2
mul2 = N * b"foobar"
[out]
def f():
r0, x, r1, mul, r2, mul2 :: bytes
L0:
r0 = b'foobar'
x = r0
r1 = b'foobarfoobar'
mul = r1
r2 = b'foobarfoobar'
mul2 = r2
return 1
[case testComplexConstantFolding]
from typing_extensions import Final
N: Final = 1
FLOAT_N: Final = 1.5
def integral() -> None:
pos = 1+2j
pos_2 = 2j+N
neg = 1-2j
neg_2 = 2j-N
def floating() -> None:
pos = 1.5+2j
pos_2 = 2j+FLOAT_N
neg = 1.5-2j
neg_2 = 2j-FLOAT_N
[out]
def integral():
r0, pos, r1, pos_2, r2, neg, r3, neg_2 :: object
L0:
r0 = (1+2j)
pos = r0
r1 = (1+2j)
pos_2 = r1
r2 = (1-2j)
neg = r2
r3 = (-1+2j)
neg_2 = r3
return 1
def floating():
r0, pos, r1, pos_2, r2, neg, r3, neg_2 :: object
L0:
r0 = (1.5+2j)
pos = r0
r1 = (1.5+2j)
pos_2 = r1
r2 = (1.5-2j)
neg = r2
r3 = (-1.5+2j)
neg_2 = r3
return 1

View File

@@ -0,0 +1,585 @@
[case testDictGet]
from typing import Dict
def f(d: Dict[int, bool]) -> bool:
return d[0]
[out]
def f(d):
d :: dict
r0, r1 :: object
r2 :: bool
L0:
r0 = object 0
r1 = CPyDict_GetItem(d, r0)
r2 = unbox(bool, r1)
return r2
[case testDictSet]
from typing import Dict
def f(d: Dict[int, bool]) -> None:
d[0] = False
[out]
def f(d):
d :: dict
r0, r1 :: object
r2 :: i32
r3 :: bit
L0:
r0 = object 0
r1 = box(bool, 0)
r2 = CPyDict_SetItem(d, r0, r1)
r3 = r2 >= 0 :: signed
return 1
[case testNewEmptyDict]
from typing import Dict
def f() -> None:
d = {} # type: Dict[bool, int]
[out]
def f():
r0, d :: dict
L0:
r0 = PyDict_New()
d = r0
return 1
[case testNewEmptyDictViaFunc]
from typing import Dict
def f() -> None:
d: Dict[bool, int] = dict()
[out]
def f():
r0, d :: dict
L0:
r0 = PyDict_New()
d = r0
return 1
[case testNewDictWithValues]
def f(x: object) -> None:
d = {1: 2, '': x}
[out]
def f(x):
x :: object
r0 :: str
r1, r2 :: object
r3, d :: dict
L0:
r0 = ''
r1 = object 1
r2 = object 2
r3 = CPyDict_Build(2, r1, r2, r0, x)
d = r3
return 1
[case testInDict]
from typing import Dict
def f(d: Dict[int, int]) -> bool:
if 4 in d:
return True
else:
return False
[out]
def f(d):
d :: dict
r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
L0:
r0 = object 4
r1 = PyDict_Contains(d, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
if r3 goto L1 else goto L2 :: bool
L1:
return 1
L2:
return 0
L3:
unreachable
[case testNotInDict]
from typing import Dict
def f(d: Dict[int, int]) -> bool:
if 4 not in d:
return True
else:
return False
[out]
def f(d):
d :: dict
r0 :: object
r1 :: i32
r2 :: bit
r3, r4 :: bool
L0:
r0 = object 4
r1 = PyDict_Contains(d, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
r4 = r3 ^ 1
if r4 goto L1 else goto L2 :: bool
L1:
return 1
L2:
return 0
L3:
unreachable
[case testDictUpdate]
from typing import Dict
def f(a: Dict[int, int], b: Dict[int, int]) -> None:
a.update(b)
[out]
def f(a, b):
a, b :: dict
r0 :: i32
r1 :: bit
L0:
r0 = CPyDict_Update(a, b)
r1 = r0 >= 0 :: signed
return 1
[case testDictKeyLvalue]
from typing import Dict
def increment(d: Dict[str, int]) -> Dict[str, int]:
for k in d:
d[k] += 1
return d
[out]
def increment(d):
d :: dict
r0 :: short_int
r1 :: native_int
r2 :: short_int
r3 :: object
r4 :: tuple[bool, short_int, object]
r5 :: short_int
r6 :: bool
r7 :: object
r8, k :: str
r9, r10, r11 :: object
r12 :: i32
r13, r14, r15 :: bit
L0:
r0 = 0
r1 = PyDict_Size(d)
r2 = r1 << 1
r3 = CPyDict_GetKeysIter(d)
L1:
r4 = CPyDict_NextKey(r3, r0)
r5 = r4[1]
r0 = r5
r6 = r4[0]
if r6 goto L2 else goto L4 :: bool
L2:
r7 = r4[2]
r8 = cast(str, r7)
k = r8
r9 = CPyDict_GetItem(d, k)
r10 = object 1
r11 = PyNumber_InPlaceAdd(r9, r10)
r12 = CPyDict_SetItem(d, k, r11)
r13 = r12 >= 0 :: signed
L3:
r14 = CPyDict_CheckSize(d, r2)
goto L1
L4:
r15 = CPy_NoErrOccured()
L5:
return d
[case testDictDisplay]
from typing import Dict
def f(x: str, y: Dict[str, int]) -> Dict[str, int]:
return {x: 2, **y, 'z': 3}
[out]
def f(x, y):
x :: str
y :: dict
r0 :: str
r1 :: object
r2 :: dict
r3 :: i32
r4 :: bit
r5 :: object
r6 :: i32
r7 :: bit
L0:
r0 = 'z'
r1 = object 2
r2 = CPyDict_Build(1, x, r1)
r3 = CPyDict_UpdateInDisplay(r2, y)
r4 = r3 >= 0 :: signed
r5 = object 3
r6 = CPyDict_SetItem(r2, r0, r5)
r7 = r6 >= 0 :: signed
return r2
[case testDictIterationMethods]
from typing import Dict, Union
from typing_extensions import TypedDict
class Person(TypedDict):
name: str
age: int
def print_dict_methods(d1: Dict[int, int], d2: Dict[int, int]) -> None:
for v in d1.values():
if v in d2:
return
for k, v in d2.items():
d2[k] += v
def union_of_dicts(d: Union[Dict[str, int], Dict[str, str]]) -> None:
new = {}
for k, v in d.items():
new[k] = int(v)
def typeddict(d: Person) -> None:
for k, v in d.items():
if k == "name":
name = v
[out]
def print_dict_methods(d1, d2):
d1, d2 :: dict
r0 :: short_int
r1 :: native_int
r2 :: short_int
r3 :: object
r4 :: tuple[bool, short_int, object]
r5 :: short_int
r6 :: bool
r7 :: object
r8, v :: int
r9 :: object
r10 :: i32
r11 :: bit
r12 :: bool
r13, r14 :: bit
r15 :: short_int
r16 :: native_int
r17 :: short_int
r18 :: object
r19 :: tuple[bool, short_int, object, object]
r20 :: short_int
r21 :: bool
r22, r23 :: object
r24, r25, k :: int
r26, r27, r28, r29, r30 :: object
r31 :: i32
r32, r33, r34 :: bit
L0:
r0 = 0
r1 = PyDict_Size(d1)
r2 = r1 << 1
r3 = CPyDict_GetValuesIter(d1)
L1:
r4 = CPyDict_NextValue(r3, r0)
r5 = r4[1]
r0 = r5
r6 = r4[0]
if r6 goto L2 else goto L6 :: bool
L2:
r7 = r4[2]
r8 = unbox(int, r7)
v = r8
r9 = box(int, v)
r10 = PyDict_Contains(d2, r9)
r11 = r10 >= 0 :: signed
r12 = truncate r10: i32 to builtins.bool
if r12 goto L3 else goto L4 :: bool
L3:
return 1
L4:
L5:
r13 = CPyDict_CheckSize(d1, r2)
goto L1
L6:
r14 = CPy_NoErrOccured()
L7:
r15 = 0
r16 = PyDict_Size(d2)
r17 = r16 << 1
r18 = CPyDict_GetItemsIter(d2)
L8:
r19 = CPyDict_NextItem(r18, r15)
r20 = r19[1]
r15 = r20
r21 = r19[0]
if r21 goto L9 else goto L11 :: bool
L9:
r22 = r19[2]
r23 = r19[3]
r24 = unbox(int, r22)
r25 = unbox(int, r23)
k = r24
v = r25
r26 = box(int, k)
r27 = CPyDict_GetItem(d2, r26)
r28 = box(int, v)
r29 = PyNumber_InPlaceAdd(r27, r28)
r30 = box(int, k)
r31 = CPyDict_SetItem(d2, r30, r29)
r32 = r31 >= 0 :: signed
L10:
r33 = CPyDict_CheckSize(d2, r17)
goto L8
L11:
r34 = CPy_NoErrOccured()
L12:
return 1
def union_of_dicts(d):
d, r0, new :: dict
r1 :: short_int
r2 :: native_int
r3 :: short_int
r4 :: object
r5 :: tuple[bool, short_int, object, object]
r6 :: short_int
r7 :: bool
r8, r9 :: object
r10 :: str
r11 :: union[int, str]
k :: str
v :: union[int, str]
r12, r13 :: object
r14 :: int
r15 :: object
r16 :: i32
r17, r18, r19 :: bit
L0:
r0 = PyDict_New()
new = r0
r1 = 0
r2 = PyDict_Size(d)
r3 = r2 << 1
r4 = CPyDict_GetItemsIter(d)
L1:
r5 = CPyDict_NextItem(r4, r1)
r6 = r5[1]
r1 = r6
r7 = r5[0]
if r7 goto L2 else goto L4 :: bool
L2:
r8 = r5[2]
r9 = r5[3]
r10 = cast(str, r8)
r11 = cast(union[int, str], r9)
k = r10
v = r11
r12 = load_address PyLong_Type
r13 = PyObject_CallFunctionObjArgs(r12, v, 0)
r14 = unbox(int, r13)
r15 = box(int, r14)
r16 = CPyDict_SetItem(new, k, r15)
r17 = r16 >= 0 :: signed
L3:
r18 = CPyDict_CheckSize(d, r3)
goto L1
L4:
r19 = CPy_NoErrOccured()
L5:
return 1
def typeddict(d):
d :: dict
r0 :: short_int
r1 :: native_int
r2 :: short_int
r3 :: object
r4 :: tuple[bool, short_int, object, object]
r5 :: short_int
r6 :: bool
r7, r8 :: object
r9, k :: str
v :: object
r10 :: str
r11 :: i32
r12 :: bit
r13 :: object
r14, r15, r16 :: bit
name :: object
r17, r18 :: bit
L0:
r0 = 0
r1 = PyDict_Size(d)
r2 = r1 << 1
r3 = CPyDict_GetItemsIter(d)
L1:
r4 = CPyDict_NextItem(r3, r0)
r5 = r4[1]
r0 = r5
r6 = r4[0]
if r6 goto L2 else goto L9 :: bool
L2:
r7 = r4[2]
r8 = r4[3]
r9 = cast(str, r7)
k = r9
v = r8
r10 = 'name'
r11 = PyUnicode_Compare(k, r10)
r12 = r11 == -1
if r12 goto L3 else goto L5 :: bool
L3:
r13 = PyErr_Occurred()
r14 = r13 != 0
if r14 goto L4 else goto L5 :: bool
L4:
r15 = CPy_KeepPropagating()
L5:
r16 = r11 == 0
if r16 goto L6 else goto L7 :: bool
L6:
name = v
L7:
L8:
r17 = CPyDict_CheckSize(d, r2)
goto L1
L9:
r18 = CPy_NoErrOccured()
L10:
return 1
[case testDictLoadAddress]
def f() -> None:
x = dict
[out]
def f():
r0, x :: object
L0:
r0 = load_address PyDict_Type
x = r0
return 1
[case testDictClear]
from typing import Dict
def f(d: Dict[int, int]) -> None:
return d.clear()
[out]
def f(d):
d :: dict
r0 :: bit
L0:
r0 = CPyDict_Clear(d)
return 1
[case testDictCopy]
from typing import Dict
def f(d: Dict[int, int]) -> Dict[int, int]:
return d.copy()
[out]
def f(d):
d, r0 :: dict
L0:
r0 = CPyDict_Copy(d)
return r0
[case testDictSetdefault]
from typing import Dict
def f(d: Dict[object, object]) -> object:
return d.setdefault('a', 'b')
def f2(d: Dict[object, object], flag: bool) -> object:
if flag:
return d.setdefault('a', set())
else:
return d.setdefault('a', set('b'))
def f3(d: Dict[object, object], flag: bool) -> object:
if flag:
return d.setdefault('a', [])
else:
return d.setdefault('a', [1])
def f4(d: Dict[object, object], flag: bool) -> object:
if flag:
return d.setdefault('a', {})
else:
return d.setdefault('a', {'c': 1})
[out]
def f(d):
d :: dict
r0, r1 :: str
r2 :: object
L0:
r0 = 'a'
r1 = 'b'
r2 = CPyDict_SetDefault(d, r0, r1)
return r2
def f2(d, flag):
d :: dict
flag :: bool
r0 :: str
r1 :: object
r2, r3 :: str
r4 :: set
r5, r6 :: object
L0:
if flag goto L1 else goto L2 :: bool
L1:
r0 = 'a'
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 3)
return r1
L2:
r2 = 'a'
r3 = 'b'
r4 = PySet_New(r3)
r5 = CPyDict_SetDefault(d, r2, r4)
return r5
L3:
r6 = box(None, 1)
return r6
def f3(d, flag):
d :: dict
flag :: bool
r0 :: str
r1 :: object
r2 :: str
r3 :: list
r4 :: object
r5, r6 :: ptr
r7, r8 :: object
L0:
if flag goto L1 else goto L2 :: bool
L1:
r0 = 'a'
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 1)
return r1
L2:
r2 = 'a'
r3 = PyList_New(1)
r4 = object 1
r5 = get_element_ptr r3 ob_item :: PyListObject
r6 = load_mem r5 :: ptr*
set_mem r6, r4 :: builtins.object*
keep_alive r3
r7 = CPyDict_SetDefault(d, r2, r3)
return r7
L3:
r8 = box(None, 1)
return r8
def f4(d, flag):
d :: dict
flag :: bool
r0 :: str
r1 :: object
r2, r3 :: str
r4 :: object
r5 :: dict
r6, r7 :: object
L0:
if flag goto L1 else goto L2 :: bool
L1:
r0 = 'a'
r1 = CPyDict_SetDefaultWithEmptyDatatype(d, r0, 2)
return r1
L2:
r2 = 'a'
r3 = 'c'
r4 = object 1
r5 = CPyDict_Build(1, r3, r4)
r6 = CPyDict_SetDefault(d, r2, r5)
return r6
L3:
r7 = box(None, 1)
return r7

View File

@@ -0,0 +1,223 @@
# Test cases for (some) dunder methods
[case testDundersLen]
class C:
def __len__(self) -> int:
return 2
def f(c: C) -> int:
return len(c)
[out]
def C.__len__(self):
self :: __main__.C
L0:
return 4
def f(c):
c :: __main__.C
r0 :: int
r1 :: native_int
r2, r3, r4 :: bit
r5 :: bool
L0:
r0 = c.__len__()
r1 = r0 & 1
r2 = r1 != 0
if r2 goto L1 else goto L2 :: bool
L1:
r3 = CPyTagged_IsLt_(r0, 0)
if r3 goto L3 else goto L4 :: bool
L2:
r4 = r0 >= 0 :: signed
if r4 goto L4 else goto L3 :: bool
L3:
r5 = raise ValueError('__len__() should return >= 0')
unreachable
L4:
return r0
[case testDundersSetItem]
class C:
def __setitem__(self, key: int, value: int) -> None:
pass
def f(c: C) -> None:
c[3] = 4
[out]
def C.__setitem__(self, key, value):
self :: __main__.C
key, value :: int
L0:
return 1
def f(c):
c :: __main__.C
r0 :: None
L0:
r0 = c.__setitem__(6, 8)
return 1
[case testDundersContains]
from typing import Any
class C:
def __contains__(self, x: int) -> bool:
return False
def f(c: C) -> bool:
return 7 in c
def g(c: C) -> bool:
return 7 not in c
class D:
def __contains__(self, x: int) -> Any:
return 'x'
def h(d: D) -> bool:
return 7 not in d
[out]
def C.__contains__(self, x):
self :: __main__.C
x :: int
L0:
return 0
def f(c):
c :: __main__.C
r0 :: bool
L0:
r0 = c.__contains__(14)
return r0
def g(c):
c :: __main__.C
r0, r1 :: bool
L0:
r0 = c.__contains__(14)
r1 = r0 ^ 1
return r1
def D.__contains__(self, x):
self :: __main__.D
x :: int
r0 :: str
L0:
r0 = 'x'
return r0
def h(d):
d :: __main__.D
r0 :: object
r1 :: i32
r2 :: bit
r3, r4 :: bool
L0:
r0 = d.__contains__(14)
r1 = PyObject_IsTrue(r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
r4 = r3 ^ 1
return r4
[case testDundersDelItem]
class C:
def __delitem__(self, x: int) -> None:
pass
def f(c: C) -> None:
del c[5]
[out]
def C.__delitem__(self, x):
self :: __main__.C
x :: int
L0:
return 1
def f(c):
c :: __main__.C
r0 :: None
L0:
r0 = c.__delitem__(10)
return 1
[case testDundersUnary]
class C:
def __neg__(self) -> int:
return 1
def __invert__(self) -> int:
return 2
def __int__(self) -> int:
return 3
def __float__(self) -> float:
return 4.0
def __pos__(self) -> int:
return 5
def __abs__(self) -> int:
return 6
def __bool__(self) -> bool:
return False
def __complex__(self) -> complex:
return 7j
def f(c: C) -> None:
-c
~c
int(c)
float(c)
+c
abs(c)
bool(c)
complex(c)
[out]
def C.__neg__(self):
self :: __main__.C
L0:
return 2
def C.__invert__(self):
self :: __main__.C
L0:
return 4
def C.__int__(self):
self :: __main__.C
L0:
return 6
def C.__float__(self):
self :: __main__.C
L0:
return 4.0
def C.__pos__(self):
self :: __main__.C
L0:
return 10
def C.__abs__(self):
self :: __main__.C
L0:
return 12
def C.__bool__(self):
self :: __main__.C
L0:
return 0
def C.__complex__(self):
self :: __main__.C
r0 :: object
L0:
r0 = 7j
return r0
def f(c):
c :: __main__.C
r0, r1, r2 :: int
r3 :: float
r4, r5 :: int
r6 :: bool
r7 :: object
L0:
r0 = c.__neg__()
r1 = c.__invert__()
r2 = c.__int__()
r3 = c.__float__()
r4 = c.__pos__()
r5 = c.__abs__()
r6 = c.__bool__()
r7 = c.__complex__()
return 1

View File

@@ -0,0 +1,497 @@
[case testFloatAdd]
def f(x: float, y: float) -> float:
return x + y
def g(x: float) -> float:
z = x - 1.5
return 2.5 * z
[out]
def f(x, y):
x, y, r0 :: float
L0:
r0 = x + y
return r0
def g(x):
x, r0, z, r1 :: float
L0:
r0 = x - 1.5
z = r0
r1 = 2.5 * z
return r1
[case testFloatBoxAndUnbox]
from typing import Any
def f(x: float) -> object:
return x
def g(x: Any) -> float:
return x
[out]
def f(x):
x :: float
r0 :: object
L0:
r0 = box(float, x)
return r0
def g(x):
x :: object
r0 :: float
L0:
r0 = unbox(float, x)
return r0
[case testFloatNegAndPos]
def f(x: float) -> float:
y = +x * -0.5
return -y
[out]
def f(x):
x, r0, y, r1 :: float
L0:
r0 = x * -0.5
y = r0
r1 = -y
return r1
[case testFloatCoerceFromInt]
def from_int(x: int) -> float:
return x
def from_literal() -> float:
return 5
def from_literal_neg() -> float:
return -2
[out]
def from_int(x):
x :: int
r0 :: float
L0:
r0 = CPyFloat_FromTagged(x)
return r0
def from_literal():
L0:
return 5.0
def from_literal_neg():
L0:
return -2.0
[case testConvertBetweenFloatAndInt]
def to_int(x: float) -> int:
return int(x)
def from_int(x: int) -> float:
return float(x)
[out]
def to_int(x):
x :: float
r0 :: int
L0:
r0 = CPyTagged_FromFloat(x)
return r0
def from_int(x):
x :: int
r0 :: float
L0:
r0 = CPyFloat_FromTagged(x)
return r0
[case testFloatOperatorAssignment]
def f(x: float, y: float) -> float:
x += y
x -= 5.0
return x
[out]
def f(x, y):
x, y, r0, r1 :: float
L0:
r0 = x + y
x = r0
r1 = x - 5.0
x = r1
return x
[case testFloatOperatorAssignmentWithInt]
def f(x: float, y: int) -> None:
x += y
x -= 5
[out]
def f(x, y):
x :: float
y :: int
r0, r1, r2 :: float
L0:
r0 = CPyFloat_FromTagged(y)
r1 = x + r0
x = r1
r2 = x - 5.0
x = r2
return 1
[case testFloatComparison]
def lt(x: float, y: float) -> bool:
return x < y
def eq(x: float, y: float) -> bool:
return x == y
[out]
def lt(x, y):
x, y :: float
r0 :: bit
L0:
r0 = x < y
return r0
def eq(x, y):
x, y :: float
r0 :: bit
L0:
r0 = x == y
return r0
[case testFloatOpWithLiteralInt]
def f(x: float) -> None:
y = x * 2
z = 1 - y
b = z < 3
c = 0 == z
[out]
def f(x):
x, r0, y, r1, z :: float
r2 :: bit
b :: bool
r3 :: bit
c :: bool
L0:
r0 = x * 2.0
y = r0
r1 = 1.0 - y
z = r1
r2 = z < 3.0
b = r2
r3 = 0.0 == z
c = r3
return 1
[case testFloatCallFunctionWithLiteralInt]
def f(x: float) -> None: pass
def g() -> None:
f(3)
f(-2)
[out]
def f(x):
x :: float
L0:
return 1
def g():
r0, r1 :: None
L0:
r0 = f(3.0)
r1 = f(-2.0)
return 1
[case testFloatAsBool]
def f(x: float) -> int:
if x:
return 2
else:
return 5
[out]
def f(x):
x :: float
r0 :: bit
L0:
r0 = x != 0.0
if r0 goto L1 else goto L2 :: bool
L1:
return 4
L2:
return 10
L3:
unreachable
[case testCallSqrtViaMathModule]
import math
def f(x: float) -> float:
return math.sqrt(x)
[out]
def f(x):
x, r0 :: float
L0:
r0 = CPyFloat_Sqrt(x)
return r0
[case testFloatFinalConstant]
from typing_extensions import Final
X: Final = 123.0
Y: Final = -1.0
def f() -> float:
a = X
return a + Y
[out]
def f():
a, r0 :: float
L0:
a = 123.0
r0 = a + -1.0
return r0
[case testFloatDefaultArg]
def f(x: float = 1.5) -> float:
return x
[out]
def f(x, __bitmap):
x :: float
__bitmap, r0 :: u32
r1 :: bit
L0:
r0 = __bitmap & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
x = 1.5
L2:
return x
[case testFloatMixedOperations]
def f(x: float, y: int) -> None:
if x < y:
z = x + y
x -= y
z = y + z
if y == x:
x -= 1
[out]
def f(x, y):
x :: float
y :: int
r0 :: float
r1 :: bit
r2, r3, z, r4, r5, r6, r7, r8 :: float
r9 :: bit
r10 :: float
L0:
r0 = CPyFloat_FromTagged(y)
r1 = x < r0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = CPyFloat_FromTagged(y)
r3 = x + r2
z = r3
r4 = CPyFloat_FromTagged(y)
r5 = x - r4
x = r5
r6 = CPyFloat_FromTagged(y)
r7 = r6 + z
z = r7
L2:
r8 = CPyFloat_FromTagged(y)
r9 = r8 == x
if r9 goto L3 else goto L4 :: bool
L3:
r10 = x - 1.0
x = r10
L4:
return 1
[case testFloatDivideSimple]
def f(x: float, y: float) -> float:
z = x / y
z = z / 2.0
return z / 3
[out]
def f(x, y):
x, y :: float
r0 :: bit
r1 :: bool
r2, z, r3, r4 :: float
L0:
r0 = y == 0.0
if r0 goto L1 else goto L2 :: bool
L1:
r1 = raise ZeroDivisionError('float division by zero')
unreachable
L2:
r2 = x / y
z = r2
r3 = z / 2.0
z = r3
r4 = z / 3.0
return r4
[case testFloatDivideIntOperand]
def f(n: int, m: int) -> float:
return n / m
[out]
def f(n, m):
n, m :: int
r0 :: float
L0:
r0 = CPyTagged_TrueDivide(n, m)
return r0
[case testFloatResultOfIntDivide]
def f(f: float, n: int) -> float:
x = f / n
return n / x
[out]
def f(f, n):
f :: float
n :: int
r0 :: float
r1 :: bit
r2 :: bool
r3, x, r4 :: float
r5 :: bit
r6 :: bool
r7 :: float
L0:
r0 = CPyFloat_FromTagged(n)
r1 = r0 == 0.0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = raise ZeroDivisionError('float division by zero')
unreachable
L2:
r3 = f / r0
x = r3
r4 = CPyFloat_FromTagged(n)
r5 = x == 0.0
if r5 goto L3 else goto L4 :: bool
L3:
r6 = raise ZeroDivisionError('float division by zero')
unreachable
L4:
r7 = r4 / x
return r7
[case testFloatExplicitConversions]
def f(f: float, n: int) -> int:
x = float(n)
y = float(x) # no-op
return int(y)
[out]
def f(f, n):
f :: float
n :: int
r0, x, y :: float
r1 :: int
L0:
r0 = CPyFloat_FromTagged(n)
x = r0
y = x
r1 = CPyTagged_FromFloat(y)
return r1
[case testFloatModulo]
def f(x: float, y: float) -> float:
return x % y
[out]
def f(x, y):
x, y :: float
r0 :: bit
r1 :: bool
r2, r3 :: float
r4, r5, r6, r7 :: bit
r8, r9 :: float
L0:
r0 = y == 0.0
if r0 goto L1 else goto L2 :: bool
L1:
r1 = raise ZeroDivisionError('float modulo')
unreachable
L2:
r2 = x % y
r3 = r2
r4 = r3 == 0.0
if r4 goto L5 else goto L3 :: bool
L3:
r5 = x < 0.0
r6 = y < 0.0
r7 = r5 == r6
if r7 goto L6 else goto L4 :: bool
L4:
r8 = r3 + y
r3 = r8
goto L6
L5:
r9 = copysign(0.0, y)
r3 = r9
L6:
return r3
[case testFloatFloorDivide]
def f(x: float, y: float) -> float:
return x // y
def g(x: float, y: int) -> float:
return x // y
[out]
def f(x, y):
x, y, r0 :: float
L0:
r0 = CPyFloat_FloorDivide(x, y)
return r0
def g(x, y):
x :: float
y :: int
r0, r1 :: float
L0:
r0 = CPyFloat_FromTagged(y)
r1 = CPyFloat_FloorDivide(x, r0)
return r1
[case testFloatNarrowToIntDisallowed]
class C:
x: float
def narrow_local(x: float, n: int) -> int:
x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return x
def narrow_tuple_lvalue(x: float, y: float, n: int) -> int:
x, y = 1.0, n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return y
def narrow_multiple_lvalues(x: float, y: float, n: int) -> int:
x = a = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
a = y = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return x + y
def narrow_attribute(c: C, n: int) -> int:
c.x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return c.x
def narrow_using_int_literal(x: float) -> int:
x = 1 # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return x
def narrow_using_declaration(n: int) -> int:
x: float
x = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
return x
[case testFloatInitializeFromInt]
def init(n: int) -> None:
# These are strictly speaking safe, since these don't narrow, but for consistency with
# narrowing assignments, generate errors here
x: float = n # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
y: float = 5 # E: Incompatible value representations in assignment (expression has type "int", variable has type "float")
[case testFloatCoerceTupleFromIntValues]
from __future__ import annotations
def f(x: int) -> None:
t: tuple[float, float, float] = (x, 2.5, -7)
[out]
def f(x):
x :: int
r0 :: tuple[int, float, int]
r1 :: int
r2 :: float
r3, t :: tuple[float, float, float]
L0:
r0 = (x, 2.5, -14)
r1 = r0[0]
r2 = CPyFloat_FromTagged(r1)
r3 = (r2, 2.5, -7.0)
t = r3
return 1

View File

@@ -0,0 +1,151 @@
[case testGenericFunction]
from typing import TypeVar, List
T = TypeVar('T')
def f(x: T) -> T:
return x
def g(x: List[T]) -> List[T]:
return [x[0]]
def h(x: int, y: List[int]) -> None:
x = f(x)
y = g(y)
[out]
def f(x):
x :: object
L0:
return x
def g(x):
x :: list
r0 :: object
r1 :: list
r2, r3 :: ptr
L0:
r0 = CPyList_GetItemShort(x, 0)
r1 = PyList_New(1)
r2 = get_element_ptr r1 ob_item :: PyListObject
r3 = load_mem r2 :: ptr*
set_mem r3, r0 :: builtins.object*
keep_alive r1
return r1
def h(x, y):
x :: int
y :: list
r0, r1 :: object
r2 :: int
r3 :: list
L0:
r0 = box(int, x)
r1 = f(r0)
r2 = unbox(int, r1)
x = r2
r3 = g(y)
y = r3
return 1
[case testGenericAttrAndTypeApplication]
from typing import TypeVar, Generic
T = TypeVar('T')
class C(Generic[T]):
x: T
def f() -> None:
c = C[int]()
c.x = 1
2 + c.x
[out]
def f():
r0, c :: __main__.C
r1 :: object
r2 :: bool
r3 :: object
r4, r5 :: int
L0:
r0 = C()
c = r0
r1 = object 1
c.x = r1; r2 = is_error
r3 = borrow c.x
r4 = unbox(int, r3)
r5 = CPyTagged_Add(4, r4)
keep_alive c
return 1
[case testGenericMethod]
from typing import TypeVar, Generic
T = TypeVar('T')
class C(Generic[T]):
x: T
def __init__(self, x: T) -> None:
self.x = x
def get(self) -> T:
return self.x
def set(self, y: T) -> None:
self.x = y
def f(x: C[int]) -> None:
y = x.get()
x.set(y + 1)
x = C(2)
[out]
def C.__init__(self, x):
self :: __main__.C
x :: object
r0 :: bool
L0:
self.x = x; r0 = is_error
return 1
def C.get(self):
self :: __main__.C
r0 :: object
L0:
r0 = self.x
return r0
def C.set(self, y):
self :: __main__.C
y :: object
r0 :: bool
L0:
self.x = y; r0 = is_error
return 1
def f(x):
x :: __main__.C
r0 :: object
r1, y, r2 :: int
r3 :: object
r4 :: None
r5 :: object
r6 :: __main__.C
L0:
r0 = x.get()
r1 = unbox(int, r0)
y = r1
r2 = CPyTagged_Add(y, 2)
r3 = box(int, r2)
r4 = x.set(r3)
r5 = object 2
r6 = C(r5)
x = r6
return 1
[case testMax]
from typing import TypeVar
T = TypeVar('T')
def f(x: T, y: T) -> T:
return max(x, y)
[out]
def f(x, y):
x, y, r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
r4 :: object
L0:
r0 = PyObject_RichCompare(y, x, 4)
r1 = PyObject_IsTrue(r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
if r3 goto L1 else goto L2 :: bool
L1:
r4 = y
goto L3
L2:
r4 = x
L3:
return r4

View File

@@ -0,0 +1,437 @@
# Test cases for glue methods.
#
# These are used when subclass method signature has a different representation
# compared to the base class.
[case testSubclassSpecialize2]
class A:
def foo(self, x: int) -> object:
return str(x)
class B(A):
def foo(self, x: object) -> object:
return x
class C(B):
def foo(self, x: object) -> int:
return id(x)
def use_a(x: A, y: int) -> object:
return x.foo(y)
def use_b(x: B, y: object) -> object:
return x.foo(y)
def use_c(x: C, y: object) -> int:
return x.foo(y)
[out]
def A.foo(self, x):
self :: __main__.A
x :: int
r0 :: str
L0:
r0 = CPyTagged_Str(x)
return r0
def B.foo(self, x):
self :: __main__.B
x :: object
L0:
return x
def B.foo__A_glue(self, x):
self :: __main__.B
x :: int
r0, r1 :: object
L0:
r0 = box(int, x)
r1 = B.foo(self, r0)
return r1
def C.foo(self, x):
self :: __main__.C
x :: object
r0 :: int
L0:
r0 = CPyTagged_Id(x)
return r0
def C.foo__B_glue(self, x):
self :: __main__.C
x :: object
r0 :: int
r1 :: object
L0:
r0 = C.foo(self, x)
r1 = box(int, r0)
return r1
def C.foo__A_glue(self, x):
self :: __main__.C
x :: int
r0 :: object
r1 :: int
r2 :: object
L0:
r0 = box(int, x)
r1 = C.foo(self, r0)
r2 = box(int, r1)
return r2
def use_a(x, y):
x :: __main__.A
y :: int
r0 :: object
L0:
r0 = x.foo(y)
return r0
def use_b(x, y):
x :: __main__.B
y, r0 :: object
L0:
r0 = x.foo(y)
return r0
def use_c(x, y):
x :: __main__.C
y :: object
r0 :: int
L0:
r0 = x.foo(y)
return r0
[case testPropertyDerivedGen]
from typing import Callable
class BaseProperty:
@property
def value(self) -> object:
return self._incrementer
@property
def bad_value(self) -> object:
return self._incrementer
@property
def next(self) -> BaseProperty:
return BaseProperty(self._incrementer + 1)
def __init__(self, value: int) -> None:
self._incrementer = value
class DerivedProperty(BaseProperty):
@property
def value(self) -> int:
return self._incrementer
@property
def bad_value(self) -> object:
return self._incrementer
@property
def next(self) -> DerivedProperty:
return DerivedProperty(self._incr_func, self._incr_func(self.value))
def __init__(self, incr_func: Callable[[int], int], value: int) -> None:
BaseProperty.__init__(self, value)
self._incr_func = incr_func
class AgainProperty(DerivedProperty):
@property
def next(self) -> AgainProperty:
return AgainProperty(self._incr_func, self._incr_func(self._incr_func(self.value)))
@property
def bad_value(self) -> int:
return self._incrementer
[out]
def BaseProperty.value(self):
self :: __main__.BaseProperty
r0 :: int
r1 :: object
L0:
r0 = self._incrementer
r1 = box(int, r0)
return r1
def BaseProperty.bad_value(self):
self :: __main__.BaseProperty
r0 :: int
r1 :: object
L0:
r0 = self._incrementer
r1 = box(int, r0)
return r1
def BaseProperty.next(self):
self :: __main__.BaseProperty
r0, r1 :: int
r2 :: __main__.BaseProperty
L0:
r0 = borrow self._incrementer
r1 = CPyTagged_Add(r0, 2)
keep_alive self
r2 = BaseProperty(r1)
return r2
def BaseProperty.__init__(self, value):
self :: __main__.BaseProperty
value :: int
L0:
self._incrementer = value
return 1
def DerivedProperty.value(self):
self :: __main__.DerivedProperty
r0 :: int
L0:
r0 = self._incrementer
return r0
def DerivedProperty.value__BaseProperty_glue(__mypyc_self__):
__mypyc_self__ :: __main__.DerivedProperty
r0 :: int
r1 :: object
L0:
r0 = __mypyc_self__.value
r1 = box(int, r0)
return r1
def DerivedProperty.bad_value(self):
self :: __main__.DerivedProperty
r0 :: int
r1 :: object
L0:
r0 = self._incrementer
r1 = box(int, r0)
return r1
def DerivedProperty.next(self):
self :: __main__.DerivedProperty
r0 :: object
r1 :: int
r2, r3, r4 :: object
r5 :: int
r6 :: __main__.DerivedProperty
L0:
r0 = self._incr_func
r1 = self.value
r2 = self._incr_func
r3 = box(int, r1)
r4 = PyObject_CallFunctionObjArgs(r2, r3, 0)
r5 = unbox(int, r4)
r6 = DerivedProperty(r0, r5)
return r6
def DerivedProperty.next__BaseProperty_glue(__mypyc_self__):
__mypyc_self__, r0 :: __main__.DerivedProperty
L0:
r0 = __mypyc_self__.next
return r0
def DerivedProperty.__init__(self, incr_func, value):
self :: __main__.DerivedProperty
incr_func :: object
value :: int
r0 :: None
L0:
r0 = BaseProperty.__init__(self, value)
self._incr_func = incr_func
return 1
def AgainProperty.next(self):
self :: __main__.AgainProperty
r0 :: object
r1 :: int
r2, r3, r4 :: object
r5 :: int
r6, r7, r8 :: object
r9 :: int
r10 :: __main__.AgainProperty
L0:
r0 = self._incr_func
r1 = self.value
r2 = self._incr_func
r3 = box(int, r1)
r4 = PyObject_CallFunctionObjArgs(r2, r3, 0)
r5 = unbox(int, r4)
r6 = self._incr_func
r7 = box(int, r5)
r8 = PyObject_CallFunctionObjArgs(r6, r7, 0)
r9 = unbox(int, r8)
r10 = AgainProperty(r0, r9)
return r10
def AgainProperty.next__DerivedProperty_glue(__mypyc_self__):
__mypyc_self__, r0 :: __main__.AgainProperty
L0:
r0 = __mypyc_self__.next
return r0
def AgainProperty.next__BaseProperty_glue(__mypyc_self__):
__mypyc_self__, r0 :: __main__.AgainProperty
L0:
r0 = __mypyc_self__.next
return r0
def AgainProperty.bad_value(self):
self :: __main__.AgainProperty
r0 :: int
L0:
r0 = self._incrementer
return r0
def AgainProperty.bad_value__DerivedProperty_glue(__mypyc_self__):
__mypyc_self__ :: __main__.AgainProperty
r0 :: int
r1 :: object
L0:
r0 = __mypyc_self__.bad_value
r1 = box(int, r0)
return r1
def AgainProperty.bad_value__BaseProperty_glue(__mypyc_self__):
__mypyc_self__ :: __main__.AgainProperty
r0 :: int
r1 :: object
L0:
r0 = __mypyc_self__.bad_value
r1 = box(int, r0)
return r1
[case testPropertyTraitSubclassing]
from mypy_extensions import trait
@trait
class SubclassedTrait:
@property
def this(self) -> SubclassedTrait:
return self
@property
def boxed(self) -> object:
return 3
class DerivingObject(SubclassedTrait):
@property
def this(self) -> DerivingObject:
return self
@property
def boxed(self) -> int:
return 5
[out]
def SubclassedTrait.this(self):
self :: __main__.SubclassedTrait
L0:
return self
def SubclassedTrait.boxed(self):
self :: __main__.SubclassedTrait
r0 :: object
L0:
r0 = object 3
return r0
def DerivingObject.this(self):
self :: __main__.DerivingObject
L0:
return self
def DerivingObject.this__SubclassedTrait_glue(__mypyc_self__):
__mypyc_self__, r0 :: __main__.DerivingObject
L0:
r0 = __mypyc_self__.this
return r0
def DerivingObject.boxed(self):
self :: __main__.DerivingObject
L0:
return 10
def DerivingObject.boxed__SubclassedTrait_glue(__mypyc_self__):
__mypyc_self__ :: __main__.DerivingObject
r0 :: int
r1 :: object
L0:
r0 = __mypyc_self__.boxed
r1 = box(int, r0)
return r1
[case testI64GlueWithExtraDefaultArg]
from mypy_extensions import i64
class C:
def f(self) -> None: pass
class D(C):
def f(self, x: i64 = 44) -> None: pass
[out]
def C.f(self):
self :: __main__.C
L0:
return 1
def D.f(self, x, __bitmap):
self :: __main__.D
x :: i64
__bitmap, r0 :: u32
r1 :: bit
L0:
r0 = __bitmap & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
x = 44
L2:
return 1
def D.f__C_glue(self):
self :: __main__.D
r0 :: None
L0:
r0 = D.f(self, 0, 0)
return r0
[case testI64GlueWithSecondDefaultArg]
from mypy_extensions import i64
class C:
def f(self, x: i64 = 11) -> None: pass
class D(C):
def f(self, x: i64 = 12, y: i64 = 13) -> None: pass
[out]
def C.f(self, x, __bitmap):
self :: __main__.C
x :: i64
__bitmap, r0 :: u32
r1 :: bit
L0:
r0 = __bitmap & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
x = 11
L2:
return 1
def D.f(self, x, y, __bitmap):
self :: __main__.D
x, y :: i64
__bitmap, r0 :: u32
r1 :: bit
r2 :: u32
r3 :: bit
L0:
r0 = __bitmap & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
x = 12
L2:
r2 = __bitmap & 2
r3 = r2 == 0
if r3 goto L3 else goto L4 :: bool
L3:
y = 13
L4:
return 1
def D.f__C_glue(self, x, __bitmap):
self :: __main__.D
x :: i64
__bitmap :: u32
r0 :: None
L0:
r0 = D.f(self, x, 0, __bitmap)
return r0
[case testI64GlueWithInvalidOverride]
from mypy_extensions import i64
class C:
def f(self, x: i64, y: i64 = 5) -> None: pass
def ff(self, x: int) -> None: pass
class CC(C):
def f(self, x: i64 = 12, y: i64 = 5) -> None: pass # Line 7
def ff(self, x: int = 12) -> None: pass
class D:
def f(self, x: int) -> None: pass
class DD(D):
def f(self, x: i64) -> None: pass # Line 13
class E:
def f(self, x: i64) -> None: pass
class EE(E):
def f(self, x: int) -> None: pass # Line 18
[out]
main:7: error: An argument with type "i64" cannot be given a default value in a method override
main:13: error: Incompatible argument type "i64" (base class has type "int")
main:18: error: Incompatible argument type "int" (base class has type "i64")

View File

@@ -0,0 +1,526 @@
# Test cases for i16 native ints. Focus on things that are different from i64; no need to
# duplicate all i64 test cases here.
[case testI16BinaryOp]
from mypy_extensions import i16
def add_op(x: i16, y: i16) -> i16:
x = y + x
y = x + 5
y += x
y += 7
x = 5 + y
return x
def compare(x: i16, y: i16) -> None:
a = x == y
b = x == -5
c = x < y
d = x < -5
e = -5 == x
f = -5 < x
[out]
def add_op(x, y):
x, y, r0, r1, r2, r3, r4 :: i16
L0:
r0 = y + x
x = r0
r1 = x + 5
y = r1
r2 = y + x
y = r2
r3 = y + 7
y = r3
r4 = 5 + y
x = r4
return x
def compare(x, y):
x, y :: i16
r0 :: bit
a :: bool
r1 :: bit
b :: bool
r2 :: bit
c :: bool
r3 :: bit
d :: bool
r4 :: bit
e :: bool
r5 :: bit
f :: bool
L0:
r0 = x == y
a = r0
r1 = x == -5
b = r1
r2 = x < y :: signed
c = r2
r3 = x < -5 :: signed
d = r3
r4 = -5 == x
e = r4
r5 = -5 < x :: signed
f = r5
return 1
[case testI16UnaryOp]
from mypy_extensions import i16
def unary(x: i16) -> i16:
y = -x
x = ~y
y = +x
return y
[out]
def unary(x):
x, r0, y, r1 :: i16
L0:
r0 = 0 - x
y = r0
r1 = y ^ -1
x = r1
y = x
return y
[case testI16DivisionByConstant]
from mypy_extensions import i16
def div_by_constant(x: i16) -> i16:
x = x // 5
x //= 17
return x
[out]
def div_by_constant(x):
x, r0, r1 :: i16
r2, r3, r4 :: bit
r5 :: i16
r6 :: bit
r7, r8, r9 :: i16
r10, r11, r12 :: bit
r13 :: i16
r14 :: bit
r15 :: i16
L0:
r0 = x / 5
r1 = r0
r2 = x < 0 :: signed
r3 = 5 < 0 :: signed
r4 = r2 == r3
if r4 goto L3 else goto L1 :: bool
L1:
r5 = r1 * 5
r6 = r5 == x
if r6 goto L3 else goto L2 :: bool
L2:
r7 = r1 - 1
r1 = r7
L3:
x = r1
r8 = x / 17
r9 = r8
r10 = x < 0 :: signed
r11 = 17 < 0 :: signed
r12 = r10 == r11
if r12 goto L6 else goto L4 :: bool
L4:
r13 = r9 * 17
r14 = r13 == x
if r14 goto L6 else goto L5 :: bool
L5:
r15 = r9 - 1
r9 = r15
L6:
x = r9
return x
[case testI16ModByConstant]
from mypy_extensions import i16
def mod_by_constant(x: i16) -> i16:
x = x % 5
x %= 17
return x
[out]
def mod_by_constant(x):
x, r0, r1 :: i16
r2, r3, r4, r5 :: bit
r6, r7, r8 :: i16
r9, r10, r11, r12 :: bit
r13 :: i16
L0:
r0 = x % 5
r1 = r0
r2 = x < 0 :: signed
r3 = 5 < 0 :: signed
r4 = r2 == r3
if r4 goto L3 else goto L1 :: bool
L1:
r5 = r1 == 0
if r5 goto L3 else goto L2 :: bool
L2:
r6 = r1 + 5
r1 = r6
L3:
x = r1
r7 = x % 17
r8 = r7
r9 = x < 0 :: signed
r10 = 17 < 0 :: signed
r11 = r9 == r10
if r11 goto L6 else goto L4 :: bool
L4:
r12 = r8 == 0
if r12 goto L6 else goto L5 :: bool
L5:
r13 = r8 + 17
r8 = r13
L6:
x = r8
return x
[case testI16DivModByVariable]
from mypy_extensions import i16
def divmod(x: i16, y: i16) -> i16:
a = x // y
return a % y
[out]
def divmod(x, y):
x, y, r0, a, r1 :: i16
L0:
r0 = CPyInt16_Divide(x, y)
a = r0
r1 = CPyInt16_Remainder(a, y)
return r1
[case testI16BinaryOperationWithOutOfRangeOperand]
from mypy_extensions import i16
def out_of_range(x: i16) -> None:
x + (-32769)
(-32770) + x
x * 32768
x + 32767 # OK
(-32768) + x # OK
[out]
main:4: error: Value -32769 is out of range for "i16"
main:5: error: Value -32770 is out of range for "i16"
main:6: error: Value 32768 is out of range for "i16"
[case testI16BoxAndUnbox]
from typing import Any
from mypy_extensions import i16
def f(x: Any) -> Any:
y: i16 = x
return y
[out]
def f(x):
x :: object
r0, y :: i16
r1 :: object
L0:
r0 = unbox(i16, x)
y = r0
r1 = box(i16, y)
return r1
[case testI16MixedCompare1]
from mypy_extensions import i16
def f(x: int, y: i16) -> bool:
return x == y
[out]
def f(x, y):
x :: int
y :: i16
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i16
r7 :: bit
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 65536 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -65536 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i16
r6 = r5
goto L5
L4:
CPyInt16_Overflow()
unreachable
L5:
r7 = r6 == y
return r7
[case testI16MixedCompare2]
from mypy_extensions import i16
def f(x: i16, y: int) -> bool:
return x == y
[out]
def f(x, y):
x :: i16
y :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i16
r7 :: bit
L0:
r0 = y & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = y < 65536 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = y >= -65536 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = y >> 1
r5 = truncate r4: native_int to i16
r6 = r5
goto L5
L4:
CPyInt16_Overflow()
unreachable
L5:
r7 = x == r6
return r7
[case testI16ConvertToInt]
from mypy_extensions import i16
def i16_to_int(a: i16) -> int:
return a
[out]
def i16_to_int(a):
a :: i16
r0 :: native_int
r1 :: int
L0:
r0 = extend signed a: i16 to native_int
r1 = r0 << 1
return r1
[case testI16OperatorAssignmentMixed]
from mypy_extensions import i16
def f(a: i16) -> None:
x = 0
x += a
[out]
def f(a):
a :: i16
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6, r7 :: i16
r8 :: native_int
r9 :: int
L0:
x = 0
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 65536 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -65536 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i16
r6 = r5
goto L5
L4:
CPyInt16_Overflow()
unreachable
L5:
r7 = r6 + a
r8 = extend signed r7: i16 to native_int
r9 = r8 << 1
x = r9
return 1
[case testI16InitializeFromLiteral]
from mypy_extensions import i16, i64
def f() -> None:
x: i16 = 0
y: i16 = -127
z: i16 = 5 + 7
[out]
def f():
x, y, z :: i16
L0:
x = 0
y = -127
z = 12
return 1
[case testI16ExplicitConversionFromNativeInt]
from mypy_extensions import i64, i32, i16
def from_i16(x: i16) -> i16:
return i16(x)
def from_i32(x: i32) -> i16:
return i16(x)
def from_i64(x: i64) -> i16:
return i16(x)
[out]
def from_i16(x):
x :: i16
L0:
return x
def from_i32(x):
x :: i32
r0 :: i16
L0:
r0 = truncate x: i32 to i16
return r0
def from_i64(x):
x :: i64
r0 :: i16
L0:
r0 = truncate x: i64 to i16
return r0
[case testI16ExplicitConversionFromInt]
from mypy_extensions import i16
def f(x: int) -> i16:
return i16(x)
[out]
def f(x):
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i16
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 65536 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -65536 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i16
r6 = r5
goto L5
L4:
CPyInt16_Overflow()
unreachable
L5:
return r6
[case testI16ExplicitConversionFromLiteral]
from mypy_extensions import i16
def f() -> None:
x = i16(0)
y = i16(11)
z = i16(-3)
a = i16(32767)
b = i16(32768) # Truncate
c = i16(-32768)
d = i16(-32769) # Truncate
[out]
def f():
x, y, z, a, b, c, d :: i16
L0:
x = 0
y = 11
z = -3
a = 32767
b = -32768
c = -32768
d = 32767
return 1
[case testI16ExplicitConversionFromVariousTypes]
from mypy_extensions import i16
def bool_to_i16(b: bool) -> i16:
return i16(b)
def str_to_i16(s: str) -> i16:
return i16(s)
class C:
def __int__(self) -> i16:
return 5
def instance_to_i16(c: C) -> i16:
return i16(c)
def float_to_i16(x: float) -> i16:
return i16(x)
[out]
def bool_to_i16(b):
b :: bool
r0 :: i16
L0:
r0 = extend b: builtins.bool to i16
return r0
def str_to_i16(s):
s :: str
r0 :: object
r1 :: i16
L0:
r0 = CPyLong_FromStr(s)
r1 = unbox(i16, r0)
return r1
def C.__int__(self):
self :: __main__.C
L0:
return 5
def instance_to_i16(c):
c :: __main__.C
r0 :: i16
L0:
r0 = c.__int__()
return r0
def float_to_i16(x):
x :: float
r0 :: int
r1 :: native_int
r2, r3, r4 :: bit
r5 :: native_int
r6, r7 :: i16
L0:
r0 = CPyTagged_FromFloat(x)
r1 = r0 & 1
r2 = r1 == 0
if r2 goto L1 else goto L4 :: bool
L1:
r3 = r0 < 65536 :: signed
if r3 goto L2 else goto L4 :: bool
L2:
r4 = r0 >= -65536 :: signed
if r4 goto L3 else goto L4 :: bool
L3:
r5 = r0 >> 1
r6 = truncate r5: native_int to i16
r7 = r6
goto L5
L4:
CPyInt16_Overflow()
unreachable
L5:
return r7

View File

@@ -0,0 +1,598 @@
# Test cases for i32 native ints. Focus on things that are different from i64; no need to
# duplicate all i64 test cases here.
[case testI32BinaryOp]
from mypy_extensions import i32
def add_op(x: i32, y: i32) -> i32:
x = y + x
y = x + 5
y += x
y += 7
x = 5 + y
return x
def compare(x: i32, y: i32) -> None:
a = x == y
b = x == -5
c = x < y
d = x < -5
e = -5 == x
f = -5 < x
[out]
def add_op(x, y):
x, y, r0, r1, r2, r3, r4 :: i32
L0:
r0 = y + x
x = r0
r1 = x + 5
y = r1
r2 = y + x
y = r2
r3 = y + 7
y = r3
r4 = 5 + y
x = r4
return x
def compare(x, y):
x, y :: i32
r0 :: bit
a :: bool
r1 :: bit
b :: bool
r2 :: bit
c :: bool
r3 :: bit
d :: bool
r4 :: bit
e :: bool
r5 :: bit
f :: bool
L0:
r0 = x == y
a = r0
r1 = x == -5
b = r1
r2 = x < y :: signed
c = r2
r3 = x < -5 :: signed
d = r3
r4 = -5 == x
e = r4
r5 = -5 < x :: signed
f = r5
return 1
[case testI32UnaryOp]
from mypy_extensions import i32
def unary(x: i32) -> i32:
y = -x
x = ~y
y = +x
return y
[out]
def unary(x):
x, r0, y, r1 :: i32
L0:
r0 = 0 - x
y = r0
r1 = y ^ -1
x = r1
y = x
return y
[case testI32DivisionByConstant]
from mypy_extensions import i32
def div_by_constant(x: i32) -> i32:
x = x // 5
x //= 17
return x
[out]
def div_by_constant(x):
x, r0, r1 :: i32
r2, r3, r4 :: bit
r5 :: i32
r6 :: bit
r7, r8, r9 :: i32
r10, r11, r12 :: bit
r13 :: i32
r14 :: bit
r15 :: i32
L0:
r0 = x / 5
r1 = r0
r2 = x < 0 :: signed
r3 = 5 < 0 :: signed
r4 = r2 == r3
if r4 goto L3 else goto L1 :: bool
L1:
r5 = r1 * 5
r6 = r5 == x
if r6 goto L3 else goto L2 :: bool
L2:
r7 = r1 - 1
r1 = r7
L3:
x = r1
r8 = x / 17
r9 = r8
r10 = x < 0 :: signed
r11 = 17 < 0 :: signed
r12 = r10 == r11
if r12 goto L6 else goto L4 :: bool
L4:
r13 = r9 * 17
r14 = r13 == x
if r14 goto L6 else goto L5 :: bool
L5:
r15 = r9 - 1
r9 = r15
L6:
x = r9
return x
[case testI32ModByConstant]
from mypy_extensions import i32
def mod_by_constant(x: i32) -> i32:
x = x % 5
x %= 17
return x
[out]
def mod_by_constant(x):
x, r0, r1 :: i32
r2, r3, r4, r5 :: bit
r6, r7, r8 :: i32
r9, r10, r11, r12 :: bit
r13 :: i32
L0:
r0 = x % 5
r1 = r0
r2 = x < 0 :: signed
r3 = 5 < 0 :: signed
r4 = r2 == r3
if r4 goto L3 else goto L1 :: bool
L1:
r5 = r1 == 0
if r5 goto L3 else goto L2 :: bool
L2:
r6 = r1 + 5
r1 = r6
L3:
x = r1
r7 = x % 17
r8 = r7
r9 = x < 0 :: signed
r10 = 17 < 0 :: signed
r11 = r9 == r10
if r11 goto L6 else goto L4 :: bool
L4:
r12 = r8 == 0
if r12 goto L6 else goto L5 :: bool
L5:
r13 = r8 + 17
r8 = r13
L6:
x = r8
return x
[case testI32DivModByVariable]
from mypy_extensions import i32
def divmod(x: i32, y: i32) -> i32:
a = x // y
return a % y
[out]
def divmod(x, y):
x, y, r0, a, r1 :: i32
L0:
r0 = CPyInt32_Divide(x, y)
a = r0
r1 = CPyInt32_Remainder(a, y)
return r1
[case testI32BoxAndUnbox]
from typing import Any
from mypy_extensions import i32
def f(x: Any) -> Any:
y: i32 = x
return y
[out]
def f(x):
x :: object
r0, y :: i32
r1 :: object
L0:
r0 = unbox(i32, x)
y = r0
r1 = box(i32, y)
return r1
[case testI32MixedCompare1_64bit]
from mypy_extensions import i32
def f(x: int, y: i32) -> bool:
return x == y
[out]
def f(x, y):
x :: int
y :: i32
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i32
r7 :: bit
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 4294967296 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -4294967296 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i32
r6 = r5
goto L5
L4:
CPyInt32_Overflow()
unreachable
L5:
r7 = r6 == y
return r7
[case testI32MixedCompare2_64bit]
from mypy_extensions import i32
def f(x: i32, y: int) -> bool:
return x == y
[out]
def f(x, y):
x :: i32
y :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i32
r7 :: bit
L0:
r0 = y & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = y < 4294967296 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = y >= -4294967296 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = y >> 1
r5 = truncate r4: native_int to i32
r6 = r5
goto L5
L4:
CPyInt32_Overflow()
unreachable
L5:
r7 = x == r6
return r7
[case testI32MixedCompare_32bit]
from mypy_extensions import i32
def f(x: int, y: i32) -> bool:
return x == y
[out]
def f(x, y):
x :: int
y :: i32
r0 :: native_int
r1 :: bit
r2, r3 :: i32
r4 :: ptr
r5 :: c_ptr
r6 :: i32
r7 :: bit
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = x >> 1
r3 = r2
goto L3
L2:
r4 = x ^ 1
r5 = r4
r6 = CPyLong_AsInt32(r5)
r3 = r6
keep_alive x
L3:
r7 = r3 == y
return r7
[case testI32ConvertToInt_64bit]
from mypy_extensions import i32
def i32_to_int(a: i32) -> int:
return a
[out]
def i32_to_int(a):
a :: i32
r0 :: native_int
r1 :: int
L0:
r0 = extend signed a: i32 to native_int
r1 = r0 << 1
return r1
[case testI32ConvertToInt_32bit]
from mypy_extensions import i32
def i32_to_int(a: i32) -> int:
return a
[out]
def i32_to_int(a):
a :: i32
r0, r1 :: bit
r2, r3, r4 :: int
L0:
r0 = a <= 1073741823 :: signed
if r0 goto L1 else goto L2 :: bool
L1:
r1 = a >= -1073741824 :: signed
if r1 goto L3 else goto L2 :: bool
L2:
r2 = CPyTagged_FromSsize_t(a)
r3 = r2
goto L4
L3:
r4 = a << 1
r3 = r4
L4:
return r3
[case testI32OperatorAssignmentMixed_64bit]
from mypy_extensions import i32
def f(a: i32) -> None:
x = 0
x += a
[out]
def f(a):
a :: i32
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6, r7 :: i32
r8 :: native_int
r9 :: int
L0:
x = 0
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 4294967296 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -4294967296 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i32
r6 = r5
goto L5
L4:
CPyInt32_Overflow()
unreachable
L5:
r7 = r6 + a
r8 = extend signed r7: i32 to native_int
r9 = r8 << 1
x = r9
return 1
[case testI32InitializeFromLiteral]
from mypy_extensions import i32, i64
def f() -> None:
x: i32 = 0
y: i32 = -127
z: i32 = 5 + 7
[out]
def f():
x, y, z :: i32
L0:
x = 0
y = -127
z = 12
return 1
[case testI32ExplicitConversionFromNativeInt]
from mypy_extensions import i64, i32, i16
def from_i16(x: i16) -> i32:
return i32(x)
def from_i32(x: i32) -> i32:
return i32(x)
def from_i64(x: i64) -> i32:
return i32(x)
[out]
def from_i16(x):
x :: i16
r0 :: i32
L0:
r0 = extend signed x: i16 to i32
return r0
def from_i32(x):
x :: i32
L0:
return x
def from_i64(x):
x :: i64
r0 :: i32
L0:
r0 = truncate x: i64 to i32
return r0
[case testI32ExplicitConversionFromInt_64bit]
from mypy_extensions import i32
def f(x: int) -> i32:
return i32(x)
[out]
def f(x):
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: i32
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 4294967296 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= -4294967296 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to i32
r6 = r5
goto L5
L4:
CPyInt32_Overflow()
unreachable
L5:
return r6
[case testI32ExplicitConversionFromLiteral_64bit]
from mypy_extensions import i32
def f() -> None:
x = i32(0)
y = i32(11)
z = i32(-3)
a = i32(2**31)
[out]
def f():
x, y, z, a :: i32
L0:
x = 0
y = 11
z = -3
a = -2147483648
return 1
[case testI32ExplicitConversionFromVariousTypes_64bit]
from mypy_extensions import i32
def bool_to_i32(b: bool) -> i32:
return i32(b)
def str_to_i32(s: str) -> i32:
return i32(s)
class C:
def __int__(self) -> i32:
return 5
def instance_to_i32(c: C) -> i32:
return i32(c)
def float_to_i32(x: float) -> i32:
return i32(x)
[out]
def bool_to_i32(b):
b :: bool
r0 :: i32
L0:
r0 = extend b: builtins.bool to i32
return r0
def str_to_i32(s):
s :: str
r0 :: object
r1 :: i32
L0:
r0 = CPyLong_FromStr(s)
r1 = unbox(i32, r0)
return r1
def C.__int__(self):
self :: __main__.C
L0:
return 5
def instance_to_i32(c):
c :: __main__.C
r0 :: i32
L0:
r0 = c.__int__()
return r0
def float_to_i32(x):
x :: float
r0 :: int
r1 :: native_int
r2, r3, r4 :: bit
r5 :: native_int
r6, r7 :: i32
L0:
r0 = CPyTagged_FromFloat(x)
r1 = r0 & 1
r2 = r1 == 0
if r2 goto L1 else goto L4 :: bool
L1:
r3 = r0 < 4294967296 :: signed
if r3 goto L2 else goto L4 :: bool
L2:
r4 = r0 >= -4294967296 :: signed
if r4 goto L3 else goto L4 :: bool
L3:
r5 = r0 >> 1
r6 = truncate r5: native_int to i32
r7 = r6
goto L5
L4:
CPyInt32_Overflow()
unreachable
L5:
return r7
[case testI32ExplicitConversionFromFloat_32bit]
from mypy_extensions import i32
def float_to_i32(x: float) -> i32:
return i32(x)
[out]
def float_to_i32(x):
x :: float
r0 :: int
r1 :: native_int
r2 :: bit
r3, r4 :: i32
r5 :: ptr
r6 :: c_ptr
r7 :: i32
L0:
r0 = CPyTagged_FromFloat(x)
r1 = r0 & 1
r2 = r1 == 0
if r2 goto L1 else goto L2 :: bool
L1:
r3 = r0 >> 1
r4 = r3
goto L3
L2:
r5 = r0 ^ 1
r6 = r5
r7 = CPyLong_AsInt32(r6)
r4 = r7
keep_alive r0
L3:
return r4

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
[case testIntNeq]
def f(x: int, y: int) -> bool:
return x != y
[out]
def f(x, y):
x, y :: int
r0 :: native_int
r1, r2 :: bit
r3 :: bool
r4, r5 :: bit
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = x != y
r3 = r2
goto L3
L2:
r4 = CPyTagged_IsEq_(x, y)
r5 = r4 ^ 1
r3 = r5
L3:
return r3
[case testShortIntComparisons]
def f(x: int) -> int:
if x == 3:
return 1
elif x != 4:
return 2
elif 5 == x:
return 3
elif 6 != x:
return 4
elif x < 4:
return 5
return 6
[out]
def f(x):
x :: int
r0, r1, r2, r3 :: bit
r4 :: native_int
r5, r6, r7 :: bit
L0:
r0 = x == 6
if r0 goto L1 else goto L2 :: bool
L1:
return 2
L2:
r1 = x != 8
if r1 goto L3 else goto L4 :: bool
L3:
return 4
L4:
r2 = 10 == x
if r2 goto L5 else goto L6 :: bool
L5:
return 6
L6:
r3 = 12 != x
if r3 goto L7 else goto L8 :: bool
L7:
return 8
L8:
r4 = x & 1
r5 = r4 != 0
if r5 goto L9 else goto L10 :: bool
L9:
r6 = CPyTagged_IsLt_(x, 8)
if r6 goto L11 else goto L12 :: bool
L10:
r7 = x < 8 :: signed
if r7 goto L11 else goto L12 :: bool
L11:
return 10
L12:
L13:
L14:
L15:
L16:
return 12
[case testIntMin]
def f(x: int, y: int) -> int:
return min(x, y)
[out]
def f(x, y):
x, y :: int
r0 :: native_int
r1 :: bit
r2 :: native_int
r3, r4, r5 :: bit
r6 :: bool
r7 :: bit
r8 :: int
L0:
r0 = y & 1
r1 = r0 == 0
r2 = x & 1
r3 = r2 == 0
r4 = r1 & r3
if r4 goto L1 else goto L2 :: bool
L1:
r5 = y < x :: signed
r6 = r5
goto L3
L2:
r7 = CPyTagged_IsLt_(y, x)
r6 = r7
L3:
if r6 goto L4 else goto L5 :: bool
L4:
r8 = y
goto L6
L5:
r8 = x
L6:
return r8
[case testIntFloorDivideByPowerOfTwo]
def divby1(x: int) -> int:
return x // 1
def divby2(x: int) -> int:
return x // 2
def divby3(x: int) -> int:
return x // 3
def divby4(x: int) -> int:
return x // 4
def divby8(x: int) -> int:
return x // 8
[out]
def divby1(x):
x, r0 :: int
L0:
r0 = CPyTagged_FloorDivide(x, 2)
return r0
def divby2(x):
x, r0 :: int
L0:
r0 = CPyTagged_Rshift(x, 2)
return r0
def divby3(x):
x, r0 :: int
L0:
r0 = CPyTagged_FloorDivide(x, 6)
return r0
def divby4(x):
x, r0 :: int
L0:
r0 = CPyTagged_Rshift(x, 4)
return r0
def divby8(x):
x, r0 :: int
L0:
r0 = CPyTagged_Rshift(x, 6)
return r0
[case testFinalConstantFolding]
from typing_extensions import Final
X: Final = -1
Y: Final = -(1 + 3*2)
Z: Final = Y + 1
class C:
A: Final = 1
B: Final = -1
def f1() -> int:
return X
def f2() -> int:
return X + Y
def f3() -> int:
return Z
def f4() -> int:
return C.A
def f5() -> int:
return C.B
[out]
def C.__mypyc_defaults_setup(__mypyc_self__):
__mypyc_self__ :: __main__.C
L0:
__mypyc_self__.A = 2
__mypyc_self__.B = -2
return 1
def f1():
L0:
return -2
def f2():
L0:
return -16
def f3():
L0:
return -12
def f4():
L0:
return 2
def f5():
L0:
return -2
[case testConvertIntegralToInt]
def bool_to_int(b: bool) -> int:
return int(b)
def int_to_int(n: int) -> int:
return int(n)
[out]
def bool_to_int(b):
b, r0 :: bool
r1 :: int
L0:
r0 = b << 1
r1 = extend r0: builtins.bool to builtins.int
return r1
def int_to_int(n):
n :: int
L0:
return n
[case testIntUnaryPlus]
def unary_plus(n: int) -> int:
x = +n
return x
[out]
def unary_plus(n):
n, x :: int
L0:
x = n
return x

View File

@@ -0,0 +1,109 @@
[case testIsinstanceInt]
def is_int(value: object) -> bool:
return isinstance(value, int)
[out]
def is_int(value):
value, r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
L0:
r0 = load_address PyLong_Type
r1 = PyObject_IsInstance(value, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
return r3
[case testIsinstanceNotBool1]
def is_not_bool(value: object) -> bool:
return not isinstance(value, bool)
[out]
def is_not_bool(value):
value, r0 :: object
r1 :: i32
r2 :: bit
r3, r4 :: bool
L0:
r0 = load_address PyBool_Type
r1 = PyObject_IsInstance(value, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
r4 = r3 ^ 1
return r4
[case testIsinstanceIntAndNotBool]
# This test is to ensure that 'value' doesn't get coerced to int when we are
# checking if it's a bool, since an int can never be an instance of a bool
def is_not_bool_and_is_int(value: object) -> bool:
return isinstance(value, int) and not isinstance(value, bool)
[out]
def is_not_bool_and_is_int(value):
value, r0 :: object
r1 :: i32
r2 :: bit
r3, r4 :: bool
r5 :: object
r6 :: i32
r7 :: bit
r8, r9 :: bool
L0:
r0 = load_address PyLong_Type
r1 = PyObject_IsInstance(value, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
if r3 goto L2 else goto L1 :: bool
L1:
r4 = r3
goto L3
L2:
r5 = load_address PyBool_Type
r6 = PyObject_IsInstance(value, r5)
r7 = r6 >= 0 :: signed
r8 = truncate r6: i32 to builtins.bool
r9 = r8 ^ 1
r4 = r9
L3:
return r4
[case testBorrowSpecialCaseWithIsinstance]
class C:
s: str
def g() -> object:
pass
def f() -> None:
x = g()
if isinstance(x, C):
x.s
[out]
def g():
r0 :: object
L0:
r0 = box(None, 1)
return r0
def f():
r0, x, r1 :: object
r2 :: ptr
r3 :: object
r4 :: bit
r5 :: __main__.C
r6 :: str
L0:
r0 = g()
x = r0
r1 = __main__.C :: type
r2 = get_element_ptr x ob_type :: PyObject
r3 = load_mem r2 :: builtins.object*
keep_alive x
r4 = r3 == r1
if r4 goto L1 else goto L2 :: bool
L1:
r5 = borrow cast(__main__.C, x)
r6 = r5.s
keep_alive x
L2:
return 1

View File

@@ -0,0 +1,547 @@
[case testListGet]
from typing import List
def f(x: List[int]) -> int:
return x[0]
[out]
def f(x):
x :: list
r0 :: object
r1 :: int
L0:
r0 = CPyList_GetItemShort(x, 0)
r1 = unbox(int, r0)
return r1
[case testListOfListGet]
from typing import List
def f(x: List[List[int]]) -> List[int]:
return x[0]
[out]
def f(x):
x :: list
r0 :: object
r1 :: list
L0:
r0 = CPyList_GetItemShort(x, 0)
r1 = cast(list, r0)
return r1
[case testListOfListGet2]
from typing import List
def f(x: List[List[int]]) -> int:
return x[0][1]
[out]
def f(x):
x :: list
r0 :: object
r1 :: list
r2 :: object
r3 :: int
L0:
r0 = CPyList_GetItemShortBorrow(x, 0)
r1 = borrow cast(list, r0)
r2 = CPyList_GetItemShort(r1, 2)
r3 = unbox(int, r2)
keep_alive x, r0
return r3
[case testListSet]
from typing import List
def f(x: List[int]) -> None:
x[0] = 1
[out]
def f(x):
x :: list
r0 :: object
r1 :: bit
L0:
r0 = object 1
r1 = CPyList_SetItem(x, 0, r0)
return 1
[case testNewListEmpty]
from typing import List
def f() -> None:
x = [] # type: List[int]
[out]
def f():
r0, x :: list
L0:
r0 = PyList_New(0)
x = r0
return 1
[case testNewListEmptyViaFunc]
from typing import List
def f() -> None:
x: List[int] = list()
[out]
def f():
r0, x :: list
L0:
r0 = PyList_New(0)
x = r0
return 1
[case testNewListEmptyViaAlias]
from typing import List
ListAlias = list
def f() -> None:
x: List[int] = ListAlias()
[out]
def f():
r0, x :: list
L0:
r0 = PyList_New(0)
x = r0
return 1
[case testNewListTwoItems]
from typing import List
def f() -> None:
x: List[int] = [1, 2]
[out]
def f():
r0 :: list
r1, r2 :: object
r3, r4, r5 :: ptr
x :: list
L0:
r0 = PyList_New(2)
r1 = object 1
r2 = object 2
r3 = get_element_ptr r0 ob_item :: PyListObject
r4 = load_mem r3 :: ptr*
set_mem r4, r1 :: builtins.object*
r5 = r4 + WORD_SIZE*1
set_mem r5, r2 :: builtins.object*
keep_alive r0
x = r0
return 1
[case testNewListTenItems]
from typing import List
def f() -> None:
x: List[str] = ['a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j']
[out]
def f():
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9 :: str
r10, x :: list
L0:
r0 = 'a'
r1 = 'b'
r2 = 'c'
r3 = 'd'
r4 = 'e'
r5 = 'f'
r6 = 'g'
r7 = 'h'
r8 = 'i'
r9 = 'j'
r10 = CPyList_Build(10, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9)
x = r10
return 1
[case testListMultiply]
from typing import List
def f(a: List[int]) -> None:
b = a * 2
b = 3 * [4]
[out]
def f(a):
a, r0, b, r1 :: list
r2 :: object
r3, r4 :: ptr
r5 :: list
L0:
r0 = CPySequence_Multiply(a, 4)
b = r0
r1 = PyList_New(1)
r2 = object 4
r3 = get_element_ptr r1 ob_item :: PyListObject
r4 = load_mem r3 :: ptr*
set_mem r4, r2 :: builtins.object*
keep_alive r1
r5 = CPySequence_RMultiply(6, r1)
b = r5
return 1
[case testListLen]
from typing import List
def f(a: List[int]) -> int:
return len(a)
[out]
def f(a):
a :: list
r0 :: ptr
r1 :: native_int
r2 :: short_int
L0:
r0 = get_element_ptr a ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive a
r2 = r1 << 1
return r2
[case testListAppend]
from typing import List
def f(a: List[int], x: int) -> None:
a.append(x)
[out]
def f(a, x):
a :: list
x :: int
r0 :: object
r1 :: i32
r2 :: bit
L0:
r0 = box(int, x)
r1 = PyList_Append(a, r0)
r2 = r1 >= 0 :: signed
return 1
[case testIndexLvalue]
from typing import List
def increment(l: List[int]) -> List[int]:
for i in range(len(l)):
l[i] += 1
return l
[out]
def increment(l):
l :: list
r0 :: ptr
r1 :: native_int
r2, r3 :: short_int
i :: int
r4 :: bit
r5, r6, r7 :: object
r8 :: bit
r9 :: short_int
L0:
r0 = get_element_ptr l ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive l
r2 = r1 << 1
r3 = 0
i = r3
L1:
r4 = r3 < r2 :: signed
if r4 goto L2 else goto L4 :: bool
L2:
r5 = CPyList_GetItem(l, i)
r6 = object 1
r7 = PyNumber_InPlaceAdd(r5, r6)
r8 = CPyList_SetItem(l, i, r7)
L3:
r9 = r3 + 2
r3 = r9
i = r9
goto L1
L4:
return l
[case testListDisplay]
from typing import List
def f(x: List[int], y: List[int]) -> List[int]:
return [1, 2, *x, *y, 3]
[out]
def f(x, y):
x, y, r0 :: list
r1, r2 :: object
r3, r4, r5 :: ptr
r6, r7, r8 :: object
r9 :: i32
r10 :: bit
L0:
r0 = PyList_New(2)
r1 = object 1
r2 = object 2
r3 = get_element_ptr r0 ob_item :: PyListObject
r4 = load_mem r3 :: ptr*
set_mem r4, r1 :: builtins.object*
r5 = r4 + WORD_SIZE*1
set_mem r5, r2 :: builtins.object*
keep_alive r0
r6 = CPyList_Extend(r0, x)
r7 = CPyList_Extend(r0, y)
r8 = object 3
r9 = PyList_Append(r0, r8)
r10 = r9 >= 0 :: signed
return r0
[case testListIn]
from typing import List
def f(x: List[int], y: int) -> bool:
return y in x
[out]
def f(x, y):
x :: list
y :: int
r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
L0:
r0 = box(int, y)
r1 = PySequence_Contains(x, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
return r3
[case testListInsert]
from typing import List
def f(x: List[int], y: int) -> None:
x.insert(0, y)
[out]
def f(x, y):
x :: list
y :: int
r0 :: object
r1 :: i32
r2 :: bit
L0:
r0 = box(int, y)
r1 = CPyList_Insert(x, 0, r0)
r2 = r1 >= 0 :: signed
return 1
[case testListBuiltFromGenerator]
from typing import List
def f(source: List[int]) -> None:
a = list(x + 1 for x in source)
b = [x + 1 for x in source]
[out]
def f(source):
source :: list
r0 :: ptr
r1 :: native_int
r2 :: list
r3 :: short_int
r4 :: ptr
r5 :: native_int
r6 :: short_int
r7 :: bit
r8 :: object
r9, x, r10 :: int
r11 :: object
r12 :: bit
r13 :: short_int
a :: list
r14 :: ptr
r15 :: native_int
r16 :: list
r17 :: short_int
r18 :: ptr
r19 :: native_int
r20 :: short_int
r21 :: bit
r22 :: object
r23, x_2, r24 :: int
r25 :: object
r26 :: bit
r27 :: short_int
b :: list
L0:
r0 = get_element_ptr source ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive source
r2 = PyList_New(r1)
r3 = 0
L1:
r4 = get_element_ptr source ob_size :: PyVarObject
r5 = load_mem r4 :: native_int*
keep_alive source
r6 = r5 << 1
r7 = r3 < r6 :: signed
if r7 goto L2 else goto L4 :: bool
L2:
r8 = CPyList_GetItemUnsafe(source, r3)
r9 = unbox(int, r8)
x = r9
r10 = CPyTagged_Add(x, 2)
r11 = box(int, r10)
r12 = CPyList_SetItemUnsafe(r2, r3, r11)
L3:
r13 = r3 + 2
r3 = r13
goto L1
L4:
a = r2
r14 = get_element_ptr source ob_size :: PyVarObject
r15 = load_mem r14 :: native_int*
keep_alive source
r16 = PyList_New(r15)
r17 = 0
L5:
r18 = get_element_ptr source ob_size :: PyVarObject
r19 = load_mem r18 :: native_int*
keep_alive source
r20 = r19 << 1
r21 = r17 < r20 :: signed
if r21 goto L6 else goto L8 :: bool
L6:
r22 = CPyList_GetItemUnsafe(source, r17)
r23 = unbox(int, r22)
x_2 = r23
r24 = CPyTagged_Add(x_2, 2)
r25 = box(int, r24)
r26 = CPyList_SetItemUnsafe(r16, r17, r25)
L7:
r27 = r17 + 2
r17 = r27
goto L5
L8:
b = r16
return 1
[case testGeneratorNext]
from typing import List, Optional
def test(x: List[int]) -> None:
res = next((i for i in x), None)
[out]
def test(x):
x :: list
r0 :: short_int
r1 :: ptr
r2 :: native_int
r3 :: short_int
r4 :: bit
r5 :: object
r6, i :: int
r7 :: object
r8 :: union[int, None]
r9 :: short_int
r10 :: object
res :: union[int, None]
L0:
r0 = 0
L1:
r1 = get_element_ptr x ob_size :: PyVarObject
r2 = load_mem r1 :: native_int*
keep_alive x
r3 = r2 << 1
r4 = r0 < r3 :: signed
if r4 goto L2 else goto L4 :: bool
L2:
r5 = CPyList_GetItemUnsafe(x, r0)
r6 = unbox(int, r5)
i = r6
r7 = box(int, i)
r8 = r7
goto L5
L3:
r9 = r0 + 2
r0 = r9
goto L1
L4:
r10 = box(None, 1)
r8 = r10
L5:
res = r8
return 1
[case testSimplifyListUnion]
from typing import List, Union, Optional
def narrow(a: Union[List[str], List[bytes], int]) -> int:
if isinstance(a, list):
return len(a)
return a
def loop(a: Union[List[str], List[bytes]]) -> None:
for x in a:
pass
def nested_union(a: Union[List[str], List[Optional[str]]]) -> None:
for x in a:
pass
[out]
def narrow(a):
a :: union[list, int]
r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
r4 :: list
r5 :: ptr
r6 :: native_int
r7 :: short_int
r8 :: int
L0:
r0 = load_address PyList_Type
r1 = PyObject_IsInstance(a, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
if r3 goto L1 else goto L2 :: bool
L1:
r4 = borrow cast(list, a)
r5 = get_element_ptr r4 ob_size :: PyVarObject
r6 = load_mem r5 :: native_int*
keep_alive r4
r7 = r6 << 1
keep_alive a
return r7
L2:
r8 = unbox(int, a)
return r8
def loop(a):
a :: list
r0 :: short_int
r1 :: ptr
r2 :: native_int
r3 :: short_int
r4 :: bit
r5 :: object
r6, x :: union[str, bytes]
r7 :: short_int
L0:
r0 = 0
L1:
r1 = get_element_ptr a ob_size :: PyVarObject
r2 = load_mem r1 :: native_int*
keep_alive a
r3 = r2 << 1
r4 = r0 < r3 :: signed
if r4 goto L2 else goto L4 :: bool
L2:
r5 = CPyList_GetItemUnsafe(a, r0)
r6 = cast(union[str, bytes], r5)
x = r6
L3:
r7 = r0 + 2
r0 = r7
goto L1
L4:
return 1
def nested_union(a):
a :: list
r0 :: short_int
r1 :: ptr
r2 :: native_int
r3 :: short_int
r4 :: bit
r5 :: object
r6, x :: union[str, None]
r7 :: short_int
L0:
r0 = 0
L1:
r1 = get_element_ptr a ob_size :: PyVarObject
r2 = load_mem r1 :: native_int*
keep_alive a
r3 = r2 << 1
r4 = r0 < r3 :: signed
if r4 goto L2 else goto L4 :: bool
L2:
r5 = CPyList_GetItemUnsafe(a, r0)
r6 = cast(union[str, None], r5)
x = r6
L3:
r7 = r0 + 2
r0 = r7
goto L1
L4:
return 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
[case testMathLiteralsAreInlined]
import math
from math import pi, e, tau, inf, nan
def f1() -> float:
return pi
def f2() -> float:
return math.pi
def f3() -> float:
return math.e
def f4() -> float:
return math.e
def f5() -> float:
return math.tau
def f6() -> float:
return math.tau
def f7() -> float:
return math.inf
def f8() -> float:
return math.inf
def f9() -> float:
return math.nan
def f10() -> float:
return math.nan
[out]
def f1():
L0:
return 3.141592653589793
def f2():
L0:
return 3.141592653589793
def f3():
L0:
return 2.718281828459045
def f4():
L0:
return 2.718281828459045
def f5():
L0:
return 6.283185307179586
def f6():
L0:
return 6.283185307179586
def f7():
L0:
return inf
def f8():
L0:
return inf
def f9():
L0:
return nan
def f10():
L0:
return nan

View File

@@ -0,0 +1,861 @@
[case testNestedFunctions]
from typing import Callable
def a() -> Callable[[], object]:
def inner() -> object:
return None
return inner
def b() -> Callable[[], Callable[[], str]]:
def first() -> Callable[[], str]:
def second() -> str:
return 'b.first.second: nested function'
return second
return first
def c(num: float) -> Callable[[str], str]:
def inner(s: str) -> str:
return s + '!'
return inner
def d(num: float) -> str:
def inner(s: str) -> str:
return s + '?'
a = inner('one')
b = inner('two')
return a
def inner() -> str:
return 'inner: normal function'
def first() -> str:
return 'first: normal function'
def second() -> str:
return 'second: normal function'
[out]
def inner_a_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_a_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_a_obj
r0 :: __main__.a_env
r1, inner, r2 :: object
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = box(None, 1)
return r2
def a():
r0 :: __main__.a_env
r1 :: __main__.inner_a_obj
r2, r3 :: bool
r4 :: object
L0:
r0 = a_env()
r1 = inner_a_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.inner = r1; r3 = is_error
r4 = r0.inner
return r4
def second_b_first_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def second_b_first_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.second_b_first_obj
r0 :: __main__.first_b_env
r1 :: __main__.b_env
r2, second :: object
r3 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.__mypyc_env__
r2 = r0.second
second = r2
r3 = 'b.first.second: nested function'
return r3
def first_b_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def first_b_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.first_b_obj
r0 :: __main__.b_env
r1, first :: object
r2 :: __main__.first_b_env
r3 :: bool
r4 :: __main__.second_b_first_obj
r5, r6 :: bool
r7 :: object
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.first
first = r1
r2 = first_b_env()
r2.__mypyc_env__ = r0; r3 = is_error
r4 = second_b_first_obj()
r4.__mypyc_env__ = r2; r5 = is_error
r2.second = r4; r6 = is_error
r7 = r2.second
return r7
def b():
r0 :: __main__.b_env
r1 :: __main__.first_b_obj
r2, r3 :: bool
r4 :: object
L0:
r0 = b_env()
r1 = first_b_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.first = r1; r3 = is_error
r4 = r0.first
return r4
def inner_c_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_c_obj.__call__(__mypyc_self__, s):
__mypyc_self__ :: __main__.inner_c_obj
s :: str
r0 :: __main__.c_env
r1, inner :: object
r2, r3 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = '!'
r3 = PyUnicode_Concat(s, r2)
return r3
def c(num):
num :: float
r0 :: __main__.c_env
r1 :: __main__.inner_c_obj
r2, r3 :: bool
r4 :: object
L0:
r0 = c_env()
r1 = inner_c_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.inner = r1; r3 = is_error
r4 = r0.inner
return r4
def inner_d_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_d_obj.__call__(__mypyc_self__, s):
__mypyc_self__ :: __main__.inner_d_obj
s :: str
r0 :: __main__.d_env
r1, inner :: object
r2, r3 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = '?'
r3 = PyUnicode_Concat(s, r2)
return r3
def d(num):
num :: float
r0 :: __main__.d_env
r1 :: __main__.inner_d_obj
r2, r3 :: bool
r4 :: str
r5, r6 :: object
r7, a, r8 :: str
r9, r10 :: object
r11, b :: str
L0:
r0 = d_env()
r1 = inner_d_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.inner = r1; r3 = is_error
r4 = 'one'
r5 = r0.inner
r6 = PyObject_CallFunctionObjArgs(r5, r4, 0)
r7 = cast(str, r6)
a = r7
r8 = 'two'
r9 = r0.inner
r10 = PyObject_CallFunctionObjArgs(r9, r8, 0)
r11 = cast(str, r10)
b = r11
return a
def inner():
r0 :: str
L0:
r0 = 'inner: normal function'
return r0
def first():
r0 :: str
L0:
r0 = 'first: normal function'
return r0
def second():
r0 :: str
L0:
r0 = 'second: normal function'
return r0
[case testFreeVars]
from typing import Callable
def a(num: int) -> int:
def inner() -> int:
return num
return inner()
def b() -> int:
num = 3
def inner() -> int:
nonlocal num
num = 4
foo = 6
return num
return inner() + num
def c(flag: bool) -> str:
if flag:
def inner() -> str:
return 'f.inner: first definition'
else:
def inner() -> str:
return 'f.inner: second definition'
return inner()
[out]
def inner_a_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_a_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_a_obj
r0 :: __main__.a_env
r1, inner :: object
r2 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = r0.num
return r2
def a(num):
num :: int
r0 :: __main__.a_env
r1 :: bool
r2 :: __main__.inner_a_obj
r3, r4 :: bool
r5, r6 :: object
r7 :: int
L0:
r0 = a_env()
r0.num = num; r1 = is_error
r2 = inner_a_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r0.inner = r2; r4 = is_error
r5 = r0.inner
r6 = PyObject_CallFunctionObjArgs(r5, 0)
r7 = unbox(int, r6)
return r7
def inner_b_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_b_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_b_obj
r0 :: __main__.b_env
r1, inner :: object
r2 :: bool
foo, r3 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r0.num = 8; r2 = is_error
foo = 12
r3 = r0.num
return r3
def b():
r0 :: __main__.b_env
r1 :: bool
r2 :: __main__.inner_b_obj
r3, r4 :: bool
r5, r6 :: object
r7, r8, r9 :: int
L0:
r0 = b_env()
r0.num = 6; r1 = is_error
r2 = inner_b_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r0.inner = r2; r4 = is_error
r5 = r0.inner
r6 = PyObject_CallFunctionObjArgs(r5, 0)
r7 = unbox(int, r6)
r8 = r0.num
r9 = CPyTagged_Add(r7, r8)
return r9
def inner_c_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_c_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_c_obj
r0 :: __main__.c_env
r1, inner :: object
r2 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = 'f.inner: first definition'
return r2
def inner_c_obj_0.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_c_obj_0.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_c_obj_0
r0 :: __main__.c_env
r1, inner :: object
r2 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = 'f.inner: second definition'
return r2
def c(flag):
flag :: bool
r0 :: __main__.c_env
r1 :: __main__.inner_c_obj
r2, r3 :: bool
r4 :: __main__.inner_c_obj_0
r5, r6 :: bool
r7, r8 :: object
r9 :: str
L0:
r0 = c_env()
if flag goto L1 else goto L2 :: bool
L1:
r1 = inner_c_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.inner = r1; r3 = is_error
goto L3
L2:
r4 = inner_c_obj_0()
r4.__mypyc_env__ = r0; r5 = is_error
r0.inner = r4; r6 = is_error
L3:
r7 = r0.inner
r8 = PyObject_CallFunctionObjArgs(r7, 0)
r9 = cast(str, r8)
return r9
[case testSpecialNested]
def a() -> int:
x = 1
def b() -> int:
x += 1
def c() -> int:
return x
return c()
return b()
[out]
def c_a_b_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def c_a_b_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.c_a_b_obj
r0 :: __main__.b_a_env
r1 :: __main__.a_env
r2, c :: object
r3 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.__mypyc_env__
r2 = r0.c
c = r2
r3 = r1.x
return r3
def b_a_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def b_a_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.b_a_obj
r0 :: __main__.a_env
r1, b :: object
r2 :: __main__.b_a_env
r3 :: bool
r4, r5 :: int
r6 :: bool
r7 :: __main__.c_a_b_obj
r8, r9 :: bool
r10, r11 :: object
r12 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.b
b = r1
r2 = b_a_env()
r2.__mypyc_env__ = r0; r3 = is_error
r4 = r0.x
r5 = CPyTagged_Add(r4, 2)
r0.x = r5; r6 = is_error
r7 = c_a_b_obj()
r7.__mypyc_env__ = r2; r8 = is_error
r2.c = r7; r9 = is_error
r10 = r2.c
r11 = PyObject_CallFunctionObjArgs(r10, 0)
r12 = unbox(int, r11)
return r12
def a():
r0 :: __main__.a_env
r1 :: bool
r2 :: __main__.b_a_obj
r3, r4 :: bool
r5, r6 :: object
r7 :: int
L0:
r0 = a_env()
r0.x = 2; r1 = is_error
r2 = b_a_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r0.b = r2; r4 = is_error
r5 = r0.b
r6 = PyObject_CallFunctionObjArgs(r5, 0)
r7 = unbox(int, r6)
return r7
[case testNestedFunctionInsideStatements]
def f(flag: bool) -> str:
if flag:
def inner() -> str:
return 'f.inner: first definition'
else:
def inner() -> str:
return 'f.inner: second definition'
return inner()
[out]
def inner_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_f_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_f_obj
r0 :: __main__.f_env
r1, inner :: object
r2 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = 'f.inner: first definition'
return r2
def inner_f_obj_0.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def inner_f_obj_0.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.inner_f_obj_0
r0 :: __main__.f_env
r1, inner :: object
r2 :: str
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.inner
inner = r1
r2 = 'f.inner: second definition'
return r2
def f(flag):
flag :: bool
r0 :: __main__.f_env
r1 :: __main__.inner_f_obj
r2, r3 :: bool
r4 :: __main__.inner_f_obj_0
r5, r6 :: bool
r7, r8 :: object
r9 :: str
L0:
r0 = f_env()
if flag goto L1 else goto L2 :: bool
L1:
r1 = inner_f_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.inner = r1; r3 = is_error
goto L3
L2:
r4 = inner_f_obj_0()
r4.__mypyc_env__ = r0; r5 = is_error
r0.inner = r4; r6 = is_error
L3:
r7 = r0.inner
r8 = PyObject_CallFunctionObjArgs(r7, 0)
r9 = cast(str, r8)
return r9
[case testNestedFunctionsCallEachOther]
from typing import Callable, List
def f(a: int) -> int:
def foo() -> int:
return a + 1
def bar() -> int:
return foo()
def baz(n: int) -> int:
if n == 0:
return 0
return n + baz(n - 1)
return bar() + baz(a)
[out]
def foo_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def foo_f_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.foo_f_obj
r0 :: __main__.f_env
r1, foo :: object
r2, r3 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.foo
foo = r1
r2 = r0.a
r3 = CPyTagged_Add(r2, 2)
return r3
def bar_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def bar_f_obj.__call__(__mypyc_self__):
__mypyc_self__ :: __main__.bar_f_obj
r0 :: __main__.f_env
r1, bar, r2, r3 :: object
r4 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.bar
bar = r1
r2 = r0.foo
r3 = PyObject_CallFunctionObjArgs(r2, 0)
r4 = unbox(int, r3)
return r4
def baz_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def baz_f_obj.__call__(__mypyc_self__, n):
__mypyc_self__ :: __main__.baz_f_obj
n :: int
r0 :: __main__.f_env
r1, baz :: object
r2 :: bit
r3 :: int
r4, r5 :: object
r6, r7 :: int
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.baz
baz = r1
r2 = n == 0
if r2 goto L1 else goto L2 :: bool
L1:
return 0
L2:
r3 = CPyTagged_Subtract(n, 2)
r4 = box(int, r3)
r5 = PyObject_CallFunctionObjArgs(baz, r4, 0)
r6 = unbox(int, r5)
r7 = CPyTagged_Add(n, r6)
return r7
def f(a):
a :: int
r0 :: __main__.f_env
r1 :: bool
r2 :: __main__.foo_f_obj
r3, r4 :: bool
r5 :: __main__.bar_f_obj
r6, r7 :: bool
r8 :: __main__.baz_f_obj
r9, r10 :: bool
r11, r12 :: object
r13, r14 :: int
r15, r16, r17 :: object
r18, r19 :: int
L0:
r0 = f_env()
r0.a = a; r1 = is_error
r2 = foo_f_obj()
r2.__mypyc_env__ = r0; r3 = is_error
r0.foo = r2; r4 = is_error
r5 = bar_f_obj()
r5.__mypyc_env__ = r0; r6 = is_error
r0.bar = r5; r7 = is_error
r8 = baz_f_obj()
r8.__mypyc_env__ = r0; r9 = is_error
r0.baz = r8; r10 = is_error
r11 = r0.bar
r12 = PyObject_CallFunctionObjArgs(r11, 0)
r13 = unbox(int, r12)
r14 = r0.a
r15 = r0.baz
r16 = box(int, r14)
r17 = PyObject_CallFunctionObjArgs(r15, r16, 0)
r18 = unbox(int, r17)
r19 = CPyTagged_Add(r13, r18)
return r19
[case testLambdas]
def f(x: int, y: int) -> None:
s = lambda a, b: a + b
t = lambda a, b: s(a, b)
return t(x, y)
[out]
def __mypyc_lambda__0_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def __mypyc_lambda__0_f_obj.__call__(__mypyc_self__, a, b):
__mypyc_self__ :: __main__.__mypyc_lambda__0_f_obj
a, b :: object
r0 :: __main__.f_env
r1 :: object
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = PyNumber_Add(a, b)
return r1
def __mypyc_lambda__1_f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def __mypyc_lambda__1_f_obj.__call__(__mypyc_self__, a, b):
__mypyc_self__ :: __main__.__mypyc_lambda__1_f_obj
a, b :: object
r0 :: __main__.f_env
r1, r2 :: object
L0:
r0 = __mypyc_self__.__mypyc_env__
r1 = r0.s
r2 = PyObject_CallFunctionObjArgs(r1, a, b, 0)
return r2
def f(x, y):
x, y :: int
r0 :: __main__.f_env
r1 :: __main__.__mypyc_lambda__0_f_obj
r2, r3 :: bool
r4 :: __main__.__mypyc_lambda__1_f_obj
r5 :: bool
t, r6, r7, r8 :: object
r9 :: None
L0:
r0 = f_env()
r1 = __mypyc_lambda__0_f_obj()
r1.__mypyc_env__ = r0; r2 = is_error
r0.s = r1; r3 = is_error
r4 = __mypyc_lambda__1_f_obj()
r4.__mypyc_env__ = r0; r5 = is_error
t = r4
r6 = box(int, x)
r7 = box(int, y)
r8 = PyObject_CallFunctionObjArgs(t, r6, r7, 0)
r9 = unbox(None, r8)
return r9
[case testRecursiveFunction]
from typing import Callable
def baz(n: int) -> int:
if n == 0:
return 0
return n + baz(n - 1)
[out]
def baz(n):
n :: int
r0 :: bit
r1, r2, r3 :: int
L0:
r0 = n == 0
if r0 goto L1 else goto L2 :: bool
L1:
return 0
L2:
r1 = CPyTagged_Subtract(n, 2)
r2 = baz(r1)
r3 = CPyTagged_Add(n, r2)
return r3

View File

@@ -0,0 +1,536 @@
[case testIsNone]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> int:
if x is None:
return 1
return 2
[out]
def f(x):
x :: union[__main__.A, None]
r0 :: object
r1 :: bit
L0:
r0 = load_address _Py_NoneStruct
r1 = x == r0
if r1 goto L1 else goto L2 :: bool
L1:
return 2
L2:
return 4
[case testIsNotNone]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> int:
if x is not None:
return 1
return 2
[out]
def f(x):
x :: union[__main__.A, None]
r0 :: object
r1 :: bit
L0:
r0 = load_address _Py_NoneStruct
r1 = x != r0
if r1 goto L1 else goto L2 :: bool
L1:
return 2
L2:
return 4
[case testIsTruthy]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> int:
if x:
return 1
return 2
[out]
def f(x):
x :: union[__main__.A, None]
r0 :: object
r1 :: bit
L0:
r0 = load_address _Py_NoneStruct
r1 = x != r0
if r1 goto L1 else goto L2 :: bool
L1:
return 2
L2:
return 4
[case testIsTruthyOverride]
from typing import Optional
class A: pass
class B(A):
def __bool__(self) -> bool:
return False
def f(x: Optional[A]) -> int:
if x:
return 1
return 2
[out]
def B.__bool__(self):
self :: __main__.B
L0:
return 0
def f(x):
x :: union[__main__.A, None]
r0 :: object
r1 :: bit
r2 :: __main__.A
r3 :: i32
r4 :: bit
r5 :: bool
L0:
r0 = load_address _Py_NoneStruct
r1 = x != r0
if r1 goto L1 else goto L3 :: bool
L1:
r2 = cast(__main__.A, x)
r3 = PyObject_IsTrue(r2)
r4 = r3 >= 0 :: signed
r5 = truncate r3: i32 to builtins.bool
if r5 goto L2 else goto L3 :: bool
L2:
return 2
L3:
return 4
[case testAssignToOptional]
from typing import Optional
class A:
a: Optional[int]
def f(x: Optional[A], y: Optional[A], z: Optional[int]) -> None:
x = None
x = A()
x = y
z = 1
a = A()
a.a = 1
a.a = None
[out]
def f(x, y, z):
x, y :: union[__main__.A, None]
z :: union[int, None]
r0 :: object
r1 :: __main__.A
r2 :: object
r3, a :: __main__.A
r4 :: object
r5 :: bool
r6 :: object
r7 :: bool
L0:
r0 = box(None, 1)
x = r0
r1 = A()
x = r1
x = y
r2 = object 1
z = r2
r3 = A()
a = r3
r4 = object 1
a.a = r4; r5 = is_error
r6 = box(None, 1)
a.a = r6; r7 = is_error
return 1
[case testBoxOptionalListItem]
from typing import List, Optional
def f(x: List[Optional[int]]) -> None:
x[0] = 0
x[1] = None
[out]
def f(x):
x :: list
r0 :: object
r1 :: bit
r2 :: object
r3 :: bit
L0:
r0 = object 0
r1 = CPyList_SetItem(x, 0, r0)
r2 = box(None, 1)
r3 = CPyList_SetItem(x, 2, r2)
return 1
[case testNarrowDownFromOptional]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> A:
y = A()
if x is not None:
y = x
return x
return y
[out]
def f(x):
x :: union[__main__.A, None]
r0, y :: __main__.A
r1 :: object
r2 :: bit
r3, r4 :: __main__.A
L0:
r0 = A()
y = r0
r1 = load_address _Py_NoneStruct
r2 = x != r1
if r2 goto L1 else goto L2 :: bool
L1:
r3 = cast(__main__.A, x)
y = r3
r4 = cast(__main__.A, x)
return r4
L2:
return y
[case testPartialOptionalType]
def f(y: int) -> None:
x = None
if y == 1:
x = y
if x is not None:
y = x
[out]
def f(y):
y :: int
r0 :: object
x :: union[int, None]
r1 :: bit
r2, r3 :: object
r4 :: bit
r5 :: int
L0:
r0 = box(None, 1)
x = r0
r1 = y == 2
if r1 goto L1 else goto L2 :: bool
L1:
r2 = box(int, y)
x = r2
L2:
r3 = load_address _Py_NoneStruct
r4 = x != r3
if r4 goto L3 else goto L4 :: bool
L3:
r5 = unbox(int, x)
y = r5
L4:
return 1
[case testUnionType]
from typing import Union
class A:
a: int
def f(x: Union[int, A]) -> int:
if isinstance(x, int):
return x + 1
else:
return x.a
[out]
def f(x):
x :: union[int, __main__.A]
r0 :: object
r1 :: i32
r2 :: bit
r3 :: bool
r4, r5 :: int
r6 :: __main__.A
r7 :: int
L0:
r0 = load_address PyLong_Type
r1 = PyObject_IsInstance(x, r0)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
if r3 goto L1 else goto L2 :: bool
L1:
r4 = unbox(int, x)
r5 = CPyTagged_Add(r4, 2)
return r5
L2:
r6 = borrow cast(__main__.A, x)
r7 = r6.a
keep_alive x
return r7
L3:
unreachable
[case testUnionTypeInList]
from typing import List, Union
def f(x: List[Union[int, str]]) -> object:
return x[0]
[out]
def f(x):
x :: list
r0 :: object
r1 :: union[int, str]
L0:
r0 = CPyList_GetItemShort(x, 0)
r1 = cast(union[int, str], r0)
return r1
[case testUnionAttributeAccess]
from typing import Union
class A:
a: int
class B:
a: object
def get(o: Union[A, B]) -> None:
z = o.a
def set(o: Union[A, B], s: str) -> None:
o.a = s
[out]
def get(o):
o :: union[__main__.A, __main__.B]
r0 :: object
r1 :: ptr
r2 :: object
r3 :: bit
r4 :: __main__.A
r5 :: int
r6, r7 :: object
r8 :: __main__.B
r9, z :: object
L0:
r0 = __main__.A :: type
r1 = get_element_ptr o ob_type :: PyObject
r2 = load_mem r1 :: builtins.object*
keep_alive o
r3 = r2 == r0
if r3 goto L1 else goto L2 :: bool
L1:
r4 = cast(__main__.A, o)
r5 = r4.a
r6 = box(int, r5)
r7 = r6
goto L3
L2:
r8 = cast(__main__.B, o)
r9 = r8.a
r7 = r9
L3:
z = r7
return 1
def set(o, s):
o :: union[__main__.A, __main__.B]
s, r0 :: str
r1 :: i32
r2 :: bit
L0:
r0 = 'a'
r1 = PyObject_SetAttr(o, r0, s)
r2 = r1 >= 0 :: signed
return 1
[case testUnionMethodCall]
from typing import Union
class A:
def f(self, x: int) -> int:
return x
class B:
def f(self, x: object) -> object:
return x
class C:
def f(self, x: object) -> int:
return 0
def g(o: Union[A, B, C]) -> None:
z = o.f(1)
[out]
def A.f(self, x):
self :: __main__.A
x :: int
L0:
return x
def B.f(self, x):
self :: __main__.B
x :: object
L0:
return x
def C.f(self, x):
self :: __main__.C
x :: object
L0:
return 0
def g(o):
o :: union[__main__.A, __main__.B, __main__.C]
r0 :: object
r1 :: ptr
r2 :: object
r3 :: bit
r4 :: __main__.A
r5 :: int
r6, r7, r8 :: object
r9 :: ptr
r10 :: object
r11 :: bit
r12 :: __main__.B
r13, r14 :: object
r15 :: __main__.C
r16 :: object
r17 :: int
r18, z :: object
L0:
r0 = __main__.A :: type
r1 = get_element_ptr o ob_type :: PyObject
r2 = load_mem r1 :: builtins.object*
keep_alive o
r3 = r2 == r0
if r3 goto L1 else goto L2 :: bool
L1:
r4 = cast(__main__.A, o)
r5 = r4.f(2)
r6 = box(int, r5)
r7 = r6
goto L5
L2:
r8 = __main__.B :: type
r9 = get_element_ptr o ob_type :: PyObject
r10 = load_mem r9 :: builtins.object*
keep_alive o
r11 = r10 == r8
if r11 goto L3 else goto L4 :: bool
L3:
r12 = cast(__main__.B, o)
r13 = object 1
r14 = r12.f(r13)
r7 = r14
goto L5
L4:
r15 = cast(__main__.C, o)
r16 = object 1
r17 = r15.f(r16)
r18 = box(int, r17)
r7 = r18
L5:
z = r7
return 1
[case testUnionWithNonNativeItem]
from typing import Union
from m import B
class A:
x: int
def f(o: Union[A, B]) -> None:
o.x
def g(o: Union[B, A]) -> None:
o.x
[file m.py]
class B:
x: int
[out]
def f(o):
o :: union[__main__.A, object]
r0 :: object
r1 :: ptr
r2 :: object
r3 :: bit
r4 :: __main__.A
r5, r6 :: int
r7 :: object
r8 :: str
r9 :: object
r10 :: int
L0:
r0 = __main__.A :: type
r1 = get_element_ptr o ob_type :: PyObject
r2 = load_mem r1 :: builtins.object*
keep_alive o
r3 = r2 == r0
if r3 goto L1 else goto L2 :: bool
L1:
r4 = cast(__main__.A, o)
r5 = r4.x
r6 = r5
goto L3
L2:
r7 = o
r8 = 'x'
r9 = CPyObject_GetAttr(r7, r8)
r10 = unbox(int, r9)
r6 = r10
L3:
return 1
def g(o):
o :: union[object, __main__.A]
r0 :: object
r1 :: ptr
r2 :: object
r3 :: bit
r4 :: __main__.A
r5, r6 :: int
r7 :: object
r8 :: str
r9 :: object
r10 :: int
L0:
r0 = __main__.A :: type
r1 = get_element_ptr o ob_type :: PyObject
r2 = load_mem r1 :: builtins.object*
keep_alive o
r3 = r2 == r0
if r3 goto L1 else goto L2 :: bool
L1:
r4 = cast(__main__.A, o)
r5 = r4.x
r6 = r5
goto L3
L2:
r7 = o
r8 = 'x'
r9 = CPyObject_GetAttr(r7, r8)
r10 = unbox(int, r9)
r6 = r10
L3:
return 1
[case testUnionWithNoNativeItems]
from typing import Union
from m import A, B
def f(o: Union[A, B]) -> None:
o.x
[file m.py]
class A:
x: object
class B:
x: int
[out]
def f(o):
o :: object
r0 :: str
r1 :: object
L0:
r0 = 'x'
r1 = CPyObject_GetAttr(o, r0)
return 1

View File

@@ -0,0 +1,838 @@
[case testNewSet]
from typing import Set
def f() -> Set[int]:
return {1, 2, 3}
[out]
def f():
r0 :: set
r1 :: object
r2 :: i32
r3 :: bit
r4 :: object
r5 :: i32
r6 :: bit
r7 :: object
r8 :: i32
r9 :: bit
L0:
r0 = PySet_New(0)
r1 = object 1
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = object 2
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
r7 = object 3
r8 = PySet_Add(r0, r7)
r9 = r8 >= 0 :: signed
return r0
[case testNewEmptySet]
from typing import Set
def f() -> Set[int]:
return set()
[out]
def f():
r0 :: set
L0:
r0 = PySet_New(0)
return r0
[case testNewSetFromIterable]
from typing import Set, List
def f(l: List[T]) -> Set[T]:
return set(l)
[out]
def f(l):
l :: list
r0 :: set
L0:
r0 = PySet_New(l)
return r0
[case testNewSetFromIterable2]
def f(x: int) -> int:
return x
def test1() -> None:
tmp_list = [1, 3, 5]
a = set(f(x) for x in tmp_list)
def test2() -> None:
tmp_tuple = (1, 3, 5)
b = set(f(x) for x in tmp_tuple)
def test3() -> None:
tmp_dict = {1: '1', 3: '3', 5: '5'}
c = set(f(x) for x in tmp_dict)
def test4() -> None:
d = set(f(x) for x in range(1, 6, 2))
def test5() -> None:
e = set((f(x) for x in range(1, 6, 2)))
[out]
def f(x):
x :: int
L0:
return x
def test1():
r0 :: list
r1, r2, r3 :: object
r4, r5, r6, r7 :: ptr
tmp_list :: list
r8 :: set
r9 :: short_int
r10 :: ptr
r11 :: native_int
r12 :: short_int
r13 :: bit
r14 :: object
r15, x, r16 :: int
r17 :: object
r18 :: i32
r19 :: bit
r20 :: short_int
a :: set
L0:
r0 = PyList_New(3)
r1 = object 1
r2 = object 3
r3 = object 5
r4 = get_element_ptr r0 ob_item :: PyListObject
r5 = load_mem r4 :: ptr*
set_mem r5, r1 :: builtins.object*
r6 = r5 + WORD_SIZE*1
set_mem r6, r2 :: builtins.object*
r7 = r5 + WORD_SIZE*2
set_mem r7, r3 :: builtins.object*
keep_alive r0
tmp_list = r0
r8 = PySet_New(0)
r9 = 0
L1:
r10 = get_element_ptr tmp_list ob_size :: PyVarObject
r11 = load_mem r10 :: native_int*
keep_alive tmp_list
r12 = r11 << 1
r13 = r9 < r12 :: signed
if r13 goto L2 else goto L4 :: bool
L2:
r14 = CPyList_GetItemUnsafe(tmp_list, r9)
r15 = unbox(int, r14)
x = r15
r16 = f(x)
r17 = box(int, r16)
r18 = PySet_Add(r8, r17)
r19 = r18 >= 0 :: signed
L3:
r20 = r9 + 2
r9 = r20
goto L1
L4:
a = r8
return 1
def test2():
r0, tmp_tuple :: tuple[int, int, int]
r1 :: set
r2, r3, r4 :: object
r5, x, r6 :: int
r7 :: object
r8 :: i32
r9, r10 :: bit
b :: set
L0:
r0 = (2, 6, 10)
tmp_tuple = r0
r1 = PySet_New(0)
r2 = box(tuple[int, int, int], tmp_tuple)
r3 = PyObject_GetIter(r2)
L1:
r4 = PyIter_Next(r3)
if is_error(r4) goto L4 else goto L2
L2:
r5 = unbox(int, r4)
x = r5
r6 = f(x)
r7 = box(int, r6)
r8 = PySet_Add(r1, r7)
r9 = r8 >= 0 :: signed
L3:
goto L1
L4:
r10 = CPy_NoErrOccured()
L5:
b = r1
return 1
def test3():
r0, r1, r2 :: str
r3, r4, r5 :: object
r6, tmp_dict :: dict
r7 :: set
r8 :: short_int
r9 :: native_int
r10 :: short_int
r11 :: object
r12 :: tuple[bool, short_int, object]
r13 :: short_int
r14 :: bool
r15 :: object
r16, x, r17 :: int
r18 :: object
r19 :: i32
r20, r21, r22 :: bit
c :: set
L0:
r0 = '1'
r1 = '3'
r2 = '5'
r3 = object 1
r4 = object 3
r5 = object 5
r6 = CPyDict_Build(3, r3, r0, r4, r1, r5, r2)
tmp_dict = r6
r7 = PySet_New(0)
r8 = 0
r9 = PyDict_Size(tmp_dict)
r10 = r9 << 1
r11 = CPyDict_GetKeysIter(tmp_dict)
L1:
r12 = CPyDict_NextKey(r11, r8)
r13 = r12[1]
r8 = r13
r14 = r12[0]
if r14 goto L2 else goto L4 :: bool
L2:
r15 = r12[2]
r16 = unbox(int, r15)
x = r16
r17 = f(x)
r18 = box(int, r17)
r19 = PySet_Add(r7, r18)
r20 = r19 >= 0 :: signed
L3:
r21 = CPyDict_CheckSize(tmp_dict, r10)
goto L1
L4:
r22 = CPy_NoErrOccured()
L5:
c = r7
return 1
def test4():
r0 :: set
r1 :: short_int
x :: int
r2 :: bit
r3 :: int
r4 :: object
r5 :: i32
r6 :: bit
r7 :: short_int
d :: set
L0:
r0 = PySet_New(0)
r1 = 2
x = r1
L1:
r2 = r1 < 12 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = f(x)
r4 = box(int, r3)
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
L3:
r7 = r1 + 4
r1 = r7
x = r7
goto L1
L4:
d = r0
return 1
def test5():
r0 :: set
r1 :: short_int
x :: int
r2 :: bit
r3 :: int
r4 :: object
r5 :: i32
r6 :: bit
r7 :: short_int
e :: set
L0:
r0 = PySet_New(0)
r1 = 2
x = r1
L1:
r2 = r1 < 12 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = f(x)
r4 = box(int, r3)
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
L3:
r7 = r1 + 4
r1 = r7
x = r7
goto L1
L4:
e = r0
return 1
[case testNewSetFromIterable3]
def f1(x: int) -> int:
return x
def f2(x: int) -> int:
return x * 10
def f3(x: int) -> int:
return x + 1
def test() -> None:
tmp_list = [1, 2, 3, 4, 5]
a = set(f3(x) for x in (f2(y) for y in (f1(z) for z in tmp_list if z < 4)))
[out]
def f1(x):
x :: int
L0:
return x
def f2(x):
x, r0 :: int
L0:
r0 = CPyTagged_Multiply(x, 20)
return r0
def f3(x):
x, r0 :: int
L0:
r0 = CPyTagged_Add(x, 2)
return r0
def test():
r0 :: list
r1, r2, r3, r4, r5 :: object
r6, r7, r8, r9, r10, r11 :: ptr
tmp_list :: list
r12 :: set
r13, r14 :: list
r15 :: short_int
r16 :: ptr
r17 :: native_int
r18 :: short_int
r19 :: bit
r20 :: object
r21, z :: int
r22 :: native_int
r23 :: bit
r24 :: native_int
r25, r26, r27 :: bit
r28 :: bool
r29 :: bit
r30 :: int
r31 :: object
r32 :: i32
r33 :: bit
r34 :: short_int
r35, r36, r37 :: object
r38, y, r39 :: int
r40 :: object
r41 :: i32
r42, r43 :: bit
r44, r45, r46 :: object
r47, x, r48 :: int
r49 :: object
r50 :: i32
r51, r52 :: bit
a :: set
L0:
r0 = PyList_New(5)
r1 = object 1
r2 = object 2
r3 = object 3
r4 = object 4
r5 = object 5
r6 = get_element_ptr r0 ob_item :: PyListObject
r7 = load_mem r6 :: ptr*
set_mem r7, r1 :: builtins.object*
r8 = r7 + WORD_SIZE*1
set_mem r8, r2 :: builtins.object*
r9 = r7 + WORD_SIZE*2
set_mem r9, r3 :: builtins.object*
r10 = r7 + WORD_SIZE*3
set_mem r10, r4 :: builtins.object*
r11 = r7 + WORD_SIZE*4
set_mem r11, r5 :: builtins.object*
keep_alive r0
tmp_list = r0
r12 = PySet_New(0)
r13 = PyList_New(0)
r14 = PyList_New(0)
r15 = 0
L1:
r16 = get_element_ptr tmp_list ob_size :: PyVarObject
r17 = load_mem r16 :: native_int*
keep_alive tmp_list
r18 = r17 << 1
r19 = r15 < r18 :: signed
if r19 goto L2 else goto L9 :: bool
L2:
r20 = CPyList_GetItemUnsafe(tmp_list, r15)
r21 = unbox(int, r20)
z = r21
r22 = z & 1
r23 = r22 == 0
r24 = 8 & 1
r25 = r24 == 0
r26 = r23 & r25
if r26 goto L3 else goto L4 :: bool
L3:
r27 = z < 8 :: signed
r28 = r27
goto L5
L4:
r29 = CPyTagged_IsLt_(z, 8)
r28 = r29
L5:
if r28 goto L7 else goto L6 :: bool
L6:
goto L8
L7:
r30 = f1(z)
r31 = box(int, r30)
r32 = PyList_Append(r14, r31)
r33 = r32 >= 0 :: signed
L8:
r34 = r15 + 2
r15 = r34
goto L1
L9:
r35 = PyObject_GetIter(r14)
r36 = PyObject_GetIter(r35)
L10:
r37 = PyIter_Next(r36)
if is_error(r37) goto L13 else goto L11
L11:
r38 = unbox(int, r37)
y = r38
r39 = f2(y)
r40 = box(int, r39)
r41 = PyList_Append(r13, r40)
r42 = r41 >= 0 :: signed
L12:
goto L10
L13:
r43 = CPy_NoErrOccured()
L14:
r44 = PyObject_GetIter(r13)
r45 = PyObject_GetIter(r44)
L15:
r46 = PyIter_Next(r45)
if is_error(r46) goto L18 else goto L16
L16:
r47 = unbox(int, r46)
x = r47
r48 = f3(x)
r49 = box(int, r48)
r50 = PySet_Add(r12, r49)
r51 = r50 >= 0 :: signed
L17:
goto L15
L18:
r52 = CPy_NoErrOccured()
L19:
a = r12
return 1
[case testSetSize]
from typing import Set
def f() -> int:
return len({1, 2, 3})
[out]
def f():
r0 :: set
r1 :: object
r2 :: i32
r3 :: bit
r4 :: object
r5 :: i32
r6 :: bit
r7 :: object
r8 :: i32
r9 :: bit
r10 :: ptr
r11 :: native_int
r12 :: short_int
L0:
r0 = PySet_New(0)
r1 = object 1
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = object 2
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
r7 = object 3
r8 = PySet_Add(r0, r7)
r9 = r8 >= 0 :: signed
r10 = get_element_ptr r0 used :: PySetObject
r11 = load_mem r10 :: native_int*
keep_alive r0
r12 = r11 << 1
return r12
[case testSetContains]
from typing import Set
def f() -> bool:
x = {3, 4}
return (5 in x)
[out]
def f():
r0 :: set
r1 :: object
r2 :: i32
r3 :: bit
r4 :: object
r5 :: i32
r6 :: bit
x :: set
r7 :: object
r8 :: i32
r9 :: bit
r10 :: bool
L0:
r0 = PySet_New(0)
r1 = object 3
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = object 4
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
x = r0
r7 = object 5
r8 = PySet_Contains(x, r7)
r9 = r8 >= 0 :: signed
r10 = truncate r8: i32 to builtins.bool
return r10
[case testSetRemove]
from typing import Set
def f() -> Set[int]:
x = set() # type: Set[int]
x.remove(1)
return x
[out]
def f():
r0, x :: set
r1 :: object
r2 :: bit
L0:
r0 = PySet_New(0)
x = r0
r1 = object 1
r2 = CPySet_Remove(x, r1)
return x
[case testSetDiscard]
from typing import Set
def f() -> Set[int]:
x = set() # type: Set[int]
x.discard(1)
return x
[out]
def f():
r0, x :: set
r1 :: object
r2 :: i32
r3 :: bit
L0:
r0 = PySet_New(0)
x = r0
r1 = object 1
r2 = PySet_Discard(x, r1)
r3 = r2 >= 0 :: signed
return x
[case testSetAdd]
from typing import Set
def f() -> Set[int]:
x = set() # type: Set[int]
x.add(1)
return x
[out]
def f():
r0, x :: set
r1 :: object
r2 :: i32
r3 :: bit
L0:
r0 = PySet_New(0)
x = r0
r1 = object 1
r2 = PySet_Add(x, r1)
r3 = r2 >= 0 :: signed
return x
[case testSetClear]
from typing import Set
def f() -> Set[int]:
x = set() # type: Set[int]
x.clear()
return x
[out]
def f():
r0, x :: set
r1 :: i32
r2 :: bit
L0:
r0 = PySet_New(0)
x = r0
r1 = PySet_Clear(x)
r2 = r1 >= 0 :: signed
return x
[case testSetPop]
from typing import Set
def f(s : Set[int]) -> int:
return s.pop()
[out]
def f(s):
s :: set
r0 :: object
r1 :: int
L0:
r0 = PySet_Pop(s)
r1 = unbox(int, r0)
return r1
[case testSetUpdate]
from typing import Set, List
def update(s: Set[int], x: List[int]) -> None:
s.update(x)
[out]
def update(s, x):
s :: set
x :: list
r0 :: i32
r1 :: bit
L0:
r0 = _PySet_Update(s, x)
r1 = r0 >= 0 :: signed
return 1
[case testSetDisplay]
from typing import Set
def f(x: Set[int], y: Set[int]) -> Set[int]:
return {1, 2, *x, *y, 3}
[out]
def f(x, y):
x, y, r0 :: set
r1 :: object
r2 :: i32
r3 :: bit
r4 :: object
r5 :: i32
r6 :: bit
r7 :: i32
r8 :: bit
r9 :: i32
r10 :: bit
r11 :: object
r12 :: i32
r13 :: bit
L0:
r0 = PySet_New(0)
r1 = object 1
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = object 2
r5 = PySet_Add(r0, r4)
r6 = r5 >= 0 :: signed
r7 = _PySet_Update(r0, x)
r8 = r7 >= 0 :: signed
r9 = _PySet_Update(r0, y)
r10 = r9 >= 0 :: signed
r11 = object 3
r12 = PySet_Add(r0, r11)
r13 = r12 >= 0 :: signed
return r0
[case testOperatorInSetLiteral]
from typing_extensions import Final
CONST: Final = "daylily"
non_const = 10
def precomputed(i: object) -> bool:
return i in {1, 2.0, 1 +2, 4j, "foo", b"bar", CONST, (None, (27,)), (), False}
def not_precomputed_non_final_name(i: int) -> bool:
return i in {non_const}
def not_precomputed_nested_set(i: int) -> bool:
return i in {frozenset({1}), 2}
[out]
def precomputed(i):
i :: object
r0 :: set
r1 :: i32
r2 :: bit
r3 :: bool
L0:
r0 = frozenset({(), (None, (27,)), 1, 2.0, 3, 4j, False, b'bar', 'daylily', 'foo'})
r1 = PySet_Contains(r0, i)
r2 = r1 >= 0 :: signed
r3 = truncate r1: i32 to builtins.bool
return r3
def not_precomputed_non_final_name(i):
i :: int
r0 :: dict
r1 :: str
r2 :: object
r3 :: int
r4 :: set
r5 :: object
r6 :: i32
r7 :: bit
r8 :: object
r9 :: i32
r10 :: bit
r11 :: bool
L0:
r0 = __main__.globals :: static
r1 = 'non_const'
r2 = CPyDict_GetItem(r0, r1)
r3 = unbox(int, r2)
r4 = PySet_New(0)
r5 = box(int, r3)
r6 = PySet_Add(r4, r5)
r7 = r6 >= 0 :: signed
r8 = box(int, i)
r9 = PySet_Contains(r4, r8)
r10 = r9 >= 0 :: signed
r11 = truncate r9: i32 to builtins.bool
return r11
def not_precomputed_nested_set(i):
i :: int
r0 :: set
r1 :: object
r2 :: i32
r3 :: bit
r4 :: object
r5 :: set
r6 :: i32
r7 :: bit
r8 :: object
r9 :: i32
r10 :: bit
r11 :: object
r12 :: i32
r13 :: bit
r14 :: bool
L0:
r0 = PySet_New(0)
r1 = object 1
r2 = PySet_Add(r0, r1)
r3 = r2 >= 0 :: signed
r4 = PyFrozenSet_New(r0)
r5 = PySet_New(0)
r6 = PySet_Add(r5, r4)
r7 = r6 >= 0 :: signed
r8 = object 2
r9 = PySet_Add(r5, r8)
r10 = r9 >= 0 :: signed
r11 = box(int, i)
r12 = PySet_Contains(r5, r11)
r13 = r12 >= 0 :: signed
r14 = truncate r12: i32 to builtins.bool
return r14
[case testForSetLiteral]
from typing_extensions import Final
CONST: Final = 10
non_const = 20
def precomputed() -> None:
for _ in {"None", "True", "False"}:
pass
def precomputed2() -> None:
for _ in {None, False, 1, 2.0, "4", b"5", (6,), 7j, CONST, CONST + 1}:
pass
def not_precomputed() -> None:
for not_optimized in {non_const}:
pass
[out]
def precomputed():
r0 :: set
r1, r2 :: object
r3 :: str
_ :: object
r4 :: bit
L0:
r0 = frozenset({'False', 'None', 'True'})
r1 = PyObject_GetIter(r0)
L1:
r2 = PyIter_Next(r1)
if is_error(r2) goto L4 else goto L2
L2:
r3 = cast(str, r2)
_ = r3
L3:
goto L1
L4:
r4 = CPy_NoErrOccured()
L5:
return 1
def precomputed2():
r0 :: set
r1, r2, _ :: object
r3 :: bit
L0:
r0 = frozenset({(6,), 1, 10, 11, 2.0, '4', 7j, False, None, b'5'})
r1 = PyObject_GetIter(r0)
L1:
r2 = PyIter_Next(r1)
if is_error(r2) goto L4 else goto L2
L2:
_ = r2
L3:
goto L1
L4:
r3 = CPy_NoErrOccured()
L5:
return 1
def not_precomputed():
r0 :: dict
r1 :: str
r2 :: object
r3 :: int
r4 :: set
r5 :: object
r6 :: i32
r7 :: bit
r8, r9 :: object
r10, not_optimized :: int
r11 :: bit
L0:
r0 = __main__.globals :: static
r1 = 'non_const'
r2 = CPyDict_GetItem(r0, r1)
r3 = unbox(int, r2)
r4 = PySet_New(0)
r5 = box(int, r3)
r6 = PySet_Add(r4, r5)
r7 = r6 >= 0 :: signed
r8 = PyObject_GetIter(r4)
L1:
r9 = PyIter_Next(r8)
if is_error(r9) goto L4 else goto L2
L2:
r10 = unbox(int, r9)
not_optimized = r10
L3:
goto L1
L4:
r11 = CPy_NoErrOccured()
L5:
return 1

View File

@@ -0,0 +1,257 @@
[case testNativeCallsUsedInDispatchFunction]
from functools import singledispatch
@singledispatch
def f(arg) -> bool:
return False
@f.register
def g(arg: int) -> bool:
return True
[out]
def __mypyc_singledispatch_main_function_f__(arg):
arg :: object
L0:
return 0
def f_obj.__init__(__mypyc_self__):
__mypyc_self__ :: __main__.f_obj
r0, r1 :: dict
r2 :: str
r3 :: i32
r4 :: bit
L0:
r0 = PyDict_New()
__mypyc_self__.registry = r0
r1 = PyDict_New()
r2 = 'dispatch_cache'
r3 = PyObject_SetAttr(__mypyc_self__, r2, r1)
r4 = r3 >= 0 :: signed
return 1
def f_obj.__call__(__mypyc_self__, arg):
__mypyc_self__ :: __main__.f_obj
arg :: object
r0 :: ptr
r1 :: object
r2 :: dict
r3, r4 :: object
r5 :: bit
r6, r7 :: object
r8 :: str
r9 :: object
r10 :: dict
r11 :: object
r12 :: i32
r13 :: bit
r14 :: object
r15 :: ptr
r16 :: object
r17 :: bit
r18 :: int
r19 :: bit
r20 :: int
r21 :: bool
r22 :: object
r23 :: bool
L0:
r0 = get_element_ptr arg ob_type :: PyObject
r1 = load_mem r0 :: builtins.object*
keep_alive arg
r2 = __mypyc_self__.dispatch_cache
r3 = CPyDict_GetWithNone(r2, r1)
r4 = load_address _Py_NoneStruct
r5 = r3 != r4
if r5 goto L1 else goto L2 :: bool
L1:
r6 = r3
goto L3
L2:
r7 = functools :: module
r8 = '_find_impl'
r9 = CPyObject_GetAttr(r7, r8)
r10 = __mypyc_self__.registry
r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0)
r12 = CPyDict_SetItem(r2, r1, r11)
r13 = r12 >= 0 :: signed
r6 = r11
L3:
r14 = load_address PyLong_Type
r15 = get_element_ptr r6 ob_type :: PyObject
r16 = load_mem r15 :: builtins.object*
keep_alive r6
r17 = r16 == r14
if r17 goto L4 else goto L7 :: bool
L4:
r18 = unbox(int, r6)
r19 = r18 == 0
if r19 goto L5 else goto L6 :: bool
L5:
r20 = unbox(int, arg)
r21 = g(r20)
return r21
L6:
unreachable
L7:
r22 = PyObject_CallFunctionObjArgs(r6, arg, 0)
r23 = unbox(bool, r22)
return r23
def f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def f_obj.register(__mypyc_self__, cls, func):
__mypyc_self__ :: __main__.f_obj
cls, func, r0 :: object
L0:
r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func)
return r0
def f(arg):
arg :: object
r0 :: dict
r1 :: str
r2 :: object
r3 :: bool
L0:
r0 = __main__.globals :: static
r1 = 'f'
r2 = CPyDict_GetItem(r0, r1)
r3 = f_obj.__call__(r2, arg)
return r3
def g(arg):
arg :: int
L0:
return 1
[case testCallsToSingledispatchFunctionsAreNative]
from functools import singledispatch
@singledispatch
def f(x: object) -> None:
pass
def test():
f('a')
[out]
def __mypyc_singledispatch_main_function_f__(x):
x :: object
L0:
return 1
def f_obj.__init__(__mypyc_self__):
__mypyc_self__ :: __main__.f_obj
r0, r1 :: dict
r2 :: str
r3 :: i32
r4 :: bit
L0:
r0 = PyDict_New()
__mypyc_self__.registry = r0
r1 = PyDict_New()
r2 = 'dispatch_cache'
r3 = PyObject_SetAttr(__mypyc_self__, r2, r1)
r4 = r3 >= 0 :: signed
return 1
def f_obj.__call__(__mypyc_self__, x):
__mypyc_self__ :: __main__.f_obj
x :: object
r0 :: ptr
r1 :: object
r2 :: dict
r3, r4 :: object
r5 :: bit
r6, r7 :: object
r8 :: str
r9 :: object
r10 :: dict
r11 :: object
r12 :: i32
r13 :: bit
r14 :: object
r15 :: ptr
r16 :: object
r17 :: bit
r18 :: int
r19 :: object
r20 :: None
L0:
r0 = get_element_ptr x ob_type :: PyObject
r1 = load_mem r0 :: builtins.object*
keep_alive x
r2 = __mypyc_self__.dispatch_cache
r3 = CPyDict_GetWithNone(r2, r1)
r4 = load_address _Py_NoneStruct
r5 = r3 != r4
if r5 goto L1 else goto L2 :: bool
L1:
r6 = r3
goto L3
L2:
r7 = functools :: module
r8 = '_find_impl'
r9 = CPyObject_GetAttr(r7, r8)
r10 = __mypyc_self__.registry
r11 = PyObject_CallFunctionObjArgs(r9, r1, r10, 0)
r12 = CPyDict_SetItem(r2, r1, r11)
r13 = r12 >= 0 :: signed
r6 = r11
L3:
r14 = load_address PyLong_Type
r15 = get_element_ptr r6 ob_type :: PyObject
r16 = load_mem r15 :: builtins.object*
keep_alive r6
r17 = r16 == r14
if r17 goto L4 else goto L5 :: bool
L4:
r18 = unbox(int, r6)
unreachable
L5:
r19 = PyObject_CallFunctionObjArgs(r6, x, 0)
r20 = unbox(None, r19)
return r20
def f_obj.__get__(__mypyc_self__, instance, owner):
__mypyc_self__, instance, owner, r0 :: object
r1 :: bit
r2 :: object
L0:
r0 = load_address _Py_NoneStruct
r1 = instance == r0
if r1 goto L1 else goto L2 :: bool
L1:
return __mypyc_self__
L2:
r2 = PyMethod_New(__mypyc_self__, instance)
return r2
def f_obj.register(__mypyc_self__, cls, func):
__mypyc_self__ :: __main__.f_obj
cls, func, r0 :: object
L0:
r0 = CPySingledispatch_RegisterFunction(__mypyc_self__, cls, func)
return r0
def f(x):
x :: object
r0 :: dict
r1 :: str
r2 :: object
r3 :: None
L0:
r0 = __main__.globals :: static
r1 = 'f'
r2 = CPyDict_GetItem(r0, r1)
r3 = f_obj.__call__(r2, x)
return r3
def test():
r0 :: str
r1 :: None
r2 :: object
L0:
r0 = 'a'
r1 = f(r0)
r2 = box(None, 1)
return r2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,314 @@
[case testStrSplit]
from typing import Optional, List
def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
if sep is not None:
if max_split is not None:
return s.split(sep, max_split)
else:
return s.split(sep)
return s.split()
[out]
def do_split(s, sep, max_split):
s :: str
sep :: union[str, None]
max_split :: union[int, None]
r0, r1, r2 :: object
r3 :: bit
r4 :: object
r5 :: bit
r6 :: str
r7 :: int
r8 :: list
r9 :: str
r10, r11 :: list
L0:
if is_error(sep) goto L1 else goto L2
L1:
r0 = box(None, 1)
sep = r0
L2:
if is_error(max_split) goto L3 else goto L4
L3:
r1 = box(None, 1)
max_split = r1
L4:
r2 = load_address _Py_NoneStruct
r3 = sep != r2
if r3 goto L5 else goto L9 :: bool
L5:
r4 = load_address _Py_NoneStruct
r5 = max_split != r4
if r5 goto L6 else goto L7 :: bool
L6:
r6 = cast(str, sep)
r7 = unbox(int, max_split)
r8 = CPyStr_Split(s, r6, r7)
return r8
L7:
r9 = cast(str, sep)
r10 = PyUnicode_Split(s, r9, -1)
return r10
L8:
L9:
r11 = PyUnicode_Split(s, 0, -1)
return r11
[case testStrEquality]
def eq(x: str, y: str) -> bool:
return x == y
def neq(x: str, y: str) -> bool:
return x != y
[out]
def eq(x, y):
x, y :: str
r0 :: i32
r1 :: bit
r2 :: object
r3, r4, r5 :: bit
L0:
r0 = PyUnicode_Compare(x, y)
r1 = r0 == -1
if r1 goto L1 else goto L3 :: bool
L1:
r2 = PyErr_Occurred()
r3 = r2 != 0
if r3 goto L2 else goto L3 :: bool
L2:
r4 = CPy_KeepPropagating()
L3:
r5 = r0 == 0
return r5
def neq(x, y):
x, y :: str
r0 :: i32
r1 :: bit
r2 :: object
r3, r4, r5 :: bit
L0:
r0 = PyUnicode_Compare(x, y)
r1 = r0 == -1
if r1 goto L1 else goto L3 :: bool
L1:
r2 = PyErr_Occurred()
r3 = r2 != 0
if r3 goto L2 else goto L3 :: bool
L2:
r4 = CPy_KeepPropagating()
L3:
r5 = r0 != 0
return r5
[case testStrReplace]
from typing import Optional
def do_replace(s: str, old_substr: str, new_substr: str, max_count: Optional[int] = None) -> str:
if max_count is not None:
return s.replace(old_substr, new_substr, max_count)
else:
return s.replace(old_substr, new_substr)
[out]
def do_replace(s, old_substr, new_substr, max_count):
s, old_substr, new_substr :: str
max_count :: union[int, None]
r0, r1 :: object
r2 :: bit
r3 :: int
r4, r5 :: str
L0:
if is_error(max_count) goto L1 else goto L2
L1:
r0 = box(None, 1)
max_count = r0
L2:
r1 = load_address _Py_NoneStruct
r2 = max_count != r1
if r2 goto L3 else goto L4 :: bool
L3:
r3 = unbox(int, max_count)
r4 = CPyStr_Replace(s, old_substr, new_substr, r3)
return r4
L4:
r5 = PyUnicode_Replace(s, old_substr, new_substr, -1)
return r5
L5:
unreachable
[case testStrToBool]
def is_true(x: str) -> bool:
if x:
return True
else:
return False
[out]
def is_true(x):
x :: str
r0 :: bit
L0:
r0 = CPyStr_IsTrue(x)
if r0 goto L1 else goto L2 :: bool
L1:
return 1
L2:
return 0
L3:
unreachable
[case testStringFormatMethod]
def f(s: str, num: int) -> None:
s1 = "Hi! I'm {}, and I'm {} years old.".format(s, num)
s2 = ''.format()
s3 = 'abc'.format()
s4 = '}}{}{{{}}}{{{}'.format(num, num, num)
[out]
def f(s, num):
s :: str
num :: int
r0, r1, r2, r3, r4, s1, r5, s2, r6, s3, r7, r8, r9, r10, r11, r12, r13, s4 :: str
L0:
r0 = CPyTagged_Str(num)
r1 = "Hi! I'm "
r2 = ", and I'm "
r3 = ' years old.'
r4 = CPyStr_Build(5, r1, s, r2, r0, r3)
s1 = r4
r5 = ''
s2 = r5
r6 = 'abc'
s3 = r6
r7 = CPyTagged_Str(num)
r8 = CPyTagged_Str(num)
r9 = CPyTagged_Str(num)
r10 = '}'
r11 = '{'
r12 = '}{'
r13 = CPyStr_Build(6, r10, r7, r11, r8, r12, r9)
s4 = r13
return 1
[case testFStrings]
def f(var: str, num: int) -> None:
s1 = f"Hi! I'm {var}. I am {num} years old."
s2 = f'Hello {var:>{num}}'
s3 = f''
s4 = f'abc'
[out]
def f(var, num):
var :: str
num :: int
r0, r1, r2, r3, r4, s1, r5, r6, r7, r8, r9, r10, r11 :: str
r12 :: object
r13 :: str
r14 :: list
r15, r16, r17 :: ptr
r18, s2, r19, s3, r20, s4 :: str
L0:
r0 = "Hi! I'm "
r1 = '. I am '
r2 = CPyTagged_Str(num)
r3 = ' years old.'
r4 = CPyStr_Build(5, r0, var, r1, r2, r3)
s1 = r4
r5 = ''
r6 = 'Hello '
r7 = '{:{}}'
r8 = '>'
r9 = CPyTagged_Str(num)
r10 = CPyStr_Build(2, r8, r9)
r11 = 'format'
r12 = CPyObject_CallMethodObjArgs(r7, r11, var, r10, 0)
r13 = cast(str, r12)
r14 = PyList_New(2)
r15 = get_element_ptr r14 ob_item :: PyListObject
r16 = load_mem r15 :: ptr*
set_mem r16, r6 :: builtins.object*
r17 = r16 + WORD_SIZE*1
set_mem r17, r13 :: builtins.object*
keep_alive r14
r18 = PyUnicode_Join(r5, r14)
s2 = r18
r19 = ''
s3 = r19
r20 = 'abc'
s4 = r20
return 1
[case testStringFormattingCStyle]
def f(var: str, num: int) -> None:
s1 = "Hi! I'm %s." % var
s2 = "I am %d years old." % num
s3 = "Hi! I'm %s. I am %d years old." % (var, num)
s4 = "Float: %f" % num
[typing fixtures/typing-full.pyi]
[out]
def f(var, num):
var :: str
num :: int
r0, r1, r2, s1, r3, r4, r5, r6, s2, r7, r8, r9, r10, r11, s3, r12 :: str
r13, r14 :: object
r15, s4 :: str
L0:
r0 = "Hi! I'm "
r1 = '.'
r2 = CPyStr_Build(3, r0, var, r1)
s1 = r2
r3 = CPyTagged_Str(num)
r4 = 'I am '
r5 = ' years old.'
r6 = CPyStr_Build(3, r4, r3, r5)
s2 = r6
r7 = CPyTagged_Str(num)
r8 = "Hi! I'm "
r9 = '. I am '
r10 = ' years old.'
r11 = CPyStr_Build(5, r8, var, r9, r7, r10)
s3 = r11
r12 = 'Float: %f'
r13 = box(int, num)
r14 = PyNumber_Remainder(r12, r13)
r15 = cast(str, r14)
s4 = r15
return 1
[case testDecode]
def f(b: bytes) -> None:
b.decode()
b.decode('utf-8')
b.decode('utf-8', 'backslashreplace')
[out]
def f(b):
b :: bytes
r0, r1, r2, r3, r4, r5 :: str
L0:
r0 = CPy_Decode(b, 0, 0)
r1 = 'utf-8'
r2 = CPy_Decode(b, r1, 0)
r3 = 'utf-8'
r4 = 'backslashreplace'
r5 = CPy_Decode(b, r3, r4)
return 1
[case testEncode]
def f(s: str) -> None:
s.encode()
s.encode('utf-8')
s.encode('ascii', 'backslashreplace')
[out]
def f(s):
s :: str
r0 :: bytes
r1 :: str
r2 :: bytes
r3, r4 :: str
r5 :: bytes
L0:
r0 = CPy_Encode(s, 0, 0)
r1 = 'utf-8'
r2 = CPy_Encode(s, r1, 0)
r3 = 'ascii'
r4 = 'backslashreplace'
r5 = CPy_Encode(s, r3, r4)
return 1

View File

@@ -0,0 +1,12 @@
[case testStripAssert1]
def g():
x = 1 + 2
assert x < 5
return x
[out]
def g():
r0, x :: object
L0:
r0 = object 3
x = r0
return x

View File

@@ -0,0 +1,523 @@
[case testTryExcept1]
def g() -> None:
try:
object()
except:
print("weeee")
[out]
def g():
r0 :: object
r1 :: str
r2, r3 :: object
r4 :: tuple[object, object, object]
r5 :: str
r6 :: object
r7 :: str
r8, r9 :: object
r10 :: bit
L0:
L1:
r0 = builtins :: module
r1 = 'object'
r2 = CPyObject_GetAttr(r0, r1)
r3 = PyObject_CallFunctionObjArgs(r2, 0)
goto L5
L2: (handler for L1)
r4 = CPy_CatchError()
r5 = 'weeee'
r6 = builtins :: module
r7 = 'print'
r8 = CPyObject_GetAttr(r6, r7)
r9 = PyObject_CallFunctionObjArgs(r8, r5, 0)
L3:
CPy_RestoreExcInfo(r4)
goto L5
L4: (handler for L2)
CPy_RestoreExcInfo(r4)
r10 = CPy_KeepPropagating()
unreachable
L5:
return 1
[case testTryExcept2]
def g(b: bool) -> None:
try:
if b:
object()
else:
str('hi')
except:
print("weeee")
[out]
def g(b):
b :: bool
r0 :: object
r1 :: str
r2, r3 :: object
r4, r5 :: str
r6 :: tuple[object, object, object]
r7 :: str
r8 :: object
r9 :: str
r10, r11 :: object
r12 :: bit
L0:
L1:
if b goto L2 else goto L3 :: bool
L2:
r0 = builtins :: module
r1 = 'object'
r2 = CPyObject_GetAttr(r0, r1)
r3 = PyObject_CallFunctionObjArgs(r2, 0)
goto L4
L3:
r4 = 'hi'
r5 = PyObject_Str(r4)
L4:
goto L8
L5: (handler for L1, L2, L3, L4)
r6 = CPy_CatchError()
r7 = 'weeee'
r8 = builtins :: module
r9 = 'print'
r10 = CPyObject_GetAttr(r8, r9)
r11 = PyObject_CallFunctionObjArgs(r10, r7, 0)
L6:
CPy_RestoreExcInfo(r6)
goto L8
L7: (handler for L5)
CPy_RestoreExcInfo(r6)
r12 = CPy_KeepPropagating()
unreachable
L8:
return 1
[case testTryExcept3]
def g() -> None:
try:
print('a')
try:
object()
except AttributeError as e:
print('b', e)
except:
print("weeee")
[out]
def g():
r0 :: str
r1 :: object
r2 :: str
r3, r4, r5 :: object
r6 :: str
r7, r8 :: object
r9 :: tuple[object, object, object]
r10 :: object
r11 :: str
r12 :: object
r13 :: bit
r14, e :: object
r15 :: str
r16 :: object
r17 :: str
r18, r19 :: object
r20 :: bit
r21 :: tuple[object, object, object]
r22 :: str
r23 :: object
r24 :: str
r25, r26 :: object
r27 :: bit
L0:
L1:
r0 = 'a'
r1 = builtins :: module
r2 = 'print'
r3 = CPyObject_GetAttr(r1, r2)
r4 = PyObject_CallFunctionObjArgs(r3, r0, 0)
L2:
r5 = builtins :: module
r6 = 'object'
r7 = CPyObject_GetAttr(r5, r6)
r8 = PyObject_CallFunctionObjArgs(r7, 0)
goto L8
L3: (handler for L2)
r9 = CPy_CatchError()
r10 = builtins :: module
r11 = 'AttributeError'
r12 = CPyObject_GetAttr(r10, r11)
r13 = CPy_ExceptionMatches(r12)
if r13 goto L4 else goto L5 :: bool
L4:
r14 = CPy_GetExcValue()
e = r14
r15 = 'b'
r16 = builtins :: module
r17 = 'print'
r18 = CPyObject_GetAttr(r16, r17)
r19 = PyObject_CallFunctionObjArgs(r18, r15, e, 0)
goto L6
L5:
CPy_Reraise()
unreachable
L6:
CPy_RestoreExcInfo(r9)
goto L8
L7: (handler for L3, L4, L5)
CPy_RestoreExcInfo(r9)
r20 = CPy_KeepPropagating()
unreachable
L8:
goto L12
L9: (handler for L1, L6, L7, L8)
r21 = CPy_CatchError()
r22 = 'weeee'
r23 = builtins :: module
r24 = 'print'
r25 = CPyObject_GetAttr(r23, r24)
r26 = PyObject_CallFunctionObjArgs(r25, r22, 0)
L10:
CPy_RestoreExcInfo(r21)
goto L12
L11: (handler for L9)
CPy_RestoreExcInfo(r21)
r27 = CPy_KeepPropagating()
unreachable
L12:
return 1
[case testTryExcept4]
def g() -> None:
try:
pass
except KeyError:
print("weeee")
except IndexError:
print("yo")
[out]
def g():
r0 :: tuple[object, object, object]
r1 :: object
r2 :: str
r3 :: object
r4 :: bit
r5 :: str
r6 :: object
r7 :: str
r8, r9, r10 :: object
r11 :: str
r12 :: object
r13 :: bit
r14 :: str
r15 :: object
r16 :: str
r17, r18 :: object
r19 :: bit
L0:
L1:
goto L9
L2: (handler for L1)
r0 = CPy_CatchError()
r1 = builtins :: module
r2 = 'KeyError'
r3 = CPyObject_GetAttr(r1, r2)
r4 = CPy_ExceptionMatches(r3)
if r4 goto L3 else goto L4 :: bool
L3:
r5 = 'weeee'
r6 = builtins :: module
r7 = 'print'
r8 = CPyObject_GetAttr(r6, r7)
r9 = PyObject_CallFunctionObjArgs(r8, r5, 0)
goto L7
L4:
r10 = builtins :: module
r11 = 'IndexError'
r12 = CPyObject_GetAttr(r10, r11)
r13 = CPy_ExceptionMatches(r12)
if r13 goto L5 else goto L6 :: bool
L5:
r14 = 'yo'
r15 = builtins :: module
r16 = 'print'
r17 = CPyObject_GetAttr(r15, r16)
r18 = PyObject_CallFunctionObjArgs(r17, r14, 0)
goto L7
L6:
CPy_Reraise()
unreachable
L7:
CPy_RestoreExcInfo(r0)
goto L9
L8: (handler for L2, L3, L4, L5, L6)
CPy_RestoreExcInfo(r0)
r19 = CPy_KeepPropagating()
unreachable
L9:
return 1
[case testTryFinally]
def a(b: bool) -> None:
try:
if b:
raise Exception('hi')
finally:
print('finally')
[out]
def a(b):
b :: bool
r0 :: str
r1 :: object
r2 :: str
r3, r4 :: object
r5, r6, r7 :: tuple[object, object, object]
r8 :: str
r9 :: object
r10 :: str
r11, r12 :: object
r13 :: bit
L0:
L1:
if b goto L2 else goto L3 :: bool
L2:
r0 = 'hi'
r1 = builtins :: module
r2 = 'Exception'
r3 = CPyObject_GetAttr(r1, r2)
r4 = PyObject_CallFunctionObjArgs(r3, r0, 0)
CPy_Raise(r4)
unreachable
L3:
L4:
L5:
r5 = <error> :: tuple[object, object, object]
r6 = r5
goto L7
L6: (handler for L1, L2, L3)
r7 = CPy_CatchError()
r6 = r7
L7:
r8 = 'finally'
r9 = builtins :: module
r10 = 'print'
r11 = CPyObject_GetAttr(r9, r10)
r12 = PyObject_CallFunctionObjArgs(r11, r8, 0)
if is_error(r6) goto L9 else goto L8
L8:
CPy_Reraise()
unreachable
L9:
goto L13
L10: (handler for L7, L8)
if is_error(r6) goto L12 else goto L11
L11:
CPy_RestoreExcInfo(r6)
L12:
r13 = CPy_KeepPropagating()
unreachable
L13:
return 1
[case testWith]
from typing import Any
def foo(x: Any) -> None:
with x() as y:
print('hello')
[out]
def foo(x):
x, r0, r1 :: object
r2 :: str
r3 :: object
r4 :: str
r5, r6 :: object
r7 :: bool
y :: object
r8 :: str
r9 :: object
r10 :: str
r11, r12 :: object
r13, r14 :: tuple[object, object, object]
r15, r16, r17, r18 :: object
r19 :: i32
r20 :: bit
r21 :: bool
r22 :: bit
r23, r24, r25 :: tuple[object, object, object]
r26, r27 :: object
r28 :: bit
L0:
r0 = PyObject_CallFunctionObjArgs(x, 0)
r1 = PyObject_Type(r0)
r2 = '__exit__'
r3 = CPyObject_GetAttr(r1, r2)
r4 = '__enter__'
r5 = CPyObject_GetAttr(r1, r4)
r6 = PyObject_CallFunctionObjArgs(r5, r0, 0)
r7 = 1
L1:
L2:
y = r6
r8 = 'hello'
r9 = builtins :: module
r10 = 'print'
r11 = CPyObject_GetAttr(r9, r10)
r12 = PyObject_CallFunctionObjArgs(r11, r8, 0)
goto L8
L3: (handler for L2)
r13 = CPy_CatchError()
r7 = 0
r14 = CPy_GetExcInfo()
r15 = r14[0]
r16 = r14[1]
r17 = r14[2]
r18 = PyObject_CallFunctionObjArgs(r3, r0, r15, r16, r17, 0)
r19 = PyObject_IsTrue(r18)
r20 = r19 >= 0 :: signed
r21 = truncate r19: i32 to builtins.bool
if r21 goto L5 else goto L4 :: bool
L4:
CPy_Reraise()
unreachable
L5:
L6:
CPy_RestoreExcInfo(r13)
goto L8
L7: (handler for L3, L4, L5)
CPy_RestoreExcInfo(r13)
r22 = CPy_KeepPropagating()
unreachable
L8:
L9:
L10:
r23 = <error> :: tuple[object, object, object]
r24 = r23
goto L12
L11: (handler for L1, L6, L7, L8)
r25 = CPy_CatchError()
r24 = r25
L12:
if r7 goto L13 else goto L14 :: bool
L13:
r26 = load_address _Py_NoneStruct
r27 = PyObject_CallFunctionObjArgs(r3, r0, r26, r26, r26, 0)
L14:
if is_error(r24) goto L16 else goto L15
L15:
CPy_Reraise()
unreachable
L16:
goto L20
L17: (handler for L12, L13, L14, L15)
if is_error(r24) goto L19 else goto L18
L18:
CPy_RestoreExcInfo(r24)
L19:
r28 = CPy_KeepPropagating()
unreachable
L20:
return 1
[case testWithNativeSimple]
class DummyContext:
def __enter__(self) -> None:
pass
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
pass
def foo(x: DummyContext) -> None:
with x:
print('hello')
[out]
def DummyContext.__enter__(self):
self :: __main__.DummyContext
L0:
return 1
def DummyContext.__exit__(self, exc_type, exc_val, exc_tb):
self :: __main__.DummyContext
exc_type, exc_val, exc_tb :: object
L0:
return 1
def foo(x):
x :: __main__.DummyContext
r0 :: None
r1 :: bool
r2 :: str
r3 :: object
r4 :: str
r5, r6 :: object
r7, r8 :: tuple[object, object, object]
r9, r10, r11 :: object
r12 :: None
r13 :: object
r14 :: i32
r15 :: bit
r16 :: bool
r17 :: bit
r18, r19, r20 :: tuple[object, object, object]
r21 :: object
r22 :: None
r23 :: bit
L0:
r0 = x.__enter__()
r1 = 1
L1:
L2:
r2 = 'hello'
r3 = builtins :: module
r4 = 'print'
r5 = CPyObject_GetAttr(r3, r4)
r6 = PyObject_CallFunctionObjArgs(r5, r2, 0)
goto L8
L3: (handler for L2)
r7 = CPy_CatchError()
r1 = 0
r8 = CPy_GetExcInfo()
r9 = r8[0]
r10 = r8[1]
r11 = r8[2]
r12 = x.__exit__(r9, r10, r11)
r13 = box(None, r12)
r14 = PyObject_IsTrue(r13)
r15 = r14 >= 0 :: signed
r16 = truncate r14: i32 to builtins.bool
if r16 goto L5 else goto L4 :: bool
L4:
CPy_Reraise()
unreachable
L5:
L6:
CPy_RestoreExcInfo(r7)
goto L8
L7: (handler for L3, L4, L5)
CPy_RestoreExcInfo(r7)
r17 = CPy_KeepPropagating()
unreachable
L8:
L9:
L10:
r18 = <error> :: tuple[object, object, object]
r19 = r18
goto L12
L11: (handler for L1, L6, L7, L8)
r20 = CPy_CatchError()
r19 = r20
L12:
if r1 goto L13 else goto L14 :: bool
L13:
r21 = load_address _Py_NoneStruct
r22 = x.__exit__(r21, r21, r21)
L14:
if is_error(r19) goto L16 else goto L15
L15:
CPy_Reraise()
unreachable
L16:
goto L20
L17: (handler for L12, L13, L14, L15)
if is_error(r19) goto L19 else goto L18
L18:
CPy_RestoreExcInfo(r19)
L19:
r23 = CPy_KeepPropagating()
unreachable
L20:
return 1

View File

@@ -0,0 +1,462 @@
[case testTupleGet]
from typing import Tuple
def f(x: Tuple[Tuple[int, bool], bool]) -> int:
return x[0][0]
[out]
def f(x):
x :: tuple[tuple[int, bool], bool]
r0 :: tuple[int, bool]
r1 :: int
L0:
r0 = x[0]
r1 = r0[0]
return r1
[case testTupleNew]
from typing import Tuple
def f() -> int:
t = (True, 1)
return t[1]
[out]
def f():
r0, t :: tuple[bool, int]
r1 :: int
L0:
r0 = (1, 2)
t = r0
r1 = t[1]
return r1
[case testTupleLen]
from typing import Tuple
def f(x: Tuple[bool, bool, int]) -> int:
return len(x)
[out]
def f(x):
x :: tuple[bool, bool, int]
L0:
return 6
[case testSequenceTuple]
from typing import List
def f(x: List[bool]) -> bool:
return tuple(x)[1]
[out]
def f(x):
x :: list
r0 :: tuple
r1 :: object
r2 :: bool
L0:
r0 = PyList_AsTuple(x)
r1 = CPySequenceTuple_GetItem(r0, 2)
r2 = unbox(bool, r1)
return r2
[case testSequenceTupleLen]
from typing import Tuple
def f(x: Tuple[int, ...]) -> int:
return len(x)
[out]
def f(x):
x :: tuple
r0 :: ptr
r1 :: native_int
r2 :: short_int
L0:
r0 = get_element_ptr x ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive x
r2 = r1 << 1
return r2
[case testSequenceTupleForced]
from typing import Tuple
def f() -> int:
t = (1, 2) # type: Tuple[int, ...]
return t[1]
[out]
def f():
r0 :: tuple[int, int]
r1 :: object
t :: tuple
r2 :: object
r3 :: int
L0:
r0 = (2, 4)
r1 = box(tuple[int, int], r0)
t = r1
r2 = CPySequenceTuple_GetItem(t, 2)
r3 = unbox(int, r2)
return r3
[case testTupleDisplay]
from typing import Sequence, Tuple
def f(x: Sequence[int], y: Sequence[int]) -> Tuple[int, ...]:
return (1, 2, *x, *y, 3)
[out]
def f(x, y):
x, y :: object
r0 :: list
r1, r2 :: object
r3, r4, r5 :: ptr
r6, r7, r8 :: object
r9 :: i32
r10 :: bit
r11 :: tuple
L0:
r0 = PyList_New(2)
r1 = object 1
r2 = object 2
r3 = get_element_ptr r0 ob_item :: PyListObject
r4 = load_mem r3 :: ptr*
set_mem r4, r1 :: builtins.object*
r5 = r4 + WORD_SIZE*1
set_mem r5, r2 :: builtins.object*
keep_alive r0
r6 = CPyList_Extend(r0, x)
r7 = CPyList_Extend(r0, y)
r8 = object 3
r9 = PyList_Append(r0, r8)
r10 = r9 >= 0 :: signed
r11 = PyList_AsTuple(r0)
return r11
[case testTupleFor]
from typing import Tuple, List
def f(xs: Tuple[str, ...]) -> None:
for x in xs:
pass
[out]
def f(xs):
xs :: tuple
r0 :: short_int
r1 :: ptr
r2 :: native_int
r3 :: short_int
r4 :: bit
r5 :: object
r6, x :: str
r7 :: short_int
L0:
r0 = 0
L1:
r1 = get_element_ptr xs ob_size :: PyVarObject
r2 = load_mem r1 :: native_int*
keep_alive xs
r3 = r2 << 1
r4 = r0 < r3 :: signed
if r4 goto L2 else goto L4 :: bool
L2:
r5 = CPySequenceTuple_GetItem(xs, r0)
r6 = cast(str, r5)
x = r6
L3:
r7 = r0 + 2
r0 = r7
goto L1
L4:
return 1
[case testNamedTupleAttribute]
from typing import NamedTuple
NT = NamedTuple('NT', [('x', int), ('y', int)])
def f(nt: NT, b: bool) -> int:
if b:
return nt.x
return nt.y
[out]
def f(nt, b):
nt :: tuple
b :: bool
r0 :: object
r1 :: int
r2 :: object
r3 :: int
L0:
if b goto L1 else goto L2 :: bool
L1:
r0 = CPySequenceTuple_GetItem(nt, 0)
r1 = unbox(int, r0)
return r1
L2:
r2 = CPySequenceTuple_GetItem(nt, 2)
r3 = unbox(int, r2)
return r3
[case testTupleOperatorIn]
def f(i: int) -> bool:
return i in [1, 2, 3]
[out]
def f(i):
i :: int
r0 :: native_int
r1, r2 :: bit
r3 :: bool
r4 :: bit
r5 :: bool
r6 :: native_int
r7, r8 :: bit
r9 :: bool
r10 :: bit
r11 :: bool
r12 :: native_int
r13, r14 :: bit
r15 :: bool
r16 :: bit
L0:
r0 = i & 1
r1 = r0 == 0
if r1 goto L1 else goto L2 :: bool
L1:
r2 = i == 2
r3 = r2
goto L3
L2:
r4 = CPyTagged_IsEq_(i, 2)
r3 = r4
L3:
if r3 goto L4 else goto L5 :: bool
L4:
r5 = r3
goto L9
L5:
r6 = i & 1
r7 = r6 == 0
if r7 goto L6 else goto L7 :: bool
L6:
r8 = i == 4
r9 = r8
goto L8
L7:
r10 = CPyTagged_IsEq_(i, 4)
r9 = r10
L8:
r5 = r9
L9:
if r5 goto L10 else goto L11 :: bool
L10:
r11 = r5
goto L15
L11:
r12 = i & 1
r13 = r12 == 0
if r13 goto L12 else goto L13 :: bool
L12:
r14 = i == 6
r15 = r14
goto L14
L13:
r16 = CPyTagged_IsEq_(i, 6)
r15 = r16
L14:
r11 = r15
L15:
return r11
[case testTupleBuiltFromList]
def f(val: int) -> bool:
return val % 2 == 0
def test() -> None:
source = [1, 2, 3]
a = tuple(f(x) for x in source)
[out]
def f(val):
val, r0 :: int
r1 :: native_int
r2, r3 :: bit
r4 :: bool
r5 :: bit
L0:
r0 = CPyTagged_Remainder(val, 4)
r1 = r0 & 1
r2 = r1 == 0
if r2 goto L1 else goto L2 :: bool
L1:
r3 = r0 == 0
r4 = r3
goto L3
L2:
r5 = CPyTagged_IsEq_(r0, 0)
r4 = r5
L3:
return r4
def test():
r0 :: list
r1, r2, r3 :: object
r4, r5, r6, r7 :: ptr
source :: list
r8 :: ptr
r9 :: native_int
r10 :: tuple
r11 :: short_int
r12 :: ptr
r13 :: native_int
r14 :: short_int
r15 :: bit
r16 :: object
r17, x :: int
r18 :: bool
r19 :: object
r20 :: bit
r21 :: short_int
a :: tuple
L0:
r0 = PyList_New(3)
r1 = object 1
r2 = object 2
r3 = object 3
r4 = get_element_ptr r0 ob_item :: PyListObject
r5 = load_mem r4 :: ptr*
set_mem r5, r1 :: builtins.object*
r6 = r5 + WORD_SIZE*1
set_mem r6, r2 :: builtins.object*
r7 = r5 + WORD_SIZE*2
set_mem r7, r3 :: builtins.object*
keep_alive r0
source = r0
r8 = get_element_ptr source ob_size :: PyVarObject
r9 = load_mem r8 :: native_int*
keep_alive source
r10 = PyTuple_New(r9)
r11 = 0
L1:
r12 = get_element_ptr source ob_size :: PyVarObject
r13 = load_mem r12 :: native_int*
keep_alive source
r14 = r13 << 1
r15 = r11 < r14 :: signed
if r15 goto L2 else goto L4 :: bool
L2:
r16 = CPyList_GetItemUnsafe(source, r11)
r17 = unbox(int, r16)
x = r17
r18 = f(x)
r19 = box(bool, r18)
r20 = CPySequenceTuple_SetItemUnsafe(r10, r11, r19)
L3:
r21 = r11 + 2
r11 = r21
goto L1
L4:
a = r10
return 1
[case testTupleBuiltFromStr]
def f2(val: str) -> str:
return val + "f2"
def test() -> None:
source = "abc"
a = tuple(f2(x) for x in source)
[out]
def f2(val):
val, r0, r1 :: str
L0:
r0 = 'f2'
r1 = PyUnicode_Concat(val, r0)
return r1
def test():
r0, source :: str
r1 :: native_int
r2 :: bit
r3 :: tuple
r4 :: short_int
r5 :: native_int
r6 :: bit
r7 :: short_int
r8 :: bit
r9, x, r10 :: str
r11 :: bit
r12 :: short_int
a :: tuple
L0:
r0 = 'abc'
source = r0
r1 = CPyStr_Size_size_t(source)
r2 = r1 >= 0 :: signed
r3 = PyTuple_New(r1)
r4 = 0
L1:
r5 = CPyStr_Size_size_t(source)
r6 = r5 >= 0 :: signed
r7 = r5 << 1
r8 = r4 < r7 :: signed
if r8 goto L2 else goto L4 :: bool
L2:
r9 = CPyStr_GetItem(source, r4)
x = r9
r10 = f2(x)
r11 = CPySequenceTuple_SetItemUnsafe(r3, r4, r10)
L3:
r12 = r4 + 2
r4 = r12
goto L1
L4:
a = r3
return 1
[case testTupleBuiltFromVariableLengthTuple]
from typing import Tuple
def f(val: bool) -> bool:
return not val
def test(source: Tuple[bool, ...]) -> None:
a = tuple(f(x) for x in source)
[out]
def f(val):
val, r0 :: bool
L0:
r0 = val ^ 1
return r0
def test(source):
source :: tuple
r0 :: ptr
r1 :: native_int
r2 :: tuple
r3 :: short_int
r4 :: ptr
r5 :: native_int
r6 :: short_int
r7 :: bit
r8 :: object
r9, x, r10 :: bool
r11 :: object
r12 :: bit
r13 :: short_int
a :: tuple
L0:
r0 = get_element_ptr source ob_size :: PyVarObject
r1 = load_mem r0 :: native_int*
keep_alive source
r2 = PyTuple_New(r1)
r3 = 0
L1:
r4 = get_element_ptr source ob_size :: PyVarObject
r5 = load_mem r4 :: native_int*
keep_alive source
r6 = r5 << 1
r7 = r3 < r6 :: signed
if r7 goto L2 else goto L4 :: bool
L2:
r8 = CPySequenceTuple_GetItem(source, r3)
r9 = unbox(bool, r8)
x = r9
r10 = f(x)
r11 = box(bool, r10)
r12 = CPySequenceTuple_SetItemUnsafe(r2, r3, r11)
L3:
r13 = r3 + 2
r3 = r13
goto L1
L4:
a = r2
return 1

View File

@@ -0,0 +1,543 @@
# Test cases for u8 native ints. Focus on things that are different from i64; no need to
# duplicate all i64 test cases here.
[case testU8BinaryOp]
from mypy_extensions import u8
def add_op(x: u8, y: u8) -> u8:
x = y + x
y = x + 5
y += x
y += 7
x = 5 + y
return x
def compare(x: u8, y: u8) -> None:
a = x == y
b = x == 5
c = x < y
d = x < 5
e = 5 == x
f = 5 < x
[out]
def add_op(x, y):
x, y, r0, r1, r2, r3, r4 :: u8
L0:
r0 = y + x
x = r0
r1 = x + 5
y = r1
r2 = y + x
y = r2
r3 = y + 7
y = r3
r4 = 5 + y
x = r4
return x
def compare(x, y):
x, y :: u8
r0 :: bit
a :: bool
r1 :: bit
b :: bool
r2 :: bit
c :: bool
r3 :: bit
d :: bool
r4 :: bit
e :: bool
r5 :: bit
f :: bool
L0:
r0 = x == y
a = r0
r1 = x == 5
b = r1
r2 = x < y :: unsigned
c = r2
r3 = x < 5 :: unsigned
d = r3
r4 = 5 == x
e = r4
r5 = 5 < x :: unsigned
f = r5
return 1
[case testU8UnaryOp]
from mypy_extensions import u8
def unary(x: u8) -> u8:
y = -x
x = ~y
y = +x
return y
[out]
def unary(x):
x, r0, y, r1 :: u8
L0:
r0 = 0 - x
y = r0
r1 = y ^ 255
x = r1
y = x
return y
[case testU8DivisionByConstant]
from mypy_extensions import u8
def div_by_constant(x: u8) -> u8:
x = x // 5
x //= 17
return x
[out]
def div_by_constant(x):
x, r0, r1 :: u8
L0:
r0 = x / 5
x = r0
r1 = x / 17
x = r1
return x
[case testU8ModByConstant]
from mypy_extensions import u8
def mod_by_constant(x: u8) -> u8:
x = x % 5
x %= 17
return x
[out]
def mod_by_constant(x):
x, r0, r1 :: u8
L0:
r0 = x % 5
x = r0
r1 = x % 17
x = r1
return x
[case testU8DivModByVariable]
from mypy_extensions import u8
def divmod(x: u8, y: u8) -> u8:
a = x // y
return a % y
[out]
def divmod(x, y):
x, y :: u8
r0 :: bit
r1 :: bool
r2, a :: u8
r3 :: bit
r4 :: bool
r5 :: u8
L0:
r0 = y == 0
if r0 goto L1 else goto L2 :: bool
L1:
r1 = raise ZeroDivisionError('integer division or modulo by zero')
unreachable
L2:
r2 = x / y
a = r2
r3 = y == 0
if r3 goto L3 else goto L4 :: bool
L3:
r4 = raise ZeroDivisionError('integer division or modulo by zero')
unreachable
L4:
r5 = a % y
return r5
[case testU8BinaryOperationWithOutOfRangeOperand]
from mypy_extensions import u8
def out_of_range(x: u8) -> None:
x + (-1)
(-2) + x
x * 256
-1 < x
x > -5
x == 1000
x + 255 # OK
255 + x # OK
[out]
main:4: error: Value -1 is out of range for "u8"
main:5: error: Value -2 is out of range for "u8"
main:6: error: Value 256 is out of range for "u8"
main:7: error: Value -1 is out of range for "u8"
main:8: error: Value -5 is out of range for "u8"
main:9: error: Value 1000 is out of range for "u8"
[case testU8DetectMoreOutOfRangeLiterals]
from mypy_extensions import u8
def out_of_range() -> None:
a: u8 = 256
b: u8 = -1
f(256)
# The following are ok
c: u8 = 0
d: u8 = 255
f(0)
f(255)
def f(x: u8) -> None: pass
[out]
main:4: error: Value 256 is out of range for "u8"
main:5: error: Value -1 is out of range for "u8"
main:6: error: Value 256 is out of range for "u8"
[case testU8BoxAndUnbox]
from typing import Any
from mypy_extensions import u8
def f(x: Any) -> Any:
y: u8 = x
return y
[out]
def f(x):
x :: object
r0, y :: u8
r1 :: object
L0:
r0 = unbox(u8, x)
y = r0
r1 = box(u8, y)
return r1
[case testU8MixedCompare1]
from mypy_extensions import u8
def f(x: int, y: u8) -> bool:
return x == y
[out]
def f(x, y):
x :: int
y :: u8
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: u8
r7 :: bit
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 512 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= 0 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to u8
r6 = r5
goto L5
L4:
CPyUInt8_Overflow()
unreachable
L5:
r7 = r6 == y
return r7
[case testU8MixedCompare2]
from mypy_extensions import u8
def f(x: u8, y: int) -> bool:
return x == y
[out]
def f(x, y):
x :: u8
y :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: u8
r7 :: bit
L0:
r0 = y & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = y < 512 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = y >= 0 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = y >> 1
r5 = truncate r4: native_int to u8
r6 = r5
goto L5
L4:
CPyUInt8_Overflow()
unreachable
L5:
r7 = x == r6
return r7
[case testU8ConvertToInt]
from mypy_extensions import u8
def u8_to_int(a: u8) -> int:
return a
[out]
def u8_to_int(a):
a :: u8
r0 :: native_int
r1 :: int
L0:
r0 = extend a: u8 to native_int
r1 = r0 << 1
return r1
[case testU8OperatorAssignmentMixed]
from mypy_extensions import u8
def f(a: u8) -> None:
x = 0
x += a
[out]
def f(a):
a :: u8
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6, r7 :: u8
r8 :: native_int
r9 :: int
L0:
x = 0
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 512 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= 0 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to u8
r6 = r5
goto L5
L4:
CPyUInt8_Overflow()
unreachable
L5:
r7 = r6 + a
r8 = extend r7: u8 to native_int
r9 = r8 << 1
x = r9
return 1
[case testU8InitializeFromLiteral]
from mypy_extensions import u8, i64
def f() -> None:
x: u8 = 0
y: u8 = 255
z: u8 = 5 + 7
[out]
def f():
x, y, z :: u8
L0:
x = 0
y = 255
z = 12
return 1
[case testU8ExplicitConversionFromNativeInt]
from mypy_extensions import i64, i32, i16, u8
def from_u8(x: u8) -> u8:
return u8(x)
def from_i16(x: i16) -> u8:
return u8(x)
def from_i32(x: i32) -> u8:
return u8(x)
def from_i64(x: i64) -> u8:
return u8(x)
[out]
def from_u8(x):
x :: u8
L0:
return x
def from_i16(x):
x :: i16
r0 :: u8
L0:
r0 = truncate x: i16 to u8
return r0
def from_i32(x):
x :: i32
r0 :: u8
L0:
r0 = truncate x: i32 to u8
return r0
def from_i64(x):
x :: i64
r0 :: u8
L0:
r0 = truncate x: i64 to u8
return r0
[case testU8ExplicitConversionToNativeInt]
from mypy_extensions import i64, i32, i16, u8
def to_i16(x: u8) -> i16:
return i16(x)
def to_i32(x: u8) -> i32:
return i32(x)
def to_i64(x: u8) -> i64:
return i64(x)
[out]
def to_i16(x):
x :: u8
r0 :: i16
L0:
r0 = extend x: u8 to i16
return r0
def to_i32(x):
x :: u8
r0 :: i32
L0:
r0 = extend x: u8 to i32
return r0
def to_i64(x):
x :: u8
r0 :: i64
L0:
r0 = extend x: u8 to i64
return r0
[case testU8ExplicitConversionFromInt]
from mypy_extensions import u8
def f(x: int) -> u8:
return u8(x)
[out]
def f(x):
x :: int
r0 :: native_int
r1, r2, r3 :: bit
r4 :: native_int
r5, r6 :: u8
L0:
r0 = x & 1
r1 = r0 == 0
if r1 goto L1 else goto L4 :: bool
L1:
r2 = x < 512 :: signed
if r2 goto L2 else goto L4 :: bool
L2:
r3 = x >= 0 :: signed
if r3 goto L3 else goto L4 :: bool
L3:
r4 = x >> 1
r5 = truncate r4: native_int to u8
r6 = r5
goto L5
L4:
CPyUInt8_Overflow()
unreachable
L5:
return r6
[case testU8ExplicitConversionFromLiteral]
from mypy_extensions import u8
def f() -> None:
x = u8(0)
y = u8(11)
z = u8(-3) # Truncate
zz = u8(258) # Truncate
a = u8(255)
[out]
def f():
x, y, z, zz, a :: u8
L0:
x = 0
y = 11
z = 253
zz = 2
a = 255
return 1
[case testU8ExplicitConversionFromVariousTypes]
from mypy_extensions import u8
def bool_to_u8(b: bool) -> u8:
return u8(b)
def str_to_u8(s: str) -> u8:
return u8(s)
class C:
def __int__(self) -> u8:
return 5
def instance_to_u8(c: C) -> u8:
return u8(c)
def float_to_u8(x: float) -> u8:
return u8(x)
[out]
def bool_to_u8(b):
b :: bool
r0 :: u8
L0:
r0 = extend b: builtins.bool to u8
return r0
def str_to_u8(s):
s :: str
r0 :: object
r1 :: u8
L0:
r0 = CPyLong_FromStr(s)
r1 = unbox(u8, r0)
return r1
def C.__int__(self):
self :: __main__.C
L0:
return 5
def instance_to_u8(c):
c :: __main__.C
r0 :: u8
L0:
r0 = c.__int__()
return r0
def float_to_u8(x):
x :: float
r0 :: int
r1 :: native_int
r2, r3, r4 :: bit
r5 :: native_int
r6, r7 :: u8
L0:
r0 = CPyTagged_FromFloat(x)
r1 = r0 & 1
r2 = r1 == 0
if r2 goto L1 else goto L4 :: bool
L1:
r3 = r0 < 512 :: signed
if r3 goto L2 else goto L4 :: bool
L2:
r4 = r0 >= 0 :: signed
if r4 goto L3 else goto L4 :: bool
L3:
r5 = r0 >> 1
r6 = truncate r5: native_int to u8
r7 = r6
goto L5
L4:
CPyUInt8_Overflow()
unreachable
L5:
return r7

View File

@@ -0,0 +1,106 @@
# Test cases for unreachable expressions
[case testUnreachableMemberExpr]
import sys
def f() -> None:
y = sys.platform == "x" and sys.version_info > (3, 5)
[out]
def f():
r0 :: object
r1 :: str
r2 :: object
r3, r4 :: str
r5 :: i32
r6 :: bit
r7 :: object
r8, r9, r10 :: bit
r11, r12 :: bool
r13 :: object
r14 :: str
r15 :: object
r16 :: tuple[int, int]
r17, r18 :: object
r19, y :: bool
L0:
r0 = sys :: module
r1 = 'platform'
r2 = CPyObject_GetAttr(r0, r1)
r3 = cast(str, r2)
r4 = 'x'
r5 = PyUnicode_Compare(r3, r4)
r6 = r5 == -1
if r6 goto L1 else goto L3 :: bool
L1:
r7 = PyErr_Occurred()
r8 = r7 != 0
if r8 goto L2 else goto L3 :: bool
L2:
r9 = CPy_KeepPropagating()
L3:
r10 = r5 == 0
if r10 goto L5 else goto L4 :: bool
L4:
r11 = r10
goto L6
L5:
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
r13 = box(None, 1)
r14 = 'version_info'
r15 = CPyObject_GetAttr(r13, r14)
r16 = (6, 10)
r17 = box(tuple[int, int], r16)
r18 = PyObject_RichCompare(r15, r17, 4)
r19 = unbox(bool, r18)
r11 = r19
L6:
y = r11
return 1
[case testUnreachableNameExpr]
import sys
def f() -> None:
y = sys.platform == 'x' and foobar
[out]
def f():
r0 :: object
r1 :: str
r2 :: object
r3, r4 :: str
r5 :: i32
r6 :: bit
r7 :: object
r8, r9, r10 :: bit
r11, r12 :: bool
r13 :: object
r14, y :: bool
L0:
r0 = sys :: module
r1 = 'platform'
r2 = CPyObject_GetAttr(r0, r1)
r3 = cast(str, r2)
r4 = 'x'
r5 = PyUnicode_Compare(r3, r4)
r6 = r5 == -1
if r6 goto L1 else goto L3 :: bool
L1:
r7 = PyErr_Occurred()
r8 = r7 != 0
if r8 goto L2 else goto L3 :: bool
L2:
r9 = CPy_KeepPropagating()
L3:
r10 = r5 == 0
if r10 goto L5 else goto L4 :: bool
L4:
r11 = r10
goto L6
L5:
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
r13 = box(None, 1)
r14 = unbox(bool, r13)
r11 = r14
L6:
y = r11
return 1

View File

@@ -0,0 +1,153 @@
-- Test cases for calls using the vectorcall API (Python 3.8+)
--
-- Vectorcalls are faster than the legacy API, especially with keyword arguments,
-- since there is no need to allocate a temporary dictionary for keyword args.
[case testeVectorcallBasic_python3_8]
from typing import Any
def f(c: Any) -> None:
c()
c('x', 'y')
[out]
def f(c):
c, r0 :: object
r1, r2 :: str
r3 :: object[2]
r4 :: object_ptr
r5 :: object
L0:
r0 = _PyObject_Vectorcall(c, 0, 0, 0)
r1 = 'x'
r2 = 'y'
r3 = [r1, r2]
r4 = load_address r3
r5 = _PyObject_Vectorcall(c, r4, 2, 0)
keep_alive r1, r2
return 1
[case testVectorcallKeywords_python3_8]
from typing import Any
def f(c: Any) -> None:
c(x='a')
c('x', a='y', b='z')
[out]
def f(c):
c :: object
r0 :: str
r1 :: object[1]
r2 :: object_ptr
r3, r4 :: object
r5, r6, r7 :: str
r8 :: object[3]
r9 :: object_ptr
r10, r11 :: object
L0:
r0 = 'a'
r1 = [r0]
r2 = load_address r1
r3 = ('x',)
r4 = _PyObject_Vectorcall(c, r2, 0, r3)
keep_alive r0
r5 = 'x'
r6 = 'y'
r7 = 'z'
r8 = [r5, r6, r7]
r9 = load_address r8
r10 = ('a', 'b')
r11 = _PyObject_Vectorcall(c, r9, 1, r10)
keep_alive r5, r6, r7
return 1
[case testVectorcallMethod_python3_8]
from typing import Any
def f(o: Any) -> None:
# On Python 3.8 vectorcalls are only faster with keyword args
o.m('x')
o.m('x', a='y')
[out]
def f(o):
o :: object
r0, r1 :: str
r2 :: object
r3, r4, r5 :: str
r6 :: object
r7 :: object[2]
r8 :: object_ptr
r9, r10 :: object
L0:
r0 = 'x'
r1 = 'm'
r2 = CPyObject_CallMethodObjArgs(o, r1, r0, 0)
r3 = 'x'
r4 = 'y'
r5 = 'm'
r6 = CPyObject_GetAttr(o, r5)
r7 = [r3, r4]
r8 = load_address r7
r9 = ('a',)
r10 = _PyObject_Vectorcall(r6, r8, 1, r9)
keep_alive r3, r4
return 1
[case testVectorcallMethod_python3_9_64bit]
from typing import Any
def f(o: Any) -> None:
# Python 3.9 has a new API for calling methods
o.m('x')
o.m('x', 'y', a='z')
[out]
def f(o):
o :: object
r0, r1 :: str
r2 :: object[2]
r3 :: object_ptr
r4 :: object
r5, r6, r7, r8 :: str
r9 :: object[4]
r10 :: object_ptr
r11, r12 :: object
L0:
r0 = 'x'
r1 = 'm'
r2 = [o, r0]
r3 = load_address r2
r4 = PyObject_VectorcallMethod(r1, r3, 9223372036854775810, 0)
keep_alive o, r0
r5 = 'x'
r6 = 'y'
r7 = 'z'
r8 = 'm'
r9 = [o, r5, r6, r7]
r10 = load_address r9
r11 = ('a',)
r12 = PyObject_VectorcallMethod(r8, r10, 9223372036854775811, r11)
keep_alive o, r5, r6, r7
return 1
[case testVectorcallMethod_python3_9_32bit]
from typing import Any
def f(o: Any) -> None:
# The IR is slightly different on 32-bit platforms
o.m('x', a='y')
[out]
def f(o):
o :: object
r0, r1, r2 :: str
r3 :: object[3]
r4 :: object_ptr
r5, r6 :: object
L0:
r0 = 'x'
r1 = 'y'
r2 = 'm'
r3 = [o, r0, r1]
r4 = load_address r3
r5 = ('a',)
r6 = PyObject_VectorcallMethod(r2, r4, 2147483650, r5)
keep_alive o, r0, r1
return 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
# async test cases (compile and run)
[case testAsync]
import asyncio
async def h() -> int:
return 1
async def g() -> int:
await asyncio.sleep(0)
return await h()
async def f() -> int:
return await g()
[file asyncio/__init__.pyi]
async def sleep(t: float) -> None: ...
[typing fixtures/typing-full.pyi]
[file driver.py]
from native import f
import asyncio
result = asyncio.run(f())
assert result == 1
[case testAsyncWith]
from testutil import async_val
class async_ctx:
async def __aenter__(self) -> str:
await async_val("enter")
return "test"
async def __aexit__(self, x, y, z) -> None:
await async_val("exit")
async def async_with() -> str:
async with async_ctx() as x:
return await async_val("body")
[file driver.py]
from native import async_with
from testutil import run_generator
yields, val = run_generator(async_with(), [None, 'x', None])
assert yields == ('enter', 'body', 'exit'), yields
assert val == 'x', val
[case testAsyncReturn]
from testutil import async_val
async def async_return() -> str:
try:
return 'test'
finally:
await async_val('foo')
[file driver.py]
from native import async_return
from testutil import run_generator
yields, val = run_generator(async_return())
assert yields == ('foo',)
assert val == 'test', val
[case testAsyncFor]
from typing import AsyncIterable, List, Set, Dict
async def async_iter(xs: AsyncIterable[int]) -> List[int]:
ys = []
async for x in xs:
ys.append(x)
return ys
async def async_comp(xs: AsyncIterable[int]) -> List[int]:
ys = [x async for x in xs]
return ys
async def async_comp_set(xs: AsyncIterable[int]) -> Set[int]:
return {x async for x in xs}
async def async_comp_dict(xs: AsyncIterable[int]) -> Dict[int, str]:
return {x: str(x) async for x in xs}
[typing fixtures/typing-full.pyi]
[file driver.py]
from native import async_iter, async_comp, async_comp_set, async_comp_dict
from testutil import run_generator, async_val
from typing import AsyncIterable, List
# defined here since we couldn't do it inside the test yet...
async def foo() -> AsyncIterable[int]:
for x in range(3):
await async_val(x)
yield x
yields, val = run_generator(async_iter(foo()))
assert val == [0,1,2], val
assert yields == (0,1,2), yields
yields, val = run_generator(async_comp(foo()))
assert val == [0,1,2], val
assert yields == (0,1,2), yields
yields, val = run_generator(async_comp_set(foo()))
assert val == {0,1,2}, val
assert yields == (0,1,2), yields
yields, val = run_generator(async_comp_dict(foo()))
assert val == {0: '0',1: '1', 2: '2'}, val
assert yields == (0,1,2), yields
[case testAsyncFor2]
from typing import AsyncIterable, List
async def async_iter(xs: AsyncIterable[int]) -> List[int]:
ys = []
async for x in xs:
ys.append(x)
return ys
[typing fixtures/typing-full.pyi]
[file driver.py]
from native import async_iter
from testutil import run_generator, async_val
from typing import AsyncIterable, List
# defined here since we couldn't do it inside the test yet...
async def foo() -> AsyncIterable[int]:
for x in range(3):
await async_val(x)
yield x
raise Exception('lol no')
yields, val = run_generator(async_iter(foo()))
assert yields == (0,1,2), yields
assert val == 'lol no', val

View File

@@ -0,0 +1,318 @@
-- Test cases for dataclasses based on the attrs library, where auto_attribs=True
[case testRunAttrsclass]
import attr
from typing import Set, List, Callable, Any
@attr.s(auto_attribs=True)
class Person1:
age : int
name : str
def __bool__(self) -> bool:
return self.name == 'robot'
def testBool(p: Person1) -> bool:
if p:
return True
else:
return False
@attr.s(auto_attribs=True)
class Person1b(Person1):
id: str = '000'
@attr.s(auto_attribs=True)
class Person2:
age : int
name : str = attr.ib(default='robot')
@attr.s(auto_attribs=True, order=True)
class Person3:
age : int = attr.ib(default = 6)
friendIDs : List[int] = attr.ib(factory = list)
def get_age(self) -> int:
return (self.age)
def set_age(self, new_age : int) -> None:
self.age = new_age
def add_friendID(self, fid : int) -> None:
self.friendIDs.append(fid)
def get_friendIDs(self) -> List[int]:
return self.friendIDs
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
def f(a: Any) -> int:
return g(a) + 1
return f
@attr.s(auto_attribs=True)
class Person4:
age : int
_name : str = 'Bot'
@get_next_age
def get_age(self) -> int:
return self.age
@property
def name(self) -> str:
return self._name
@attr.s(auto_attribs=True)
class Point:
x : int = attr.ib(converter=int)
y : int = attr.ib(init=False)
def __attrs_post_init__(self):
self.y = self.x + 1
[file other.py]
from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point
i1 = Person1(age = 5, name = 'robot')
assert i1.age == 5
assert i1.name == 'robot'
assert testBool(i1) == True
assert testBool(Person1(age = 5, name = 'robo')) == False
i1b = Person1b(age = 5, name = 'robot')
assert i1b.age == 5
assert i1b.name == 'robot'
assert i1b.id == '000'
assert testBool(i1b) == True
assert testBool(Person1b(age = 5, name = 'robo')) == False
i1c = Person1b(age = 20, name = 'robot', id = 'test')
assert i1c.age == 20
assert i1c.id == 'test'
i2 = Person2(age = 5)
assert i2.age == 5
assert i2.name == 'robot'
i3 = Person2(age = 5, name = 'new_robot')
assert i3.age == 5
assert i3.name == 'new_robot'
i4 = Person3()
assert i4.age == 6
assert i4.friendIDs == []
i5 = Person3(age = 5)
assert i5.age == 5
assert i5.friendIDs == []
i6 = Person3(age = 5, friendIDs = [1,2,3])
assert i6.age == 5
assert i6.friendIDs == [1,2,3]
assert i6.get_age() == 5
i6.set_age(10)
assert i6.get_age() == 10
i6.add_friendID(4)
assert i6.get_friendIDs() == [1,2,3,4]
i7 = Person4(age = 5)
assert i7.get_age() == 6
i7.age += 3
assert i7.age == 8
assert i7.name == 'Bot'
i8 = Person3(age = 1, friendIDs = [1,2])
i9 = Person3(age = 1, friendIDs = [1,2])
assert i8 == i9
i8.age = 2
assert i8 > i9
assert Person1.__annotations__ == {'age': int, 'name': str}
assert Person2.__annotations__ == {'age': int, 'name': str}
p1 = Point(2)
assert p1.x == 2
assert p1.y == 3
p2 = Point('2')
assert p2.x == 2
assert p2.y == 3
assert Point.__annotations__ == {'x': int, 'y': int}
[file driver.py]
import sys
# PEP 526 introduced in 3.6
version = sys.version_info[:2]
if version[0] < 3 or version[1] < 6:
exit()
# Run the tests in both interpreted and compiled mode
import other
import other_interpreted
# Test for an exceptional cases
from testutil import assertRaises
from native import Person1, Person1b, Person3
from types import BuiltinMethodType
with assertRaises(TypeError, "missing 1 required positional argument"):
Person1(0)
with assertRaises(TypeError, "missing 2 required positional arguments"):
Person1b()
with assertRaises(TypeError, "int object expected; got str"):
Person1('nope', 'test')
p = Person1(0, 'test')
with assertRaises(TypeError, "int object expected; got str"):
p.age = 'nope'
assert isinstance(Person3().get_age, BuiltinMethodType)
[case testRunAttrsclassNonAuto]
import attr
from typing import Set, List, Callable, Any
@attr.s
class Person1:
age = attr.ib(type=int)
name = attr.ib(type=str)
def __bool__(self) -> bool:
return self.name == 'robot'
def testBool(p: Person1) -> bool:
if p:
return True
else:
return False
@attr.s
class Person1b(Person1):
id = attr.ib(type=str, default='000')
@attr.s
class Person2:
age = attr.ib(type=int)
name = attr.ib(type=str, default='robot')
@attr.s(order=True)
class Person3:
age = attr.ib(type=int, default=6)
friendIDs = attr.ib(factory=list, type=List[int])
def get_age(self) -> int:
return (self.age)
def set_age(self, new_age : int) -> None:
self.age = new_age
def add_friendID(self, fid : int) -> None:
self.friendIDs.append(fid)
def get_friendIDs(self) -> List[int]:
return self.friendIDs
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
def f(a: Any) -> int:
return g(a) + 1
return f
@attr.s
class Person4:
age = attr.ib(type=int)
_name = attr.ib(type=str, default='Bot')
@get_next_age
def get_age(self) -> int:
return self.age
@property
def name(self) -> str:
return self._name
@attr.s
class Point:
x = attr.ib(type=int, converter=int)
y = attr.ib(type=int, init=False)
def __attrs_post_init__(self):
self.y = self.x + 1
[file other.py]
from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point
i1 = Person1(age = 5, name = 'robot')
assert i1.age == 5
assert i1.name == 'robot'
assert testBool(i1) == True
assert testBool(Person1(age = 5, name = 'robo')) == False
i1b = Person1b(age = 5, name = 'robot')
assert i1b.age == 5
assert i1b.name == 'robot'
assert i1b.id == '000'
assert testBool(i1b) == True
assert testBool(Person1b(age = 5, name = 'robo')) == False
i1c = Person1b(age = 20, name = 'robot', id = 'test')
assert i1c.age == 20
assert i1c.id == 'test'
i2 = Person2(age = 5)
assert i2.age == 5
assert i2.name == 'robot'
i3 = Person2(age = 5, name = 'new_robot')
assert i3.age == 5
assert i3.name == 'new_robot'
i4 = Person3()
assert i4.age == 6
assert i4.friendIDs == []
i5 = Person3(age = 5)
assert i5.age == 5
assert i5.friendIDs == []
i6 = Person3(age = 5, friendIDs = [1,2,3])
assert i6.age == 5
assert i6.friendIDs == [1,2,3]
assert i6.get_age() == 5
i6.set_age(10)
assert i6.get_age() == 10
i6.add_friendID(4)
assert i6.get_friendIDs() == [1,2,3,4]
i7 = Person4(age = 5)
assert i7.get_age() == 6
i7.age += 3
assert i7.age == 8
assert i7.name == 'Bot'
i8 = Person3(age = 1, friendIDs = [1,2])
i9 = Person3(age = 1, friendIDs = [1,2])
assert i8 == i9
i8.age = 2
assert i8 > i9
p1 = Point(2)
assert p1.x == 2
assert p1.y == 3
p2 = Point('2')
assert p2.x == 2
assert p2.y == 3
[file driver.py]
import sys
# Run the tests in both interpreted and compiled mode
import other
import other_interpreted
# Test for an exceptional cases
from testutil import assertRaises
from native import Person1, Person1b, Person3
from types import BuiltinMethodType
with assertRaises(TypeError, "missing 1 required positional argument"):
Person1(0)
with assertRaises(TypeError, "missing 2 required positional arguments"):
Person1b()
with assertRaises(TypeError, "int object expected; got str"):
Person1('nope', 'test')
p = Person1(0, 'test')
with assertRaises(TypeError, "int object expected; got str"):
p.age = 'nope'
assert isinstance(Person3().get_age, BuiltinMethodType)

View File

@@ -0,0 +1,196 @@
-- TODO: build some generic benchmark harness
[case testBenchmarkTree]
from typing import Optional
class Node:
def __init__(self, value: int) -> None:
self.value = value
self.left = None # type: Optional[Node]
self.right = None # type: Optional[Node]
def sum(self) -> int:
left = 0
if self.left is not None:
left = self.left.sum()
right = 0
if self.right is not None:
right = self.right.sum()
return self.value + left + right
def sum_tree(x: Optional[Node]) -> int:
if x is None:
return 0
return x.value + sum_tree(x.left) + sum_tree(x.right)
def build(n: int) -> Optional[Node]:
if n == 0:
return None
x = Node(n)
x.left = build(n - 1)
x.right = x.left
return x
def bench_sum(x: Optional[Node]) -> None:
for i in range(1000000):
sum_tree(x)
def bench_sum_method(x: Node) -> None:
for i in range(1000000):
x.sum()
[file driver.py]
from typing import Optional
import native
import interpreted
from timeit import timeit
from time import time
import os
def dumb_time(f):
t0 = time()
f()
t1 = time()
return t1 - t0
def basic_test(m):
tree = m.build(5)
assert(m.sum_tree(tree) == 57)
assert(tree.sum() == 57)
return tree
def test(m):
tree = basic_test(m)
g = {**globals(), **locals()}
sum = timeit('m.sum_tree(tree)', globals=g)
sum2 = timeit('tree.sum()', globals=g)
fsum = dumb_time(lambda: m.bench_sum(tree))
fsum2 = dumb_time(lambda: m.bench_sum_method(tree))
build = timeit('m.build(5)', globals=g)
return (sum, sum2, fsum, fsum2, build)
# Basic functionality test
basic_test(native)
# Benchmark if we are benchmarking
if os.environ.get('MYPYC_RUN_BENCH') == '1':
nsum, nsum2, nfsum, nfsum2, nbuild = test(native)
isum, isum2, ifsum, ifsum2, ibuild = test(interpreted)
print(nsum, nsum2, nfsum, nbuild)
print("Sum speedup:", isum/nsum)
print("Sum method speedup:", isum2/nsum2)
print("Sum (fast) speedup:", ifsum/nfsum)
print("Sum (fast) method speedup:", ifsum2/nfsum2)
print("Build speedup:", ibuild/nbuild)
[case testBenchmarkVisitorTree]
from mypy_extensions import trait
from typing import cast, Generic, TypeVar, Any
T = TypeVar('T')
class Tree:
def accept(self, v: 'TreeVisitor[T]') -> T:
pass
class Leaf(Tree):
def accept(self, v: 'TreeVisitor[T]') -> T:
return v.visit_leaf(self)
class Node(Tree):
def __init__(self, value: int, left: Tree, right: Tree) -> None:
self.value = value
self.left = left
self.right = right
def accept(self, v: 'TreeVisitor[T]') -> T:
return v.visit_node(self)
@trait
class TreeVisitor(Generic[T]):
def visit_leaf(self, x: Leaf) -> T: return cast(T, None)
def visit_node(self, x: Node) -> T: return cast(T, None)
class SumVisitor(TreeVisitor[int]):
def sum(self, x: Tree) -> int:
return x.accept(self)
def visit_leaf(self, x: Leaf) -> int:
return 0
def visit_node(self, x: Node) -> int:
return x.value + self.sum(x.left) + self.sum(x.right)
def equal(x: Tree, y: Tree) -> bool:
return EqualVisitor(x).equal(y)
class EqualVisitor(TreeVisitor[bool]):
def __init__(self, left: Tree) -> None:
self.left = left
def equal(self, right: Tree) -> bool:
return right.accept(self)
def visit_leaf(self, right: Leaf) -> bool:
return isinstance(self.left, Leaf)
def visit_node(self, right: Node) -> bool:
if isinstance(self.left, Node):
# our boolean stuff is crap
if (self.left.value == right.value and equal(self.left.left, right.left)
and equal(self.left.right, right.right)):
return True
return False
def sum_tree(x: Tree) -> int:
return SumVisitor().sum(x)
def build(n: int) -> Tree:
if n == 0:
return Leaf()
return Node(n, build(n - 1), build(n - 1))
def bench_sum_tree(x: Tree) -> None:
for i in range(100000):
sum_tree(x)
def bench_equal_tree(x: Tree, y: Tree) -> None:
for i in range(100000):
equal(x, y)
[file driver.py]
from typing import Optional
import interpreted
import native
from timeit import timeit
from time import time
import os
import sys
# Side test: some stuff about MROs and generics
if sys.version_info[:3] > (3, 5, 2):
assert tuple(x.__name__ for x in interpreted.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
assert tuple(x.__name__ for x in native.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
assert str(native.TreeVisitor[native.T]) == "native.TreeVisitor[~T]"
assert native.TreeVisitor.__name__ == "TreeVisitor"
assert native.SumVisitor.__name__ == "SumVisitor"
def dumb_time(f):
t0 = time()
f()
t1 = time()
return t1 - t0
def basic_test(m):
tree = m.build(5)
tree2 = m.build(5)
tree2.right.right.right.value = 10
assert m.sum_tree(tree) == 57
assert m.equal(tree, tree)
assert not m.equal(tree, tree2)
assert isinstance(native.SumVisitor(), native.TreeVisitor)
return tree
def test(m):
tree = basic_test(m)
g = {**globals(), **locals()}
fsum = dumb_time(lambda: m.bench_sum_tree(tree))
feq = dumb_time(lambda: m.bench_equal_tree(tree, tree))
return fsum, feq
basic_test(native)
if os.environ.get('MYPYC_RUN_BENCH') == '1':
nfsum, nfeq = test(native)
ifsum, ifeq = test(interpreted)
print(nfsum)
print("Sum speedup:", ifsum/nfsum)
print("Equal speedup:", ifeq/nfeq)

View File

@@ -0,0 +1,229 @@
# Test cases for booleans (compile and run)
[case testTrueAndFalse]
def t() -> bool:
return True
def f() -> bool:
return False
[file driver.py]
from native import t, f
print(t())
print(f())
[out]
True
False
[case testBoolOps]
from typing import Optional, Any
MYPY = False
if MYPY:
from mypy_extensions import i64
def f(x: bool) -> bool:
if x:
return False
else:
return True
def test_if() -> None:
assert f(True) is False
assert f(False) is True
def test_bitwise_and() -> None:
# Use eval() to avoid constand folding
t: bool = eval('True')
f: bool = eval('False')
assert t & t == True
assert t & f == False
assert f & t == False
assert f & f == False
t &= t
assert t == True
t &= f
assert t == False
def test_bitwise_or() -> None:
# Use eval() to avoid constand folding
t: bool = eval('True')
f: bool = eval('False')
assert t | t == True
assert t | f == True
assert f | t == True
assert f | f == False
t |= f
assert t == True
f |= t
assert f == True
def test_bitwise_xor() -> None:
# Use eval() to avoid constand folding
t: bool = eval('True')
f: bool = eval('False')
assert t ^ t == False
assert t ^ f == True
assert f ^ t == True
assert f ^ f == False
t ^= f
assert t == True
t ^= t
assert t == False
f ^= f
assert f == False
def test_isinstance_bool() -> None:
a = True
b = 1.0
c = 1
d = False
assert isinstance(a, bool) == True
assert isinstance(b, bool) == False
assert isinstance(c, bool) == False
assert isinstance(d, bool) == True
class C: pass
class D:
def __init__(self, b: bool) -> None:
self.b = b
def __bool__(self) -> bool:
return self.b
class E: pass
class F(E):
def __init__(self, b: bool) -> None:
self.b = b
def __bool__(self) -> bool:
return self.b
def optional_to_bool1(o: Optional[C]) -> bool:
return bool(o)
def optional_to_bool2(o: Optional[D]) -> bool:
return bool(o)
def optional_to_bool3(o: Optional[E]) -> bool:
return bool(o)
def test_optional_to_bool() -> None:
assert not optional_to_bool1(None)
assert optional_to_bool1(C())
assert not optional_to_bool2(None)
assert not optional_to_bool2(D(False))
assert optional_to_bool2(D(True))
assert not optional_to_bool3(None)
assert optional_to_bool3(E())
assert not optional_to_bool3(F(False))
assert optional_to_bool3(F(True))
def test_any_to_bool() -> None:
a: Any = int()
b: Any = a + 1
assert not bool(a)
assert bool(b)
def eq(x: bool, y: bool) -> bool:
return x == y
def ne(x: bool, y: bool) -> bool:
return x != y
def lt(x: bool, y: bool) -> bool:
return x < y
def le(x: bool, y: bool) -> bool:
return x <= y
def gt(x: bool, y: bool) -> bool:
return x > y
def ge(x: bool, y: bool) -> bool:
return x >= y
def test_comparisons() -> None:
for x in True, False:
for y in True, False:
x2: Any = x
y2: Any = y
assert eq(x, y) == (x2 == y2)
assert ne(x, y) == (x2 != y2)
assert lt(x, y) == (x2 < y2)
assert le(x, y) == (x2 <= y2)
assert gt(x, y) == (x2 > y2)
assert ge(x, y) == (x2 >= y2)
def eq_mixed(x: bool, y: int) -> bool:
return x == y
def neq_mixed(x: int, y: bool) -> bool:
return x != y
def lt_mixed(x: bool, y: int) -> bool:
return x < y
def gt_mixed(x: int, y: bool) -> bool:
return x > y
def test_mixed_comparisons() -> None:
for x in True, False:
for n in -(1 << 70), -123, 0, 1, 1753, 1 << 70:
assert eq_mixed(x, n) == (int(x) == n)
assert neq_mixed(n, x) == (n != int(x))
assert lt_mixed(x, n) == (int(x) < n)
assert gt_mixed(n, x) == (n > int(x))
def add(x: bool, y: bool) -> int:
return x + y
def add_mixed(b: bool, n: int) -> int:
return b + n
def sub_mixed(n: int, b: bool) -> int:
return n - b
def test_arithmetic() -> None:
for x in True, False:
for y in True, False:
assert add(x, y) == int(x) + int(y)
for n in -(1 << 70), -123, 0, 1, 1753, 1 << 70:
assert add_mixed(x, n) == int(x) + n
assert sub_mixed(n, x) == n - int(x)
def add_mixed_i64(b: bool, n: i64) -> i64:
return b + n
def sub_mixed_i64(n: i64, b: bool) -> i64:
return n - b
def test_arithmetic_i64() -> None:
for x in True, False:
for n in -(1 << 62), -123, 0, 1, 1753, 1 << 62:
assert add_mixed_i64(x, n) == int(x) + n
assert sub_mixed_i64(n, x) == n - int(x)
def eq_mixed_i64(x: bool, y: i64) -> bool:
return x == y
def neq_mixed_i64(x: i64, y: bool) -> bool:
return x != y
def lt_mixed_i64(x: bool, y: i64) -> bool:
return x < y
def gt_mixed_i64(x: i64, y: bool) -> bool:
return x > y
def test_mixed_comparisons_i64() -> None:
for x in True, False:
for n in -(1 << 62), -123, 0, 1, 1753, 1 << 62:
assert eq_mixed_i64(x, n) == (int(x) == n)
assert neq_mixed_i64(n, x) == (n != int(x))
assert lt_mixed_i64(x, n) == (int(x) < n)
assert gt_mixed_i64(n, x) == (n > int(x))
[case testBoolMixInt]
y = False
print((y or 0) and True)
[out]
0

View File

@@ -0,0 +1,302 @@
# Bytes test cases (compile and run)
[case testBytesBasics]
# Note: Add tests for additional operations to testBytesOps or in a new test case
def f(x: bytes) -> bytes:
return x
def eq(a: bytes, b: bytes) -> bool:
return a == b
def neq(a: bytes, b: bytes) -> bool:
return a != b
[file driver.py]
from native import f, eq, neq
assert f(b'123') == b'123'
assert f(b'\x07 \x0b " \t \x7f \xf0') == b'\x07 \x0b " \t \x7f \xf0'
assert eq(b'123', b'123')
assert not eq(b'123', b'1234')
assert not eq(b'123', b'124')
assert not eq(b'123', b'223')
assert neq(b'123', b'1234')
try:
f('x')
assert False
except TypeError:
pass
[case testBytesInit]
def test_bytes_init() -> None:
b1 = bytes([5])
assert b1 == b'\x05'
b2 = bytes([5, 10, 12])
assert b2 == b'\x05\n\x0c'
b3 = bytes(bytearray(b'foo'))
assert b3 == b'foo'
b4 = bytes(b'aaa')
assert b4 == b'aaa'
b5 = bytes(5)
assert b5 == b'\x00\x00\x00\x00\x00'
try:
bytes('x')
assert False
except TypeError:
pass
[case testBytesOps]
from testutil import assertRaises
def test_indexing() -> None:
# Use bytes() to avoid constant folding
b = b'asdf' + bytes()
assert b[0] == 97
assert b[1] == 115
assert b[3] == 102
assert b[-1] == 102
b = b'\xae\x80\xfe\x15' + bytes()
assert b[0] == 174
assert b[1] == 128
assert b[2] == 254
assert b[3] == 21
assert b[-4] == 174
with assertRaises(IndexError, "index out of range"):
b[4]
with assertRaises(IndexError, "index out of range"):
b[-5]
with assertRaises(IndexError, "index out of range"):
b[2**26]
def test_concat() -> None:
b1 = b'123' + bytes()
b2 = b'456' + bytes()
assert b1 + b2 == b'123456'
b3 = b1 + b2
b3 = b3 + b1
assert b3 == b'123456123'
assert b1 == b'123'
assert b2 == b'456'
assert type(b1) == bytes
assert type(b2) == bytes
assert type(b3) == bytes
brr1: bytes = bytearray(3)
brr2: bytes = bytearray(range(5))
b4 = b1 + brr1
assert b4 == b'123\x00\x00\x00'
assert type(brr1) == bytearray
assert type(b4) == bytes
brr3 = brr1 + brr2
assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04')
assert len(brr3) == 8
assert type(brr3) == bytearray
brr3 = brr3 + bytearray([10])
assert brr3 == bytearray(b'\x00\x00\x00\x00\x01\x02\x03\x04\n')
b5 = brr2 + b2
assert b5 == bytearray(b'\x00\x01\x02\x03\x04456')
assert type(b5) == bytearray
b5 = b2 + brr2
assert b5 == b'456\x00\x01\x02\x03\x04'
assert type(b5) == bytes
def test_join() -> None:
seq = (b'1', b'"', b'\xf0')
assert b'\x07'.join(seq) == b'1\x07"\x07\xf0'
assert b', '.join(()) == b''
assert b', '.join([bytes() + b'ab']) == b'ab'
assert b', '.join([bytes() + b'ab', b'cd']) == b'ab, cd'
def test_len() -> None:
# Use bytes() to avoid constant folding
b = b'foo' + bytes()
assert len(b) == 3
assert len(bytes()) == 0
[case testBytesSlicing]
def test_bytes_slicing() -> None:
b = b'abcdefg'
zero = int()
ten = 10 + zero
two = 2 + zero
five = 5 + zero
seven = 7 + zero
assert b[:ten] == b'abcdefg'
assert b[0:seven] == b'abcdefg'
assert b[0:(len(b)+1)] == b'abcdefg'
assert b[two:five] == b'cde'
assert b[two:two] == b''
assert b[-two:-two] == b''
assert b[-ten:(-ten+1)] == b''
assert b[:-two] == b'abcde'
assert b[:two] == b'ab'
assert b[:] == b'abcdefg'
assert b[-two:] == b'fg'
assert b[zero:] == b'abcdefg'
assert b[:zero] == b''
assert b[-ten:] == b'abcdefg'
assert b[-ten:ten] == b'abcdefg'
big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63]
for big_int in big_ints:
assert b[1:big_int] == b'bcdefg'
assert b[big_int:] == b''
assert b[-big_int:-1] == b'abcdef'
assert b[-big_int:big_int] == b'abcdefg'
assert type(b[-big_int:-1]) == bytes
assert type(b[-ten:]) == bytes
assert type(b[:]) == bytes
[case testBytearrayBasics]
from typing import Any
def test_basics() -> None:
brr1: bytes = bytearray(3)
assert brr1 == bytearray(b'\x00\x00\x00')
assert brr1 == b'\x00\x00\x00'
l = [10, 20, 30, 40]
brr2: bytes = bytearray(l)
assert brr2 == bytearray(b'\n\x14\x1e(')
assert brr2 == b'\n\x14\x1e('
brr3: bytes = bytearray(range(5))
assert brr3 == bytearray(b'\x00\x01\x02\x03\x04')
assert brr3 == b'\x00\x01\x02\x03\x04'
brr4: bytes = bytearray('string', 'utf-8')
assert brr4 == bytearray(b'string')
assert brr4 == b'string'
assert len(brr1) == 3
assert len(brr2) == 4
def f(b: bytes) -> bool:
return True
def test_bytearray_passed_into_bytes() -> None:
assert f(bytearray(3))
brr1: Any = bytearray()
assert f(brr1)
[case testBytearraySlicing]
def test_bytearray_slicing() -> None:
b: bytes = bytearray(b'abcdefg')
zero = int()
ten = 10 + zero
two = 2 + zero
five = 5 + zero
seven = 7 + zero
assert b[:ten] == b'abcdefg'
assert b[0:seven] == b'abcdefg'
assert b[two:five] == b'cde'
assert b[two:two] == b''
assert b[-two:-two] == b''
assert b[-ten:(-ten+1)] == b''
assert b[:-two] == b'abcde'
assert b[:two] == b'ab'
assert b[:] == b'abcdefg'
assert b[-two:] == b'fg'
assert b[zero:] == b'abcdefg'
assert b[:zero] == b''
assert b[-ten:] == b'abcdefg'
assert b[-ten:ten] == b'abcdefg'
big_ints = [1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000, 2**24, 2**63]
for big_int in big_ints:
assert b[1:big_int] == b'bcdefg'
assert b[big_int:] == b''
assert b[-big_int:-1] == b'abcdef'
assert b[-big_int:big_int] == b'abcdefg'
assert type(b[-big_int:-1]) == bytearray
assert type(b[-ten:]) == bytearray
assert type(b[:]) == bytearray
[case testBytearrayIndexing]
from testutil import assertRaises
def test_bytearray_indexing() -> None:
b: bytes = bytearray(b'\xae\x80\xfe\x15')
assert b[0] == 174
assert b[1] == 128
assert b[2] == 254
assert b[3] == 21
assert b[-4] == 174
with assertRaises(IndexError, "index out of range"):
b[4]
with assertRaises(IndexError, "index out of range"):
b[-5]
b2 = bytearray([175, 255, 128, 22])
assert b2[0] == 175
assert b2[1] == 255
assert b2[-1] == 22
assert b2[2] == 128
with assertRaises(ValueError, "byte must be in range(0, 256)"):
b2[0] = -1
with assertRaises(ValueError, "byte must be in range(0, 256)"):
b2[0] = 256
[case testBytesJoin]
from typing import Any
from testutil import assertRaises
from a import bytes_subclass
def test_bytes_join() -> None:
assert b' '.join([b'a', b'b']) == b'a b'
assert b' '.join([]) == b''
x: bytes = bytearray(b' ')
assert x.join([b'a', b'b']) == b'a b'
assert type(x.join([b'a', b'b'])) == bytearray
y: bytes = bytes_subclass()
assert y.join([]) == b'spook'
n: Any = 5
with assertRaises(TypeError, "can only join an iterable"):
assert b' '.join(n)
[file a.py]
class bytes_subclass(bytes):
def join(self, iter):
return b'spook'
[case testBytesFormatting]
[typing fixtures/typing-full.pyi]
from testutil import assertRaises
# https://www.python.org/dev/peps/pep-0461/
def test_bytes_formatting() -> None:
val = 10
assert b"%x" % val == b'a'
assert b'%4x' % val == b' a'
assert b'%#4x' % val == b' 0xa'
assert b'%04X' % val == b'000A'
assert b'%c' % 48 == b'0'
assert b'%c' % b'a' == b'a'
assert b'%c%c' % (48, b'a') == b'0a'
assert b'%b' % b'abc' == b'abc'
assert b'%b' % 'some string'.encode('utf8') == b'some string'
assert b'%a' % 3.14 == b'3.14'
assert b'%a' % b'abc' == b"b'abc'"
assert b'%a' % 'def' == b"'def'"
def test_bytes_formatting_2() -> None:
var = b'bb'
num = 10
assert b'aaa%bbbb%s' % (var, var) == b'aaabbbbbbb'
assert b'aaa%dbbb%b' % (num, var) == b'aaa10bbbbb'
assert b'%s%b' % (var, var) == b'bbbb'
assert b'%b' % bytes() == b''
assert b'%b' % b'' == b''
assert b'\xff%s' % b'\xff' == b'\xff\xff'
assert b'\xff%b' % '你好'.encode() == b'\xff\xe4\xbd\xa0\xe5\xa5\xbd'
aa = b'\xe4\xbd\xa0\xe5\xa5\xbd%b' % b'\xe4\xbd\xa0\xe5\xa5\xbd'
assert aa == b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd'
assert aa.decode() == '你好你好'
class A:
def __bytes__(self):
return b'aaa'
def test_bytes_dunder() -> None:
assert b'%b' % A() == b'aaa'
assert b'%s' % A() == b'aaa'

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,334 @@
# Test cases for dicts (compile and run)
[case testDictStuff]
from typing import Dict, Any, List, Set, Tuple
from defaultdictwrap import make_dict
def f(x: int) -> int:
dict1 = {} # type: Dict[int, int]
dict1[1] = 1
dict2 = {} # type: Dict[int, int]
dict2[x] = 2
dict1.update(dict2)
l = [(5, 2)] # type: Any
dict1.update(l)
d2 = {6: 4} # type: Any
dict1.update(d2)
return dict1[1]
def g() -> int:
d = make_dict()
d['a'] = 10
d['a'] += 10
d['b'] += 10
l = [('c', 2)] # type: Any
d.update(l)
d2 = {'d': 4} # type: Any
d.update(d2)
return d['a'] + d['b']
def h() -> None:
d = {} # type: Dict[Any, Any]
d[{}]
def update_dict(x: Dict[Any, Any], y: Any):
x.update(y)
def make_dict1(x: Any) -> Dict[Any, Any]:
return dict(x)
def make_dict2(x: Dict[Any, Any]) -> Dict[Any, Any]:
return dict(x)
def u(x: int) -> int:
d = {} # type: Dict[str, int]
d.update(x=x)
return d['x']
def get_content(d: Dict[int, int]) -> Tuple[List[int], List[int], List[Tuple[int, int]]]:
return list(d.keys()), list(d.values()), list(d.items())
def get_content_set(d: Dict[int, int]) -> Tuple[Set[int], Set[int], Set[Tuple[int, int]]]:
return set(d.keys()), set(d.values()), set(d.items())
[file defaultdictwrap.py]
from typing import Dict
from collections import defaultdict # type: ignore
def make_dict() -> Dict[str, int]:
return defaultdict(int)
[file driver.py]
from collections import OrderedDict
from native import (
f, g, h, u, make_dict1, make_dict2, update_dict, get_content, get_content_set
)
assert f(1) == 2
assert f(2) == 1
assert g() == 30
# Make sure we get a TypeError from indexing with unhashable and not KeyError
try:
h()
except TypeError:
pass
else:
assert False
d = {'a': 1, 'b': 2}
assert make_dict1(d) == d
assert make_dict1(d.items()) == d
assert make_dict2(d) == d
# object.__dict__ is a "mappingproxy" and not a dict
assert make_dict1(object.__dict__) == dict(object.__dict__)
d = {}
update_dict(d, object.__dict__)
assert d == dict(object.__dict__)
assert u(10) == 10
assert get_content({1: 2}) == ([1], [2], [(1, 2)])
od = OrderedDict([(1, 2), (3, 4)])
assert get_content(od) == ([1, 3], [2, 4], [(1, 2), (3, 4)])
od.move_to_end(1)
assert get_content(od) == ([3, 1], [4, 2], [(3, 4), (1, 2)])
assert get_content_set({1: 2}) == ({1}, {2}, {(1, 2)})
assert get_content_set(od) == ({1, 3}, {2, 4}, {(1, 2), (3, 4)})
[typing fixtures/typing-full.pyi]
[case testDictIterationMethodsRun]
from typing import Dict, Union
from typing_extensions import TypedDict
class ExtensionDict(TypedDict):
python: str
c: str
def print_dict_methods(d1: Dict[int, int],
d2: Dict[int, int],
d3: Dict[int, int]) -> None:
for k in d1.keys():
print(k)
for k, v in d2.items():
print(k)
print(v)
for v in d3.values():
print(v)
def print_dict_methods_special(d1: Union[Dict[int, int], Dict[str, str]],
d2: ExtensionDict) -> None:
for k in d1.keys():
print(k)
for k, v in d1.items():
print(k)
print(v)
for v2 in d2.values():
print(v2)
for k2, v2 in d2.items():
print(k2)
print(v2)
def clear_during_iter(d: Dict[int, int]) -> None:
for k in d:
d.clear()
class Custom(Dict[int, int]): pass
[file driver.py]
from native import print_dict_methods, print_dict_methods_special, Custom, clear_during_iter
from collections import OrderedDict
print_dict_methods({}, {}, {})
print_dict_methods({1: 2}, {3: 4, 5: 6}, {7: 8})
print('==')
c = Custom({0: 1})
print_dict_methods(c, c, c)
print('==')
d = OrderedDict([(1, 2), (3, 4)])
print_dict_methods(d, d, d)
print('==')
print_dict_methods_special({1: 2}, {"python": ".py", "c": ".c"})
d.move_to_end(1)
print_dict_methods(d, d, d)
clear_during_iter({}) # OK
try:
clear_during_iter({1: 2, 3: 4})
except RuntimeError as e:
assert str(e) == "dictionary changed size during iteration"
else:
assert False
try:
clear_during_iter(d)
except RuntimeError as e:
assert str(e) == "OrderedDict changed size during iteration"
else:
assert False
class CustomMad(dict):
def __iter__(self):
return self
def __next__(self):
raise ValueError
m = CustomMad()
try:
clear_during_iter(m)
except ValueError:
pass
else:
assert False
class CustomBad(dict):
def items(self):
return [(1, 2, 3)] # Oops
b = CustomBad()
try:
print_dict_methods(b, b, b)
except TypeError as e:
assert str(e) == "a tuple of length 2 expected"
else:
assert False
[out]
1
3
4
5
6
8
==
0
0
1
1
==
1
3
1
2
3
4
2
4
==
1
1
2
.py
.c
python
.py
c
.c
3
1
3
4
1
2
4
2
[case testDictMethods]
from collections import defaultdict
from typing import Dict, Optional, List, Set
def test_dict_clear() -> None:
d = {'a': 1, 'b': 2}
d.clear()
assert d == {}
dd: Dict[str, int] = defaultdict(int)
dd['a'] = 1
dd.clear()
assert dd == {}
def test_dict_copy() -> None:
d: Dict[str, int] = {}
assert d.copy() == d
d = {'a': 1, 'b': 2}
assert d.copy() == d
assert d.copy() is not d
dd: Dict[str, int] = defaultdict(int)
dd['a'] = 1
assert dd.copy() == dd
assert isinstance(dd.copy(), defaultdict)
class MyDict(dict):
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
def setdefault(self, k, v=None):
if v is None:
if k in self.keys():
return self[k]
else:
return None
else:
return super().setdefault(k, v) + 10
def test_dict_setdefault() -> None:
d: Dict[str, Optional[int]] = {'a': 1, 'b': 2}
assert d.setdefault('a', 2) == 1
assert d.setdefault('b', 2) == 2
assert d.setdefault('c', 3) == 3
assert d['a'] == 1
assert d['c'] == 3
assert d.setdefault('a') == 1
assert d.setdefault('e') == None
assert d.setdefault('e', 100) == None
def test_dict_subclass_setdefault() -> None:
d = MyDict()
d['a'] = 1
assert d.setdefault('a', 2) == 11
assert d.setdefault('b', 2) == 12
assert d.setdefault('c', 3) == 13
assert d['a'] == 1
assert d['c'] == 3
assert d.setdefault('a') == 1
assert d.setdefault('e') == None
assert d.setdefault('e', 100) == 110
def test_dict_empty_collection_setdefault() -> None:
d1: Dict[str, List[int]] = {'a': [1, 2, 3]}
assert d1.setdefault('a', []) == [1, 2, 3]
assert d1.setdefault('b', []) == []
assert 'b' in d1
d1.setdefault('b', []).append(3)
assert d1['b'] == [3]
assert d1.setdefault('c', [1]) == [1]
d2: Dict[str, Dict[str, int]] = {'a': {'a': 1}}
assert d2.setdefault('a', {}) == {'a': 1}
assert d2.setdefault('b', {}) == {}
assert 'b' in d2
d2.setdefault('b', {})['aa'] = 2
d2.setdefault('b', {})['bb'] = 3
assert d2['b'] == {'aa': 2, 'bb': 3}
assert d2.setdefault('c', {'cc': 1}) == {'cc': 1}
d3: Dict[str, Set[str]] = {'a': set('a')}
assert d3.setdefault('a', set()) == {'a'}
assert d3.setdefault('b', set()) == set()
d3.setdefault('b', set()).add('b')
d3.setdefault('b', set()).add('c')
assert d3['b'] == {'b', 'c'}
assert d3.setdefault('c', set('d')) == {'d'}
[case testDictToBool]
from typing import Dict, List
def is_true(x: dict) -> bool:
if x:
return True
else:
return False
def is_false(x: dict) -> bool:
if not x:
return True
else:
return False
def test_dict_to_bool() -> None:
assert is_false({})
assert not is_true({})
tmp_list: List[Dict] = [{2: bool}, {'a': 'b'}]
for x in tmp_list:
assert is_true(x)
assert not is_false(x)

View File

@@ -0,0 +1,945 @@
# Test cases for (some) dunder methods (compile and run)
[case testDundersMisc]
# Legacy test case for dunders (don't add more here)
from typing import Any
class Item:
def __init__(self, value: str) -> None:
self.value = value
def __hash__(self) -> int:
return hash(self.value)
def __eq__(self, rhs: object) -> bool:
return isinstance(rhs, Item) and self.value == rhs.value
def __lt__(self, x: 'Item') -> bool:
return self.value < x.value
class Subclass1(Item):
def __bool__(self) -> bool:
return bool(self.value)
class NonBoxedThing:
def __getitem__(self, index: Item) -> Item:
return Item("2 * " + index.value + " + 1")
class BoxedThing:
def __getitem__(self, index: int) -> int:
return 2 * index + 1
class Subclass2(BoxedThing):
pass
class UsesNotImplemented:
def __eq__(self, b: object) -> bool:
return NotImplemented
def index_into(x : Any, y : Any) -> Any:
return x[y]
def internal_index_into() -> None:
x = BoxedThing()
print (x[3])
y = NonBoxedThing()
z = Item("3")
print(y[z].value)
def is_truthy(x: Item) -> bool:
return True if x else False
[file driver.py]
from native import *
x = BoxedThing()
y = 3
print(x[y], index_into(x, y))
x = Subclass2()
y = 3
print(x[y], index_into(x, y))
z = NonBoxedThing()
w = Item("3")
print(z[w].value, index_into(z, w).value)
i1 = Item('lolol')
i2 = Item('lol' + 'ol')
i3 = Item('xyzzy')
assert hash(i1) == hash(i2)
assert i1 == i2
assert not i1 != i2
assert not i1 == i3
assert i1 != i3
assert i2 < i3
assert not i1 < i2
assert i1 == Subclass1('lolol')
assert is_truthy(Item(''))
assert is_truthy(Item('a'))
assert not is_truthy(Subclass1(''))
assert is_truthy(Subclass1('a'))
assert UsesNotImplemented() != object()
internal_index_into()
[out]
7 7
7 7
2 * 3 + 1 2 * 3 + 1
7
2 * 3 + 1
[case testDundersContainer]
# Sequence/mapping dunder methods
from typing import Any
class Seq:
def __init__(self) -> None:
self.key = 0
self.value = 0
def __len__(self) -> int:
return 5
def __setitem__(self, key: int, value: int) -> None:
self.key = key
self.value = value
def __contains__(self, x: int) -> bool:
return x == 3
def __delitem__(self, key: int) -> None:
self.key = key
class Plain: pass
def any_seq() -> Any:
"""Return Any-typed Seq."""
return Seq()
def any_plain() -> Any:
"""Return Any-typed Seq."""
return Plain()
def test_len() -> None:
assert len(any_seq()) == 5
assert len(Seq()) == 5
def test_len_error() -> None:
try:
len(any_plain())
except TypeError:
pass
else:
assert False
def test_set_item() -> None:
s = any_seq()
s[44] = 66
assert s.key == 44 and s.value == 66
ss = Seq()
ss[33] = 55
assert ss.key == 33 and ss.value == 55
def test_contains() -> None:
assert 3 in any_seq()
assert 4 not in any_seq()
assert 2 not in any_seq()
assert 3 in Seq()
assert 4 not in Seq()
assert 2 not in Seq()
def test_delitem() -> None:
s = any_seq()
del s[55]
assert s.key == 55
class SeqAny:
def __contains__(self, x: Any) -> Any:
return x == 3
def __setitem__(self, x: Any, y: Any) -> Any:
self.x = x
return 'x'
def test_contains_any() -> None:
assert (3 in SeqAny()) is True
assert (2 in SeqAny()) is False
assert (3 not in SeqAny()) is False
assert (2 not in SeqAny()) is True
s = SeqAny() # type: Any
assert (3 in s) is True
assert (2 in s) is False
assert (3 not in s) is False
assert (2 not in s) is True
def test_set_item_any() -> None:
s = SeqAny()
s[4] = 6
assert s.x == 4
ss = SeqAny() # type: Any
ss[5] = 7
assert ss.x == 5
class SeqError:
def __setitem__(self, key: int, value: int) -> None:
raise RuntimeError()
def __contains__(self, x: int) -> bool:
raise RuntimeError()
def __len__(self):
return -5
def any_seq_error() -> Any:
return SeqError()
def test_set_item_error_propagate() -> None:
s = any_seq_error()
try:
s[44] = 66
except RuntimeError:
pass
else:
assert False
def test_contains_error_propagate() -> None:
s = any_seq_error()
try:
3 in s
except RuntimeError:
pass
else:
assert False
def test_negative_len() -> None:
try:
len(SeqError())
except ValueError:
pass
else:
assert False
class DelItemNoSetItem:
def __delitem__(self, x: int) -> None:
self.key = x
def test_del_item_with_no_set_item() -> None:
o = DelItemNoSetItem()
del o[22]
assert o.key == 22
a = o # type: Any
del a[12]
assert a.key == 12
try:
a[1] = 2
except TypeError as e:
assert str(e) == "'DelItemNoSetItem' object does not support item assignment"
else:
assert False
class SetItemOverride(dict):
# Only override __setitem__, __delitem__ comes from dict
def __setitem__(self, x: int, y: int) -> None:
self.key = x
self.value = y
def test_set_item_override() -> None:
o = SetItemOverride({'x': 12, 'y': 13})
o[2] = 3
assert o.key == 2 and o.value == 3
a = o # type: Any
o[4] = 5
assert o.key == 4 and o.value == 5
assert o['x'] == 12
assert o['y'] == 13
del o['x']
assert 'x' not in o and 'y' in o
del a['y']
assert 'y' not in a and 'x' not in a
class DelItemOverride(dict):
# Only override __delitem__, __setitem__ comes from dict
def __delitem__(self, x: int) -> None:
self.key = x
def test_del_item_override() -> None:
o = DelItemOverride()
del o[2]
assert o.key == 2
a = o # type: Any
del o[5]
assert o.key == 5
o['x'] = 12
assert o['x'] == 12
a['y'] = 13
assert a['y'] == 13
class SetItemOverrideNative(Seq):
def __setitem__(self, key: int, value: int) -> None:
self.key = key + 1
self.value = value + 1
def test_native_set_item_override() -> None:
o = SetItemOverrideNative()
o[1] = 4
assert o.key == 2 and o.value == 5
del o[6]
assert o.key == 6
a = o # type: Any
a[10] = 12
assert a.key == 11 and a.value == 13
del a[16]
assert a.key == 16
class DelItemOverrideNative(Seq):
def __delitem__(self, key: int) -> None:
self.key = key + 2
def test_native_del_item_override() -> None:
o = DelItemOverrideNative()
o[1] = 4
assert o.key == 1 and o.value == 4
del o[6]
assert o.key == 8
a = o # type: Any
a[10] = 12
assert a.key == 10 and a.value == 12
del a[16]
assert a.key == 18
[case testDundersNumber]
from typing import Any
class C:
def __init__(self, x: int) -> None:
self.x = x
def __neg__(self) -> int:
return self.x + 1
def __invert__(self) -> int:
return self.x + 2
def __int__(self) -> int:
return self.x + 3
def __float__(self) -> float:
return float(self.x + 4)
def __pos__(self) -> int:
return self.x + 5
def __abs__(self) -> int:
return abs(self.x) + 6
def test_unary_dunders_generic() -> None:
a: Any = C(10)
assert -a == 11
assert ~a == 12
assert int(a) == 13
assert float(a) == 14.0
assert +a == 15
assert abs(a) == 16
def test_unary_dunders_native() -> None:
c = C(10)
assert -c == 11
assert ~c == 12
assert int(c) == 13
assert float(c) == 14.0
assert +c == 15
assert abs(c) == 16
[case testDundersBinarySimple]
from typing import Any
class C:
def __init__(self) -> None:
self.x = 5
def __add__(self, y: int) -> int:
return self.x + y
def __sub__(self, y: int) -> int:
return self.x - y
def __mul__(self, y: int) -> int:
return self.x * y
def __mod__(self, y: int) -> int:
return self.x % y
def __lshift__(self, y: int) -> int:
return self.x << y
def __rshift__(self, y: int) -> int:
return self.x >> y
def __and__(self, y: int) -> int:
return self.x & y
def __or__(self, y: int) -> int:
return self.x | y
def __xor__(self, y: int) -> int:
return self.x ^ y
def __matmul__(self, y: int) -> int:
return self.x + y + 10
def __truediv__(self, y: int) -> int:
return self.x + y + 20
def __floordiv__(self, y: int) -> int:
return self.x + y + 30
def __divmod__(self, y: int) -> int:
return self.x + y + 40
def __pow__(self, y: int) -> int:
return self.x + y + 50
def test_generic() -> None:
a: Any = C()
assert a + 3 == 8
assert a - 3 == 2
assert a * 5 == 25
assert a % 2 == 1
assert a << 4 == 80
assert a >> 0 == 5
assert a >> 1 == 2
assert a & 1 == 1
assert a | 3 == 7
assert a ^ 3 == 6
assert a @ 3 == 18
assert a / 2 == 27
assert a // 2 == 37
assert divmod(a, 2) == 47
assert a ** 2 == 57
def test_native() -> None:
c = C()
assert c + 3 == 8
assert c - 3 == 2
assert divmod(c, 3) == 48
assert c ** 3 == 58
def test_error() -> None:
a: Any = C()
try:
a + 'x'
except TypeError as e:
assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
else:
assert False
try:
a - 'x'
except TypeError as e:
assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
else:
assert False
try:
a ** 'x'
except TypeError as e:
assert str(e) == "unsupported operand type(s) for **: 'C' and 'str'"
else:
assert False
[case testDundersBinaryReverse]
from typing import Any
class C:
def __init__(self) -> None:
self.x = 5
def __add__(self, y: int) -> int:
return self.x + y
def __radd__(self, y: int) -> int:
return self.x + y + 1
def __sub__(self, y: int) -> int:
return self.x - y
def __rsub__(self, y: int) -> int:
return self.x - y - 1
def __pow__(self, y: int) -> int:
return self.x**y
def __rpow__(self, y: int) -> int:
return self.x**y + 1
def test_generic() -> None:
a: Any = C()
assert a + 3 == 8
assert 4 + a == 10
assert a - 3 == 2
assert 4 - a == 0
assert a**3 == 125
assert 4**a == 626
def test_native() -> None:
c = C()
assert c + 3 == 8
assert 4 + c == 10
assert c - 3 == 2
assert 4 - c == 0
assert c**3 == 125
assert 4**c == 626
def test_errors() -> None:
a: Any = C()
try:
a + 'x'
except TypeError as e:
assert str(e) == "unsupported operand type(s) for +: 'C' and 'str'"
else:
assert False
try:
a - 'x'
except TypeError as e:
assert str(e) == "unsupported operand type(s) for -: 'C' and 'str'"
else:
assert False
try:
'x' + a
except TypeError as e:
assert str(e) in ('can only concatenate str (not "C") to str',
'must be str, not C')
else:
assert False
try:
'x' ** a
except TypeError as e:
assert str(e) == "unsupported operand type(s) for ** or pow(): 'str' and 'C'"
else:
assert False
class F:
def __add__(self, x: int) -> int:
return 5
def __pow__(self, x: int) -> int:
return -5
class G:
def __add__(self, x: int) -> int:
return 33
def __pow__(self, x: int) -> int:
return -33
def __radd__(self, x: F) -> int:
return 6
def __rpow__(self, x: F) -> int:
return -6
def test_type_mismatch_fall_back_to_reverse() -> None:
assert F() + G() == 6
assert F()**G() == -6
[case testDundersBinaryNotImplemented]
from typing import Any, Union
from testutil import assertRaises
class C:
def __init__(self, v: int) -> None:
self.v = v
def __add__(self, y: int) -> Union[int, Any]:
if y == 1:
return self.v
return NotImplemented
def test_any_add() -> None:
a: Any = C(4)
assert a + 1 == 4
try:
a + 2
except TypeError:
pass
else:
assert False
class D:
def __init__(self, x: int) -> None:
self.x = x
def __add__(self, e: E) -> Union[int, Any]:
if e.x == 1:
return 2
return NotImplemented
class E:
def __init__(self, x: int) -> None:
self.x = x
def __radd__(self, d: D) -> Union[int, Any]:
if d.x == 3:
return 4
return NotImplemented
def test_any_radd() -> None:
d1: Any = D(1)
d3: Any = D(3)
e1: Any = E(1)
e3: Any = E(3)
assert d1 + e1 == 2
assert d3 + e1 == 2
assert d3 + e3 == 4
class F:
def __init__(self, v):
self.v = v
def __add__(self, x):
if isinstance(x, int):
return self.v + x
return NotImplemented
class G:
def __radd__(self, x):
if isinstance(x, F):
return x.v + 1
if isinstance(x, str):
return 'a'
return NotImplemented
def test_unannotated_add() -> None:
o = F(4)
assert o + 5 == 9
with assertRaises(TypeError, "unsupported operand type(s) for +: 'F' and 'str'"):
o + 'x'
def test_unannotated_add_and_radd_1() -> None:
o = F(4)
assert o + G() == 5
def test_unannotated_radd() -> None:
assert 'x' + G() == 'a'
with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'G'"):
1 + G()
class H:
def __add__(self, x):
if isinstance(x, int):
return x + 1
return NotImplemented
def __radd__(self, x):
if isinstance(x, str):
return 22
return NotImplemented
def test_unannotated_add_and_radd_2() -> None:
h = H()
assert h + 5 == 6
assert 'x' + h == 22
with assertRaises(TypeError, "unsupported operand type(s) for +: 'int' and 'H'"):
1 + h
# TODO: Inheritance
[case testDifferentReverseDunders]
class C:
# __radd__ and __rsub__ are tested elsewhere
def __rmul__(self, x):
return 1
def __rtruediv__(self, x):
return 2
def __rmod__(self, x):
return 3
def __rfloordiv__(self, x):
return 4
def __rlshift__(self, x):
return 5
def __rrshift__(self, x):
return 6
def __rand__(self, x):
return 7
def __ror__(self, x):
return 8
def __rxor__(self, x):
return 9
def __rmatmul__(self, x):
return 10
def test_reverse_dunders() -> None:
x = 0
c = C()
assert x * c == 1
assert x / c == 2
assert x % c == 3
assert x // c == 4
assert x << c == 5
assert x >> c == 6
assert x & c == 7
assert x | c == 8
assert x ^ c == 9
assert x @ c == 10
[case testDundersInplace]
from typing import Any
from testutil import assertRaises
class C:
def __init__(self) -> None:
self.x = 5
def __iadd__(self, y: int) -> C:
self.x += y
return self
def __isub__(self, y: int) -> C:
self.x -= y
return self
def __imul__(self, y: int) -> C:
self.x *= y
return self
def __imod__(self, y: int) -> C:
self.x %= y
return self
def __itruediv__(self, y: int) -> C:
self.x += y + 10
return self
def __ifloordiv__(self, y: int) -> C:
self.x += y + 20
return self
def __ilshift__(self, y: int) -> C:
self.x <<= y
return self
def __irshift__(self, y: int) -> C:
self.x >>= y
return self
def __iand__(self, y: int) -> C:
self.x &= y
return self
def __ior__(self, y: int) -> C:
self.x |= y
return self
def __ixor__(self, y: int) -> C:
self.x ^= y
return self
def __imatmul__(self, y: int) -> C:
self.x += y + 5
return self
def __ipow__(self, y: int, __mod_throwaway: None = None) -> C:
self.x **= y
return self
def test_generic_1() -> None:
c: Any = C()
c += 3
assert c.x == 8
c -= 5
assert c.x == 3
c *= 3
assert c.x == 9
c %= 4
assert c.x == 1
c /= 5
assert c.x == 16
c //= 4
assert c.x == 40
c **= 2
assert c.x == 1600
def test_generic_2() -> None:
c: Any = C()
c <<= 4
assert c.x == 80
c >>= 3
assert c.x == 10
c &= 3
assert c.x == 2
c |= 6
assert c.x == 6
c ^= 12
assert c.x == 10
c @= 3
assert c.x == 18
def test_native() -> None:
c = C()
c += 3
assert c.x == 8
c -= 5
assert c.x == 3
c *= 3
assert c.x == 9
c **= 2
assert c.x == 81
def test_error() -> None:
c: Any = C()
with assertRaises(TypeError, "int object expected; got str"):
c += 'x'
class BadInplaceAdd:
def __init__(self):
self.x = 0
def __iadd__(self, x):
self.x += x
def test_in_place_operator_returns_none() -> None:
o = BadInplaceAdd()
with assertRaises(TypeError, "native.BadInplaceAdd object expected; got None"):
o += 5
[case testDunderMinMax]
class SomeItem:
def __init__(self, val: int) -> None:
self.val = val
def __lt__(self, x: 'SomeItem') -> bool:
return self.val < x.val
def __gt__(self, x: 'SomeItem') -> bool:
return self.val > x.val
class AnotherItem:
def __init__(self, val: str) -> None:
self.val = val
def __lt__(self, x: 'AnotherItem') -> bool:
return True
def __gt__(self, x: 'AnotherItem') -> bool:
return True
def test_dunder_min() -> None:
x = SomeItem(5)
y = SomeItem(10)
z = SomeItem(15)
assert min(x, y).val == 5
assert min(y, z).val == 10
assert max(x, y).val == 10
assert max(y, z).val == 15
x2 = AnotherItem('xxx')
y2 = AnotherItem('yyy')
z2 = AnotherItem('zzz')
assert min(x2, y2).val == 'yyy'
assert min(y2, x2).val == 'xxx'
assert max(x2, y2).val == 'yyy'
assert max(y2, x2).val == 'xxx'
assert min(y2, z2).val == 'zzz'
assert max(x2, z2).val == 'zzz'
[case testDundersPowerSpecial]
import sys
from typing import Any, Optional
from testutil import assertRaises
class Forward:
def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
if mod is None:
return 2**exp
else:
return 2**exp % mod
class ForwardModRequired:
def __pow__(self, exp: int, mod: int) -> int:
return 2**exp % mod
class ForwardNotImplemented:
def __pow__(self, exp: int, mod: Optional[object] = None) -> Any:
return NotImplemented
class Reverse:
def __rpow__(self, exp: int) -> int:
return 2**exp + 1
class Both:
def __pow__(self, exp: int, mod: Optional[int] = None) -> int:
if mod is None:
return 2**exp
else:
return 2**exp % mod
def __rpow__(self, exp: int) -> int:
return 2**exp + 1
class Child(ForwardNotImplemented):
def __rpow__(self, exp: object) -> int:
return 50
class Inplace:
value = 2
def __ipow__(self, exp: int, mod: Optional[int] = None) -> "Inplace":
self.value **= exp - (mod or 0)
return self
def test_native() -> None:
f = Forward()
assert f**3 == 8
assert pow(f, 3) == 8
assert pow(f, 3, 3) == 2
assert pow(ForwardModRequired(), 3, 3) == 2
b = Both()
assert b**3 == 8
assert 3**b == 9
assert pow(b, 3) == 8
assert pow(b, 3, 3) == 2
i = Inplace()
i **= 2
assert i.value == 4
def test_errors() -> None:
if sys.version_info[0] >= 3 and sys.version_info[1] >= 10:
op = "** or pow()"
else:
op = "pow()"
f = Forward()
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'Forward', 'int', 'str'"):
pow(f, 3, "x") # type: ignore
with assertRaises(TypeError, "unsupported operand type(s) for **: 'Forward' and 'str'"):
f**"x" # type: ignore
r = Reverse()
with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'str' and 'Reverse'"):
"x"**r # type: ignore
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'int', 'Reverse', 'int'"):
# Ternary pow() does not fallback to __rpow__ if LHS's __pow__ returns NotImplemented.
pow(3, r, 3) # type: ignore
with assertRaises(TypeError, f"unsupported operand type(s) for {op}: 'ForwardNotImplemented', 'Child', 'int'"):
# Ternary pow() does not try RHS's __rpow__ first when it's a subclass and redefines
# __rpow__ unlike other ops.
pow(ForwardNotImplemented(), Child(), 3) # type: ignore
with assertRaises(TypeError, "unsupported operand type(s) for ** or pow(): 'ForwardModRequired' and 'int'"):
ForwardModRequired()**3 # type: ignore

View File

@@ -0,0 +1,448 @@
# Test cases for exceptions (compile and run)
[case testException]
from typing import List
def f(x: List[int]) -> None:
g(x)
def g(x: List[int]) -> bool:
x[5] = 2
return True
def r1() -> None:
q1()
def q1() -> None:
raise Exception("test")
def r2() -> None:
q2()
def q2() -> None:
raise Exception
class A:
def __init__(self) -> None:
raise Exception
def hey() -> None:
A()
[file driver.py]
from native import f, r1, r2, hey
import traceback
try:
f([])
except IndexError:
traceback.print_exc()
try:
r1()
except Exception:
traceback.print_exc()
try:
r2()
except Exception:
traceback.print_exc()
try:
hey()
except Exception:
traceback.print_exc()
[out]
Traceback (most recent call last):
File "driver.py", line 4, in <module>
f([])
File "native.py", line 3, in f
g(x)
File "native.py", line 6, in g
x[5] = 2
IndexError: list assignment index out of range
Traceback (most recent call last):
File "driver.py", line 8, in <module>
r1()
File "native.py", line 10, in r1
q1()
File "native.py", line 13, in q1
raise Exception("test")
Exception: test
Traceback (most recent call last):
File "driver.py", line 12, in <module>
r2()
File "native.py", line 16, in r2
q2()
File "native.py", line 19, in q2
raise Exception
Exception
Traceback (most recent call last):
File "driver.py", line 16, in <module>
hey()
File "native.py", line 26, in hey
A()
File "native.py", line 23, in __init__
raise Exception
Exception
[case testTryExcept]
from typing import Any, Iterator
import wrapsys
def g(b: bool) -> None:
try:
if b:
x = [0]
x[1]
else:
raise Exception('hi')
except:
print("caught!")
def r(x: int) -> None:
if x == 0:
[0][1]
elif x == 1:
raise Exception('hi')
elif x == 2:
{1: 1}[0]
elif x == 3:
a = object() # type: Any
a.lol
def f(b: bool) -> None:
try:
r(int(b))
except AttributeError:
print('no')
except:
print(str(wrapsys.exc_info()[1]))
print(str(wrapsys.exc_info()[1]))
def h() -> None:
while True:
try:
raise Exception('gonna break')
except:
print(str(wrapsys.exc_info()[1]))
break
print(str(wrapsys.exc_info()[1]))
def i() -> None:
try:
r(0)
except:
print(type(wrapsys.exc_info()[1]))
raise
def j(n: int) -> None:
try:
r(n)
except (IndexError, KeyError):
print("lookup!")
except AttributeError as e:
print("attr! --", e)
def k() -> None:
try:
r(1)
except:
r(0)
def l() -> None:
try:
r(0)
except IndexError:
try:
r(2)
except KeyError as e:
print("key! --", e)
def m(x: object) -> int:
try:
st = id(x)
except Exception:
return -1
return st + 1
def iter_exception() -> Iterator[str]:
try:
r(0)
except KeyError as e:
yield 'lol'
[file wrapsys.py]
# This is a gross hack around some limitations of the test system/mypyc.
from typing import Any
import sys
def exc_info() -> Any:
return sys.exc_info() # type: ignore
[file driver.py]
import sys, traceback
from native import g, f, h, i, j, k, l, m, iter_exception
from testutil import assertRaises
print("== i ==")
try:
i()
except:
traceback.print_exc(file=sys.stdout)
print("== k ==")
try:
k()
except:
traceback.print_exc(file=sys.stdout)
print("== g ==")
g(True)
g(False)
print("== f ==")
f(True)
f(False)
print("== h ==")
h()
print("== j ==")
j(0)
j(2)
j(3)
try:
j(1)
except:
print("out!")
print("== l ==")
l()
m('lol')
with assertRaises(IndexError):
list(iter_exception())
[out]
== i ==
<class 'IndexError'>
Traceback (most recent call last):
File "driver.py", line 6, in <module>
i()
File "native.py", line 44, in i
r(0)
File "native.py", line 15, in r
[0][1]
IndexError: list index out of range
== k ==
Traceback (most recent call last):
File "native.py", line 59, in k
r(1)
File "native.py", line 17, in r
raise Exception('hi')
Exception: hi
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "driver.py", line 12, in <module>
k()
File "native.py", line 61, in k
r(0)
File "native.py", line 15, in r
[0][1]
IndexError: list index out of range
== g ==
caught!
caught!
== f ==
hi
None
list index out of range
None
== h ==
gonna break
None
== j ==
lookup!
lookup!
attr! -- 'object' object has no attribute 'lol'
out!
== l ==
key! -- 0
[case testTryFinally]
from typing import Any
import wrapsys
def a(b1: bool, b2: int) -> None:
try:
if b1:
raise Exception('hi')
finally:
print('finally:', str(wrapsys.exc_info()[1]))
if b2 == 2:
return
if b2 == 1:
raise Exception('again!')
def b(b1: int, b2: int) -> str:
try:
if b1 == 1:
raise Exception('hi')
elif b1 == 2:
[0][1]
elif b1 == 3:
return 'try'
except IndexError:
print('except')
finally:
print('finally:', str(wrapsys.exc_info()[1]))
if b2 == 2:
return 'finally'
if b2 == 1:
raise Exception('again!')
return 'outer'
def c() -> str:
try:
try:
return 'wee'
finally:
print("out a")
finally:
print("out b")
[file wrapsys.py]
# This is a gross hack around some limitations of the test system/mypyc.
from typing import Any
import sys
def exc_info() -> Any:
return sys.exc_info() # type: ignore
[file driver.py]
import traceback
import sys
from native import a, b, c
def run(f):
try:
x = f()
if x:
print("returned:", x)
except Exception as e:
print("caught:", type(e).__name__ + ": " + str(e))
print("== a ==")
for i in range(3):
for b1 in [False, True]:
run(lambda: a(b1, i))
print("== b ==")
for i in range(4):
for j in range(3):
run(lambda: b(i, j))
print("== b ==")
print(c())
[out]
== a ==
finally: None
finally: hi
caught: Exception: hi
finally: None
caught: Exception: again!
finally: hi
caught: Exception: again!
finally: None
finally: hi
== b ==
finally: None
returned: outer
finally: None
caught: Exception: again!
finally: None
returned: finally
finally: hi
caught: Exception: hi
finally: hi
caught: Exception: again!
finally: hi
returned: finally
except
finally: None
returned: outer
except
finally: None
caught: Exception: again!
except
finally: None
returned: finally
finally: None
returned: try
finally: None
caught: Exception: again!
finally: None
returned: finally
== b ==
out a
out b
wee
[case testCustomException]
from typing import List
class ListOutOfBounds(IndexError):
pass
class UserListWarning(UserWarning):
pass
def f(l: List[int], k: int) -> int:
try:
return l[k]
except IndexError:
raise ListOutOfBounds("Ruh-roh from f!")
def g(l: List[int], k: int) -> int:
try:
return f([1,2,3], 3)
except ListOutOfBounds:
raise ListOutOfBounds("Ruh-roh from g!")
def k(l: List[int], k: int) -> int:
try:
return g([1,2,3], 3)
except IndexError:
raise UserListWarning("Ruh-roh from k!")
def h() -> int:
try:
return k([1,2,3], 3)
except UserWarning:
return -1
[file driver.py]
from native import h
assert h() == -1
[case testExceptionAtModuleTopLevel]
from typing import Any
def f(x: int) -> None: pass
y: Any = ''
f(y)
[file driver.py]
import traceback
try:
import native
except TypeError:
traceback.print_exc()
else:
assert False
[out]
Traceback (most recent call last):
File "driver.py", line 3, in <module>
import native
File "native.py", line 6, in <module>
f(y)
TypeError: int object expected; got str

View File

@@ -0,0 +1,516 @@
# Test cases for floats (compile and run)
[case testFloatOps]
from __future__ import annotations
from typing import Any, cast
from typing_extensions import Final
from testutil import assertRaises, float_vals, FLOAT_MAGIC
import math
def test_arithmetic() -> None:
zero = float(0.0)
one = zero + 1.0
x = one + one / 2.0
assert x == 1.5
assert x - one == 0.5
assert x * x == 2.25
assert x / 2.0 == 0.75
assert x * (-0.5) == -0.75
assert -x == -1.5
for x in float_vals:
assert repr(-x) == repr(getattr(x, "__neg__")())
for y in float_vals:
assert repr(x + y) == repr(getattr(x, "__add__")(y))
assert repr(x - y) == repr(getattr(x, "__sub__")(y))
assert repr(x * y) == repr(getattr(x, "__mul__")(y))
if y != 0:
assert repr(x / y) == repr(getattr(x, "__truediv__")(y))
def test_mod() -> None:
zero = float(0.0)
one = zero + 1.0
x = one + one / 2.0
assert x % 0.4 == 0.29999999999999993
assert (-x) % 0.4 == 0.10000000000000009
assert x % -0.4 == -0.10000000000000009
assert (-x) % -0.4 == -0.29999999999999993
for x in float_vals:
for y in float_vals:
if y != 0:
assert repr(x % y) == repr(getattr(x, "__mod__")(y))
def test_floor_div() -> None:
for x in float_vals:
for y in float_vals:
if y != 0:
assert repr(x // y) == repr(getattr(x, "__floordiv__")(y))
else:
with assertRaises(ZeroDivisionError, "float floor division by zero"):
x // y
def test_mixed_arithmetic() -> None:
zf = float(0.0)
zn = int()
assert (zf + 5.5) + (zn + 1) == 6.5
assert (zn - 2) - (zf - 5.5) == 3.5
x = zf + 3.4
x += zn + 2
assert x == 5.4
def test_arithmetic_errors() -> None:
zero = float(0.0)
one = zero + 1.0
with assertRaises(ZeroDivisionError, "float division by zero"):
print(one / zero)
with assertRaises(ZeroDivisionError, "float modulo"):
print(one % zero)
def test_comparisons() -> None:
zero = float(0.0)
one = zero + 1.0
x = one + one / 2.0
assert x < (1.51 + zero)
assert not (x < (1.49 + zero))
assert x > (1.49 + zero)
assert not (x > (1.51 + zero))
assert x <= (1.5 + zero)
assert not (x <= (1.49 + zero))
assert x >= (1.5 + zero)
assert not (x >= (1.51 + zero))
for x in float_vals:
for y in float_vals:
assert (x <= y) == getattr(x, "__le__")(y)
assert (x < y) == getattr(x, "__lt__")(y)
assert (x >= y) == getattr(x, "__ge__")(y)
assert (x > y) == getattr(x, "__gt__")(y)
assert (x == y) == getattr(x, "__eq__")(y)
assert (x != y) == getattr(x, "__ne__")(y)
def test_mixed_comparisons() -> None:
zf = float(0.0)
zn = int()
if (zf + 1.0) == (zn + 1):
assert True
else:
assert False
if (zf + 1.1) == (zn + 1):
assert False
else:
assert True
assert (zf + 1.1) != (zn + 1)
assert (zf + 1.1) > (zn + 1)
assert not (zf + 0.9) > (zn + 1)
assert (zn + 1) < (zf + 1.1)
def test_boxing_and_unboxing() -> None:
x = 1.5
boxed: Any = x
assert repr(boxed) == "1.5"
assert type(boxed) is float
y: float = boxed
assert y == x
boxed_int: Any = 5
assert [type(boxed_int)] == [int] # Avoid mypy type narrowing
z: float = boxed_int
assert z == 5.0
for xx in float_vals:
bb: Any = xx
yy: float = bb
assert repr(xx) == repr(bb)
assert repr(xx) == repr(yy)
for b in True, False:
boxed_bool: Any = b
assert type(boxed_bool) is bool
zz: float = boxed_bool
assert zz == int(b)
def test_unboxing_failure() -> None:
boxed: Any = '1.5'
with assertRaises(TypeError):
x: float = boxed
def identity(x: float) -> float:
return x
def test_coerce_from_int_literal() -> None:
assert identity(34) == 34.0
assert identity(-1) == -1.0
def test_coerce_from_short_tagged_int() -> None:
n = int() - 17
assert identity(n) == -17.0
for i in range(-300, 300):
assert identity(i) == float(i)
def test_coerce_from_long_tagged_int() -> None:
n = int() + 2**100
x = identity(n)
assert repr(x) == '1.2676506002282294e+30'
n = int() - 2**100
y = identity(n)
assert repr(y) == '-1.2676506002282294e+30'
def test_coerce_from_very_long_tagged_int() -> None:
n = int() + 10**1000
with assertRaises(OverflowError, "int too large to convert to float"):
identity(n)
with assertRaises(OverflowError, "int too large to convert to float"):
identity(int(n))
n = int() - 10**1000
with assertRaises(OverflowError, "int too large to convert to float"):
identity(n)
with assertRaises(OverflowError, "int too large to convert to float"):
identity(int(n))
def test_explicit_conversion_from_int() -> None:
float_any: Any = float
a = [0, 1, 2, 3, -1, -2, 13257, -928745]
for n in range(1, 100):
for delta in -1, 0, 1, 2342345:
a.append(2**n + delta)
a.append(-2**n + delta)
for x in a:
assert repr(float(x)) == repr(float_any(x))
def test_explicit_conversion_to_int() -> None:
int_any: Any = int
for x in float_vals:
if math.isinf(x):
with assertRaises(OverflowError, "cannot convert float infinity to integer"):
int(x)
elif math.isnan(x):
with assertRaises(ValueError, "cannot convert float NaN to integer"):
int(x)
else:
assert repr(int(x)) == repr(int_any(x))
# Test some edge cases
assert 2**30 == int(2.0**30 + int())
assert 2**30 - 1 == int(1073741823.9999999 + int()) # math.nextafter(2.0**30, 0))
assert -2**30 - 1 == int(-2.0**30 - 1 + int())
assert -2**30 == int(-1073741824.9999998 + int()) # math.nextafter(-2.0**30 - 1, 0)
assert 2**62 == int(2.0**62 + int())
assert 2**62 == int(2.0**62 - 1 + int())
assert -2**62 == int(-2.0**62 + int())
assert -2**62 == int(-2.0**62 - 1 + int())
def str_to_float(x: str) -> float:
return float(x)
def test_str_to_float() -> None:
assert str_to_float("1") == 1.0
assert str_to_float("1.234567") == 1.234567
assert str_to_float("44324") == 44324.0
assert str_to_float("23.4") == 23.4
assert str_to_float("-43.44e-4") == -43.44e-4
assert str_to_float("-43.44e-4") == -43.44e-4
assert math.isinf(str_to_float("inf"))
assert math.isinf(str_to_float("-inf"))
assert str_to_float("inf") > 0.0
assert str_to_float("-inf") < 0.0
assert math.isnan(str_to_float("nan"))
assert math.isnan(str_to_float("NaN"))
assert repr(str_to_float("-0.0")) == "-0.0"
def test_abs() -> None:
assert abs(0.0) == 0.0
assert abs(-1.234567) == 1.234567
assert abs(44324.732) == 44324.732
assert abs(-23.4) == 23.4
assert abs(-43.44e-4) == 43.44e-4
abs_any: Any = abs
for x in float_vals:
assert repr(abs(x)) == repr(abs_any(x))
def test_float_min_max() -> None:
for x in float_vals:
for y in float_vals:
min_any: Any = min
assert repr(min(x, y)) == repr(min_any(x, y))
max_any: Any = max
assert repr(max(x, y)) == repr(max_any(x, y))
def default(x: float = 2) -> float:
return x + 1
def test_float_default_value() -> None:
assert default(1.2) == 2.2
for i in range(-200, 200):
assert default(float(i)) == i + 1
assert default() == 3.0
def test_float_default_value_wrapper() -> None:
f: Any = default
assert f(1.2) == 2.2
for i in range(-200, 200):
assert f(float(i)) == i + 1
assert f() == 3.0
class C:
def __init__(self, x: float) -> None:
self.x = x
def test_float_attr() -> None:
for i in range(-200, 200):
f = float(i)
c = C(f)
assert c.x == f
a: Any = c
assert a.x == f
c.x = FLOAT_MAGIC
assert c.x == FLOAT_MAGIC
assert a.x == FLOAT_MAGIC
a.x = 1.0
assert a.x == 1.0
a.x = FLOAT_MAGIC
assert a.x == FLOAT_MAGIC
class D:
def __init__(self, x: float) -> None:
if x:
self.x = x
def test_float_attr_maybe_undefned() -> None:
for i in range(-200, 200):
if i == 0:
d = D(0.0)
with assertRaises(AttributeError):
d.x
a: Any = d
with assertRaises(AttributeError):
a.x
d.x = FLOAT_MAGIC
assert d.x == FLOAT_MAGIC
assert a.x == FLOAT_MAGIC
d.x = 0.0
assert d.x == 0.0
assert a.x == 0.0
a.x = FLOAT_MAGIC
assert a.x == FLOAT_MAGIC
d = D(0.0)
a = cast(Any, d)
a.x = FLOAT_MAGIC
assert d.x == FLOAT_MAGIC
else:
f = float(i)
d = D(f)
assert d.x == f
a2: Any = d
assert a2.x == f
def f(x: float) -> float:
return x + 1
def test_return_values() -> None:
a: Any = f
for i in range(-200, 200):
x = float(i)
assert f(x) == x + 1
assert a(x) == x + 1
for x in float_vals:
if not math.isnan(x):
assert f(x) == x + 1
else:
assert math.isnan(f(x))
def exc() -> float:
raise IndexError('x')
def test_exception() -> None:
with assertRaises(IndexError):
exc()
a: Any = exc
with assertRaises(IndexError):
a()
def test_undefined_local_var() -> None:
if not int():
x = -113.0
assert x == -113.0
if int():
y = -113.0
with assertRaises(UnboundLocalError, 'local variable "y" referenced before assignment'):
print(y)
if not int():
x2 = -1.0
assert x2 == -1.0
if int():
y2 = -1.0
with assertRaises(UnboundLocalError, 'local variable "y2" referenced before assignment'):
print(y2)
def test_tuples() -> None:
t1: tuple[float, float] = (1.5, 2.5)
assert t1 == tuple([1.5, 2.5])
n = int() + 5
t2: tuple[float, float, float, float] = (n, 1.5, -7, -113)
assert t2 == tuple([5.0, 1.5, -7.0, -113.0])
[case testFloatGlueMethodsAndInheritance]
from typing import Any
from typing_extensions import Final
from mypy_extensions import trait
from testutil import assertRaises
MAGIC: Final = -113.0
class Base:
def foo(self) -> float:
return 5.0
def bar(self, x: float = 2.0) -> float:
return x + 1
def hoho(self, x: float) -> float:
return x - 1
class Derived(Base):
def foo(self, x: float = 5.0) -> float:
return x + 10
def bar(self, x: float = 3, y: float = 20) -> float:
return x + y + 2
def hoho(self, x: float = 7) -> float:
return x - 2
def test_derived_adds_bitmap() -> None:
b: Base = Derived()
assert b.foo() == 15
def test_derived_adds_another_default_arg() -> None:
b: Base = Derived()
assert b.bar() == 25
assert b.bar(1) == 23
assert b.bar(MAGIC) == MAGIC + 22
def test_derived_switches_arg_to_have_default() -> None:
b: Base = Derived()
assert b.hoho(5) == 3
assert b.hoho(MAGIC) == MAGIC - 2
@trait
class T:
@property
def x(self) -> float: ...
@property
def y(self) -> float: ...
class C(T):
x: float = 1.0
y: float = 4
def test_read_only_property_in_trait_implemented_as_attribute() -> None:
c = C()
c.x = 5.5
assert c.x == 5.5
c.x = MAGIC
assert c.x == MAGIC
assert c.y == 4
c.y = 6.5
assert c.y == 6.5
t: T = C()
assert t.y == 4
t = c
assert t.x == MAGIC
c.x = 55.5
assert t.x == 55.5
assert t.y == 6.5
a: Any = c
assert a.x == 55.5
assert a.y == 6.5
a.x = 7.0
a.y = 8.0
assert a.x == 7
assert a.y == 8
class D(T):
xx: float
@property
def x(self) -> float:
return self.xx
@property
def y(self) -> float:
raise TypeError
def test_read_only_property_in_trait_implemented_as_property() -> None:
d = D()
d.xx = 5.0
assert d.x == 5
d.xx = MAGIC
assert d.x == MAGIC
with assertRaises(TypeError):
d.y
t: T = d
assert t.x == MAGIC
d.xx = 6.0
assert t.x == 6
with assertRaises(TypeError):
t.y
@trait
class T2:
x: float
y: float
class C2(T2):
pass
def test_inherit_trait_attribute() -> None:
c = C2()
c.x = 5.0
assert c.x == 5
c.x = MAGIC
assert c.x == MAGIC
with assertRaises(AttributeError):
c.y
c.y = 6.0
assert c.y == 6.0
t: T2 = C2()
with assertRaises(AttributeError):
t.y
t = c
assert t.x == MAGIC
c.x = 55.0
assert t.x == 55
assert t.y == 6
a: Any = c
assert a.x == 55
assert a.y == 6
a.x = 7.0
a.y = 8.0
assert a.x == 7
assert a.y == 8
class D2(T2):
x: float
y: float = 4
def test_implement_trait_attribute() -> None:
d = D2()
d.x = 5.0
assert d.x == 5
d.x = MAGIC
assert d.x == MAGIC
assert d.y == 4
d.y = 6.0
assert d.y == 6
t: T2 = D2()
assert t.y == 4
t = d
assert t.x == MAGIC
d.x = 55.0
assert t.x == 55
assert t.y == 6
a: Any = d
assert a.x == 55
assert a.y == 6
a.x = 7.0
a.y = 8.0
assert a.x == 7
assert a.y == 8

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,681 @@
# Test cases for generators and yield (compile and run)
[case testYield]
from typing import Generator, Iterable, Union, Tuple, Dict
def yield_three_times() -> Iterable[int]:
yield 1
yield 2
yield 3
def yield_twice_and_return() -> Generator[int, None, int]:
yield 1
yield 2
return 4
def yield_while_loop() -> Generator[int, None, int]:
i = 0
while i < 5:
if i == 3:
return i
yield i
i += 1
return -1
def yield_for_loop() -> Iterable[int]:
l = [i for i in range(3)]
for i in l:
yield i
d = {k: None for k in range(3)}
for k in d:
yield k
for i in range(3):
yield i
for i in range(three()):
yield i
def yield_with_except() -> Generator[int, None, None]:
yield 10
try:
return
except:
print('Caught exception inside generator function')
def complex_yield(a: int, b: str, c: float) -> Generator[Union[str, int], None, float]:
x = 2
while x < a:
if x % 2 == 0:
dummy_var = 1
yield str(x) + ' ' + b
dummy_var = 1
else:
dummy_var = 1
yield x
dummy_var = 1
x += 1
return c
def yield_with_default(x: bool = False) -> Iterable[int]:
if x:
yield 0
def yield_dict_methods(d1: Dict[int, int],
d2: Dict[int, int],
d3: Dict[int, int]) -> Iterable[int]:
for k in d1.keys():
yield k
for k, v in d2.items():
yield k
yield v
for v in d3.values():
yield v
def three() -> int:
return 3
class A(object):
def __init__(self, x: int) -> None:
self.x = x
def generator(self) -> Iterable[int]:
yield self.x
def return_tuple() -> Generator[int, None, Tuple[int, int]]:
yield 0
return 1, 2
[file driver.py]
from native import (
yield_three_times,
yield_twice_and_return,
yield_while_loop,
yield_for_loop,
yield_with_except,
complex_yield,
yield_with_default,
A,
return_tuple,
yield_dict_methods,
)
from testutil import run_generator
from collections import defaultdict
assert run_generator(yield_three_times()) == ((1, 2, 3), None)
assert run_generator(yield_twice_and_return()) == ((1, 2), 4)
assert run_generator(yield_while_loop()) == ((0, 1, 2), 3)
assert run_generator(yield_for_loop()) == (tuple(4 * [i for i in range(3)]), None)
assert run_generator(yield_with_except()) == ((10,), None)
assert run_generator(complex_yield(5, 'foo', 1.0)) == (('2 foo', 3, '4 foo'), 1.0)
assert run_generator(yield_with_default()) == ((), None)
assert run_generator(A(0).generator()) == ((0,), None)
assert run_generator(return_tuple()) == ((0,), (1, 2))
assert run_generator(yield_dict_methods({}, {}, {})) == ((), None)
assert run_generator(yield_dict_methods({1: 2}, {3: 4}, {5: 6})) == ((1, 3, 4, 6), None)
dd = defaultdict(int, {0: 1})
assert run_generator(yield_dict_methods(dd, dd, dd)) == ((0, 0, 1, 1), None)
for i in yield_twice_and_return():
print(i)
for i in yield_while_loop():
print(i)
[out]
1
2
0
1
2
[case testYieldTryFinallyWith]
from typing import Generator, Any
class Thing:
def __init__(self, x: str) -> None:
self.x = x
def __enter__(self) -> str:
print('enter!', self.x)
if self.x == 'crash':
raise Exception('ohno')
return self.x
def __exit__(self, x: Any, y: Any, z: Any) -> None:
print('exit!', self.x, y)
def yield_try_finally() -> Generator[int, None, str]:
try:
yield 1
yield 2
return 'lol'
except Exception:
raise
finally:
print('goodbye!')
def yield_with(i: int) -> Generator[int, None, int]:
with Thing('a') as x:
yield 1
print("yooo?", x)
if i == 0:
yield 2
return 10
elif i == 1:
raise Exception('exception!')
return -1
[file driver.py]
from native import yield_try_finally, yield_with
from testutil import run_generator
print(run_generator(yield_try_finally(), p=True))
print(run_generator(yield_with(0), p=True))
print(run_generator(yield_with(1), p=True))
[out]
1
2
goodbye!
((1, 2), 'lol')
enter! a
1
yooo? a
2
exit! a None
((1, 2), 10)
enter! a
1
yooo? a
exit! a exception!
((1,), 'exception!')
[case testYieldNested]
from typing import Callable, Generator
def normal(a: int, b: float) -> Callable:
def generator(x: int, y: str) -> Generator:
yield a
yield b
yield x
yield y
return generator
def generator(a: int) -> Generator:
def normal(x: int) -> int:
return a + x
for i in range(3):
yield normal(i)
def triple() -> Callable:
def generator() -> Generator:
x = 0
def inner() -> int:
x += 1
return x
while x < 3:
yield inner()
return generator
def another_triple() -> Callable:
def generator() -> Generator:
x = 0
def inner_generator() -> Generator:
x += 1
yield x
yield next(inner_generator())
return generator
def outer() -> Generator:
def recursive(n: int) -> Generator:
if n < 10:
for i in range(n):
yield i
return
for i in recursive(5):
yield i
return recursive(10)
[file driver.py]
from native import normal, generator, triple, another_triple, outer
from testutil import run_generator
assert run_generator(normal(1, 2.0)(3, '4.00')) == ((1, 2.0, 3, '4.00'), None)
assert run_generator(generator(1)) == ((1, 2, 3), None)
assert run_generator(triple()()) == ((1, 2, 3), None)
assert run_generator(another_triple()()) == ((1,), None)
assert run_generator(outer()) == ((0, 1, 2, 3, 4), None)
[case testYieldThrow]
from typing import Generator, Iterable, Any
from traceback import print_tb
from contextlib import contextmanager
import wrapsys
def generator() -> Iterable[int]:
try:
yield 1
yield 2
yield 3
except Exception as e:
print_tb(wrapsys.exc_info()[2])
s = str(e)
if s:
print('caught exception with value ' + s)
else:
print('caught exception without value')
return 0
def no_except() -> Iterable[int]:
yield 1
yield 2
def raise_something() -> Iterable[int]:
yield 1
yield 2
raise Exception('failure')
def wrapper(x: Any) -> Any:
return (yield from x)
def foo() -> Generator[int, None, None]:
try:
yield 1
except Exception as e:
print(str(e))
finally:
print('goodbye')
ctx_manager = contextmanager(foo)
[file wrapsys.py]
# This is a gross hack around some limitations of the test system/mypyc.
from typing import Any
import sys
def exc_info() -> Any:
return sys.exc_info() # type: ignore
[file driver.py]
import sys
from typing import Generator, Tuple, TypeVar, Sequence
from native import generator, ctx_manager, wrapper, no_except, raise_something
T = TypeVar('T')
U = TypeVar('U')
def run_generator_and_throw(gen: Generator[T, None, U],
num_times: int,
value: object = None,
traceback: object = None) -> Tuple[Sequence[T], U]:
res = []
try:
for i in range(num_times):
res.append(next(gen))
if value is not None and traceback is not None:
gen.throw(Exception, value, traceback)
elif value is not None:
gen.throw(Exception, value)
else:
gen.throw(Exception)
except StopIteration as e:
return (tuple(res), e.value)
except Exception as e:
return (tuple(res), str(e))
assert run_generator_and_throw(generator(), 0, 'hello') == ((), 'hello')
assert run_generator_and_throw(generator(), 3) == ((1, 2, 3), 0)
assert run_generator_and_throw(generator(), 2, 'some string') == ((1, 2), 0)
try:
raise Exception
except Exception as e:
tb = sys.exc_info()[2]
assert run_generator_and_throw(generator(), 1, 'some other string', tb) == ((1,), 0)
assert run_generator_and_throw(wrapper(generator()), 0, 'hello') == ((), 'hello')
assert run_generator_and_throw(wrapper(generator()), 3) == ((1, 2, 3), 0)
assert run_generator_and_throw(wrapper(generator()), 2, 'some string') == ((1, 2), 0)
# Make sure we aren't leaking exc_info
assert sys.exc_info()[0] is None
assert run_generator_and_throw(wrapper([1, 2, 3]), 3, 'lol') == ((1, 2, 3), 'lol')
assert run_generator_and_throw(wrapper(no_except()), 2, 'lol') == ((1, 2), 'lol')
assert run_generator_and_throw(wrapper(raise_something()), 3) == ((1, 2), 'failure')
with ctx_manager() as c:
raise Exception('exception')
[out]
File "native.py", line 10, in generator
yield 3
File "native.py", line 9, in generator
yield 2
File "native.py", line 8, in generator
yield 1
File "driver.py", line 31, in <module>
raise Exception
File "native.py", line 10, in generator
yield 3
File "native.py", line 30, in wrapper
return (yield from x)
File "native.py", line 9, in generator
yield 2
File "native.py", line 30, in wrapper
return (yield from x)
caught exception without value
caught exception with value some string
caught exception with value some other string
caught exception without value
caught exception with value some string
exception
goodbye
[case testYieldSend]
from typing import Generator
def basic() -> Generator[int, int, int]:
x = yield 1
y = yield (x + 1)
return y
def use_from() -> Generator[int, int, int]:
return (yield from basic())
[file driver.py]
from native import basic, use_from
from testutil import run_generator
assert run_generator(basic(), [5, 50]) == ((1, 6), 50)
assert run_generator(use_from(), [5, 50]) == ((1, 6), 50)
[case testYieldFrom]
from typing import Generator, Iterator, List
def basic() -> Iterator[int]:
yield from [1, 2, 3]
def call_next() -> int:
x = [] # type: List[int]
return next(iter(x))
def inner(b: bool) -> Generator[int, None, int]:
if b:
yield from [1, 2, 3]
return 10
def with_return(b: bool) -> Generator[int, None, int]:
x = yield from inner(b)
for a in [1, 2]:
pass
return x
[file driver.py]
from native import basic, call_next, with_return
from testutil import run_generator, assertRaises
assert run_generator(basic()) == ((1, 2, 3), None)
with assertRaises(StopIteration):
call_next()
assert run_generator(with_return(True)) == ((1, 2, 3), 10)
assert run_generator(with_return(False)) == ((), 10)
[case testNextGenerator]
from typing import Iterable
def f(x: int) -> int:
print(x)
return x
def call_next_loud(l: Iterable[int], val: int) -> int:
return next(i for i in l if f(i) == val)
def call_next_default(l: Iterable[int], val: int) -> int:
return next((i*2 for i in l if i == val), -1)
def call_next_default_list(l: Iterable[int], val: int) -> int:
return next((i*2 for i in l if i == val), -1)
[file driver.py]
from native import call_next_loud, call_next_default, call_next_default_list
from testutil import assertRaises
assert call_next_default([0, 1, 2], 0) == 0
assert call_next_default([0, 1, 2], 1) == 2
assert call_next_default([0, 1, 2], 2) == 4
assert call_next_default([0, 1, 2], 3) == -1
assert call_next_default([], 0) == -1
assert call_next_default_list([0, 1, 2], 0) == 0
assert call_next_default_list([0, 1, 2], 1) == 2
assert call_next_default_list([0, 1, 2], 2) == 4
assert call_next_default_list([0, 1, 2], 3) == -1
assert call_next_default_list([], 0) == -1
assert call_next_loud([0, 1, 2], 0) == 0
assert call_next_loud([0, 1, 2], 1) == 1
assert call_next_loud([0, 1, 2], 2) == 2
with assertRaises(StopIteration):
call_next_loud([42], 3)
with assertRaises(StopIteration):
call_next_loud([], 3)
[out]
0
0
1
0
1
2
42
[case testGeneratorSuper]
from typing import Iterator, Callable, Any
class A():
def testA(self) -> int:
return 2
class B(A):
def testB(self) -> Iterator[int]:
x = super().testA()
while True:
yield x
def testAsserts():
b = B()
b_gen = b.testB()
assert next(b_gen) == 2
[file driver.py]
from native import testAsserts
testAsserts()
[case testNameClashIssues]
class A:
def foo(self) -> object:
yield
class B:
def foo(self) -> object:
yield
class C:
def foo(self) -> None:
def bar(self) -> None:
pass
def C___foo() -> None: pass
class D:
def foo(self) -> None:
def bar(self) -> None:
pass
class E:
default: int
switch: int
[file driver.py]
# really I only care it builds
[case testCloseStopIterationRaised]
def g() -> object:
try:
yield 1
except GeneratorExit:
raise
[file driver.py]
from native import g
gen = g()
next(gen)
gen.close()
[case testCloseGeneratorExitRaised]
def g() -> object:
yield 1
[file driver.py]
from native import g
gen = g()
next(gen)
gen.close()
[case testCloseGeneratorExitIgnored]
def g() -> object:
try:
yield 1
except GeneratorExit:
pass
yield 2
[file driver.py]
from native import g
gen = g()
next(gen)
try:
gen.close()
except RuntimeError as e:
assert str(e) == 'generator ignored GeneratorExit'
else:
assert False
[case testCloseGeneratorRaisesAnotherException]
def g() -> object:
try:
yield 1
except GeneratorExit:
raise RuntimeError("error")
[file driver.py]
from native import g
gen = g()
next(gen)
try:
gen.close()
except RuntimeError as e:
assert str(e) == 'error'
else:
assert False
[case testBorrowingInGeneratorNearYield]
from typing import Iterator
class Foo:
flag: bool
class C:
foo: Foo
def genf(self) -> Iterator[None]:
self.foo.flag = True
yield
self.foo.flag = False
[case testGeneratorEarlyReturnWithBorrows]
from typing import Iterator
class Bar:
bar = 0
class Foo:
bar = Bar()
def f(self) -> Iterator[int]:
if self:
self.bar.bar += 1
return
yield 0
[case testBorrowingInGeneratorInTupleAssignment]
from typing import Iterator
class Foo:
flag1: bool
flag2: bool
class C:
foo: Foo
def genf(self) -> Iterator[None]:
self.foo.flag1, self.foo.flag2 = True, True
yield
self.foo.flag1, self.foo.flag2 = False, False
def test_generator() -> None:
c = C()
c.foo = Foo()
gen = c.genf()
next(gen)
assert c.foo.flag1 == c.foo.flag2 == True
assert list(gen) == []
assert c.foo.flag1 == c.foo.flag2 == False
[case testYieldInFinally]
from typing import Generator
def finally_yield() -> Generator[str, None, str]:
try:
return 'test'
finally:
yield 'x'
[file driver.py]
from native import finally_yield
from testutil import run_generator
yields, val = run_generator(finally_yield())
assert yields == ('x',)
assert val == 'test', val
[case testUnreachableComprehensionNoCrash]
from typing import List
def list_comp() -> List[int]:
if True:
return [5]
return [i for i in [5]]
[file driver.py]
from native import list_comp
assert list_comp() == [5]
[case testWithNative]
class DummyContext:
def __init__(self) -> None:
self.x = 0
def __enter__(self) -> None:
self.x += 1
def __exit__(self, exc_type, exc_value, exc_tb) -> None:
self.x -= 1
def test_basic() -> None:
context = DummyContext()
with context:
assert context.x == 1
assert context.x == 0

View File

@@ -0,0 +1,338 @@
[case testI16BasicOps]
from typing import Any, Tuple
from mypy_extensions import i16, i32, i64
from testutil import assertRaises
def test_box_and_unbox() -> None:
values = (list(range(-2**15, -2**15 + 100)) +
list(range(-1000, 1000)) +
list(range(2**15 - 100, 2**15)))
for i in values:
o: Any = i
x: i16 = o
o2: Any = x
assert o == o2
assert x == i
with assertRaises(OverflowError, "int too large to convert to i16"):
o = 2**15
x2: i16 = o
with assertRaises(OverflowError, "int too large to convert to i16"):
o = -2**15 - 1
x3: i16 = o
def div_by_7(x: i16) -> i16:
return x // 7
def div_by_neg_7(x: i16) -> i16:
return x // -7
def div(x: i16, y: i16) -> i16:
return x // y
def test_divide_by_constant() -> None:
for i in range(-1000, 1000):
assert div_by_7(i) == i // 7
for i in range(-2**15, -2**15 + 1000):
assert div_by_7(i) == i // 7
for i in range(2**15 - 1000, 2**15):
assert div_by_7(i) == i // 7
def test_divide_by_negative_constant() -> None:
for i in range(-1000, 1000):
assert div_by_neg_7(i) == i // -7
for i in range(-2**15, -2**15 + 1000):
assert div_by_neg_7(i) == i // -7
for i in range(2**15 - 1000, 2**15):
assert div_by_neg_7(i) == i // -7
def test_divide_by_variable() -> None:
values = (list(range(-50, 50)) +
list(range(-2**15, -2**15 + 10)) +
list(range(2**15 - 10, 2**15)))
for x in values:
for y in values:
if y != 0:
if x // y == 2**15:
with assertRaises(OverflowError, "integer division overflow"):
div(x, y)
else:
assert div(x, y) == x // y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
div(x, y)
def mod_by_7(x: i16) -> i16:
return x % 7
def mod_by_neg_7(x: i16) -> i16:
return x // -7
def mod(x: i16, y: i16) -> i16:
return x % y
def test_mod_by_constant() -> None:
for i in range(-1000, 1000):
assert mod_by_7(i) == i % 7
for i in range(-2**15, -2**15 + 1000):
assert mod_by_7(i) == i % 7
for i in range(2**15 - 1000, 2**15):
assert mod_by_7(i) == i % 7
def test_mod_by_negative_constant() -> None:
for i in range(-1000, 1000):
assert mod_by_neg_7(i) == i // -7
for i in range(-2**15, -2**15 + 1000):
assert mod_by_neg_7(i) == i // -7
for i in range(2**15 - 1000, 2**15):
assert mod_by_neg_7(i) == i // -7
def test_mod_by_variable() -> None:
values = (list(range(-50, 50)) +
list(range(-2**15, -2**15 + 10)) +
list(range(2**15 - 10, 2**15)))
for x in values:
for y in values:
if y != 0:
assert mod(x, y) == x % y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
mod(x, y)
def test_simple_arithmetic_ops() -> None:
zero: i16 = int()
one: i16 = zero + 1
two: i16 = one + 1
neg_one: i16 = -one
assert one + one == 2
assert one + two == 3
assert one + neg_one == 0
assert one - one == 0
assert one - two == -1
assert one * one == 1
assert one * two == 2
assert two * two == 4
assert two * neg_one == -2
assert neg_one * one == -1
assert neg_one * neg_one == 1
assert two * 0 == 0
assert 0 * two == 0
assert -one == -1
assert -two == -2
assert -neg_one == 1
assert -zero == 0
def test_bitwise_ops() -> None:
x: i16 = 13855 + int()
y: i16 = 367 + int()
z: i16 = -11091 + int()
zero: i16 = int()
one: i16 = zero + 1
two: i16 = zero + 2
neg_one: i16 = -one
assert x & y == 15
assert x & z == 5133
assert z & z == z
assert x & zero == 0
assert x | y == 14207
assert x | z == -2369
assert z | z == z
assert x | 0 == x
assert x ^ y == 14192
assert x ^ z == -7502
assert z ^ z == 0
assert z ^ 0 == z
assert x << one == 27710
assert x << two == -10116
assert z << two == 21172
assert z << 0 == z
assert x >> one == 6927
assert x >> two == 3463
assert z >> two == -2773
assert z >> 0 == z
assert ~x == -13856
assert ~z == 11090
assert ~zero == -1
assert ~neg_one == 0
def eq(x: i16, y: i16) -> bool:
return x == y
def test_eq() -> None:
assert eq(int(), int())
assert eq(5 + int(), 5 + int())
assert eq(-5 + int(), -5 + int())
assert not eq(int(), 1 + int())
assert not eq(5 + int(), 6 + int())
assert not eq(-5 + int(), -6 + int())
assert not eq(-5 + int(), 5 + int())
def test_comparisons() -> None:
one: i16 = 1 + int()
one2: i16 = 1 + int()
two: i16 = 2 + int()
assert one < two
assert not (one < one2)
assert not (two < one)
assert two > one
assert not (one > one2)
assert not (one > two)
assert one <= two
assert one <= one2
assert not (two <= one)
assert two >= one
assert one >= one2
assert not (one >= two)
assert one == one2
assert not (one == two)
assert one != two
assert not (one != one2)
def test_mixed_comparisons() -> None:
i16_3: i16 = int() + 3
int_5 = int() + 5
assert i16_3 < int_5
assert int_5 > i16_3
b = i16_3 > int_5
assert not b
int_largest = int() + (1 << 15) - 1
assert int_largest > i16_3
int_smallest = int() - (1 << 15)
assert i16_3 > int_smallest
int_too_big = int() + (1 << 15)
int_too_small = int() - (1 << 15) - 1
with assertRaises(OverflowError):
assert i16_3 < int_too_big
with assertRaises(OverflowError):
assert int_too_big < i16_3
with assertRaises(OverflowError):
assert i16_3 > int_too_small
with assertRaises(OverflowError):
assert int_too_small < i16_3
def test_mixed_arithmetic_and_bitwise_ops() -> None:
i16_3: i16 = int() + 3
int_5 = int() + 5
assert i16_3 + int_5 == 8
assert int_5 - i16_3 == 2
assert i16_3 << int_5 == 96
assert int_5 << i16_3 == 40
assert i16_3 ^ int_5 == 6
assert int_5 | i16_3 == 7
int_largest = int() + (1 << 15) - 1
assert int_largest - i16_3 == 32764
int_smallest = int() - (1 << 15)
assert int_smallest + i16_3 == -32765
int_too_big = int() + (1 << 15)
int_too_small = int() - (1 << 15) - 1
with assertRaises(OverflowError):
assert i16_3 & int_too_big
with assertRaises(OverflowError):
assert int_too_small & i16_3
def test_coerce_to_and_from_int() -> None:
for shift in range(0, 16):
for sign in 1, -1:
for delta in range(-5, 5):
n = sign * (1 << shift) + delta
if -(1 << 15) <= n < (1 << 15):
x: i16 = n
m: int = x
assert m == n
def test_explicit_conversion_to_i16() -> None:
x = i16(5)
assert x == 5
y = int() - 113
x = i16(y)
assert x == -113
n64: i64 = 1733
x = i16(n64)
assert x == 1733
n32: i32 = -1733
x = i16(n32)
assert x == -1733
z = i16(x)
assert z == -1733
def test_explicit_conversion_overflow() -> None:
max_i16 = int() + 2**15 - 1
x = i16(max_i16)
assert x == 2**15 - 1
assert int(x) == max_i16
min_i16 = int() - 2**15
y = i16(min_i16)
assert y == -2**15
assert int(y) == min_i16
too_big = int() + 2**15
with assertRaises(OverflowError):
x = i16(too_big)
too_small = int() - 2**15 - 1
with assertRaises(OverflowError):
x = i16(too_small)
def test_i16_from_large_small_literal() -> None:
x = i16(2**15 - 1)
assert x == 2**15 - 1
x = i16(-2**15)
assert x == -2**15
def test_i16_truncate_from_i64() -> None:
large = i64(2**32 + 65536 + 157 + int())
x = i16(large)
assert x == 157
small = i64(-2**32 - 65536 - 157 + int())
x = i16(small)
assert x == -157
large2 = i64(2**15 + int())
x = i16(large2)
assert x == -2**15
small2 = i64(-2**15 - 1 - int())
x = i16(small2)
assert x == 2**15 - 1
def test_i16_truncate_from_i32() -> None:
large = i32(2**16 + 2**30 + 5 + int())
assert i16(large) == 5
small = i32(-2**16 - 2**30 - 1 + int())
assert i16(small) == -1
def from_float(x: float) -> i16:
return i16(x)
def test_explicit_conversion_from_float() -> None:
assert from_float(0.0) == 0
assert from_float(1.456) == 1
assert from_float(-1234.567) == -1234
assert from_float(2**15 - 1) == 2**15 - 1
assert from_float(-2**15) == -2**15
# The error message could be better, but this is acceptable
with assertRaises(OverflowError, "int too large to convert to i16"):
assert from_float(float(2**15))
with assertRaises(OverflowError, "int too large to convert to i16"):
# One ulp below the lowest valid i64 value
from_float(float(-2**15 - 1))
def test_tuple_i16() -> None:
a: i16 = 1
b: i16 = 2
t = (a, b)
a, b = t
assert a == 1
assert b == 2
x: Any = t
tt: Tuple[i16, i16] = x
assert tt == (1, 2)

View File

@@ -0,0 +1,336 @@
[case testI32BasicOps]
from typing import Any, Tuple
from mypy_extensions import i16, i32, i64
from testutil import assertRaises
def test_box_and_unbox() -> None:
values = (list(range(-2**31, -2**31 + 100)) +
list(range(-1000, 1000)) +
list(range(2**31 - 100, 2**31)))
for i in values:
o: Any = i
x: i32 = o
o2: Any = x
assert o == o2
assert x == i
with assertRaises(OverflowError, "int too large to convert to i32"):
o = 2**31
x2: i32 = o
with assertRaises(OverflowError, "int too large to convert to i32"):
o = -2**32 - 1
x3: i32 = o
def div_by_7(x: i32) -> i32:
return x // 7
def div_by_neg_7(x: i32) -> i32:
return x // -7
def div(x: i32, y: i32) -> i32:
return x // y
def test_divide_by_constant() -> None:
for i in range(-1000, 1000):
assert div_by_7(i) == i // 7
for i in range(-2**31, -2**31 + 1000):
assert div_by_7(i) == i // 7
for i in range(2**31 - 1000, 2**31):
assert div_by_7(i) == i // 7
def test_divide_by_negative_constant() -> None:
for i in range(-1000, 1000):
assert div_by_neg_7(i) == i // -7
for i in range(-2**31, -2**31 + 1000):
assert div_by_neg_7(i) == i // -7
for i in range(2**31 - 1000, 2**31):
assert div_by_neg_7(i) == i // -7
def test_divide_by_variable() -> None:
values = (list(range(-50, 50)) +
list(range(-2**31, -2**31 + 10)) +
list(range(2**31 - 10, 2**31)))
for x in values:
for y in values:
if y != 0:
if x // y == 2**31:
with assertRaises(OverflowError, "integer division overflow"):
div(x, y)
else:
assert div(x, y) == x // y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
div(x, y)
def mod_by_7(x: i32) -> i32:
return x % 7
def mod_by_neg_7(x: i32) -> i32:
return x // -7
def mod(x: i32, y: i32) -> i32:
return x % y
def test_mod_by_constant() -> None:
for i in range(-1000, 1000):
assert mod_by_7(i) == i % 7
for i in range(-2**31, -2**31 + 1000):
assert mod_by_7(i) == i % 7
for i in range(2**31 - 1000, 2**31):
assert mod_by_7(i) == i % 7
def test_mod_by_negative_constant() -> None:
for i in range(-1000, 1000):
assert mod_by_neg_7(i) == i // -7
for i in range(-2**31, -2**31 + 1000):
assert mod_by_neg_7(i) == i // -7
for i in range(2**31 - 1000, 2**31):
assert mod_by_neg_7(i) == i // -7
def test_mod_by_variable() -> None:
values = (list(range(-50, 50)) +
list(range(-2**31, -2**31 + 10)) +
list(range(2**31 - 10, 2**31)))
for x in values:
for y in values:
if y != 0:
assert mod(x, y) == x % y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
mod(x, y)
def test_simple_arithmetic_ops() -> None:
zero: i32 = int()
one: i32 = zero + 1
two: i32 = one + 1
neg_one: i32 = -one
assert one + one == 2
assert one + two == 3
assert one + neg_one == 0
assert one - one == 0
assert one - two == -1
assert one * one == 1
assert one * two == 2
assert two * two == 4
assert two * neg_one == -2
assert neg_one * one == -1
assert neg_one * neg_one == 1
assert two * 0 == 0
assert 0 * two == 0
assert -one == -1
assert -two == -2
assert -neg_one == 1
assert -zero == 0
def test_bitwise_ops() -> None:
x: i32 = 1920687484 + int()
y: i32 = 383354614 + int()
z: i32 = -1879040563 + int()
zero: i32 = int()
one: i32 = zero + 1
two: i32 = zero + 2
neg_one: i32 = -one
assert x & y == 307823732
assert x & z == 268442956
assert z & z == z
assert x & zero == 0
assert x | y == 1996218366
assert x | z == -226796035
assert z | z == z
assert x | 0 == x
assert x ^ y == 1688394634
assert x ^ z == -495238991
assert z ^ z == 0
assert z ^ 0 == z
assert x << one == -453592328
assert x << two == -907184656
assert z << two == 1073772340
assert z << 0 == z
assert x >> one == 960343742
assert x >> two == 480171871
assert z >> two == -469760141
assert z >> 0 == z
assert ~x == -1920687485
assert ~z == 1879040562
assert ~zero == -1
assert ~neg_one == 0
def eq(x: i32, y: i32) -> bool:
return x == y
def test_eq() -> None:
assert eq(int(), int())
assert eq(5 + int(), 5 + int())
assert eq(-5 + int(), -5 + int())
assert not eq(int(), 1 + int())
assert not eq(5 + int(), 6 + int())
assert not eq(-5 + int(), -6 + int())
assert not eq(-5 + int(), 5 + int())
def test_comparisons() -> None:
one: i32 = 1 + int()
one2: i32 = 1 + int()
two: i32 = 2 + int()
assert one < two
assert not (one < one2)
assert not (two < one)
assert two > one
assert not (one > one2)
assert not (one > two)
assert one <= two
assert one <= one2
assert not (two <= one)
assert two >= one
assert one >= one2
assert not (one >= two)
assert one == one2
assert not (one == two)
assert one != two
assert not (one != one2)
def test_mixed_comparisons() -> None:
i32_3: i32 = int() + 3
int_5 = int() + 5
assert i32_3 < int_5
assert int_5 > i32_3
b = i32_3 > int_5
assert not b
int_largest = int() + (1 << 31) - 1
assert int_largest > i32_3
int_smallest = int() - (1 << 31)
assert i32_3 > int_smallest
int_too_big = int() + (1 << 31)
int_too_small = int() - (1 << 31) - 1
with assertRaises(OverflowError):
assert i32_3 < int_too_big
with assertRaises(OverflowError):
assert int_too_big < i32_3
with assertRaises(OverflowError):
assert i32_3 > int_too_small
with assertRaises(OverflowError):
assert int_too_small < i32_3
def test_mixed_arithmetic_and_bitwise_ops() -> None:
i32_3: i32 = int() + 3
int_5 = int() + 5
assert i32_3 + int_5 == 8
assert int_5 - i32_3 == 2
assert i32_3 << int_5 == 96
assert int_5 << i32_3 == 40
assert i32_3 ^ int_5 == 6
assert int_5 | i32_3 == 7
int_largest = int() + (1 << 31) - 1
assert int_largest - i32_3 == 2147483644
int_smallest = int() - (1 << 31)
assert int_smallest + i32_3 == -2147483645
int_too_big = int() + (1 << 31)
int_too_small = int() - (1 << 31) - 1
with assertRaises(OverflowError):
assert i32_3 & int_too_big
with assertRaises(OverflowError):
assert int_too_small & i32_3
def test_coerce_to_and_from_int() -> None:
for shift in range(0, 32):
for sign in 1, -1:
for delta in range(-5, 5):
n = sign * (1 << shift) + delta
if -(1 << 31) <= n < (1 << 31):
x: i32 = n
m: int = x
assert m == n
def test_explicit_conversion_to_i32() -> None:
x = i32(5)
assert x == 5
y = int() - 113
x = i32(y)
assert x == -113
n64: i64 = 1733
x = i32(n64)
assert x == 1733
n32: i32 = -1733
x = i32(n32)
assert x == -1733
z = i32(x)
assert z == -1733
a: i16 = int() + 19764
assert i32(a) == 19764
a = int() - 1
assert i32(a) == -1
def test_explicit_conversion_overflow() -> None:
max_i32 = int() + 2**31 - 1
x = i32(max_i32)
assert x == 2**31 - 1
assert int(x) == max_i32
min_i32 = int() - 2**31
y = i32(min_i32)
assert y == -2**31
assert int(y) == min_i32
too_big = int() + 2**31
with assertRaises(OverflowError):
x = i32(too_big)
too_small = int() - 2**31 - 1
with assertRaises(OverflowError):
x = i32(too_small)
def test_i32_from_large_small_literal() -> None:
x = i32(2**31 - 1)
assert x == 2**31 - 1
x = i32(-2**31)
assert x == -2**31
def test_i32_truncate_from_i64() -> None:
large = i64(2**32 + 157 + int())
x = i32(large)
assert x == 157
small = i64(-2**32 - 157 + int())
x = i32(small)
assert x == -157
large2 = i64(2**31 + int())
x = i32(large2)
assert x == -2**31
small2 = i64(-2**31 - 1 - int())
x = i32(small2)
assert x == 2**31 - 1
def from_float(x: float) -> i32:
return i32(x)
def test_explicit_conversion_from_float() -> None:
assert from_float(0.0) == 0
assert from_float(1.456) == 1
assert from_float(-1234.567) == -1234
assert from_float(2**31 - 1) == 2**31 - 1
assert from_float(-2**31) == -2**31
# The error message could be better, but this is acceptable
with assertRaises(OverflowError, "int too large to convert to i32"):
assert from_float(float(2**31))
with assertRaises(OverflowError, "int too large to convert to i32"):
# One ulp below the lowest valid i64 value
from_float(float(-2**31 - 2048))
def test_tuple_i32() -> None:
a: i32 = 1
b: i32 = 2
t = (a, b)
a, b = t
assert a == 1
assert b == 2
x: Any = t
tt: Tuple[i32, i32] = x
assert tt == (1, 2)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
# Test cases for imports and related features (compile and run)
[case testImports]
import testmodule
import pkg2.mod
import pkg2.mod2 as mm2
def f(x: int) -> int:
return testmodule.factorial(5)
def g(x: int) -> int:
from welp import foo
return foo(x)
def test_import_basics() -> None:
assert f(5) == 120
assert g(5) == 5
assert "pkg2.mod" not in globals(), "the root module should be in globals!"
assert pkg2.mod.x == 1
assert "mod2" not in globals(), "pkg2.mod2 is aliased to mm2!"
assert mm2.y == 2
def test_import_submodule_within_function() -> None:
import pkg.mod
assert pkg.x == 1
assert pkg.mod.y == 2
assert "pkg.mod" not in globals(), "the root module should be in globals!"
def test_import_as_submodule_within_function() -> None:
import pkg.mod as mm
assert mm.y == 2
assert "pkg.mod" not in globals(), "the root module should be in globals!"
# TODO: Don't add local imports to globals()
#
# def test_local_import_not_in_globals() -> None:
# import nob
# assert 'nob' not in globals()
def test_import_module_without_stub_in_function() -> None:
# 'psutil' must not have a stub in typeshed for this test case
import psutil # type: ignore
# TODO: We shouldn't add local imports to globals()
# assert 'psutil' not in globals()
assert isinstance(psutil.__name__, str)
def test_import_as_module_without_stub_in_function() -> None:
# 'psutil' must not have a stub in typeshed for this test case
import psutil as pp # type: ignore
assert 'psutil' not in globals()
# TODO: We shouldn't add local imports to globals()
# assert 'pp' not in globals()
assert isinstance(pp.__name__, str)
[file testmodule.py]
def factorial(x: int) -> int:
if x == 0:
return 1
else:
return x * factorial(x-1)
[file welp.py]
def foo(x: int) -> int:
return x
[file pkg/__init__.py]
x = 1
[file pkg/mod.py]
y = 2
[file pkg2/__init__.py]
[file pkg2/mod.py]
x = 1
[file pkg2/mod2.py]
y = 2
[file nob.py]
z = 3
[case testImportMissing]
# The unchecked module is configured by the test harness to not be
# picked up by mypy, so we can test that we do that right thing when
# calling library modules without stubs.
import unchecked # type: ignore
import unchecked as lol # type: ignore
assert unchecked.x == 10
assert lol.x == 10
[file unchecked.py]
x = 10
[file driver.py]
import native
[case testFromImport]
from testmodule import g
def f(x: int) -> int:
return g(x)
[file testmodule.py]
def g(x: int) -> int:
return x + 1
[file driver.py]
from native import f
assert f(1) == 2
[case testFromImportWithUntypedModule]
# avoid including an __init__.py and use type: ignore to test what happens
# if mypy can't tell if mod isn't a module
from pkg import mod # type: ignore
def test_import() -> None:
assert mod.h(8) == 24
[file pkg/mod.py]
def h(x):
return x * 3
[case testFromImportWithKnownModule]
from pkg import mod1
from pkg import mod2 as modmod
from pkg.mod2 import g as gg
from pkg.mod3 import h as h2, g as g2
def test_import() -> None:
assert mod1.h(8) == 24
assert modmod.g(1) == 1
assert gg(2) == 2
assert h2(10) == 12
assert g2(10) == 13
[file pkg/__init__.py]
[file pkg/mod1.py]
def h(x: int) -> int:
return x * 3
[file pkg/mod2.py]
def g(x: int) -> int:
return x
[file pkg/mod3.py]
def h(x: int) -> int:
return x + 2
def g(x: int) -> int:
return x + 3
[case testFromImportWithUnKnownModule]
def test_import() -> None:
try:
from pkg import a # type: ignore
except ImportError:
pass
[file pkg/__init__.py]
[case testMultipleFromImportsWithSamePackageButDifferentModules]
from pkg import a
from pkg import b
def test_import() -> None:
assert a.g() == 4
assert b.h() == 39
[file pkg/__init__.py]
[file pkg/a.py]
def g() -> int:
return 4
[file pkg/b.py]
def h() -> int:
return 39
[case testReexport]
# Test that we properly handle accessing values that have been reexported
import a
def f(x: int) -> int:
return a.g(x) + a.foo + a.b.foo
whatever = a.A()
[file a.py]
from b import g as g, A as A, foo as foo
import b
[file b.py]
def g(x: int) -> int:
return x + 1
class A:
pass
foo = 20
[file driver.py]
from native import f, whatever
import b
assert f(20) == 61
assert isinstance(whatever, b.A)
[case testAssignModule]
import a
assert a.x == 20
a.x = 10
[file a.py]
x = 20
[file driver.py]
import native
[case testLazyImport]
import shared
def do_import() -> None:
import a
assert shared.counter == 0
do_import()
assert shared.counter == 1
[file a.py]
import shared
shared.counter += 1
[file shared.py]
counter = 0
[case testDelayedImport]
import a
print("inbetween")
import b
[file a.py]
print("first")
[file b.py]
print("last")
[out]
first
inbetween
last
[case testImportErrorLineNumber]
try:
import enum
import dataclasses, missing # type: ignore[import]
except ImportError as e:
line = e.__traceback__.tb_lineno # type: ignore[attr-defined]
assert line == 3, f"traceback's line number is {line}, expected 3"
[case testImportGroupIsolation]
def func() -> None:
import second
import first
func()
[file first.py]
print("first")
[file second.py]
print("second")
[out]
first
second

View File

@@ -0,0 +1,540 @@
# Test cases for integers (compile and run)
[case testInc]
def inc(x: int) -> int:
return x + 1
[file driver.py]
from native import inc
print(inc(3))
print(inc(-5))
print(inc(10**20))
[out]
4
-4
100000000000000000001
[case testCount]
def count(n: int) -> int:
i = 1
while i <= n:
i = i + 1
return i
[file driver.py]
from native import count
print(count(0))
print(count(1))
print(count(5))
[out]
1
2
6
[case testIntMathOps]
# This tests integer math things that are either easier to test in Python than
# in our C tests or are tested here because (for annoying reasons) we don't run
# the C unit tests in our 32-bit CI.
def multiply(x: int, y: int) -> int:
return x * y
# these stringify their outputs because that will catch if exceptions are mishandled
def floor_div(x: int, y: int) -> str:
return str(x // y)
def remainder(x: int, y: int) -> str:
return str(x % y)
[file driver.py]
from native import multiply, floor_div, remainder
def test_multiply(x, y):
assert multiply(x, y) == x * y
def test_floor_div(x, y):
assert floor_div(x, y) == str(x // y)
def test_remainder(x, y):
assert remainder(x, y) == str(x % y)
test_multiply(10**6, 10**6)
test_multiply(2**15, 2**15-1)
test_multiply(2**14, 2**14)
test_multiply(10**12, 10**12)
test_multiply(2**30, 2**30-1)
test_multiply(2**29, 2**29)
test_floor_div(-2**62, -1)
test_floor_div(-2**30, -1)
try:
floor_div(10, 0)
except ZeroDivisionError:
pass
else:
assert False, "Expected ZeroDivisionError"
test_remainder(-2**62, -1)
test_remainder(-2**30, -1)
try:
remainder(10, 0)
except ZeroDivisionError:
pass
else:
assert False, "Expected ZeroDivisionError"
[case testBigIntLiteral]
def big_int() -> None:
a_62_bit = 4611686018427387902
max_62_bit = 4611686018427387903
b_63_bit = 4611686018427387904
c_63_bit = 9223372036854775806
max_63_bit = 9223372036854775807
d_64_bit = 9223372036854775808
max_32_bit = 2147483647
max_32_bit_plus1 = 2147483648
max_31_bit = 1073741823
max_31_bit_plus1 = 1073741824
neg = -1234567
min_signed_63_bit = -4611686018427387904
underflow = -4611686018427387905
min_signed_64_bit = -9223372036854775808
min_signed_31_bit = -1073741824
min_signed_31_bit_plus1 = -1073741823
min_signed_31_bit_minus1 = -1073741825
min_signed_32_bit = -2147483648
print(a_62_bit)
print(max_62_bit)
print(b_63_bit)
print(c_63_bit)
print(max_63_bit)
print(d_64_bit)
print('==')
print(max_32_bit)
print(max_32_bit_plus1)
print(max_31_bit)
print(max_31_bit_plus1)
print(neg)
print(min_signed_63_bit)
print(underflow)
print(min_signed_64_bit)
print(min_signed_31_bit)
print(min_signed_31_bit_plus1)
print(min_signed_31_bit_minus1)
print(min_signed_32_bit)
[file driver.py]
from native import big_int
big_int()
[out]
4611686018427387902
4611686018427387903
4611686018427387904
9223372036854775806
9223372036854775807
9223372036854775808
==
2147483647
2147483648
1073741823
1073741824
-1234567
-4611686018427387904
-4611686018427387905
-9223372036854775808
-1073741824
-1073741823
-1073741825
-2147483648
[case testNeg]
def neg(x: int) -> int:
return -x
[file driver.py]
from native import neg
assert neg(5) == -5
assert neg(-5) == 5
assert neg(1073741823) == -1073741823
assert neg(-1073741823) == 1073741823
assert neg(1073741824) == -1073741824
assert neg(-1073741824) == 1073741824
assert neg(2147483647) == -2147483647
assert neg(-2147483647) == 2147483647
assert neg(2147483648) == -2147483648
assert neg(-2147483648) == 2147483648
assert neg(4611686018427387904) == -4611686018427387904
assert neg(-4611686018427387904) == 4611686018427387904
assert neg(9223372036854775807) == -9223372036854775807
assert neg(-9223372036854775807) == 9223372036854775807
assert neg(9223372036854775808) == -9223372036854775808
assert neg(-9223372036854775808) == 9223372036854775808
[case testIsinstanceIntAndNotBool]
def test_isinstance_int_and_not_bool(value: object) -> bool:
return isinstance(value, int) and not isinstance(value, bool)
[file driver.py]
from native import test_isinstance_int_and_not_bool
assert test_isinstance_int_and_not_bool(True) == False
assert test_isinstance_int_and_not_bool(1) == True
[case testIntOps]
from typing import Any
from testutil import assertRaises
def check_and(x: int, y: int) -> None:
# eval() can be trusted to calculate expected result
expected = eval('{} & {}'.format(x, y))
actual = x & y
assert actual == expected, '{} & {}: got {}, expected {}'.format(x, y, actual, expected)
def check_or(x: int, y: int) -> None:
# eval() can be trusted to calculate expected result
expected = eval('{} | {}'.format(x, y))
actual = x | y
assert actual == expected, '{} | {}: got {}, expected {}'.format(x, y, actual, expected)
def check_xor(x: int, y: int) -> None:
# eval() can be trusted to calculate expected result
expected = eval('{} ^ {}'.format(x, y))
actual = x ^ y
assert actual == expected, '{} ^ {}: got {}, expected {}'.format(x, y, actual, expected)
def check_bitwise(x: int, y: int) -> None:
for l, r in (x, y), (y, x):
for ll, rr in (l, r), (-l, r), (l, -r), (-l, -r):
check_and(ll, rr)
check_or(ll, rr)
check_xor(ll, rr)
SHIFT = 30
DIGIT0a = 615729753
DIGIT0b = 832796681
DIGIT1a = 744342356 << SHIFT
DIGIT1b = 321006080 << SHIFT
DIGIT2a = 643582106 << (SHIFT * 2)
DIGIT2b = 656420725 << (SHIFT * 2)
DIGIT50 = 315723472 << (SHIFT * 50)
DIGIT100a = 1020652627 << (SHIFT * 100)
DIGIT100b = 923752451 << (SHIFT * 100)
BIG_SHORT = 3491190729721336556
MAX_SHORT = (1 << 62) - 1
MIN_SHORT = -(1 << 62)
MAX_SHORT_32 = (1 << 30) - 1
MIN_SHORT_32 = -(1 << 30)
def test_and_or_xor() -> None:
check_bitwise(0, 0)
check_bitwise(0, 1)
check_bitwise(1, 1)
check_bitwise(DIGIT0a, DIGIT0b)
check_bitwise(DIGIT1a, DIGIT1b)
check_bitwise(DIGIT2a, DIGIT2b)
check_bitwise(DIGIT100a, DIGIT100b)
check_bitwise(DIGIT0a, DIGIT0b + DIGIT2a)
check_bitwise(DIGIT0a, DIGIT0b + DIGIT50)
check_bitwise(DIGIT50 + DIGIT1a, DIGIT100a + DIGIT2b)
check_bitwise(BIG_SHORT, DIGIT0a)
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a)
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a)
check_bitwise(BIG_SHORT, DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
for x in range(-25, 25):
for y in range(-25, 25):
check_bitwise(x, y)
def test_bitwise_inplace() -> None:
# Basic sanity checks; these should use the same code as the non-in-place variants
for x, y in (DIGIT0a, DIGIT1a), (DIGIT2a, DIGIT0a + DIGIT2b):
n = x
n &= y
assert n == x & y
n = x
n |= y
assert n == x | y
n = x
n ^= y
assert n == x ^ y
def check_invert(x: int) -> None:
# Use eval() as the source of truth
assert ~x == eval('~{}'.format(x))
assert ~(-x) == eval('~({})'.format(-x))
def test_invert() -> None:
check_invert(0)
check_invert(1)
check_invert(DIGIT0a)
check_invert(DIGIT0a + DIGIT1a)
check_invert(DIGIT0a + DIGIT1a + DIGIT2a)
check_invert(DIGIT0a + DIGIT1a + DIGIT2a + DIGIT50)
check_invert(BIG_SHORT)
for delta in -1, 0, 1:
check_invert(MAX_SHORT + delta)
check_invert(MIN_SHORT + delta)
check_invert(MAX_SHORT_32 + delta)
check_invert(MIN_SHORT_32 + delta)
def check_right_shift(x: int, n: int) -> None:
if n < 0:
try:
x >> n
except ValueError:
return
assert False, "no exception raised"
# Use eval() as the source of truth
expected = eval('{} >> {}'.format(x, n))
actual = x >> n
assert actual == expected, "{} >> {}: got {}, expected {}".format(x, n, actual, expected)
def test_right_shift() -> None:
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
for n in 0, 1, 2, 3, 4, 10, 40, 10000, DIGIT1a, -1, -1334444, -DIGIT1a:
check_right_shift(x, n)
check_right_shift(-x, n)
x = DIGIT0a
x >>= 1
assert x == DIGIT0a >> 1
x = DIGIT50
x >>= 5
assert x == DIGIT50 >> 5
for i in range(256):
check_right_shift(1, i)
check_right_shift(137, i)
check_right_shift(MAX_SHORT, i)
check_right_shift(MAX_SHORT_32, i)
check_right_shift(MAX_SHORT + 1, i)
check_right_shift(MAX_SHORT_32 + 1, i)
for x in 1, DIGIT50:
try:
# It's okay if this raises an exception
assert x >> DIGIT2a == 0
except Exception:
pass
try:
x >> -DIGIT2a
assert False
except Exception:
pass
def check_left_shift(x: int, n: int) -> None:
if n < 0:
try:
x << n
except ValueError:
return
assert False, "no exception raised"
# Use eval() as the source of truth
expected = eval('{} << {}'.format(x, n))
actual = x << n
assert actual == expected, "{} << {}: got {}, expected {}".format(x, n, actual, expected)
def test_left_shift() -> None:
for x in 0, 1, 1235, DIGIT0a, DIGIT0a + DIGIT1a, DIGIT0a + DIGIT50:
for n in 0, 1, 2, 10, 40, 10000, -1, -1334444:
check_left_shift(x, n)
check_left_shift(-x, n)
x = DIGIT0a
x <<= 1
assert x == DIGIT0a << 1
x = DIGIT50
x <<= 5
assert x == DIGIT50 << 5
for shift in range(256):
check_left_shift(1, shift)
check_left_shift(137, shift)
for x in 1, DIGIT50:
try:
x << DIGIT50
assert False
except Exception:
pass
try:
x << -DIGIT50
assert False
except Exception:
pass
def is_true(x: int) -> bool:
if x:
return True
else:
return False
def is_true2(x: int) -> bool:
return bool(x)
def is_false(x: int) -> bool:
if not x:
return True
else:
return False
def test_int_as_bool() -> None:
assert not is_true(0)
assert not is_true2(0)
assert is_false(0)
for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101):
assert is_true(x)
assert is_true2(x)
assert not is_false(x)
def bool_as_int(b: bool) -> int:
return b
def bool_as_int2(b: bool) -> int:
return int(b)
def test_bool_as_int() -> None:
assert bool_as_int(False) == 0
assert bool_as_int(True) == 1
assert bool_as_int2(False) == 0
assert bool_as_int2(True) == 1
def no_op_conversion(n: int) -> int:
return int(n)
def test_no_op_conversion() -> None:
for x in 1, 55, -1, -7, 1 << 50, 1 << 101, -(1 << 50), -(1 << 101):
assert no_op_conversion(x) == x
def test_floor_divide() -> None:
for x in range(-100, 100):
for y in range(-100, 100):
if y != 0:
assert x // y == getattr(x, "__floordiv__")(y)
def test_mod() -> None:
for x in range(-100, 100):
for y in range(-100, 100):
if y != 0:
assert x % y == getattr(x, "__mod__")(y)
def test_constant_fold() -> None:
assert str(-5 + 3) == "-2"
assert str(15 - 3) == "12"
assert str(1000 * 1000) == "1000000"
assert str(12325 // 12 ) == "1027"
assert str(87645 % 321) == "12"
assert str(674253 | 76544) == "748493"
assert str(765 ^ 82) == "687"
assert str(6546 << 3) == "52368"
assert str(6546 >> 7) == "51"
assert str(3**5) == "243"
assert str(~76) == "-77"
try:
2 / 0
except ZeroDivisionError:
pass
else:
assert False, "no exception raised"
x = int()
y = int() - 1
assert x == -1 or y != -3
assert -1 <= x
assert -1 == y
# Use int() to avoid constant propagation
i30 = (1 << 30) + int()
assert i30 == 1 << 30
i31 = (1 << 31) + int()
assert i31 == 1 << 31
i32 = (1 << 32) + int()
assert i32 == 1 << 32
i62 = (1 << 62) + int()
assert i62 == 1 << 62
i63 = (1 << 63) + int()
assert i63 == 1 << 63
i64 = (1 << 64) + int()
assert i64 == 1 << 64
n30 = -(1 << 30) + int()
assert n30 == -(1 << 30)
n31 = -(1 << 31) + int()
assert n31 == -(1 << 31)
n32 = -(1 << 32) + int()
assert n32 == -(1 << 32)
n62 = -(1 << 62) + int()
assert n62 == -(1 << 62)
n63 = -(1 << 63) + int()
assert n63 == -(1 << 63)
n64 = -(1 << 64) + int()
assert n64 == -(1 << 64)
def div_by_2(x: int) -> int:
return x // 2
def div_by_3(x: int) -> int:
return x // 3
def div_by_4(x: int) -> int:
return x // 4
def test_floor_divide_by_literal() -> None:
for i in range(-100, 100):
i_boxed: Any = i
assert div_by_2(i) == i_boxed // int('2')
assert div_by_3(i) == i_boxed // int('3')
assert div_by_4(i) == i_boxed // int('4')
def test_true_divide() -> None:
for x in range(-150, 100):
for y in range(-150, 100):
if y != 0:
assert x / y == getattr(x, "__truediv__")(y)
large1 = (123 + int())**123
large2 = (121 + int())**121
assert large1 / large2 == getattr(large1, "__truediv__")(large2)
assert large1 / 135 == getattr(large1, "__truediv__")(135)
assert large1 / -2 == getattr(large1, "__truediv__")(-2)
assert 17 / large2 == getattr(17, "__truediv__")(large2)
huge = 10**1000 + int()
with assertRaises(OverflowError, "integer division result too large for a float"):
huge / 2
with assertRaises(OverflowError, "integer division result too large for a float"):
huge / -2
assert 1 / huge == 0.0
[case testIntMinMax]
def test_int_min_max() -> None:
x: int = 200
y: int = 30
assert min(x, y) == 30
assert max(x, y) == 200
assert min(y, x) == 30
assert max(y, x) == 200
def test_int_hybrid_min_max() -> None:
from typing import Any
x: object = 30
y: Any = 20.0
assert min(x, y) == 20.0
assert max(x, y) == 30
u: object = 20
v: float = 30.0
assert min(u, v) == 20
assert max(u, v) == 30.0
def test_int_incompatible_min_max() -> None:
x: int = 2
y: str = 'aaa'
try:
print(min(x, y))
except TypeError as e:
assert str(e) == "'<' not supported between instances of 'str' and 'int'"
try:
print(max(x, y))
except TypeError as e:
assert str(e) == "'>' not supported between instances of 'str' and 'int'"
def test_int_bool_min_max() -> None:
x: int = 2
y: bool = False
z: bool = True
assert min(x, y) == False
assert min(x, z) == True
assert max(x, y) == 2
assert max(x, z) == 2
u: int = -10
assert min(u, y) == -10
assert min(u, z) == -10
assert max(u, y) == False
assert max(u, z) == True

View File

@@ -0,0 +1,411 @@
# Test cases for lists (compile and run)
[case testListPlusEquals]
from typing import Any
def append(x: Any) -> None:
x += [1]
[file driver.py]
from native import append
x = []
append(x)
assert x == [1]
[case testListSum]
from typing import List
def sum(a: List[int], l: int) -> int:
sum = 0
i = 0
while i < l:
sum = sum + a[i]
i = i + 1
return sum
[file driver.py]
from native import sum
print(sum([], 0))
print(sum([3], 1))
print(sum([5, 6, -4], 3))
print(sum([2**128 + 5, -2**127 - 8], 2))
[out]
0
3
7
170141183460469231731687303715884105725
[case testListSet]
from typing import List
def copy(a: List[int], b: List[int], l: int) -> int:
i = 0
while i < l:
a[i] = b[i]
i = i + 1
return 0
[file driver.py]
from native import copy
a = [0, '']
copy(a, [-1, 5], 2)
print(1, a)
copy(a, [2**128 + 5, -2**127 - 8], 2)
print(2, a)
[out]
1 [-1, 5]
2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736]
[case testSieve]
from typing import List
def primes(n: int) -> List[int]:
a = [1] * (n + 1)
a[0] = 0
a[1] = 0
i = 0
while i < n:
if a[i] == 1:
j = i * i
while j < n:
a[j] = 0
j = j + i
i = i + 1
return a
[file driver.py]
from native import primes
print(primes(3))
print(primes(13))
[out]
\[0, 0, 1, 1]
\[0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]
[case testListBuild]
def test_list_build() -> None:
# Currently LIST_BUILDING_EXPANSION_THRESHOLD equals to 10
# long list built by list_build_op
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
l1.pop()
l1.append(100)
assert l1 == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
# short list built by Setmem
l2 = [1, 2]
l2.append(3)
l2.pop()
l2.pop()
assert l2 == [1]
# empty list
l3 = []
l3.append('a')
assert l3 == ['a']
[case testListPrims]
from typing import List
def test_append() -> None:
l = [1, 2]
l.append(10)
assert l == [1, 2, 10]
l.append(3)
l.append(4)
l.append(5)
assert l == [1, 2, 10, 3, 4, 5]
def test_pop_last() -> None:
l = [1, 2, 10, 3, 4, 5]
l.pop()
l.pop()
assert l == [1, 2, 10, 3]
def test_pop_index() -> None:
l = [1, 2, 10, 3]
l.pop(2)
assert l == [1, 2, 3]
l.pop(-2)
assert l == [1, 3]
def test_count() -> None:
l = [1, 3]
assert l.count(1) == 1
assert l.count(2) == 0
def test_insert() -> None:
l = [1, 3]
l.insert(0, 0)
assert l == [0, 1, 3]
l.insert(2, 2)
assert l == [0, 1, 2, 3]
l.insert(4, 4)
assert l == [0, 1, 2, 3, 4]
l.insert(-1, 5)
assert l == [0, 1, 2, 3, 5, 4]
l = [1, 3]
l.insert(100, 5)
assert l == [1, 3, 5]
l.insert(-100, 6)
assert l == [6, 1, 3, 5]
for long_int in 1 << 100, -(1 << 100):
try:
l.insert(long_int, 5)
except Exception as e:
# The error message is used by CPython
assert type(e).__name__ == 'OverflowError'
assert str(e) == 'Python int too large to convert to C ssize_t'
else:
assert False
def test_sort() -> None:
l = [1, 4, 3, 6, -1]
l.sort()
assert l == [-1, 1, 3, 4, 6]
l.sort()
assert l == [-1, 1, 3, 4, 6]
l = []
l.sort()
assert l == []
def test_reverse() -> None:
l = [1, 4, 3, 6, -1]
l.reverse()
assert l == [-1, 6, 3, 4, 1]
l.reverse()
assert l == [1, 4, 3, 6, -1]
l = []
l.reverse()
assert l == []
def test_remove() -> None:
l = [1, 3, 4, 3]
l.remove(3)
assert l == [1, 4, 3]
l.remove(3)
assert l == [1, 4]
try:
l.remove(3)
except ValueError:
pass
else:
assert False
def test_index() -> None:
l = [1, 3, 4, 3]
assert l.index(1) == 0
assert l.index(3) == 1
assert l.index(4) == 2
try:
l.index(0)
except ValueError:
pass
else:
assert False
[case testListOfUserDefinedClass]
class C:
x: int
def f() -> int:
c = C()
c.x = 5
a = [c]
d = a[0]
return d.x + 1
def g() -> int:
a = [C()]
a[0].x = 3
return a[0].x + 4
[file driver.py]
from native import f, g
print(f())
print(g())
[out]
6
7
[case testListOps]
def test_slicing() -> None:
# Use dummy adds to avoid constant folding
zero = int()
two = zero + 2
s = ["f", "o", "o", "b", "a", "r"]
assert s[two:] == ["o", "b", "a", "r"]
assert s[:two] == ["f", "o"]
assert s[two:-two] == ["o", "b"]
assert s[two:two] == []
assert s[two:two + 1] == ["o"]
assert s[-two:] == ["a", "r"]
assert s[:-two] == ["f", "o", "o", "b"]
assert s[:] == ["f", "o", "o", "b", "a", "r"]
assert s[two:333] == ["o", "b", "a", "r"]
assert s[333:two] == []
assert s[two:-333] == []
assert s[-333:two] == ["f", "o"]
long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
assert s[1:long_int] == ["o", "o", "b", "a", "r"]
assert s[long_int:] == []
assert s[-long_int:-1] == ["f", "o", "o", "b", "a"]
[case testOperatorInExpression]
def tuple_in_int0(i: int) -> bool:
return i in []
def tuple_in_int1(i: int) -> bool:
return i in (1,)
def tuple_in_int3(i: int) -> bool:
return i in (1, 2, 3)
def tuple_not_in_int0(i: int) -> bool:
return i not in []
def tuple_not_in_int1(i: int) -> bool:
return i not in (1,)
def tuple_not_in_int3(i: int) -> bool:
return i not in (1, 2, 3)
def tuple_in_str(s: "str") -> bool:
return s in ("foo", "bar", "baz")
def tuple_not_in_str(s: "str") -> bool:
return s not in ("foo", "bar", "baz")
def list_in_int0(i: int) -> bool:
return i in []
def list_in_int1(i: int) -> bool:
return i in (1,)
def list_in_int3(i: int) -> bool:
return i in (1, 2, 3)
def list_not_in_int0(i: int) -> bool:
return i not in []
def list_not_in_int1(i: int) -> bool:
return i not in (1,)
def list_not_in_int3(i: int) -> bool:
return i not in (1, 2, 3)
def list_in_str(s: "str") -> bool:
return s in ("foo", "bar", "baz")
def list_not_in_str(s: "str") -> bool:
return s not in ("foo", "bar", "baz")
def list_in_mixed(i: object):
return i in [[], (), "", 0, 0.0, False, 0j, {}, set(), type]
[file driver.py]
from native import *
assert not tuple_in_int0(0)
assert not tuple_in_int1(0)
assert tuple_in_int1(1)
assert not tuple_in_int3(0)
assert tuple_in_int3(1)
assert tuple_in_int3(2)
assert tuple_in_int3(3)
assert not tuple_in_int3(4)
assert tuple_not_in_int0(0)
assert tuple_not_in_int1(0)
assert not tuple_not_in_int1(1)
assert tuple_not_in_int3(0)
assert not tuple_not_in_int3(1)
assert not tuple_not_in_int3(2)
assert not tuple_not_in_int3(3)
assert tuple_not_in_int3(4)
assert tuple_in_str("foo")
assert tuple_in_str("bar")
assert tuple_in_str("baz")
assert not tuple_in_str("apple")
assert not tuple_in_str("pie")
assert not tuple_in_str("\0")
assert not tuple_in_str("")
assert not list_in_int0(0)
assert not list_in_int1(0)
assert list_in_int1(1)
assert not list_in_int3(0)
assert list_in_int3(1)
assert list_in_int3(2)
assert list_in_int3(3)
assert not list_in_int3(4)
assert list_not_in_int0(0)
assert list_not_in_int1(0)
assert not list_not_in_int1(1)
assert list_not_in_int3(0)
assert not list_not_in_int3(1)
assert not list_not_in_int3(2)
assert not list_not_in_int3(3)
assert list_not_in_int3(4)
assert list_in_str("foo")
assert list_in_str("bar")
assert list_in_str("baz")
assert not list_in_str("apple")
assert not list_in_str("pie")
assert not list_in_str("\0")
assert not list_in_str("")
assert list_in_mixed(0)
assert list_in_mixed([])
assert list_in_mixed({})
assert list_in_mixed(())
assert list_in_mixed(False)
assert list_in_mixed(0.0)
assert not list_in_mixed([1])
assert not list_in_mixed(object)
assert list_in_mixed(type)
[case testListBuiltFromGenerator]
def test() -> None:
source_a = ["a", "b", "c"]
a = list(x + "f2" for x in source_a)
assert a == ["af2", "bf2", "cf2"]
source_b = [1, 2, 3, 4, 5]
b = [x * 2 for x in source_b]
assert b == [2, 4, 6, 8, 10]
source_c = [10, 20, 30]
c = [x + "f4" for x in (str(y) + "yy" for y in source_c)]
assert c == ["10yyf4", "20yyf4", "30yyf4"]
source_d = [True, False]
d = [not x for x in source_d]
assert d == [False, True]
source_e = [0, 1, 2]
e = list((x ** 2) for x in (y + 2 for y in source_e))
assert e == [4, 9, 16]
source_str = "abcd"
f = list("str:" + x for x in source_str)
assert f == ["str:a", "str:b", "str:c", "str:d"]
[case testNextBug]
from typing import List, Optional
def test(x: List[int]) -> None:
res = next((i for i in x), None)
[case testListGetItemWithBorrow]
from typing import List
class D:
def __init__(self, n: int) -> None:
self.n = n
class C:
def __init__(self, d: D) -> None:
self.d = d
def test_index_with_literal() -> None:
d1 = D(1)
d2 = D(2)
a = [C(d1), C(d2)]
d = a[0].d
assert d is d1
d = a[1].d
assert d is d2
d = a[-1].d
assert d is d2
d = a[-2].d
assert d is d1

View File

@@ -0,0 +1,485 @@
# Test cases for "range" objects, "for" and "while" loops (compile and run)
[case testFor]
from typing import List, Tuple
def count(n: int) -> None:
for i in range(n):
print(i)
def count_between(n: int, k: int) -> None:
for i in range(n, k):
print(i)
print('n=', n)
def count_down(n: int, k: int) -> None:
for i in range(n, k, -1):
print(i)
def count_double(n: int, k: int) -> None:
for i in range(n, k, 2):
print(i)
def list_iter(l: List[int]) -> None:
for i in l:
print(i)
def tuple_iter(l: Tuple[int, ...]) -> None:
for i in l:
print(i)
def str_iter(l: str) -> None:
for i in l:
print(i)
def list_rev_iter(l: List[int]) -> None:
for i in reversed(l):
print(i)
def list_rev_iter_lol(l: List[int]) -> None:
for i in reversed(l):
print(i)
if i == 3:
while l:
l.pop()
def count_down_short() -> None:
for i in range(10, 0, -1):
print(i)
[file driver.py]
from native import (
count, list_iter, list_rev_iter, list_rev_iter_lol, count_between, count_down, count_double,
count_down_short, tuple_iter, str_iter,
)
count(5)
list_iter(list(reversed(range(5))))
list_rev_iter(list(reversed(range(5))))
count_between(11, 15)
count_between(10**20, 10**20+3)
count_down(20, 10)
count_double(10, 15)
count_down_short()
print('==')
list_rev_iter_lol(list(reversed(range(5))))
tuple_iter((1, 2, 3))
str_iter("abc")
[out]
0
1
2
3
4
4
3
2
1
0
0
1
2
3
4
11
12
13
14
n= 11
100000000000000000000
100000000000000000001
100000000000000000002
n= 100000000000000000000
20
19
18
17
16
15
14
13
12
11
10
12
14
10
9
8
7
6
5
4
3
2
1
==
0
1
2
3
1
2
3
a
b
c
[case testLoopElse]
from typing import Iterator
def run_for_range(n: int) -> None:
for i in range(n):
if i == 3:
break
print(i)
else:
print(n+1)
def run_for_list(n: int) -> None:
for i in list(range(n)):
if i == 3:
break
print(i)
else:
print(n+1)
def run_for_iter(n: int) -> None:
def identity(x: Iterator[int]) -> Iterator[int]:
return x
for i in identity(range(n)):
if i == 3:
break
print(i)
else:
print(n+1)
def count(n: int) -> int:
i = 1
while i <= n:
i = i + 1
if i == 5:
break
else:
i *= -1
return i
def nested_while() -> int:
while True:
while False:
pass
else:
break
else:
return -1
return 0
def nested_for() -> int:
for x in range(1000):
for y in [1,2,3]:
pass
else:
break
else:
return -1
return 0
[file driver.py]
from native import run_for_range, run_for_list, run_for_iter, count, nested_while, nested_for
assert nested_while() == 0
assert nested_for() == 0
assert count(0) == -1
assert count(1) == -2
assert count(5) == 5
assert count(6) == 5
run_for_range(3)
run_for_range(5)
print('==')
run_for_list(3)
run_for_list(5)
print('==')
run_for_iter(3)
run_for_iter(5)
[out]
0
1
2
4
0
1
2
==
0
1
2
4
0
1
2
==
0
1
2
4
0
1
2
[case testNestedLoopSameIdx]
from typing import List, Generator
def nested_enumerate() -> None:
l1 = [0,1,2]
l2 = [0,1,2]
outer_seen = []
outer = 0
for i, j in enumerate(l1):
assert i == outer
outer_seen.append(i)
inner = 0
for i, k in enumerate(l2):
assert i == inner
inner += 1
outer += 1
assert outer_seen == l1
def nested_range() -> None:
outer = 0
outer_seen = []
for i in range(3):
assert i == outer
outer_seen.append(i)
inner = 0
for i in range(3):
assert i == inner
inner += 1
outer += 1
assert outer_seen == [0,1,2]
def nested_list() -> None:
l1 = [0,1,2]
l2 = [0,1,2]
outer_seen = []
outer = 0
for i in l1:
assert i == outer
outer_seen.append(i)
inner = 0
for i in l2:
assert i == inner
inner += 1
outer += 1
assert outer_seen == l1
def nested_yield() -> Generator:
for i in range(3):
for i in range(3):
yield i
yield i
[file driver.py]
from native import nested_enumerate, nested_range, nested_list, nested_yield
nested_enumerate()
nested_range()
nested_list()
gen = nested_yield()
for k in range(12):
assert next(gen) == k % 4
[out]
[case testForIterable]
from typing import Iterable, Dict, Any, Tuple
def iterate_over_any(a: Any) -> None:
for element in a:
print(element)
def iterate_over_iterable(iterable: Iterable[T]) -> None:
for element in iterable:
print(element)
def iterate_and_delete(d: Dict[int, int]) -> None:
for key in d:
d.pop(key)
def sum_over_values(d: Dict[int, int]) -> int:
s = 0
for key in d:
s = s + d[key]
return s
def sum_over_even_values(d: Dict[int, int]) -> int:
s = 0
for key in d:
if d[key] % 2:
continue
s = s + d[key]
return s
def sum_over_two_values(d: Dict[int, int]) -> int:
s = 0
i = 0
for key in d:
if i == 2:
break
s = s + d[key]
i = i + 1
return s
def iterate_over_tuple(iterable: Tuple[int, int, int]) -> None:
for element in iterable:
print(element)
[file driver.py]
from native import iterate_over_any, iterate_over_iterable, iterate_and_delete, sum_over_values, sum_over_even_values, sum_over_two_values, iterate_over_tuple
import traceback
def broken_generator(n):
num = 0
while num < n:
yield num
num += 1
raise Exception('Exception Manually Raised')
d = {1:1, 2:2, 3:3, 4:4, 5:5}
print(sum_over_values(d))
print(sum_over_even_values(d))
print(sum_over_two_values(d))
try:
iterate_over_any(5)
except TypeError:
traceback.print_exc()
try:
iterate_over_iterable(broken_generator(5))
except Exception:
traceback.print_exc()
try:
iterate_and_delete(d)
except RuntimeError:
traceback.print_exc()
iterate_over_tuple((1, 2, 3))
[out]
Traceback (most recent call last):
File "driver.py", line 16, in <module>
iterate_over_any(5)
File "native.py", line 3, in iterate_over_any
for element in a:
TypeError: 'int' object is not iterable
Traceback (most recent call last):
File "driver.py", line 20, in <module>
iterate_over_iterable(broken_generator(5))
File "native.py", line 7, in iterate_over_iterable
for element in iterable:
File "driver.py", line 8, in broken_generator
raise Exception('Exception Manually Raised')
Exception: Exception Manually Raised
Traceback (most recent call last):
File "driver.py", line 24, in <module>
iterate_and_delete(d)
File "native.py", line 11, in iterate_and_delete
for key in d:
RuntimeError: dictionary changed size during iteration
15
6
3
0
1
2
3
4
1
2
3
[case testContinueFor]
def f() -> None:
for n in range(5):
continue
[file driver.py]
from native import f
f()
[case testMultipleVarsWithLoops]
# Test comprehensions and for loops with multiple index variables
l = [(1, 2, 'a'), (3, 4, 'b'), (5, 6, 'c')]
l2 = [str(a*100+b)+' '+c for a, b, c in l]
l3 = []
for a, b, c in l:
l3.append(str(a*1000+b)+' '+c)
[file driver.py]
from native import l, l2, l3
for a in l2 + l3:
print(a)
[out]
102 a
304 b
506 c
1002 a
3004 b
5006 c
[case testForZipAndEnumerate]
from typing import Iterable, List, Any
def f(a: Iterable[int], b: List[int]) -> List[Any]:
res = []
for (x, y), z in zip(enumerate(a), b):
res.append((x, y, z))
return res
def g(a: Iterable[int], b: Iterable[str]) -> List[Any]:
res = []
for x, (y, z) in enumerate(zip(a, b)):
res.append((x, y, z))
return res
[file driver.py]
from native import f, g
assert f([6, 7], [8, 9]) == [(0, 6, 8), (1, 7, 9)]
assert g([6, 7], ['a', 'b']) == [(0, 6, 'a'), (1, 7, 'b')]
assert f([6, 7], [8]) == [(0, 6, 8)]
assert f([6], [8, 9]) == [(0, 6, 8)]
[case testIterTypeTrickiness]
# Test inferring the type of a for loop body doesn't cause us grief
# Extracted from somethings that broke in mypy
from typing import Optional
# really I only care that this one build
def foo(x: object) -> None:
if isinstance(x, dict):
for a in x:
pass
def bar(x: Optional[str]) -> None:
vars = (
("a", 'lol'),
("b", 'asdf'),
("lol", x),
("an int", 10),
)
for name, value in vars:
pass
[file driver.py]
from native import bar
bar(None)
[case testRangeObject]
from typing import Any
def f(x: range) -> int:
sum = 0
for i in x:
sum += i
return sum
def test_range_object() -> None:
r1 = range(4, 12, 2)
tmp_list = [x for x in r1]
assert tmp_list == [4, 6, 8, 10]
assert f(r1) == 28
r2: Any = range(10)
assert f(r2) == 45
r3: Any = 'x'
try:
f(r3)
except TypeError as e:
assert "range object expected; got str" in str(e)
try:
ff: Any = f
ff(r3)
except TypeError as e:
assert "range object expected; got str" in str(e)
try:
r4 = range(4, 12, 0)
except ValueError as e:
assert "range() arg 3 must not be zero" in str(e)

View File

@@ -0,0 +1,283 @@
[case testTheBigMatch_python3_10]
class Person:
__match_args__ = ("name", "age")
name: str
age: int
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def __str__(self) -> str:
return f"Person(name={self.name!r}, age={self.age})"
def f(x: object) -> None:
match x:
case 123:
print("test 1")
case 456 | 789:
print("test 2")
case True | False | None:
print("test 3")
case Person("bob" as name, age):
print(f"test 4 ({name=}, {age=})")
case num if num == 5:
print("test 5")
case 6 as num:
print(f"test 6 ({num=})")
case (7 | "7") as value:
print(f"test 7 ({value=})")
case Person("alice", age=123):
print("test 8")
case Person("charlie", age=123 | 456):
print("test 9")
case Person("dave", 123) as dave:
print(f"test 10 {dave}")
case {"test": 11}:
print("test 11")
case {"test": 12, **rest}:
print(f"test 12 (rest={rest})")
case {}:
print("test map final")
case ["test", 13]:
print("test 13")
case ["test", 13, _]:
print("test 13b")
case ["test", 14, *_]:
print("test 14")
# TODO: Fix "rest" being used here coliding with above "rest"
case ["test", 15, *rest2]:
print(f"test 15 ({rest2})")
case ["test", *rest3, 16]:
print(f"test 16 ({rest3})")
case [*rest4, "test", 17]:
print(f"test 17 ({rest4})")
case [*rest4, "test", 18, "some", "fluff"]:
print(f"test 18 ({rest4})")
case str("test 19"):
print("test 19")
case str(test_20) if test_20.startswith("test 20"):
print(f"test 20 ({test_20[7:]!r})")
case ("test 21" as value) | ("test 21 as well" as value):
print(f"test 21 ({value[7:]!r})")
case []:
print("test sequence final")
case _:
print("test final")
[file driver.py]
from native import f, Person
# test 1
f(123)
# test 2
f(456)
f(789)
# test 3
f(True)
f(False)
f(None)
# test 4
f(Person("bob", 123))
# test 5
f(5)
# test 6
f(6)
# test 7
f(7)
f("7")
# test 8
f(Person("alice", 123))
# test 9
f(Person("charlie", 123))
f(Person("charlie", 456))
# test 10
f(Person("dave", 123))
# test 11
f({"test": 11})
f({"test": 11, "some": "key"})
# test 12
f({"test": 12})
f({"test": 12, "key": "value"})
f({"test": 12, "key": "value", "abc": "123"})
# test map final
f({})
# test 13
f(["test", 13])
# test 13b
f(["test", 13, "fail"])
# test 14
f(["test", 14])
f(["test", 14, "something"])
# test 15
f(["test", 15])
f(["test", 15, "something"])
# test 16
f(["test", 16])
f(["test", "filler", 16])
f(["test", "more", "filler", 16])
# test 17
f(["test", 17])
f(["stuff", "test", 17])
f(["more", "stuff", "test", 17])
# test 18
f(["test", 18, "some", "fluff"])
f(["stuff", "test", 18, "some", "fluff"])
f(["more", "stuff", "test", 18, "some", "fluff"])
# test 19
f("test 19")
# test 20
f("test 20")
f("test 20 something else")
# test 21
f("test 21")
f("test 21 as well")
# test sequence final
f([])
# test final
f("")
[out]
test 1
test 2
test 2
test 3
test 3
test 3
test 4 (name='bob', age=123)
test 5
test 6 (num=6)
test 7 (value=7)
test 7 (value='7')
test 8
test 9
test 9
test 10 Person(name='dave', age=123)
test 11
test 11
test 12 (rest={})
test 12 (rest={'key': 'value'})
test 12 (rest={'key': 'value', 'abc': '123'})
test map final
test 13
test 13b
test 14
test 14
test 15 ([])
test 15 (['something'])
test 16 ([])
test 16 (['filler'])
test 16 (['more', 'filler'])
test 17 ([])
test 17 (['stuff'])
test 17 (['more', 'stuff'])
test 18 ([])
test 18 (['stuff'])
test 18 (['more', 'stuff'])
test 19
test 20 ('')
test 20 (' something else')
test 21 ('')
test 21 (' as well')
test sequence final
test final
[case testCustomMappingAndSequenceObjects_python3_10]
def f(x: object) -> None:
match x:
case {"key": "value", **rest}:
print(rest, type(rest))
case [1, 2, *rest2]:
print(rest2, type(rest2))
[file driver.py]
from collections.abc import Mapping, Sequence
from native import f
class CustomMapping(Mapping):
inner: dict
def __init__(self, inner: dict) -> None:
self.inner = inner
def __getitem__(self, key):
return self.inner[key]
def __iter__(self):
return iter(self.inner)
def __len__(self) -> int:
return len(self.inner)
class CustomSequence(Sequence):
inner: list
def __init__(self, inner: list) -> None:
self.inner = inner
def __getitem__(self, index: int) -> None:
return self.inner[index]
def __len__(self) -> int:
return len(self.inner)
mapping = CustomMapping({"key": "value", "some": "data"})
sequence = CustomSequence([1, 2, 3])
f(mapping)
f(sequence)
[out]
{'some': 'data'} <class 'dict'>
[3] <class 'list'>

View File

@@ -0,0 +1,106 @@
# Test cases for the math module (compile and run)
[case testMathOps]
from typing import Any, Callable
from typing_extensions import Final
import math
from math import pi, e, tau, inf, nan
from testutil import assertRaises, float_vals, assertDomainError, assertMathRangeError
pymath: Any = math
def validate_one_arg(test: Callable[[float], float], validate: Callable[[float], float]) -> None:
"""Ensure that test and validate behave the same for various float args."""
for x in float_vals:
try:
expected = validate(x)
except Exception as e:
try:
test(x)
assert False, f"no exception raised for {x!r}, expected {e!r}"
except Exception as e2:
assert repr(e) == repr(e2), f"actual for {x!r}: {e2!r}, expected: {e!r}"
continue
actual = test(x)
assert repr(actual) == repr(expected), (
f"actual for {x!r}: {actual!r}, expected {expected!r}")
def validate_two_arg(test: Callable[[float, float], float],
validate: Callable[[float, float], float]) -> None:
"""Ensure that test and validate behave the same for various float args."""
for x in float_vals:
for y in float_vals:
args = f"({x!r}, {y!r})"
try:
expected = validate(x, y)
except Exception as e:
try:
test(x, y)
assert False, f"no exception raised for {args}, expected {e!r}"
except Exception as e2:
assert repr(e) == repr(e2), f"actual for {args}: {e2!r}, expected: {e!r}"
continue
try:
actual = test(x, y)
except Exception as e:
assert False, f"no exception expected for {args}, got {e!r}"
assert repr(actual) == repr(expected), (
f"actual for {args}: {actual!r}, expected {expected!r}")
def test_sqrt() -> None:
validate_one_arg(lambda x: math.sqrt(x), pymath.sqrt)
def test_sin() -> None:
validate_one_arg(lambda x: math.sin(x), pymath.sin)
def test_cos() -> None:
validate_one_arg(lambda x: math.cos(x), pymath.cos)
def test_tan() -> None:
validate_one_arg(lambda x: math.tan(x), pymath.tan)
def test_exp() -> None:
validate_one_arg(lambda x: math.exp(x), pymath.exp)
def test_log() -> None:
validate_one_arg(lambda x: math.log(x), pymath.log)
def test_floor() -> None:
validate_one_arg(lambda x: math.floor(x), pymath.floor)
def test_ceil() -> None:
validate_one_arg(lambda x: math.ceil(x), pymath.ceil)
def test_fabs() -> None:
validate_one_arg(lambda x: math.fabs(x), pymath.fabs)
def test_pow() -> None:
validate_two_arg(lambda x, y: math.pow(x, y), pymath.pow)
def test_copysign() -> None:
validate_two_arg(lambda x, y: math.copysign(x, y), pymath.copysign)
def test_isinf() -> None:
for x in float_vals:
assert repr(math.isinf(x)) == repr(pymath.isinf(x))
def test_isnan() -> None:
for x in float_vals:
assert repr(math.isnan(x)) == repr(pymath.isnan(x))
def test_pi_is_inlined_correctly() -> None:
assert math.pi == pi == 3.141592653589793
def test_e_is_inlined_correctly() -> None:
assert math.e == e == 2.718281828459045
def test_tau_is_inlined_correctly() -> None:
assert math.tau == tau == 6.283185307179586
def test_inf_is_inlined_correctly() -> None:
assert math.inf == inf == float("inf")
def test_nan_is_inlined_correctly() -> None:
assert math.isnan(math.nan)
assert math.isnan(nan)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,887 @@
-- These test cases compile two or more modules at a time.
-- Any file prefixed with "other" is compiled.
--
-- Note that these are run in three compilation modes: regular,
-- multi-file and separate. See the docstrings of
-- mypyc.test.test_run.TestRunMultiFile and
-- mypyc.test.test_run.TestRunSeparate for more information.
--
-- Some of these files perform multiple incremental runs. See
-- test-data/unit/check-incremental.test for more information
-- about how this is specified (e.g. .2 file name suffixes).
[case testMultiModulePackage]
from p.other import g, _i as i
def f(x: int) -> int:
from p.other import h
return i(h(g(x + 1)))
[file p/__init__.py]
[file p/other.py]
def g(x: int) -> int:
return x + 2
def h(x: int) -> int:
return x + 1
def _i(x: int) -> int:
return x + 3
[file driver.py]
import native
from native import f
from p.other import g
assert f(3) == 10
assert g(2) == 4
try:
f(1.1)
except TypeError:
pass
else:
assert False
try:
g(1.1)
except TypeError:
pass
else:
assert False
[case testMultiModuleFastpaths]
[file other_main.py]
[file other_main.py.2]
from other_b import A, func
class B(A):
pass
def test() -> None:
a = A()
assert func() == 12
assert a.method() == "test"
test()
[file other_b.py]
class A:
def method(self) -> str:
return "test"
def func() -> int:
return 12
# Remove all the methods and functions from globals to ensure that
# they get called via the fastpaths even when doing incremental
# compilation.
setattr(A, 'method', None)
setattr(A, '__init__', None)
globals()['func'] = None
globals()['A'] = None
[file driver.py]
import other_main
[case testMultiModuleSameNames]
# Use same names in both modules
import other
def f() -> int:
return 0
class C:
x: int
def __init__(self) -> None:
self.x = 1
def f(self, x: int) -> int:
return self.x + x
class D(C): pass
def g(x: 'other.C') -> None:
pass
[file other.py]
def f(x: int) -> int:
return x + 1
class C:
x: int
def __init__(self) -> None:
self.x = 2
def f(self, x: int) -> int:
return self.x + x + 1
class D(C): pass
[file driver.py]
import native, other
assert native.f() == 0
assert other.f(3) == 4
c1 = native.C()
c1.x += 3
c2 = other.C()
c2.x += 6
assert c1.f(9) == 1 + 3 + 9
assert c2.f(7) == 2 + 6 + 7 + 1
assert isinstance(native.D(), native.C)
assert isinstance(other.D(), other.C)
assert not isinstance(native.D(), other.C)
assert not isinstance(other.D(), native.C)
[case testMultiModuleInitializeImportedModules]
from other import f
def g() -> int:
return f(1)
[file other.py]
def f(x: int) -> int:
return x + 4
[file driver.py]
import sys
assert 'other' not in sys.modules
from native import g
assert 'other' in sys.modules
assert g() == 5
f = sys.modules['other'].f
assert f(1) == 5
try:
f(1.1)
except TypeError:
pass
else:
assert False
[case testMultiModuleImportClass]
from typing import cast
from other import C, a_global
class D(C):
def __init__(self, x: int) -> None:
self.x = x
def f(c: C) -> int:
d = D(3)
o: object = c
c = cast(C, o)
return a_global + c.x + c.f() + d.x + d.f() + 1
[file other.py]
from typing_extensions import Final
a_global: Final = int('5')
class C:
x: int
def __init__(self, x: int) -> None:
self.x = x
def __hash__(self) -> int:
return self.x
def __str__(self) -> str:
return str(self.x)
def f(self) -> int:
return 2
def check(self) -> None:
assert isinstance(self, C)
[file driver.py]
from native import f, D
from other import C
c = C(4)
assert f(c) == 5 + 4 + 2 + 3 + 2 + 1
assert str(D(10)) == '10'
assert hash(10) == 10
try:
f(1)
except TypeError:
pass
else:
assert False
assert isinstance(D(10), C)
c.check()
D(10).check()
[case testMultiModuleSpecialize]
from other import A
class B(A):
def foo(self, x: object) -> int:
print(2)
return id(x)
[file other.py]
class A:
def foo(self, x: int) -> object:
print(1)
return str(x)
def use_a(x: A, y: int) -> object:
return x.foo(y)
[file driver.py]
from native import B
from other import A, use_a
a = A()
b = B()
o = object()
i = 10
assert a.foo(10) == '10'
assert b.foo(o) == id(o)
assert use_a(a, 10) == '10'
assert use_a(b, i) == id(i)
[out]
1
2
1
2
[case testMultiModuleLiterals]
from other import gs, gi, gf
def fs() -> str:
return 'f' + gs()
def fi() -> int:
return 10001000100010001000 + gi()
def ff() -> float:
return 2.0 + gf()
[file other.py]
def gi() -> int:
return 20001000100010001000
def gs() -> str:
return 'g'
def gf() -> float:
return 3.0
[file driver.py]
from native import fs, fi, ff
assert fs() == 'fg'
assert fi() == 30002000200020002000
assert ff() == 5.0
[case testMultiModuleTraceback]
from other import fail2
def fail() -> None:
fail2()
[file other.py]
def fail2() -> None:
x = [1]
x[2] = 2
[file driver.py]
import traceback
import sys
import native
import other
try:
other.fail2()
except IndexError:
tb = sys.exc_info()[2]
assert tb.tb_next.tb_frame.f_globals is other.__dict__
traceback.print_exc()
try:
native.fail()
except IndexError:
tb = sys.exc_info()[2]
assert tb.tb_next.tb_frame.f_globals is native.__dict__
traceback.print_exc()
[out]
Traceback (most recent call last):
File "driver.py", line 6, in <module>
other.fail2()
File "other.py", line 3, in fail2
x[2] = 2
IndexError: list assignment index out of range
Traceback (most recent call last):
File "driver.py", line 12, in <module>
native.fail()
File "native.py", line 4, in fail
fail2()
File "other.py", line 3, in fail2
x[2] = 2
IndexError: list assignment index out of range
[case testMultiModuleCycle]
if False:
from typing import Final
import other
x = int('0') # type: Final
def f1() -> int:
return other.f2() + other.x
def f3() -> int:
return 5
[file other.py]
if False:
from typing import Final
import native
x = int('0') # type: Final
def f2() -> int:
return native.f3() + native.x
[file driver.py]
from native import f1
assert f1() == 5
[case testMultiModuleCycleWithClasses]
import other
class D: pass
def f() -> other.C:
return other.C()
def g(c: other.C) -> D:
return c.d
[file other.py]
import native
class C:
def __init__(self) -> None:
self.d = native.D()
def h(d: native.D) -> None:
pass
[file driver.py]
from native import f, g
from other import C, h
c = f()
assert isinstance(c, C)
assert g(c) is c.d
h(c.d)
try:
g(1)
except TypeError:
pass
else:
assert False
try:
h(1)
except TypeError:
pass
else:
assert False
[case testMultiModuleCycleWithInheritance]
import other
class Deriv1(other.Base1):
def __init__(self) -> None:
super().__init__()
class Base2:
y: int
def __init__(self) -> None:
self.y = 2
[file other.py]
from typing import Tuple
import native
class Base1:
a: Tuple[int, int]
x: int
def __init__(self) -> None:
self.x = 1
def make_2() -> native.Base2:
return native.Base2()
[file driver.py]
from native import Deriv1
from other import make_2
a = Deriv1()
assert a.x == 1
b = make_2()
assert b.y == 2
[case testMultiModuleTraitInheritance]
from other import Base1, Base2
class Deriv1(Base1, Base2):
pass
[file other.py]
from mypy_extensions import trait
@trait
class Base1:
def foo(self) -> int: return 10
@trait
class Base2:
def bar(self) -> int: return 12
[file driver.py]
from native import Deriv1
a = Deriv1()
assert a.foo() == 10 and a.bar() == 12
[case testImportCycleWithNonCompiledModule]
import m
class C: pass
def f1() -> int:
m.D()
return m.f2()
def f3() -> int:
return 2
[file m.py]
# This module is NOT compiled
import native
class D: pass
def f2() -> int:
native.C()
return native.f3()
[file driver.py]
from native import f1
assert f1() == 2
[case testImportCycleWithTopLevelStatements]
import other
x = 1
print(x)
[file other.py]
import native
x = 2
print(x)
[file driver.py]
import other
print('-')
import native
print('>', native.x)
print('>', other.x)
[out]
1
2
-
> 1
> 2
[case testMultiModuleCycleIfMypy1]
from other import foo, bar
class Foo:
def foo(self) -> None:
foo(self)
class Bar:
def bar(self) -> None:
bar(self)
[file other.py]
from typing_extensions import TYPE_CHECKING
MYPY = False
if MYPY:
from native import Foo
if TYPE_CHECKING:
from native import Bar
def foo(x: 'Foo') -> None:
pass
def bar(x: 'Bar') -> None:
pass
[file driver.py]
from native import Foo, Bar
Foo().foo()
Bar().bar()
[case testMultiModuleCycleIfMypy2]
MYPY = False
if MYPY:
from other import C
class D:
def __init__(self) -> None:
self.y = 1
def f(c: 'C') -> int:
return c.x
[file other.py]
from typing_extensions import TYPE_CHECKING
if TYPE_CHECKING:
from native import D
class C:
def __init__(self) -> None:
self.x = 2
def g(d: 'D') -> int:
return d.y
[file driver.py]
from native import f, D
from other import g, C
assert f(C()) == 2
assert g(D()) == 1
try:
f(D())
except TypeError:
pass
else:
assert False
try:
g(C())
except TypeError:
pass
else:
assert False
[case testMultiModuleRelative]
from package.a import f
[file package/__init__.py]
[file package/a.py]
from . import b
from .c import c3
def f() -> None:
print("Hello " + b.b2())
print("Hello " + c3())
[file package/b.py]
def b2() -> str:
return "moon!"
[file package/c.py]
def c3() -> str:
return "sun!"
[file driver.py]
from native import f
f()
[out]
Hello moon!
Hello sun!
[case testMultiModuleCrash]
b = False
if b:
import other
def foo() -> None:
try:
other.x
except:
pass
else:
assert False
[file other.py]
x = 10
[file driver.py]
from native import foo
foo()
[case testTrivialIncremental]
# separate: [(["other.py", "other_b.py"], "stuff")]
from other import x
from other_b import z
y = x + z
[file other.py]
x = 1
[file other.py.2]
x = 2
[file other_b.py]
z = 1
[file driver.py]
from native import y
print(y)
[out]
2
[out2]
3
[rechecked other, other_b]
[case testIncrementalCompilation1]
import non_native
from other_a import A
from other_b import z
a = A()
assert a.y == z
assert non_native.foo() == 0
[file other_a.py]
from other_b import z
from typing import Iterable
class A:
def __init__(self) -> None:
self.y = z
[file other_a.py.2]
from other_b import z
from typing import Iterable
class A:
def __init__(self) -> None:
self.x = 'test'
self.y = z
[file other_b.py]
import other_a
z = 10
def foo() -> 'other_a.A':
return other_a.A()
[file other_b.py.3]
import other_a
z = 20
def foo() -> 'other_a.A':
return other_a.A()
[file non_native.py]
import other_a
def foo() -> int:
return 0
[file non_native.py.4]
import other_a
def foo() -> float:
return 0
[file driver.py]
from native import a
print(a.y, getattr(a, 'x', None))
[out]
10 None
[out2]
10 test
[out3]
20 test
[out4]
20 test
[rechecked other_a, other_b, native, non_native]
[rechecked2 other_a, other_b]
[rechecked3 native, non_native]
-- This one tests a group that is not an SCC.
[case testIncrementalCompilation2]
# separate: [(["other_a.py", "other_b.py"], "stuff")]
from other_a import A
from other_b import z
a = A()
assert a.y == z
[file other_a.py]
from other_b import z
class A:
def __init__(self) -> None:
self.y = z
[file other_a.py.2]
from other_b import z
class A:
def __init__(self) -> None:
self.x = 'test'
self.y = z
[file other_b.py]
z = 10
[file driver.py]
from native import a
print(a.y, getattr(a, 'x', None))
[out]
10 None
[out2]
10 test
[rechecked other_a, other_b, native]
[case testIncrementalCompilation3]
from other import X
Y = X
def foo() -> int:
return X
[file other.py]
from typing_extensions import Final
X: Final = 10
[file other.py.2]
from typing_extensions import Final
X: Final = 20
[file driver.py]
import native
import other
assert native.Y == other.X
assert native.foo() == other.X
[rechecked native, other]
-- This one tests a group changing
[case testIncrementalCompilation4]
# separate: [(["other_a.py", "other_b.py"], "stuff")]
# separate2: []
from other_a import A
from other_b import z
a = A()
assert a.y == z
[file other_a.py]
from other_b import z
class A:
def __init__(self) -> None:
self.y = z
[file other_b.py]
z = 10
[file wtvr.py.2]
[file driver.py]
from native import a
print(a.y, getattr(a, 'x', None))
[out]
10 None
[out2]
10 None
[rechecked other_a, other_b, native]
-- This one tests cases where other modules *do not* need rechecked
[case testIncrementalCompilation5]
import other_a
[file other_a.py]
from other_b import f
assert f(10) == 20
[file other_a.py.2]
from other_b import f
assert f(20) == 40
[file other_b.py]
def f(x: int) -> int:
return x * 2
[file driver.py]
import native
[rechecked other_a]
-- Delete one of the C files and make sure this forces recompilation
[case testIncrementalCompilation6]
import other_a
assert other_a.foo() == 10
[file other_a.py]
def foo() -> int: return 10
[file build/__native_other_a.c]
[delete build/__native_other_a.c.2]
[file driver.py]
import native
[rechecked native, other_a]
[case testSeparateCompilationWithUndefinedAttribute]
from other_a import A
def f() -> None:
a = A()
if a.x == 5:
print(a.y)
print(a.m())
else:
assert a.x == 6
try:
print(a.y)
except AttributeError:
print('y undefined')
else:
assert False
try:
print(a.m())
except AttributeError:
print('y undefined')
else:
assert False
[file other_a.py]
from other_b import B
class A(B):
def __init__(self) -> None:
self.y = 9
[file other_a.py.2]
from other_b import B
class A(B):
x = 6
def __init__(self) -> None:
pass
[file other_b.py]
class B:
x = 5
def __init__(self) -> None:
self.y = 7
def m(self) -> int:
return self.y
[file driver.py]
from native import f
f()
[rechecked native, other_a]
[out]
9
9
[out2]
y undefined
y undefined
[case testIncrementalCompilationWithDeletable]
import other_a
[file other_a.py]
from other_b import C
[file other_a.py.2]
from other_b import C
c = C()
print(getattr(c, 'x', None))
del c.x
print(getattr(c, 'x', None))
[file other_b.py]
class C:
__deletable__ = ['x']
def __init__(self) -> None:
self.x = 0
[file driver.py]
import native
[out]
[out2]
0
None

View File

@@ -0,0 +1,138 @@
-- Some test code that tries to simulate important/interesting parts of mypy itself!
[case testSimulateMypy]
from mypy_extensions import trait
from typing import List, TypeVar, cast, Generic
from abc import abstractmethod
import other_strconv as strconv
#from other_visitor import ExpressionVisitor, StatementVisitor, NodeVisitor
import other_visitor as visitor
T = TypeVar('T')
############ nodes.py
class Context:
def __init__(self) -> None:
self.line = -1
def set_line(self, line: int) -> None:
self.line = line
class Node(Context):
def accept(self, visitor: visitor.NodeVisitor[T]) -> T: return cast(T, None)
def to_str(self) -> str:
return self.accept(strconv.StrConv())
@trait
class Statement(Node):
def accept(self, visitor: visitor.StatementVisitor[T]) -> T: return cast(T, None)
@trait
class Expression(Node):
def accept(self, visitor: visitor.ExpressionVisitor[T]) -> T: return cast(T, None)
@trait
class SymbolNode(Node):
"""Nodes that can be stored in a symbol table."""
@abstractmethod
def name(self) -> str: return cast(str, None)
class FuncBase(Node):
def __init__(self) -> None:
super().__init__()
self.is_static = False
class Block(Statement):
def __init__(self, stmts: List[Statement]) -> None:
self.stmts = stmts
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
return visitor.visit_block(self)
class ExprStmt(Statement):
def __init__(self, expr: Expression) -> None:
self.expr = expr
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
return visitor.visit_expr_stmt(self)
class FuncItem(FuncBase):
def __init__(self, body: Block) -> None:
self.body = body
class FuncDef(FuncItem, SymbolNode, Statement):
def __init__(self, name: str, body: Block) -> None:
super().__init__(body)
self._name = name
def accept(self, visitor: visitor.StatementVisitor[T]) -> T:
return visitor.visit_func_def(self)
def name(self) -> str:
return self._name
class LambdaExpr(FuncItem, Expression):
def accept(self, visitor: visitor.ExpressionVisitor[T]) -> T:
return visitor.visit_lambda_expr(self)
def lol(x: Statement) -> int:
return x.line
[file other_visitor.py]
from mypy_extensions import trait
from typing import TypeVar, cast, Generic
from abc import abstractmethod
import native as nodes
T = TypeVar('T')
@trait
class ExpressionVisitor(Generic[T]):
@abstractmethod
def visit_lambda_expr(self, o: 'nodes.LambdaExpr') -> T:
return cast(T, None)
@trait
class StatementVisitor(Generic[T]):
@abstractmethod
def visit_block(self, o: 'nodes.Block') -> T:
return cast(T, None)
@abstractmethod
def visit_func_def(self, o: 'nodes.FuncDef') -> T:
return cast(T, None)
@abstractmethod
def visit_expr_stmt(self, o: 'nodes.ExprStmt') -> T:
return cast(T, None)
@trait
class NodeVisitor(Generic[T], ExpressionVisitor[T], StatementVisitor[T]):
pass
[file other_strconv.py]
from typing import List
import native as nodes
from other_visitor import NodeVisitor
class StrConv(NodeVisitor[str]):
def visit_block(self, b: nodes.Block) -> str:
# we really need comprehensions!
# TODO: PartialType unsupported
things = [] # type: List[str]
for s in b.stmts:
things.append(s.accept(self))
return "{" + "; ".join(things) + "}"
def visit_func_def(self, f: nodes.FuncDef) -> str:
return "def " + f.name() + "(): " + f.body.accept(self)
def visit_expr_stmt(self, e: nodes.ExprStmt) -> str:
return e.expr.accept(self)
def visit_lambda_expr(self, b: nodes.LambdaExpr) -> str:
return "(fn: " + b.body.accept(self) + ")"
[file driver.py]
from native import *
block = Block([Block([]), ExprStmt(LambdaExpr(Block([])))])
fn = FuncDef('test', block)
assert fn.to_str() == "def test(): {{}; (fn: {})}"

View File

@@ -0,0 +1,375 @@
# Test cases for misc primitives (compile and run)
#
# Please only add tests that don't have an obvious place in type-specific test
# files such as run-strings.test, run-lists.test, etc.
[case testGenericEquality]
def eq(a: object, b: object) -> bool:
if a == b:
return True
else:
return False
def ne(a: object, b: object) -> bool:
if a != b:
return True
else:
return False
def f(o: object) -> bool:
if [1, 2] == o:
return True
else:
return False
[file driver.py]
from native import eq, ne, f
assert eq('xz', 'x' + 'z')
assert not eq('x', 'y')
assert not ne('xz', 'x' + 'z')
assert ne('x', 'y')
assert f([1, 2])
assert not f([2, 2])
assert not f(1)
[case testGenericBinaryOps]
from typing import Any
def add(x: Any, y: Any) -> Any:
return x + y
def subtract(x: Any, y: Any) -> Any:
return x - y
def multiply(x: Any, y: Any) -> Any:
return x * y
def floor_div(x: Any, y: Any) -> Any:
return x // y
def true_div(x: Any, y: Any) -> Any:
return x / y
def remainder(x: Any, y: Any) -> Any:
return x % y
def power(x: Any, y: Any) -> Any:
return x ** y
def lshift(x: Any, y: Any) -> Any:
return x << y
def rshift(x: Any, y: Any) -> Any:
return x >> y
def num_and(x: Any, y: Any) -> Any:
return x & y
def num_xor(x: Any, y: Any) -> Any:
return x ^ y
def num_or(x: Any, y: Any) -> Any:
return x | y
def lt(x: Any, y: Any) -> Any:
if x < y:
return True
else:
return False
def le(x: Any, y: Any) -> Any:
if x <= y:
return True
else:
return False
def gt(x: Any, y: Any) -> Any:
if x > y:
return True
else:
return False
def ge(x: Any, y: Any) -> Any:
if x >= y:
return True
else:
return False
def contains(x: Any, y: Any) -> Any:
if x in y:
return True
else:
return False
def identity(x: Any, y: Any) -> Any:
if x is y:
return True
else:
return False
def disidentity(x: Any, y: Any) -> Any:
if x is not y:
return True
else:
return False
def not_eq_cond(a: Any, b: Any) -> bool:
if not (a == b):
return True
else:
return False
def eq2(a: Any, b: Any) -> bool:
return a == b
def slice1(x: Any) -> Any:
return x[:]
def slice2(x: Any, y: Any) -> Any:
return x[y:]
def slice3(x: Any, y: Any) -> Any:
return x[:y]
def slice4(x: Any, y: Any, z: Any) -> Any:
return x[y:z]
def slice5(x: Any, y: Any, z: Any, zz: Any) -> Any:
return x[y:z:zz]
[file driver.py]
from native import *
assert add(5, 6) == 11
assert add('x', 'y') == 'xy'
assert subtract(8, 3) == 5
assert multiply(8, 3) == 24
assert floor_div(8, 3) == 2
assert true_div(7, 2) == 3.5
assert remainder(11, 4) == 3
assert remainder('%.3d', 5) == '005'
assert remainder('%d-%s', (5, 'xy')) == '5-xy'
assert power(3, 4) == 81
assert lshift(5, 3) == 40
assert rshift(41, 3) == 5
assert num_and(99, 56) == 32
assert num_xor(99, 56) == 91
assert num_or(99, 56) == 123
assert lt('a', 'b')
assert not lt('a', 'a')
assert not lt('b', 'a')
assert not gt('a', 'b')
assert not gt('a', 'a')
assert gt('b', 'a')
assert le('a', 'b')
assert le('a', 'a')
assert not le('b', 'a')
assert not ge('a', 'b')
assert ge('a', 'a')
assert ge('b', 'a')
assert contains('x', 'axb')
assert not contains('X', 'axb')
assert contains('x', {'x', 'y'})
a = [1, 3, 5]
assert slice1(a) == a
assert slice1(a) is not a
assert slice2(a, 1) == [3, 5]
assert slice3(a, -1) == [1, 3]
assert slice4(a, 1, -1) == [3]
assert slice5(a, 2, 0, -1) == [5, 3]
o1, o2 = object(), object()
assert identity(o1, o1)
assert not identity(o1, o2)
assert not disidentity(o1, o1)
assert disidentity(o1, o2)
assert eq2('xz', 'x' + 'z')
assert not eq2('x', 'y')
assert not not_eq_cond('xz', 'x' + 'z')
assert not_eq_cond('x', 'y')
[case testGenericMiscOps]
from typing import Any
def neg(x: Any) -> Any:
return -x
def pos(x: Any) -> Any:
return +x
def invert(x: Any) -> Any:
return ~x
def get_item(o: Any, k: Any) -> Any:
return o[k]
def set_item(o: Any, k: Any, v: Any) -> Any:
o[k] = v
[file driver.py]
from native import *
assert neg(6) == -6
assert pos(6) == 6
assert invert(6) == -7
d = {'x': 5}
assert get_item(d, 'x') == 5
set_item(d, 'y', 6)
assert d['y'] == 6
[case testAnyAttributeAndMethodAccess]
from typing import Any, List
class C:
a: int
def m(self, x: int, a: List[int]) -> int:
return self.a + x + a[0]
def get_a(x: Any) -> Any:
return x.a
def set_a(x: Any, y: Any) -> None:
x.a = y
def call_m(x: Any) -> Any:
return x.m(1, [3])
[file driver.py]
from native import C, get_a, set_a, call_m
class D:
def m(self, x, a):
return self.a + x + a[0]
c = C()
c.a = 6
d = D()
d.a = 2
assert get_a(c) == 6
assert get_a(d) == 2
assert call_m(c) == 10
assert call_m(d) == 6
set_a(c, 5)
assert c.a == 5
set_a(d, 4)
assert d.a == 4
try:
get_a(object())
except AttributeError:
pass
else:
assert False
try:
call_m(object())
except AttributeError:
pass
else:
assert False
try:
set_a(object(), 5)
except AttributeError:
pass
else:
assert False
[case testFloat]
def assign_and_return_float_sum() -> float:
f1 = 1.0
f2 = 2.0
f3 = 3.0
return f1 * f2 + f3
def from_int(i: int) -> float:
return float(i)
def to_int(x: float) -> int:
return int(x)
def get_complex() -> complex:
return 5.2j + 3.5 + 1j
[file driver.py]
from native import assign_and_return_float_sum, from_int, to_int, get_complex
sum = 0.0
for i in range(10):
sum += assign_and_return_float_sum()
assert sum == 50.0
assert str(from_int(10)) == '10.0'
assert str(to_int(3.14)) == '3'
assert str(to_int(3)) == '3'
assert get_complex() == 3.5 + 6.2j
[case testDel]
from typing import List
from testutil import assertRaises
def printDict(dict) -> None:
l = list(dict.keys()) # type: List[str]
l.sort()
for key in l:
print(key, dict[key])
print("#########")
def delList() -> None:
l = [1, 2, 3]
print(tuple(l))
del l[1]
print(tuple(l))
def delDict() -> None:
d = {"one":1, "two":2}
printDict(d)
del d["one"]
printDict(d)
def delListMultiple() -> None:
l = [1, 2, 3, 4, 5, 6, 7]
print(tuple(l))
del l[1], l[2], l[3]
print(tuple(l))
def delDictMultiple() -> None:
d = {"one":1, "two":2, "three":3, "four":4}
printDict(d)
del d["two"], d["four"]
printDict(d)
class Dummy():
__deletable__ = ('x', 'y')
def __init__(self, x: int, y: int) -> None:
self.x = x
self.y = y
def delAttribute() -> None:
dummy = Dummy(1, 2)
del dummy.x
with assertRaises(AttributeError):
dummy.x
def delAttributeMultiple() -> None:
dummy = Dummy(1, 2)
del dummy.x, dummy.y
with assertRaises(AttributeError):
dummy.x
with assertRaises(AttributeError):
dummy.y
def delLocal(b: bool) -> int:
dummy = 10
if b:
del dummy
return dummy
def delLocalLoop() -> None:
# Try deleting a local in a loop to make sure the control flow analysis works
dummy = 1
for i in range(10):
print(dummy)
dummy *= 2
if i == 4:
del dummy
global_var = 10
del global_var
[file driver.py]
from native import (
delList, delDict, delListMultiple, delDictMultiple, delAttribute,
delAttributeMultiple, delLocal, delLocalLoop,
)
import native
from testutil import assertRaises
delList()
delDict()
delListMultiple()
delDictMultiple()
delAttribute()
delAttributeMultiple()
with assertRaises(AttributeError):
native.global_var
with assertRaises(NameError, 'local variable "dummy" referenced before assignment'):
delLocal(True)
assert delLocal(False) == 10
with assertRaises(NameError, 'local variable "dummy" referenced before assignment'):
delLocalLoop()
[out]
(1, 2, 3)
(1, 3)
one 1
two 2
#########
two 2
#########
(1, 2, 3, 4, 5, 6, 7)
(1, 3, 5, 7)
four 4
one 1
three 3
two 2
#########
one 1
three 3
#########
1
2
4
8
16

View File

@@ -0,0 +1,159 @@
-- Test cases for Python 3.7 features
[case testRunDataclass]
import dataclasses
from dataclasses import dataclass, field
from typing import Set, FrozenSet, List, Callable, Any
@dataclass
class Person1:
age : int
name : str
def __bool__(self) -> bool:
return self.name == 'robot'
def testBool(p: Person1) -> bool:
if p:
return True
else:
return False
@dataclass
class Person1b(Person1):
id: str = '000'
@dataclass
class Person2:
age : int
name : str = field(default='robot')
@dataclasses.dataclass
class Person2b:
age : int
name : str = dataclasses.field(default='robot')
@dataclass(order = True)
class Person3:
age : int = field(default = 6)
friendIDs : List[int] = field(default_factory = list)
def get_age(self) -> int:
return (self.age)
def set_age(self, new_age : int) -> None:
self.age = new_age
def add_friendID(self, fid : int) -> None:
self.friendIDs.append(fid)
def get_friendIDs(self) -> List[int]:
return self.friendIDs
def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]:
def f(a: Any) -> int:
return g(a) + 1
return f
@dataclass
class Person4:
age : int
_name : str = 'Bot'
@get_next_age
def get_age(self) -> int:
return self.age
@property
def name(self) -> str:
return self._name
@dataclass
class Person5:
weight: float
friends: Set[str] = field(default_factory=set)
parents: FrozenSet[str] = frozenset()
[file other.py]
from native import Person1, Person1b, Person2, Person3, Person4, Person5, testBool
i1 = Person1(age = 5, name = 'robot')
assert i1.age == 5
assert i1.name == 'robot'
assert testBool(i1) == True
assert testBool(Person1(age = 5, name = 'robo')) == False
i1b = Person1b(age = 5, name = 'robot')
assert i1b.age == 5
assert i1b.name == 'robot'
assert testBool(i1b) == True
assert testBool(Person1b(age = 5, name = 'robo')) == False
i1c = Person1b(age = 20, name = 'robot', id = 'test')
assert i1c.age == 20
assert i1c.id == 'test'
i2 = Person2(age = 5)
assert i2.age == 5
assert i2.name == 'robot'
i3 = Person2(age = 5, name = 'new_robot')
assert i3.age == 5
assert i3.name == 'new_robot'
i4 = Person3()
assert i4.age == 6
assert i4.friendIDs == []
i5 = Person3(age = 5)
assert i5.age == 5
assert i5.friendIDs == []
i6 = Person3(age = 5, friendIDs = [1,2,3])
assert i6.age == 5
assert i6.friendIDs == [1,2,3]
assert i6.get_age() == 5
i6.set_age(10)
assert i6.get_age() == 10
i6.add_friendID(4)
assert i6.get_friendIDs() == [1,2,3,4]
i7 = Person4(age = 5)
assert i7.get_age() == 6
i7.age += 3
assert i7.age == 8
assert i7.name == 'Bot'
i8 = Person3(age = 1, friendIDs = [1,2])
i9 = Person3(age = 1, friendIDs = [1,2])
assert i8 == i9
i8.age = 2
assert i8 > i9
assert Person1.__annotations__ == {'age': int, 'name': str}
assert Person2.__annotations__ == {'age': int, 'name': str}
assert Person5.__annotations__ == {'weight': float, 'friends': set,
'parents': frozenset}
[file driver.py]
import sys
# Dataclasses introduced in 3.7
version = sys.version_info[:2]
if version[0] < 3 or version[1] < 7:
exit()
# Run the tests in both interpreted and compiled mode
import other
import other_interpreted
# Test for an exceptional cases
from testutil import assertRaises
from native import Person1, Person1b, Person3
from types import BuiltinMethodType
with assertRaises(TypeError, "missing 1 required positional argument"):
Person1(0)
with assertRaises(TypeError, "missing 2 required positional arguments"):
Person1b()
with assertRaises(TypeError, "int object expected; got str"):
Person1('nope', 'test')
p = Person1(0, 'test')
with assertRaises(TypeError, "int object expected; got str"):
p.age = 'nope'
assert isinstance(Person3().get_age, BuiltinMethodType)

View File

@@ -0,0 +1,88 @@
-- Test cases for Python 3.8 features
[case testWalrus1]
from typing import Optional
def foo(x: int) -> Optional[int]:
if x < 0:
return None
return x
def test(x: int) -> str:
if (n := foo(x)) is not None:
return str(x)
else:
return "<fail>"
[file driver.py]
from native import test
assert test(10) == "10"
assert test(-1) == "<fail>"
[case testWalrus2]
from typing import Optional, Tuple, List
class Node:
def __init__(self, val: int, next: Optional['Node']) -> None:
self.val = val
self.next = next
def pairs(nobe: Optional[Node]) -> List[Tuple[int, int]]:
if nobe is None:
return []
l = []
while next := nobe.next:
l.append((nobe.val, next.val))
nobe = next
return l
def make(l: List[int]) -> Optional[Node]:
cur: Optional[Node] = None
for x in reversed(l):
cur = Node(x, cur)
return cur
[file driver.py]
from native import Node, make, pairs
assert pairs(make([1,2,3])) == [(1,2), (2,3)]
assert pairs(make([1])) == []
assert pairs(make([])) == []
[case testFStrings]
from datetime import datetime
def test_fstring_equal_sign() -> None:
today = datetime(year=2017, month=1, day=27)
assert f"{today=:%B %d, %Y}" == 'today=January 27, 2017' # using date format specifier and debugging
foo = "bar"
assert f"{ foo = }" == " foo = 'bar'" # preserves whitespace
line = "The mill's closed"
assert f"{line = }" == 'line = "The mill\'s closed"'
assert f"{line = :20}" == "line = The mill's closed "
assert f"{line = !r:20}" == 'line = "The mill\'s closed" '
[case testMethodOverrideDefaultPosOnly1]
class Foo:
def f(self, x: int=20, /, *, z: int=10) -> None:
pass
class Bar(Foo):
def f(self, *args: int, **kwargs: int) -> None:
print("stuff", args, kwargs)
z: Foo = Bar()
z.f(1, z=50)
z.f()
z.f(1)
z.f(z=50)
[out]
stuff (1,) {'z': 50}
stuff () {}
stuff (1,) {}
stuff () {'z': 50}

View File

@@ -0,0 +1,150 @@
# Test cases for sets (compile and run)
[case testSets]
from typing import Set, List
def instantiateLiteral() -> Set[int]:
return {1, 2, 3, 5, 8}
def fromIterator() -> List[Set[int]]:
a = set([1, 3, 5])
b = set((1, 3, 5))
c = set({1: '1', 3: '3', 5: '5'})
d = set(x for x in range(1, 6, 2))
e = set((x for x in range(1, 6, 2)))
return [a, b, c, d, e]
def fromIterator2() -> Set[int]:
tmp_list = [1, 2, 3, 4, 5]
return set((x + 1) for x in ((y * 10) for y in (z for z in tmp_list if z < 4)))
def addIncrementing(s : Set[int]) -> None:
for a in [1, 2, 3]:
if a not in s:
s.add(a)
return
def replaceWith1(s : Set[int]) -> None:
s.clear()
s.add(1)
def remove1(s : Set[int]) -> None:
s.remove(1)
def discard1(s: Set[int]) -> None:
s.discard(1)
def pop(s : Set[int]) -> int:
return s.pop()
def update(s: Set[int], x: List[int]) -> None:
s.update(x)
[file driver.py]
from native import instantiateLiteral
from testutil import assertRaises
val = instantiateLiteral()
assert 1 in val
assert 2 in val
assert 3 in val
assert 5 in val
assert 8 in val
assert len(val) == 5
assert val == {1, 2, 3, 5, 8}
s = 0
for i in val:
s += i
assert s == 19
from native import fromIterator
sets = fromIterator()
for s in sets:
assert s == {1, 3, 5}
from native import fromIterator2
s = fromIterator2()
assert s == {11, 21, 31}
from native import addIncrementing
s = set()
addIncrementing(s)
assert s == {1}
addIncrementing(s)
assert s == {1, 2}
addIncrementing(s)
assert s == {1, 2, 3}
from native import replaceWith1
s = {3, 7, 12}
replaceWith1(s)
assert s == {1}
from native import remove1
import traceback
s = {1, 4, 6}
remove1(s)
assert s == {4, 6}
with assertRaises(KeyError, '1'):
remove1(s)
from native import discard1
s = {1, 4, 6}
discard1(s)
assert s == {4, 6}
discard1(s)
assert s == {4, 6}
from native import pop
s = {1, 2, 3}
x = pop(s)
assert len(s) == 2
assert x in [1, 2, 3]
y = pop(s)
assert len(s) == 1
assert y in [1, 2, 3]
assert x != y
z = pop(s)
assert len(s) == 0
assert z in [1, 2, 3]
assert x != z
assert y != z
with assertRaises(KeyError, 'pop from an empty set'):
pop(s)
from native import update
s = {1, 2, 3}
update(s, [5, 4, 3])
assert s == {1, 2, 3, 4, 5}
[case testPrecomputedFrozenSets]
from typing import Any
from typing_extensions import Final
CONST: Final = "CONST"
non_const = "non_const"
def main_set(item: Any) -> bool:
return item in {None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST}
def main_negated_set(item: Any) -> bool:
return item not in {None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST}
def non_final_name_set(item: Any) -> bool:
return item in {non_const}
s = set()
for i in {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}:
s.add(i)
def test_in_set() -> None:
for item in (None, False, 1, 2.0, "3", b"4", 5j, (6,), ((7,),), (), CONST):
assert main_set(item), f"{item!r} should be in set_main"
assert not main_negated_set(item), item
global non_const
assert non_final_name_set(non_const)
non_const = "updated"
assert non_final_name_set("updated")
def test_for_set() -> None:
assert not s ^ {None, False, 1, 2.0, "3", b"4", 5j, (6,), CONST}, s

View File

@@ -0,0 +1,698 @@
# Test cases related to the functools.singledispatch decorator
# Most of these tests are marked as xfails because mypyc doesn't support singledispatch yet
# (These tests will be re-enabled when mypyc supports singledispatch)
[case testSpecializedImplementationUsed]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
@fun.register
def fun_specialized(arg: str) -> bool:
return True
def test_specialize() -> None:
assert fun('a')
assert not fun(3)
[case testSubclassesOfExpectedTypeUseSpecialized]
from functools import singledispatch
class A: pass
class B(A): pass
@singledispatch
def fun(arg) -> bool:
return False
@fun.register
def fun_specialized(arg: A) -> bool:
return True
def test_specialize() -> None:
assert fun(B())
assert fun(A())
[case testSuperclassImplementationNotUsedWhenSubclassHasImplementation]
from functools import singledispatch
class A: pass
class B(A): pass
@singledispatch
def fun(arg) -> bool:
# shouldn't be using this
assert False
@fun.register
def fun_specialized(arg: A) -> bool:
return False
@fun.register
def fun_specialized2(arg: B) -> bool:
return True
def test_specialize() -> None:
assert fun(B())
assert not fun(A())
[case testMultipleUnderscoreFunctionsIsntError]
from functools import singledispatch
@singledispatch
def fun(arg) -> str:
return 'default'
@fun.register
def _(arg: str) -> str:
return 'str'
@fun.register
def _(arg: int) -> str:
return 'int'
# extra function to make sure all 3 underscore functions aren't treated as one OverloadedFuncDef
def a(b): pass
@fun.register
def _(arg: list) -> str:
return 'list'
def test_singledispatch() -> None:
assert fun(0) == 'int'
assert fun('a') == 'str'
assert fun([1, 2]) == 'list'
assert fun({'a': 'b'}) == 'default'
[case testCanRegisterCompiledClasses]
from functools import singledispatch
class A: pass
@singledispatch
def fun(arg) -> bool:
return False
@fun.register
def fun_specialized(arg: A) -> bool:
return True
def test_singledispatch() -> None:
assert fun(A())
assert not fun(1)
[case testTypeUsedAsArgumentToRegister]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
@fun.register(int)
def fun_specialized(arg) -> bool:
return True
def test_singledispatch() -> None:
assert fun(1)
assert not fun('a')
[case testUseRegisterAsAFunction]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
def fun_specialized_impl(arg) -> bool:
return True
fun.register(int, fun_specialized_impl)
def test_singledispatch() -> None:
assert fun(0)
assert not fun('a')
[case testRegisterDoesntChangeFunction]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
@fun.register(int)
def fun_specialized(arg) -> bool:
return True
def test_singledispatch() -> None:
assert fun_specialized('a')
# TODO: turn this into a mypy error
[case testNoneIsntATypeWhenUsedAsArgumentToRegister]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
try:
@fun.register
def fun_specialized(arg: None) -> bool:
return True
except TypeError:
pass
[case testRegisteringTheSameFunctionSeveralTimes]
from functools import singledispatch
@singledispatch
def fun(arg) -> bool:
return False
@fun.register(int)
@fun.register(str)
def fun_specialized(arg) -> bool:
return True
def test_singledispatch() -> None:
assert fun(0)
assert fun('a')
assert not fun([1, 2])
[case testTypeIsAnABC]
from functools import singledispatch
from collections.abc import Mapping
@singledispatch
def fun(arg) -> bool:
return False
@fun.register
def fun_specialized(arg: Mapping) -> bool:
return True
def test_singledispatch() -> None:
assert not fun(1)
assert fun({'a': 'b'})
[case testSingleDispatchMethod-xfail]
from functools import singledispatchmethod
class A:
@singledispatchmethod
def fun(self, arg) -> str:
return 'default'
@fun.register
def fun_int(self, arg: int) -> str:
return 'int'
@fun.register
def fun_str(self, arg: str) -> str:
return 'str'
def test_singledispatchmethod() -> None:
x = A()
assert x.fun(5) == 'int'
assert x.fun('a') == 'str'
assert x.fun([1, 2]) == 'default'
[case testSingleDispatchMethodWithOtherDecorator-xfail]
from functools import singledispatchmethod
class A:
@singledispatchmethod
@staticmethod
def fun(arg) -> str:
return 'default'
@fun.register
@staticmethod
def fun_int(arg: int) -> str:
return 'int'
@fun.register
@staticmethod
def fun_str(arg: str) -> str:
return 'str'
def test_singledispatchmethod() -> None:
x = A()
assert x.fun(5) == 'int'
assert x.fun('a') == 'str'
assert x.fun([1, 2]) == 'default'
[case testSingledispatchTreeSumAndEqual]
from functools import singledispatch
class Tree:
pass
class Leaf(Tree):
pass
class Node(Tree):
def __init__(self, value: int, left: Tree, right: Tree) -> None:
self.value = value
self.left = left
self.right = right
@singledispatch
def calc_sum(x: Tree) -> int:
raise TypeError('invalid type for x')
@calc_sum.register
def _(x: Leaf) -> int:
return 0
@calc_sum.register
def _(x: Node) -> int:
return x.value + calc_sum(x.left) + calc_sum(x.right)
@singledispatch
def equal(to_compare: Tree, known: Tree) -> bool:
raise TypeError('invalid type for x')
@equal.register
def _(to_compare: Leaf, known: Tree) -> bool:
return isinstance(known, Leaf)
@equal.register
def _(to_compare: Node, known: Tree) -> bool:
if isinstance(known, Node):
if to_compare.value != known.value:
return False
else:
return equal(to_compare.left, known.left) and equal(to_compare.right, known.right)
return False
def build(n: int) -> Tree:
if n == 0:
return Leaf()
return Node(n, build(n - 1), build(n - 1))
def test_sum_and_equal():
tree = build(5)
tree2 = build(5)
tree2.right.right.right.value = 10
assert calc_sum(tree) == 57
assert calc_sum(tree2) == 65
assert equal(tree, tree)
assert not equal(tree, tree2)
tree3 = build(4)
assert not equal(tree, tree3)
[case testSimulateMypySingledispatch]
from functools import singledispatch
from mypy_extensions import trait
from typing import Iterator, Union, TypeVar, Any, List, Type
# based on use of singledispatch in stubtest.py
class Error:
def __init__(self, msg: str) -> None:
self.msg = msg
@trait
class Node: pass
class MypyFile(Node): pass
class TypeInfo(Node): pass
@trait
class SymbolNode(Node): pass
@trait
class Expression(Node): pass
class TypeVarLikeExpr(SymbolNode, Expression): pass
class TypeVarExpr(TypeVarLikeExpr): pass
class TypeAlias(SymbolNode): pass
class Missing: pass
MISSING = Missing()
T = TypeVar("T")
MaybeMissing = Union[T, Missing]
@singledispatch
def verify(stub: Node, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]:
yield Error('unknown node type')
@verify.register(MypyFile)
def verify_mypyfile(stub: MypyFile, a: MaybeMissing[int], b: List[str]) -> Iterator[Error]:
if isinstance(a, Missing):
yield Error("shouldn't be missing")
return
if not isinstance(a, int):
# this check should be unnecessary because of the type signature and the previous check,
# but stubtest.py has this check
yield Error("should be an int")
return
yield from verify(TypeInfo(), str, ['abc', 'def'])
@verify.register(TypeInfo)
def verify_typeinfo(stub: TypeInfo, a: MaybeMissing[Type[Any]], b: List[str]) -> Iterator[Error]:
yield Error('in TypeInfo')
yield Error('hello')
@verify.register(TypeVarExpr)
def verify_typevarexpr(stub: TypeVarExpr, a: MaybeMissing[Any], b: List[str]) -> Iterator[Error]:
if False:
yield None
def verify_list(stub, a, b) -> List[str]:
"""Helper function that converts iterator of errors to list of messages"""
return list(err.msg for err in verify(stub, a, b))
def test_verify() -> None:
assert verify_list(TypeAlias(), 'a', ['a', 'b']) == ['unknown node type']
assert verify_list(MypyFile(), MISSING, ['a', 'b']) == ["shouldn't be missing"]
assert verify_list(MypyFile(), 5, ['a', 'b']) == ['in TypeInfo', 'hello']
assert verify_list(TypeInfo(), str, ['a', 'b']) == ['in TypeInfo', 'hello']
assert verify_list(TypeVarExpr(), 'a', ['x', 'y']) == []
[case testArgsInRegisteredImplNamedDifferentlyFromMainFunction]
from functools import singledispatch
@singledispatch
def f(a) -> bool:
return False
@f.register
def g(b: int) -> bool:
return True
def test_singledispatch():
assert f(5)
assert not f('a')
[case testKeywordArguments]
from functools import singledispatch
@singledispatch
def f(arg, *, kwarg: int = 0) -> int:
return kwarg + 10
@f.register
def g(arg: int, *, kwarg: int = 5) -> int:
return kwarg - 10
def test_keywords():
assert f('a') == 10
assert f('a', kwarg=3) == 13
assert f('a', kwarg=7) == 17
assert f(1) == -5
assert f(1, kwarg=4) == -6
assert f(1, kwarg=6) == -4
[case testGeneratorAndMultipleTypesOfIterable]
from functools import singledispatch
from typing import *
@singledispatch
def f(arg: Any) -> Iterable[int]:
yield 1
@f.register
def g(arg: str) -> Iterable[int]:
return [0]
def test_iterables():
assert f(1) != [1]
assert list(f(1)) == [1]
assert f('a') == [0]
[case testRegisterUsedAtSameTimeAsOtherDecorators]
from functools import singledispatch
from typing import TypeVar
class A: pass
class B: pass
T = TypeVar('T')
def decorator(f: T) -> T:
return f
@singledispatch
def f(arg) -> int:
return 0
@f.register
@decorator
def h(arg: str) -> int:
return 2
def test_singledispatch():
assert f(1) == 0
assert f('a') == 2
[case testDecoratorModifiesFunction]
from functools import singledispatch
from typing import Callable, Any
class A: pass
def decorator(f: Callable[[Any], int]) -> Callable[[Any], int]:
def wrapper(x) -> int:
return f(x) * 7
return wrapper
@singledispatch
def f(arg) -> int:
return 10
@f.register
@decorator
def h(arg: str) -> int:
return 5
def test_singledispatch():
assert f('a') == 35
assert f(A()) == 10
[case testMoreSpecificTypeBeforeLessSpecificType]
from functools import singledispatch
class A: pass
class B(A): pass
@singledispatch
def f(arg) -> str:
return 'default'
@f.register
def g(arg: B) -> str:
return 'b'
@f.register
def h(arg: A) -> str:
return 'a'
def test_singledispatch():
assert f(B()) == 'b'
assert f(A()) == 'a'
assert f(5) == 'default'
[case testMultipleRelatedClassesBeingRegistered]
from functools import singledispatch
class A: pass
class B(A): pass
class C(B): pass
@singledispatch
def f(arg) -> str: return 'default'
@f.register
def _(arg: A) -> str: return 'a'
@f.register
def _(arg: C) -> str: return 'c'
@f.register
def _(arg: B) -> str: return 'b'
def test_singledispatch():
assert f(A()) == 'a'
assert f(B()) == 'b'
assert f(C()) == 'c'
assert f(1) == 'default'
[case testRegisteredImplementationsInDifferentFiles]
from other_a import f, A, B, C
@f.register
def a(arg: A) -> int:
return 2
@f.register
def _(arg: C) -> int:
return 3
def test_singledispatch():
assert f(B()) == 1
assert f(A()) == 2
assert f(C()) == 3
assert f(1) == 0
[file other_a.py]
from functools import singledispatch
class A: pass
class B(A): pass
class C(B): pass
@singledispatch
def f(arg) -> int:
return 0
@f.register
def g(arg: B) -> int:
return 1
[case testOrderCanOnlyBeDeterminedFromMRONotIsinstanceChecks]
from mypy_extensions import trait
from functools import singledispatch
@trait
class A: pass
@trait
class B: pass
class AB(A, B): pass
class BA(B, A): pass
@singledispatch
def f(arg) -> str:
return "default"
pass
@f.register
def fa(arg: A) -> str:
return "a"
@f.register
def fb(arg: B) -> str:
return "b"
def test_singledispatch():
assert f(AB()) == "a"
assert f(BA()) == "b"
[case testCallingFunctionBeforeAllImplementationsRegistered]
from functools import singledispatch
class A: pass
class B(A): pass
@singledispatch
def f(arg) -> str:
return 'default'
assert f(A()) == 'default'
assert f(B()) == 'default'
assert f(1) == 'default'
@f.register
def g(arg: A) -> str:
return 'a'
assert f(A()) == 'a'
assert f(B()) == 'a'
assert f(1) == 'default'
@f.register
def _(arg: B) -> str:
return 'b'
assert f(A()) == 'a'
assert f(B()) == 'b'
assert f(1) == 'default'
[case testDynamicallyRegisteringFunctionFromInterpretedCode]
from functools import singledispatch
class A: pass
class B(A): pass
class C(B): pass
class D(C): pass
@singledispatch
def f(arg) -> str:
return "default"
@f.register
def _(arg: B) -> str:
return 'b'
[file register_impl.py]
from native import f, A, B, C
@f.register(A)
def a(arg) -> str:
return 'a'
@f.register
def c(arg: C) -> str:
return 'c'
[file driver.py]
from native import f, A, B, C
from register_impl import a, c
# We need a custom driver here because register_impl has to be run before we test this (so that the
# additional implementations are registered)
assert f(C()) == 'c'
assert f(A()) == 'a'
assert f(B()) == 'b'
assert a(C()) == 'a'
assert c(A()) == 'c'
[case testMalformedDynamicRegisterCall]
from functools import singledispatch
@singledispatch
def f(arg) -> None:
pass
[file register.py]
from native import f
from testutil import assertRaises
with assertRaises(TypeError, 'Invalid first argument to `register()`'):
@f.register
def _():
pass
[file driver.py]
import register
[case testCacheClearedWhenNewFunctionRegistered]
from functools import singledispatch
@singledispatch
def f(arg) -> str:
return 'default'
[file register.py]
from native import f
class A: pass
class B: pass
class C: pass
# annotated function
assert f(A()) == 'default'
@f.register
def _(arg: A) -> str:
return 'a'
assert f(A()) == 'a'
# type passed as argument
assert f(B()) == 'default'
@f.register(B)
def _(arg: B) -> str:
return 'b'
assert f(B()) == 'b'
# 2 argument form
assert f(C()) == 'default'
def c(arg) -> str:
return 'c'
f.register(C, c)
assert f(C()) == 'c'
[file driver.py]
import register

View File

@@ -0,0 +1,641 @@
# Test cases for strings (compile and run)
[case testStrBasics]
from typing import Tuple
def f() -> str:
return 'some string'
def g() -> str:
return 'some\a \v \t \x7f " \n \0string 🐍'
def tostr(x: int) -> str:
return str(x)
def booltostr(x: bool) -> str:
return str(x)
def concat(x: str, y: str) -> str:
return x + y
def eq(x: str) -> int:
if x == 'foo':
return 0
elif x != 'bar':
return 1
return 2
def match(x: str, y: str) -> Tuple[bool, bool]:
return (x.startswith(y), x.endswith(y))
[file driver.py]
from native import f, g, tostr, booltostr, concat, eq, match
import sys
assert f() == 'some string'
assert f() is sys.intern('some string')
assert g() == 'some\a \v \t \x7f " \n \0string 🐍'
assert tostr(57) == '57'
assert concat('foo', 'bar') == 'foobar'
assert booltostr(True) == 'True'
assert booltostr(False) == 'False'
assert eq('foo') == 0
assert eq('zar') == 1
assert eq('bar') == 2
assert int(tostr(0)) == 0
assert int(tostr(20)) == 20
assert match('', '') == (True, True)
assert match('abc', '') == (True, True)
assert match('abc', 'a') == (True, False)
assert match('abc', 'c') == (False, True)
assert match('', 'abc') == (False, False)
[case testStringOps]
from typing import List, Optional
def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
if sep is not None:
if max_split is not None:
return s.split(sep, max_split)
else:
return s.split(sep)
return s.split()
ss = "abc abcd abcde abcdef"
def test_split() -> None:
assert do_split(ss) == ["abc", "abcd", "abcde", "abcdef"]
assert do_split(ss, " ") == ["abc", "abcd", "abcde", "abcdef"]
assert do_split(ss, "-") == ["abc abcd abcde abcdef"]
assert do_split(ss, " ", -1) == ["abc", "abcd", "abcde", "abcdef"]
assert do_split(ss, " ", 0) == ["abc abcd abcde abcdef"]
assert do_split(ss, " ", 1) == ["abc", "abcd abcde abcdef"]
assert do_split(ss, " ", 2) == ["abc", "abcd", "abcde abcdef"]
def getitem(s: str, index: int) -> str:
return s[index]
from testutil import assertRaises
s = "abc"
def test_getitem() -> None:
assert getitem(s, 0) == "a"
assert getitem(s, 1) == "b"
assert getitem(s, 2) == "c"
assert getitem(s, -3) == "a"
assert getitem(s, -2) == "b"
assert getitem(s, -1) == "c"
with assertRaises(IndexError, "string index out of range"):
getitem(s, 4)
with assertRaises(IndexError, "string index out of range"):
getitem(s, -4)
def str_to_int(s: str, base: Optional[int] = None) -> int:
if base:
return int(s, base)
else:
return int(s)
def test_str_to_int() -> None:
assert str_to_int("1") == 1
assert str_to_int("10") == 10
assert str_to_int("a", 16) == 10
assert str_to_int("1a", 16) == 26
with assertRaises(ValueError, "invalid literal for int() with base 10: 'xyz'"):
str_to_int("xyz")
def test_slicing() -> None:
# Use dummy adds to avoid constant folding
zero = int()
two = zero + 2
s = "foobar" + str()
assert s[two:] == "obar"
assert s[:two] == "fo"
assert s[two:-two] == "ob"
assert s[two:two] == ""
assert s[two:two + 1] == "o"
assert s[-two:] == "ar"
assert s[:-two] == "foob"
assert s[:] == "foobar"
assert s[two:333] == "obar"
assert s[333:two] == ""
assert s[two:-333] == ""
assert s[-333:two] == "fo"
big_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
assert s[1:big_int] == "oobar"
assert s[big_int:] == ""
assert s[-big_int:-1] == "fooba"
def test_str_replace() -> None:
a = "foofoofoo"
assert a.replace("foo", "bar") == "barbarbar"
assert a.replace("foo", "bar", -1) == "barbarbar"
assert a.replace("foo", "bar", 1) == "barfoofoo"
assert a.replace("foo", "bar", 4) == "barbarbar"
assert a.replace("aaa", "bar") == "foofoofoo"
assert a.replace("ofo", "xyzw") == "foxyzwxyzwo"
def is_true(x: str) -> bool:
if x:
return True
else:
return False
def is_true2(x: str) -> bool:
return bool(x)
def is_false(x: str) -> bool:
if not x:
return True
else:
return False
def test_str_to_bool() -> None:
assert is_false('')
assert not is_true('')
assert not is_true2('')
for x in 'a', 'foo', 'bar', 'some string':
assert is_true(x)
assert is_true2(x)
assert not is_false(x)
def test_str_min_max() -> None:
x: str = 'aaa'
y: str = 'bbb'
z: str = 'aa'
assert min(x, y) == 'aaa'
assert min(x, z) == 'aa'
assert max(x, y) == 'bbb'
assert max(x, z) == 'aaa'
[case testStringFormattingCStyle]
[typing fixtures/typing-full.pyi]
from typing import Tuple
var = 'mypyc'
num = 20
def test_basics() -> None:
assert 'Hello %s, this is a test' % var == "Hello mypyc, this is a test"
assert 'Hello %s %d, this is a test' % (var, num) == "Hello mypyc 20, this is a test"
t: Tuple[str, int] = (var, num)
assert 'Hello %s %d, this is a test' % t == "Hello mypyc 20, this is a test"
large_num = 2**65
assert 'number: %d' % large_num == 'number: 36893488147419103232'
neg_num = -3
assert 'negative integer: %d' % neg_num == 'negative integer: -3'
assert 'negative integer: %d' % (-large_num) == 'negative integer: -36893488147419103232'
bool_var1 = True
bool_var2 = False
assert 'bool: %s, %s' % (bool_var1, bool_var2) == 'bool: True, False'
float_num = 123.4
assert '%f' % float_num == '123.400000'
assert '%.2f' % float_num == '123.40'
assert '%.5f' % float_num == '123.40000'
assert '%10.2f' % float_num == ' 123.40'
assert '%10.5f' % float_num == ' 123.40000'
assert '%010.5f' % float_num == '0123.40000'
assert '%015.5f' % float_num == '000000123.40000'
assert '%e' % float_num == '1.234000e+02'
large_float = 1.23e30
large_float2 = 1234123412341234123400000000000000000
small_float = 1.23e-20
assert '%f, %f, %f' % (small_float, large_float, large_float2) == \
'0.000000, 1229999999999999959718843908096.000000, 1234123412341234169005079998930878464.000000'
assert '%s, %s, %s' % (small_float, large_float, large_float2) == \
'1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
assert '%d, %d, %d' % (small_float, large_float, large_float2) == \
'0, 1229999999999999959718843908096, 1234123412341234123400000000000000000'
nan_num = float('nan')
inf_num = float('inf')
assert '%s, %s' % (nan_num, inf_num) == 'nan, inf'
assert '%f, %f' % (nan_num, inf_num) == 'nan, inf'
[case testFStrings]
import decimal
from datetime import datetime
var = 'mypyc'
num = 20
def test_fstring_basics() -> None:
assert f'Hello {var}, this is a test' == "Hello mypyc, this is a test"
large_num = 2**65
assert f'number: {large_num}' == 'number: 36893488147419103232'
neg_num = -3
assert f'negative integer: {neg_num}' == 'negative integer: -3'
assert f'negative integer: {-large_num}' == 'negative integer: -36893488147419103232'
bool_var1 = True
bool_var2 = False
assert f'bool: {bool_var1}, {bool_var2}' == 'bool: True, False'
x = bytes([1, 2, 3, 4])
# assert f'bytes: {x}' == "bytes: b'\\x01\\x02\\x03\\x04'"
# error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes
float_num = 123.4
assert f'{float_num}' == '123.4'
assert f'{float_num:.2f}' == '123.40'
assert f'{float_num:.5f}' == '123.40000'
assert f'{float_num:>10.2f}' == ' 123.40'
assert f'{float_num:>10.5f}' == ' 123.40000'
assert f'{float_num:>010.5f}' == '0123.40000'
assert f'{float_num:>015.5f}' == '000000123.40000'
assert f'{float_num:e}' == '1.234000e+02'
large_float = 1.23e30
large_float2 = 1234123412341234123400000000000000000
small_float = 1.23e-20
assert f'{small_float}, {large_float}, {large_float2}' == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
nan_num = float('nan')
inf_num = float('inf')
assert f'{nan_num}, {inf_num}' == 'nan, inf'
# F-strings would be translated into ''.join[string literals, format method call, ...] in mypy AST.
# Currently we are using a str.join specializer for f-string speed up. We might not cover all cases
# and the rest ones should fall back to a normal str.join method call.
# TODO: Once we have a new pipeline for f-strings, this test case can be moved to testStringOps.
def test_str_join() -> None:
var = 'mypyc'
num = 10
assert ''.join(['a', 'b', '{}'.format(var), 'c']) == 'abmypycc'
assert ''.join(['a', 'b', '{:{}}'.format(var, ''), 'c']) == 'abmypycc'
assert ''.join(['a', 'b', '{:{}}'.format(var, '>10'), 'c']) == 'ab mypycc'
assert ''.join(['a', 'b', '{:{}}'.format(var, '>{}'.format(num)), 'c']) == 'ab mypycc'
assert var.join(['a', '{:{}}'.format(var, ''), 'b']) == 'amypycmypycmypycb'
assert ','.join(['a', '{:{}}'.format(var, ''), 'b']) == 'a,mypyc,b'
assert ''.join(['x', var]) == 'xmypyc'
class A:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'{self.name} is {self.age} years old.'
def test_fstring_datatype() -> None:
u = A('John Doe', 14)
assert f'{u}' == 'John Doe is 14 years old.'
d = {'name': 'John Doe', 'age': 14}
assert f'{d}' == "{'name': 'John Doe', 'age': 14}"
def test_fstring_escape() -> None:
assert f"{'inside'}" == 'inside'
assert f'{"inside"}' == 'inside'
assert f"""inside""" == 'inside'
assert f'''inside''' == 'inside'
assert f"\"{'inside'}\"" == '"inside"'
assert f'\'{"inside"}\'' == "'inside'"
assert f'{{10}}' == '{10}'
assert f'{{10 + 10}}' == '{10 + 10}'
assert f'{{{10 + 10}}}' == '{20}'
assert f'{{{{10 + 10}}}}' == '{{10 + 10}}'
def test_fstring_conversion() -> None:
assert f'Hello {var!r}' == "Hello 'mypyc'"
# repr() is equivalent to !r
assert f'Hello {repr(var)}' == "Hello 'mypyc'"
assert f'Hello {var!a}' == "Hello 'mypyc'"
# ascii() is equivalent to !a
assert f'Hello {ascii(var)}' == "Hello 'mypyc'"
tmp_str = """this
is a new line."""
assert f'Test: {tmp_str!a}' == "Test: 'this\\n is a new line.'"
s = 'test: āĀēĒčČ..šŠūŪžŽ'
assert f'{s}' == 'test: āĀēĒčČ..šŠūŪžŽ'
assert f'{s!a}' == "'test: \\u0101\\u0100\\u0113\\u0112\\u010d\\u010c..\\u0161\\u0160\\u016b\\u016a\\u017e\\u017d'"
assert f'Hello {var!s}' == 'Hello mypyc'
assert f'Hello {num!s}' == 'Hello 20'
def test_fstring_align() -> None:
assert f'Hello {var:>20}' == "Hello mypyc"
assert f'Hello {var!r:>20}' == "Hello 'mypyc'"
assert f'Hello {var:>{num}}' == "Hello mypyc"
assert f'Hello {var!r:>{num}}' == "Hello 'mypyc'"
def test_fstring_multi() -> None:
assert f'Hello {var}, hello again {var}' == "Hello mypyc, hello again mypyc"
a = 'py'
s = f'my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}'
assert s == 'mypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypy'
def test_fstring_python_doc() -> None:
name = 'Fred'
assert f"He said his name is {name!r}." == "He said his name is 'Fred'."
assert f"He said his name is {repr(name)}." == "He said his name is 'Fred'."
width = 10
precision = 4
value = decimal.Decimal('12.34567')
assert f'result: {value:{width}.{precision}}' == 'result: 12.35' # nested field
today = datetime(year=2017, month=1, day=27)
assert f'{today:%B %d, %Y}' == 'January 27, 2017' # using date format specifier
number = 1024
assert f'{number:#0x}' == '0x400' # using integer format specifier
[case testStringFormatMethod]
from typing import Tuple
def test_format_method_basics() -> None:
x = str()
assert 'x{}'.format(x) == 'x'
assert 'ā{}'.format(x) == 'ā'
assert '😀{}'.format(x) == '😀'
assert ''.format() == ''
assert 'abc'.format() == 'abc'
assert '{}{}'.format(1, 2) == '12'
name = 'Eric'
age = 14
assert "My name is {name}, I'm {age}.".format(name=name, age=age) == "My name is Eric, I'm 14."
assert "My name is {A}, I'm {B}.".format(A=name, B=age) == "My name is Eric, I'm 14."
assert "My name is {}, I'm {B}.".format(name, B=age) == "My name is Eric, I'm 14."
bool_var1 = True
bool_var2 = False
assert 'bool: {}, {}'.format(bool_var1, bool_var2) == 'bool: True, False'
def test_format_method_empty_braces() -> None:
name = 'Eric'
age = 14
assert 'Hello, {}!'.format(name) == 'Hello, Eric!'
assert '{}'.format(name) == 'Eric'
assert '{}! Hi!'.format(name) == 'Eric! Hi!'
assert '{}, Hi, {}'.format(name, name) == 'Eric, Hi, Eric'
assert 'Hi! {}'.format(name) == 'Hi! Eric'
assert "Hi, I'm {}. I'm {}.".format(name, age) == "Hi, I'm Eric. I'm 14."
assert '{{}}'.format() == '{}'
assert '{{{{}}}}'.format() == '{{}}'
assert '{{}}{}'.format(name) == '{}Eric'
assert 'Hi! {{{}}}'.format(name) == 'Hi! {Eric}'
assert 'Hi! {{ {}'.format(name) == 'Hi! { Eric'
assert 'Hi! {{ {} }}}}'.format(name) == 'Hi! { Eric }}'
def test_format_method_numbers() -> None:
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-233)
assert s == 'int: -233; hex: -e9; oct: -351; bin: -11101001'
num = 2**65
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(num)
assert s == 'int: 36893488147419103232; hex: 20000000000000000; oct: 4000000000000000000000; bin: 100000000000000000000000000000000000000000000000000000000000000000'
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-num)
assert s == 'int: -36893488147419103232; hex: -20000000000000000; oct: -4000000000000000000000; bin: -100000000000000000000000000000000000000000000000000000000000000000'
large_num = 2**65
assert 'number: {}'.format(large_num) == 'number: 36893488147419103232'
neg_num = -3
assert 'negative integer: {}'.format(neg_num) == 'negative integer: -3'
assert 'negative integer: {}'.format(-large_num) == 'negative integer: -36893488147419103232'
large_float = 1.23e30
large_float2 = 1234123412341234123400000000000000000
small_float = 1.23e-20
assert '{}, {}, {}'.format(small_float, large_float, large_float2) == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
nan_num = float('nan')
inf_num = float('inf')
assert '{}, {}'.format(nan_num, inf_num) == 'nan, inf'
def format_args(*args: int) -> str:
return 'x{}y{}'.format(*args)
def format_kwargs(**kwargs: int) -> str:
return 'c{x}d{y}'.format(**kwargs)
def format_args_self(*args: int) -> str:
return '{}'.format(args)
def format_kwargs_self(**kwargs: int) -> str:
return '{}'.format(kwargs)
def test_format_method_args() -> None:
assert format_args(10, 2) == 'x10y2'
assert format_args_self(10, 2) == '(10, 2)'
assert format_kwargs(x=10, y=2) == 'c10d2'
assert format_kwargs(x=10, y=2, z=1) == 'c10d2'
assert format_kwargs_self(x=10, y=2, z=1) == "{'x': 10, 'y': 2, 'z': 1}"
def test_format_method_different_kind() -> None:
s1 = "Literal['😀']"
assert 'Revealed type is {}'.format(s1) == "Revealed type is Literal['😀']"
s2 = "Revealed type is"
assert "{} Literal['😀']".format(s2) == "Revealed type is Literal['😀']"
s3 = "测试:"
assert "{}{} {}".format(s3, s2, s1) == "测试Revealed type is Literal['😀']"
assert "Test: {}{}".format(s3, s1) == "Test: 测试Literal['😀']"
assert "Test: {}{}".format(s3, s2) == "Test: 测试Revealed type is"
def test_format_method_nested() -> None:
var = 'mypyc'
num = 10
assert '{:{}}'.format(var, '') == 'mypyc'
assert '{:{}}'.format(var, '>10') == ' mypyc'
assert '{:{}}'.format(var, '>{}'.format(num)) == ' mypyc'
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return 'Point({self.x}, {self.y})'.format(self=self)
# Format examples from Python doc
# https://docs.python.org/3/library/string.html#formatexamples
def test_format_method_python_doc() -> None:
# Accessing arguments by position:
assert '{0}, {1}, {2}'.format('a', 'b', 'c') == 'a, b, c'
assert '{}, {}, {}'.format('a', 'b', 'c') == 'a, b, c'
assert '{2}, {1}, {0}'.format('a', 'b', 'c') == 'c, b, a'
assert '{2}, {1}, {0}'.format(*'abc') == 'c, b, a' # unpacking argument sequence
# assert '{0}{1}{0}'.format('abra', 'cad') = 'abracadabra' # arguments' indices can be repeated
# Accessing arguments by name:
s = 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
assert s == 'Coordinates: 37.24N, -115.81W'
coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
assert 'Coordinates: {latitude}, {longitude}'.format(**coord) == 'Coordinates: 37.24N, -115.81W'
# Accessing arguments attributes:
assert str(Point(4, 2)) == 'Point(4, 2)'
# Accessing arguments items:
coord2 = (3, 5)
assert 'X: {0[0]}; Y: {0[1]}'.format(coord2) == 'X: 3; Y: 5'
# Replacing %s and %r:
s = "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
assert s == "repr() shows quotes: 'test1'; str() doesn't: test2"
# Aligning the text and specifying a width:
assert '{:<30}'.format('left aligned') == 'left aligned '
assert '{:>30}'.format('right aligned') == ' right aligned'
assert '{:^30}'.format('centered') == ' centered '
assert '{:*^30}'.format('centered') == '***********centered***********' # use '*' as a fill char
# Replacing %+f, %-f, and % f and specifying a sign:
assert '{:+f}; {:+f}'.format(3.14, -3.14) == '+3.140000; -3.140000' # show it always
assert '{: f}; {: f}'.format(3.14, -3.14) == ' 3.140000; -3.140000' # show a space for positive numbers
assert '{:-f}; {:-f}'.format(3.14, -3.14) == '3.140000; -3.140000' # show only the minus -- same as '{:f}; {:f}'
# Replacing %x and %o and converting the value to different bases:
s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42) # format also supports binary numbers
assert s == 'int: 42; hex: 2a; oct: 52; bin: 101010'
s = 'int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42) # with 0x, 0o, or 0b as prefix:
assert s == 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
# Using the comma as a thousands separator:
assert '{:,}'.format(1234567890) == '1,234,567,890'
# Expressing a percentage:
points = 19.0
total = 22.0
assert 'Correct answers: {:.2%}'.format(points/total) == 'Correct answers: 86.36%'
# Using type-specific formatting:
import datetime
d = datetime.datetime(2010, 7, 4, 12, 15, 58)
assert '{:%Y-%m-%d %H:%M:%S}'.format(d) == '2010-07-04 12:15:58'
# Nesting arguments and more complex examples:
tmp_strs = []
for align, text in zip('<^>', ['left', 'center', 'right']):
tmp_strs.append('{0:{fill}{align}16}'.format(text, fill=align, align=align))
assert tmp_strs == ['left<<<<<<<<<<<<', '^^^^^center^^^^^', '>>>>>>>>>>>right']
octets = [192, 168, 0, 1]
assert '{:02X}{:02X}{:02X}{:02X}'.format(*octets) == 'C0A80001'
width = 5
tmp_strs = []
for num in range(5,12):
tmp_str = ''
for base in 'dXob':
tmp_str += ('{0:{width}{base}}'.format(num, base=base, width=width))
tmp_strs.append(tmp_str)
assert tmp_strs == [' 5 5 5 101',\
' 6 6 6 110',\
' 7 7 7 111',\
' 8 8 10 1000',\
' 9 9 11 1001',\
' 10 A 12 1010',\
' 11 B 13 1011']
[case testChr]
# Some test cases are from https://docs.python.org/3/howto/unicode.html
def try_invalid(x: int) -> bool:
try:
chr(x + int())
return False
except ValueError:
return True
def test_chr() -> None:
assert chr(57344) == '\ue000'
assert chr(0) == '\x00'
assert chr(65) == 'A'
assert chr(150) == '\x96'
try:
chr(-1)
assert False
except ValueError:
pass
try:
chr(1114112)
assert False
except ValueError:
pass
assert chr(1114111) == '\U0010ffff'
x = 0
assert chr(x + int()) == '\x00'
x = 100
assert chr(x + int()) == 'd'
x = 150
assert chr(x + int()) == '\x96'
x = 257
assert chr(x + int()) == 'ā'
x = 65537
assert chr(x + int()) == '𐀁'
assert try_invalid(-1)
assert try_invalid(1114112)
[case testOrd]
def test_ord() -> None:
assert ord('\ue000') == 57344
s = "a\xac\u1234\u20ac\U00008000"
# ^^^^ two-digit hex escape
# ^^^^^^ four-digit Unicode escape
# ^^^^^^^^^^ eight-digit Unicode escape
l1 = [ord(c) for c in s]
assert l1 == [97, 172, 4660, 8364, 32768]
u = 'abcdé'
assert ord(u[-1]) == 233
assert ord(b'a') == 97
assert ord(b'a' + bytes()) == 97
u2 = '\U0010ffff'
assert ord(u2) == 1114111
try:
ord('aa')
assert False
except TypeError:
pass
[case testDecode]
def test_decode() -> None:
assert "\N{GREEK CAPITAL LETTER DELTA}" == '\u0394'
assert "\u0394" == "\u0394"
assert "\U00000394" == '\u0394'
assert b'\x80abc'.decode('utf-8', 'replace') == '\ufffdabc'
assert b'\x80abc'.decode('utf-8', 'backslashreplace') == '\\x80abc'
assert b'abc'.decode() == 'abc'
assert b'abc'.decode('utf-8') == 'abc'
assert b'\x80abc'.decode('utf-8', 'ignore') == 'abc'
assert b'\x80abc'.decode('UTF-8', 'ignore') == 'abc'
assert b'\x80abc'.decode('Utf-8', 'ignore') == 'abc'
assert b'\x80abc'.decode('utf_8', 'ignore') == 'abc'
assert b'\x80abc'.decode('latin1', 'ignore') == '\x80abc'
assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('gbk', 'ignore') == '一二三'
assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('latin1', 'ignore') == 'Ò»¶þÈý'
assert b'Z\xc3\xbcrich'.decode("utf-8") == 'Zürich'
try:
b'Z\xc3\xbcrich'.decode('ascii')
assert False
except UnicodeDecodeError:
pass
assert bytearray(range(5)).decode() == '\x00\x01\x02\x03\x04'
b = bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd')
assert b.decode() == '你好'
assert b.decode('gbk') == '浣犲ソ'
assert b.decode('latin1') == 'ä½\xa0好'
[case testEncode]
from testutil import assertRaises
def test_encode() -> None:
u = chr(40960) + 'abcd' + chr(1972)
assert u.encode() == b'\xea\x80\x80abcd\xde\xb4'
assert u.encode('utf-8') == b'\xea\x80\x80abcd\xde\xb4'
with assertRaises(UnicodeEncodeError):
u.encode('ascii')
with assertRaises(LookupError):
u.encode('aaa')
assert u.encode('utf-8', 'aaaaaa') == b'\xea\x80\x80abcd\xde\xb4'
assert u.encode('ascii', 'ignore') == b'abcd'
assert u.encode('ASCII', 'ignore') == b'abcd'
assert u.encode('ascii', 'replace') == b'?abcd?'
assert u.encode('ascii', 'xmlcharrefreplace') == b'&#40960;abcd&#1972;'
assert u.encode('ascii', 'backslashreplace') == b'\\ua000abcd\\u07b4'
assert u.encode('ascii', 'namereplace') == b'\\N{YI SYLLABLE IT}abcd\\u07b4'
assert 'pythön!'.encode() == b'pyth\xc3\xb6n!'
assert '一二三'.encode('gbk') == b'\xd2\xbb\xb6\xfe\xc8\xfd'
assert u.encode('UTF-8', 'ignore') == b'\xea\x80\x80abcd\xde\xb4'
assert u.encode('Utf_8') == b'\xea\x80\x80abcd\xde\xb4'
assert u.encode('UTF_8') == b'\xea\x80\x80abcd\xde\xb4'
assert u'\u00E1'.encode('latin1') == b'\xe1'
with assertRaises(UnicodeEncodeError):
u.encode('latin1')

View File

@@ -0,0 +1,411 @@
[case testTraitBasic1]
from mypy_extensions import trait
class A:
line: int
def foo(self) -> None:
print("foo")
@trait
class T:
def bar(self) -> None:
print("bar")
def baz(self) -> object:
return None
class C(A, T):
def baz(self) -> int:
return 10
def use_t(t: T) -> object:
t.bar()
return t.baz()
def use_c(c: C) -> int:
use_t(c)
c.foo()
c.bar()
return c.baz()
use_t(C())
# This trait is dead code but there's no reason it shouldn't compile
@trait
class ChildlessTrait:
def __init__(self) -> None:
pass
[file driver.py]
from native import A, T, C, use_c, use_t
c = C()
c.foo()
c.bar()
assert c.baz() == 10
assert use_c(c) == 10
assert use_t(c) == 10
[out]
bar
foo
bar
bar
foo
bar
bar
[case testTraitBasic2]
from mypy_extensions import trait
class A:
line: int
def foo(self) -> None:
print("foo")
@trait
class T:
def bar(self) -> None:
print("bar", self.baz())
def baz(self) -> int:
return -1
@trait
class T2:
line: int
def baz(self) -> int:
return -2
class C(A, T):
def __init__(self) -> None:
self.line = 1337
self.x = 12
def baz(self) -> int:
return self.x
class D(C, T2):
def __init__(self) -> None:
self.line = 1337
self.x = 13
@trait
class T3:
def baz(self) -> int:
return -2
class E(T3):
def __init__(self) -> None:
pass
def use_t(t: T) -> None:
t.bar()
def use_t2(t: T2) -> int:
t.line = t.line
return t.line
def use_c(c: C) -> int:
use_t(c)
c.foo()
c.bar()
return c.line
def use_d(d: D) -> int:
return d.baz()
[file driver.py]
from native import A, T, C, D, use_c, use_t, use_d, use_t2
c = C()
d = D()
c.foo()
c.bar()
print("baz", c.baz())
print("baz", d.baz())
use_c(c)
use_t(c)
use_c(d)
use_t(d)
assert use_d(d) == 13
print(d.line)
assert d.line == 1337
assert use_t2(d) == 1337
[out]
foo
bar 12
baz 12
baz 13
bar 12
foo
bar 12
bar 12
bar 13
foo
bar 13
bar 13
1337
[case testTrait3]
from mypy_extensions import trait
from typing import Generic, TypeVar
@trait
class T1: pass
@trait
class T2: pass
T = TypeVar('T')
class C(Generic[T], T1, T2):
pass
@trait
class S1(Generic[T]):
def foo(self) -> None: pass
def bar(self, x: T) -> T: raise Exception
@trait
class S2(S1[T]):
def bar(self, x: T) -> T: return x
@trait
class S3(S2[T]):
def bar(self, x: T) -> T: return x
class D(S3[bool]):
def bar(self, x: bool) -> bool: return x
[file driver.py]
import native
[case testTrait4]
from mypy_extensions import trait
from typing import Generic, TypeVar
T = TypeVar('T')
@trait
class S1(Generic[T]):
def bar(self) -> T: raise Exception
class S2(S1[bool]):
def bar(self) -> bool: return False
class D(S2):
pass
def lol(x: S1) -> None:
x.bar()
[file driver.py]
import native
native.lol(native.D())
[case testTraitOrdering]
import other_b
# Regression test for a bug where inheriting from a class that
# inherited from a trait that got processed later on the command line
# filed to compile.
[file other_b.py]
from other_c import Plugin
class Whatever(Plugin):
pass
[file other_c.py]
from mypy_extensions import trait
@trait
class Base:
x = None # type: int
class Plugin(Base):
def __init__(self) -> None:
self.x = 10
[file driver.py]
from native import *
[case testDiamond]
from mypy_extensions import trait
@trait
class Base:
def get_value(self) -> str:
return "Base"
@trait
class Trait(Base):
def get_value(self) -> str:
return "Trait"
class Message(Base):
def show_message(self) -> None:
print("I am a " + self.get_value())
class DerivedMessage(Message, Trait):
pass
[file driver.py]
from native import *
a = Message()
a.show_message()
b = DerivedMessage()
b.show_message()
[out]
I am a Base
I am a Trait
[case testTraitAttrsSubTrait]
from mypy_extensions import trait
class A:
a: int
@trait
class T1:
x: int
@trait
class T2(T1):
y: int
class C(A, T2):
c: int
def f(t1: T1, t2: T2) -> None:
t1.x, t2.x = t2.x, t1.x
def g(t1: T1, t2: T2) -> None:
t2.y = t1.x
def get_x(c: C) -> int:
return c.x
def get_y(c: C) -> int:
return c.y
[file driver.py]
from native import C, f, g, get_x, get_y
c1 = C()
c2 = C()
c1.x = 1
c1.y = 0
c2.x = 2
c2.y = 0
f(c1, c2)
assert c1.x == 2
assert c2.x == 1
assert get_x(c1) == 2
assert get_x(c2) == 1
assert get_y(c2) == 0
g(c1, c2)
assert get_y(c2) == 2
[out]
[case testTraitAttrsTriangle]
from mypy_extensions import trait
class A:
a: int
@trait
class T(A):
x: int
def meth(self) -> int:
return self.a
class B(A):
b: int
class C(B, T):
pass
def take_t(t: T) -> int:
return t.x + t.meth()
def take_c(c: C) -> int:
return c.x + c.meth()
[file driver.py]
from native import C, take_t, take_c
c = C()
c.a = 1
c.x = 10
assert take_t(c) == take_c(c) == 11
[out]
[case testTraitAttrsTree]
from mypy_extensions import trait
class A:
a: int
@trait
class T1:
x: int
class B(A, T1):
b: int
@trait
class T2:
x: int
class C(B, T2):
pass
def f(t1: T1, t2: T2) -> None:
t1.x, t2.x = t2.x, t1.x
def g(c1: C, c2: C) -> None:
c1.x, c2.x = c2.x, c1.x
[file driver.py]
from native import C, f, g
c1 = C()
c2 = C()
c1.x = 1
c2.x = 2
f(c1, c2)
assert c1.x == 2
assert c2.x == 1
g(c1, c2)
assert c1.x == 1
assert c2.x == 2
[out]
[case testTraitErrorMessages]
from mypy_extensions import trait
@trait
class Trait:
pass
def create() -> Trait:
return Trait()
[file driver.py]
from native import Trait, create
from testutil import assertRaises
with assertRaises(TypeError, "traits may not be directly created"):
Trait()
with assertRaises(TypeError, "traits may not be directly created"):
create()
class Sub(Trait):
pass
with assertRaises(TypeError, "interpreted classes cannot inherit from compiled traits"):
Sub()

View File

@@ -0,0 +1,258 @@
# Test cases for tuples (compile and run)
[case testTuple]
from typing import List, Optional, Tuple
from typing import Tuple
def f(x: Tuple[int, int]) -> Tuple[int,int]:
return x
def lurr(x: List[Optional[Tuple[int, str]]]) -> object:
return x[0]
def asdf(x: Tuple[int, str]) -> None:
pass
[file driver.py]
from testutil import assertRaises
from native import f, lurr, asdf
assert f((1,2)) == (1, 2)
assert lurr([(1, '2')]) == (1, '2')
with assertRaises(TypeError):
print(lurr([(1, 2)]))
with assertRaises(TypeError):
asdf((1, 2))
[case testTupleGet]
from typing import Tuple
def f(x: Tuple[Tuple[int, bool], int]) -> int:
return x[0][0]
[file driver.py]
from native import f
print(f(((1,True),2)))
big_number = pow(2, 80)
print(f(((big_number,True),2)))
[out]
1
1208925819614629174706176
[case testSequenceTupleArg]
from typing import Tuple
def f(x: Tuple[int, ...]) -> int:
return x[1]
[file driver.py]
from native import f
print(f((1,2,3,4)))
[out]
2
[case testTupleAttr]
from typing import Tuple
class C:
b: Tuple[Tuple[Tuple[int, int], int], int, str, object]
c: Tuple[()]
def f() -> None:
c = C()
c.b = (((1, 2), 2), 1, 'hi', 'hi2')
print(c.b)
def g() -> None:
try:
h()
except Exception:
print('caught the exception')
def h() -> Tuple[Tuple[Tuple[int, int], int], int, str, object]:
raise Exception('Intentional exception')
[file driver.py]
from native import f, g, C
f()
g()
assert not hasattr(C(), 'c')
[out]
(((1, 2), 2), 1, 'hi', 'hi2')
caught the exception
[case testNamedTupleAttributeRun]
from typing import NamedTuple
NT = NamedTuple('NT', [('x', int), ('y', int)])
def f(nt: NT) -> int:
if nt.x > nt.y:
return nt.x
return nt.y
nt = NT(1, 2)
[file driver.py]
from native import NT, nt, f
assert f(nt) == 2
assert f(NT(3, 2)) == 3
class Sub(NT):
pass
assert f(Sub(3, 2)) == 3
-- Ref: https://github.com/mypyc/mypyc/issues/924
[case testNamedTupleClassSyntax]
from typing import Dict, List, NamedTuple, Optional, Tuple, Union
from typing_extensions import final
class FuncIR: pass
StealsDescription = Union[bool, List[bool]]
class Record(NamedTuple):
st_mtime: float
st_size: int
is_borrowed: bool
hash: str
python_path: Tuple[str, ...]
type: 'ClassIR'
method: FuncIR
shadow_method: Optional[FuncIR]
classes: Dict[str, 'ClassIR']
steals: StealsDescription
ordering: Optional[List[int]]
extra_int_constants: List[Tuple[int]]
# Make sure mypyc loads the annotation string for this forward reference.
# Ref: https://github.com/mypyc/mypyc/issues/938
class ClassIR: pass
# Ref: https://github.com/mypyc/mypyc/issues/927
@final
class Inextensible(NamedTuple):
x: int
[file driver.py]
from typing import ForwardRef, Optional
from native import ClassIR, FuncIR, Record
assert Record.__annotations__ == {
'st_mtime': float,
'st_size': int,
'is_borrowed': bool,
'hash': str,
'python_path': tuple,
'type': ForwardRef('ClassIR'),
'method': FuncIR,
'shadow_method': type,
'classes': dict,
'steals': type,
'ordering': type,
'extra_int_constants': list,
}, Record.__annotations__
[case testTupleOps]
from typing import Tuple, List, Any, Optional
from typing_extensions import Final
def f() -> Tuple[()]:
return ()
def test_empty_tuple() -> None:
assert f() == ()
def f2() -> Any:
return ()
def test_empty_tuple_with_any_type():
assert f2() == ()
def f3() -> int:
x = (False, 1)
return x[1]
def test_new_tuple() -> None:
assert f3() == 1
def f4(y: int) -> int:
x = (False, y)
return x[1]
def test_new_tuple_boxed_int() -> None:
big_number = 1208925819614629174706176
assert f4(big_number) == big_number
def f5(x: List[int]) -> int:
return tuple(x)[1]
def test_sequence_tuple() -> None:
assert f5([1,2,3,4]) == 2
def f6(x: List[int]) -> int:
return len(tuple(x))
def test_sequence_tuple_len() -> None:
assert f6([1,2,3,4]) == 4
def f7(x: List[Tuple[int, int]]) -> int:
a, b = x[0]
return a + b
def test_unbox_tuple() -> None:
assert f7([(5, 6)]) == 11
# Test that order is irrelevant to unions. Really I only care that this builds.
class A:
pass
def lol() -> A:
return A()
def foo(x: bool, y: bool) -> Tuple[Optional[A], bool]:
z = lol()
return None if y else z, x
def test_slicing() -> None:
# Use dummy adds to avoid constant folding
zero = int()
two = zero + 2
s: Tuple[str, ...] = ("f", "o", "o", "b", "a", "r")
assert s[two:] == ("o", "b", "a", "r")
assert s[:two] == ("f", "o")
assert s[two:-two] == ("o", "b")
assert s[two:two] == ()
assert s[two:two + 1] == ("o",)
assert s[-two:] == ("a", "r")
assert s[:-two] == ("f", "o", "o", "b")
assert s[:] == ("f", "o", "o", "b", "a", "r")
assert s[two:333] == ("o", "b", "a", "r")
assert s[333:two] == ()
assert s[two:-333] == ()
assert s[-333:two] == ("f", "o")
long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
assert s[1:long_int] == ("o", "o", "b", "a", "r")
assert s[long_int:] == ()
assert s[-long_int:-1] == ("f", "o", "o", "b", "a")
def f8(val: int) -> bool:
return val % 2 == 0
def test_sequence_generator() -> None:
source_list = [1, 2, 3]
a = tuple(f8(x) for x in source_list)
assert a == (False, True, False)
source_tuple: Tuple[int, ...] = (1, 2, 3)
a = tuple(f8(x) for x in source_tuple)
assert a == (False, True, False)
source_fixed_length_tuple = (1, 2, 3, 4)
a = tuple(f8(x) for x in source_fixed_length_tuple)
assert a == (False, True, False, True)
source_str = 'abbc'
b = tuple('s:' + x for x in source_str)
assert b == ('s:a', 's:b', 's:b', 's:c')
TUPLE: Final[Tuple[str, ...]] = ('x', 'y')
def test_final_boxed_tuple() -> None:
t = TUPLE
assert t == ('x', 'y')

View File

@@ -0,0 +1,303 @@
[case testU8BasicOps]
from typing import Any, Tuple
from mypy_extensions import u8, i16, i32, i64
from typing_extensions import Final
from testutil import assertRaises
ERROR: Final = 239
def test_box_and_unbox() -> None:
for i in range(0, 256):
o: Any = i
x: u8 = o
o2: Any = x
assert o == o2
assert x == i
with assertRaises(OverflowError, "int too large or small to convert to u8"):
o = 256
x2: u8 = o
with assertRaises(OverflowError, "int too large or small to convert to u8"):
o = -1
x3: u8 = o
def div_by_7(x: u8) -> u8:
return x // 7
def div(x: u8, y: u8) -> u8:
return x // y
def test_divide_by_constant() -> None:
for i in range(0, 256):
assert div_by_7(i) == i // 7
def test_divide_by_variable() -> None:
for x in range(0, 256):
for y in range(0, 256):
if y != 0:
assert div(x, y) == x // y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
div(x, y)
def mod_by_7(x: u8) -> u8:
return x % 7
def mod(x: u8, y: u8) -> u8:
return x % y
def test_mod_by_constant() -> None:
for i in range(0, 256):
assert mod_by_7(i) == i % 7
def test_mod_by_variable() -> None:
for x in range(0, 256):
for y in range(0, 256):
if y != 0:
assert mod(x, y) == x % y
else:
with assertRaises(ZeroDivisionError, "integer division or modulo by zero"):
mod(x, y)
def test_simple_arithmetic_ops() -> None:
zero: u8 = int()
one: u8 = zero + 1
two: u8 = one + 1
neg_one: u8 = -one
assert neg_one == 255
assert one + one == 2
assert one + two == 3
assert one + neg_one == 0
assert one - one == 0
assert one - two == 255
assert one * one == 1
assert one * two == 2
assert two * two == 4
assert two * neg_one == 254
assert neg_one * one == 255
assert neg_one * neg_one == 1
assert two * 0 == 0
assert 0 * two == 0
assert -one == 255
assert -two == 254
assert -neg_one == 1
assert -zero == 0
def test_bitwise_ops() -> None:
x: u8 = 184 + int()
y: u8 = 79 + int()
z: u8 = 113 + int()
zero: u8 = int()
one: u8 = zero + 1
two: u8 = zero + 2
neg_one: u8 = -one
assert x & y == 8
assert x & z == 48
assert z & z == z
assert x & zero == 0
assert x | y == 255
assert x | z == 249
assert z | z == z
assert x | 0 == x
assert x ^ y == 247
assert x ^ z == 201
assert z ^ z == 0
assert z ^ 0 == z
assert x << one == 112
assert x << two == 224
assert z << two == 196
assert z << 0 == z
assert x >> one == 92
assert x >> two == 46
assert z >> two == 28
assert z >> 0 == z
for i in range(256):
t: u8 = i
assert ~t == (~(i + int()) & 0xff)
def eq(x: u8, y: u8) -> bool:
return x == y
def test_eq() -> None:
assert eq(int(), int())
assert eq(5 + int(), 5 + int())
assert not eq(int(), 1 + int())
assert not eq(5 + int(), 6 + int())
def test_comparisons() -> None:
one: u8 = 1 + int()
one2: u8 = 1 + int()
two: u8 = 2 + int()
assert one < two
assert not (one < one2)
assert not (two < one)
assert two > one
assert not (one > one2)
assert not (one > two)
assert one <= two
assert one <= one2
assert not (two <= one)
assert two >= one
assert one >= one2
assert not (one >= two)
assert one == one2
assert not (one == two)
assert one != two
assert not (one != one2)
def test_mixed_comparisons() -> None:
u8_3: u8 = int() + 3
int_5 = int() + 5
assert u8_3 < int_5
assert int_5 > u8_3
b = u8_3 > int_5
assert not b
int_largest = int() + 255
assert int_largest > u8_3
int_smallest = int()
assert u8_3 > int_smallest
int_too_big = int() + 256
int_too_small = int() -1
with assertRaises(OverflowError):
assert u8_3 < int_too_big
with assertRaises(OverflowError):
assert int_too_big < u8_3
with assertRaises(OverflowError):
assert u8_3 > int_too_small
with assertRaises(OverflowError):
assert int_too_small < u8_3
def test_mixed_arithmetic_and_bitwise_ops() -> None:
u8_3: u8 = int() + 3
int_5 = int() + 5
assert u8_3 + int_5 == 8
assert int_5 - u8_3 == 2
assert u8_3 << int_5 == 96
assert int_5 << u8_3 == 40
assert u8_3 ^ int_5 == 6
assert int_5 | u8_3 == 7
int_largest = int() + 255
assert int_largest - u8_3 == 252
int_smallest = int()
assert int_smallest + u8_3 == 3
int_too_big = int() + 256
int_too_small = int() - 1
with assertRaises(OverflowError):
assert u8_3 & int_too_big
with assertRaises(OverflowError):
assert int_too_small & u8_3
def test_coerce_to_and_from_int() -> None:
for n in range(0, 256):
x: u8 = n
m: int = x
assert m == n
def test_explicit_conversion_to_u8() -> None:
x = u8(5)
assert x == 5
y = int() + ERROR
x = u8(y)
assert x == ERROR
n64: i64 = 233
x = u8(n64)
assert x == 233
n32: i32 = 234
x = u8(n32)
assert x == 234
z = u8(x)
assert z == 234
n16: i16 = 231
x = u8(n16)
assert x == 231
def test_explicit_conversion_overflow() -> None:
max_u8 = int() + 255
x = u8(max_u8)
assert x == 255
assert int(x) == max_u8
min_u8 = int()
y = u8(min_u8)
assert y == 0
assert int(y) == min_u8
too_big = int() + 256
with assertRaises(OverflowError):
x = u8(too_big)
too_small = int() - 1
with assertRaises(OverflowError):
x = u8(too_small)
def test_u8_from_large_small_literal() -> None:
x = u8(255) # XXX u8(2**15 - 1)
assert x == 255
x = u8(0)
assert x == 0
def test_u8_truncate_from_i64() -> None:
large = i64(2**32 + 256 + 157 + int())
x = u8(large)
assert x == 157
small = i64(-2**32 - 256 - 157 + int())
x = u8(small)
assert x == 256 - 157
large2 = i64(2**8 + int())
x = u8(large2)
assert x == 0
small2 = i64(-2**8 - 1 - int())
x = u8(small2)
assert x == 255
def test_u8_truncate_from_i32() -> None:
large = i32(2**16 + 2**8 + 5 + int())
assert u8(large) == 5
small = i32(-2**16 - 2**8 - 1 + int())
assert u8(small) == 255
def from_float(x: float) -> u8:
return u8(x)
def test_explicit_conversion_from_float() -> None:
assert from_float(0.0) == 0
assert from_float(1.456) == 1
assert from_float(234.567) == 234
assert from_float(255) == 255
assert from_float(0) == 0
assert from_float(-0.999) == 0
# The error message could be better, but this is acceptable
with assertRaises(OverflowError, "int too large or small to convert to u8"):
assert from_float(float(256))
with assertRaises(OverflowError, "int too large or small to convert to u8"):
# One ulp below the lowest valid i64 value
from_float(float(-1.0))
def test_tuple_u8() -> None:
a: u8 = 1
b: u8 = 2
t = (a, b)
a, b = t
assert a == 1
assert b == 2
x: Any = t
tt: Tuple[u8, u8] = x
assert tt == (1, 2)
def test_convert_u8_to_native_int() -> None:
for i in range(256):
x: u8 = i
assert i16(x) == i
assert i32(x) == i
assert i64(x) == i