[case testEmptyClass]
class Empty: pass

def f(e: Empty) -> Empty:
    return e
[file driver.py]
from native import Empty, f

print(isinstance(Empty, type))
print(Empty)
print(str(Empty())[:20])

e = Empty()
print(f(e) is e)
[out]
True
<class 'native.Empty'>
<native.Empty object
True

[case testClassWithFields]
class C:
    x: int
    y: int
    z: 'D'
class D:
    pass
[file driver.py]
from native import C

c = C()
assert not hasattr(c, 'x')
assert not hasattr(c, 'y')
c.x = 1
c.y = 2
print(c.x)
print(c.y)
c.x = 10**30
print(c.x)
c.x = 10**30+1
print(c.x)
assert hasattr(c, 'x')
assert hasattr(c, 'y')
assert not hasattr(c, 'z')
del c.x
assert not hasattr(c, 'x')
assert hasattr(c, 'y')
del c.y
assert not hasattr(c, 'y')
c.x = 10**30+2
print(c.x)
assert hasattr(c, 'x')
[out]
1
2
1000000000000000000000000000000
1000000000000000000000000000001
1000000000000000000000000000002

[case testNonExtMisc]
from typing import Any, overload

def decorator(cls) -> Any:
    return cls

@decorator
class C:
    def __init__(self) -> None:
        self.c = 3

    def get_c(self) -> int:
        return self.c

@decorator
class B(C):
    def __init__(self) -> None:
        super().__init__()
        self.b = 2

    def get_b(self) -> int:
        return self.b

@decorator
class A(B):
    def __init__(self) -> None:
        super().__init__()
        self.a = 1

    @classmethod
    def constant(cls) -> int:
        return 4

    def get_a(self) -> int:
        return self.a

@decorator
class Overload:
    @overload
    def get(self, index: int) -> int: ...

    @overload
    def get(self, index: str) -> str: ...

    def get(self, index: Any) -> Any:
        return index

def get(c: Overload, s: str) -> str:
    return c.get(s)

[file driver.py]
from native import A, Overload, get
a = A()
assert a.a == 1
assert a.b == 2
assert a.c == 3
assert a.get_a() == 1
assert a.get_b() == 2
assert a.get_c() == 3
assert A.constant() == 4

o = Overload()
assert get(o, "test") == "test"
assert o.get(20) == 20

[case testEnum]
from enum import Enum

class TestEnum(Enum):
    _order_ = "a b"
    a : int = 1
    b : int = 2

    @classmethod
    def test(cls) -> int:
        return 3

assert TestEnum.test() == 3

[file other.py]
# Force a multi-module test to make sure we can compile multi-file with
# non-extension classes

[file driver.py]
import sys
# "_order_" isn't supported in 3.5
if sys.version_info[:2] > (3, 5):
    from native import TestEnum
    assert TestEnum.a.name == 'a'
    assert TestEnum.a.value == 1
    assert TestEnum.b.name == 'b'
    assert TestEnum.b.value == 2

[case testGetAttribute]
class C:
    x: int
    y: int

def getx(c: C) -> int:
    return c.x

def gety(c: C) -> int:
    return c.y
[file driver.py]
from native import C, getx, gety
c = C()
c.x = 10**30
c.y = 10**30 + 1
print(getx(c))
print(gety(c))
[out]
1000000000000000000000000000000
1000000000000000000000000000001

[case testSetAttribute]
class C:
    x: int
    y: int

def setx(c: C, v: int) -> None:
    c.x = v

def sety(c: C, v: int) -> None:
    c.y = v
[file driver.py]
from native import C, setx, sety
c = C()
setx(c, 10**30)
sety(c, 10**30 + 1)
print(c.x)
print(c.y)
setx(c, 4)
sety(c, 5)
print(c.x, c.y)
setx(c, 10**30 + 2)
sety(c, 10**30 + 3)
print(c.x)
print(c.y)
[out]
1000000000000000000000000000000
1000000000000000000000000000001
4 5
1000000000000000000000000000002
1000000000000000000000000000003

[case testAttributeTypes]
from typing import List, Tuple
class C:
    a: List[int]
    b: bool
    c: C
    d: object

def setattrs(o: C, a: List[int], b: bool, c: C) -> None:
    o.a = a
    o.b = b
    o.c = c

def getattrs(o: C) -> Tuple[List[int], bool, C]:
    return o.a, o.b, o.c
[file driver.py]
from native import C, setattrs, getattrs
c1 = C()
c2 = C()
aa = [2]
setattrs(c1, aa, True, c2)
a, b, c = getattrs(c1)
assert a is aa
assert b is True
assert c is c2

o = object()
c1.d = o
assert c1.d is o

[case testInitMethodWithMissingNoneReturnAnnotation]
class C:
    def __init__(self):
        self.x = 42
[file driver.py]
from native import C
c = C()
assert c is not None
assert c.x == 42

[case testConstructClassWithDefaultConstructor]
class C:
    a: int
    b: int

def f() -> C:
    c = C()
    c.a = 13
    return c
[file driver.py]
from native import f, C
c = f()
assert c.a == 13
assert type(c) == C
assert not hasattr(c, 'b')

[case testCastUserClass]
from typing import List

class C:
    x: int

def f(a: List[C]) -> C:
    return a[0]
[file driver.py]
from native import f, C
c = C()
assert f([c]) is c

[case testClass1]
class A:
    def __init__(self, x: int) -> None:
        self.x = x
    def foo(self) -> int:
        return self.x+1
def foo() -> int:
    a = A(20)
    return a.foo()
[file driver.py]
from native import A, foo
a = A(10)
assert a.foo() == 11
assert foo() == 21

[case testGenericClass]
from typing import TypeVar, Generic, Sequence
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

# Test subclassing generic classes both with and without a generic param
class A(Sequence[int]):
    pass
class B(Sequence[T]):
    pass

def f(c: C[int]) -> int:
    y = c.get()
    d = C[int](2)
    c.set(c.get() + 1 + d.get())
    c.x = c.x + 2
    return c.x

[file driver.py]
from native import C, f
c = C(6)
assert f(c) == 11
c.x = 'x'
assert c.x == 'x'
c.set([1])
assert c.x == [1]
assert c.get() == [1]

[case testSubclass1]
from typing import Tuple

class A:
    def __init__(self) -> None:
        self.x = 10
    def hi(self, suffix: str) -> str:
        return str(self.x) + suffix
class B(A):
    def __init__(self) -> None:
        self.x = 20
        self.y = 'world'
    def hi(self, suffix: str) -> str:
        return 'hello ' + str(self.y) + suffix

def use_a(x: A) -> Tuple[int, str]:
    return (x.x, x.hi(''))
def use_b(x: B) -> str:
    return x.hi('')

[file driver.py]
from native import A, B, use_a, use_b
a = A()
b = B()
assert use_a(a) == (10, '10')
assert use_a(b) == (20, 'hello world')
assert a.x == 10
assert b.x == 20
assert b.y == 'world'
assert a.hi('!') == '10!'
assert b.hi('!') == 'hello world!'
assert use_b(b) == 'hello world'

[case testSubclassSpecialize1]
class A:
    def foo(self, x: int) -> object:
        print('A')
        return str(x)
    def bar(self, x: int) -> None:
        print(x + 1)
class B(A):
    def foo(self, x: object) -> int:
        print('B')
        return id(x)
    def bar(self, x: object) -> None:
        print(x)

def use_a(x: A, y: int) -> object:
    x.bar(10)
    return x.foo(y)

def use_b(x: B, y: object) -> int:
    return x.foo(y)

[file driver.py]
from native import A, B, use_a, use_b
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_b(b, o) == id(o)
assert use_a(b, i) == id(i)
[out]
A
B
11
A
B
10
B

[case testSubclassSpecialize2]
class A:
    def foo(self, x: int) -> object:
        print('A')
        return str(x)
class B(A):
    def foo(self, x: object) -> object:
        print('B')
        return x
class C(B):
    def foo(self, x: object) -> int:
        print('C')
        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)

[file driver.py]
from native import A, B, C, use_a, use_b, use_c
a = A()
b = B()
c = C()
o = object()
i = 10
assert a.foo(10) == '10'
assert b.foo(o) == o
assert c.foo(o) == id(o)
assert use_a(a, 10) == '10'
assert use_a(b, i) is i
assert use_a(c, i) == id(i)
assert use_b(b, o) == o
assert use_b(c, o) == id(o)
assert use_c(c, o) == id(o)
[out]
A
B
C
A
B
C
B
C
C

[case testIsInstance]
from typing import Optional
class X: pass
class A(X): pass
class B(A): pass

def isa(x: object) -> bool:
    return isinstance(x, A)
def isint(x: object) -> bool:
    return isinstance(x, int)
def isstr(x: object) -> bool:
    return isinstance(x, str)
def islist(x: object) -> bool:
    return isinstance(x, list)
def ist(x: object, t: object) -> bool:  # TODO: Second argument should be 'type'
    return isinstance(x, t)
def pointless(x: Optional[X]) -> str:
    if isinstance(x, A):
        return str(x)
    return ''
[file driver.py]
from native import X, A, B, isa, isint, isstr, islist, ist
assert isa(1) == False
assert isa(A()) == True
assert isa(B()) == True
assert isa(X()) == False

assert isint(1) == True
assert isint('') == False
assert isint(A()) == False

assert isstr(1) == False
assert isstr('') == True

assert islist(1) == False
assert islist([]) == True

assert ist(1, int) == True
assert ist(1, str) == False
try:
    ist(1, 2)
except TypeError:
    pass
else:
    assert False

[case testSubclassUninitAttr]
class X:
    x: int
class A(X):
    pass
[file driver.py]
import traceback
from native import A
try:
    A().x
except AttributeError:
    traceback.print_exc()
[out]
Traceback (most recent call last):
  File "driver.py", line 4, in <module>
    A().x
AttributeError: attribute 'x' of 'X' undefined

[case testClassMethods]
MYPY = False
if MYPY:
    from typing import ClassVar
class C:
    lurr: 'ClassVar[int]' = 9
    @staticmethod
    def foo(x: int) -> int: return 10 + x
    @classmethod
    def bar(cls, x: int) -> int: return cls.lurr + x
    @staticmethod
    def baz(x: int, y: int = 10) -> int: return y - x
    @classmethod
    def quux(cls, x: int, y: int = 10) -> int: return y - x

class D(C):
    def f(self) -> int:
        return super().foo(1) + super().bar(2) + super().baz(10) + super().quux(10)

def test1() -> int:
    return C.foo(1) + C.bar(2) + C.baz(10) + C.quux(10) + C.quux(y=10, x=9)
def test2() -> int:
    c = C()
    return c.foo(1) + c.bar(2) + c.baz(10)
[file driver.py]
from native import *
assert C.foo(10) == 20
assert C.bar(10) == 19
c = C()
assert c.foo(10) == 20
assert c.bar(10) == 19

assert test1() == 23
assert test2() == 22

d = D()
assert d.f() == 22

[case testSuper]
from mypy_extensions import trait
from typing import List

class A:
    def __init__(self, x: int) -> None:
        self.x = x

    def foo(self, x: int) -> int:
        return x

class B(A):
    def __init__(self, x: int, y: int) -> None:
        super().__init__(x)
        self.y = y

    def foo(self, x: int) -> int:
        return super().foo(x+1)

class C(B):
    def __init__(self, x: int, y: int) -> None:
        init = super(C, self).__init__
        init(x, y+1)

    def foo(self, x: int) -> int:
        # should go to A, not B
        return super(B, self).foo(x+1)

class X:
    def __init__(self, x: int) -> None:
        self.x = x
class Y(X):
    pass
class Z(Y):
    def __init__(self, x: int, y: int) -> None:
        super().__init__(x)
        self.y = y

@trait
class T:
    def v_int(self, x: int) -> None: pass
    def v_list(self, x: List[int]) -> None:
        if x:
            self.v_int(x[0])
            self.v_list(x[1:])

class PrintList(T):
    def v_int(self, x: int) -> None:
        print(x)
    def v_list(self, x: List[int]) -> None:
        print('yo!')
        super().v_list(x)

[file driver.py]
import traceback
from native import *
b = B(10, 20)
assert b.x == 10 and b.y == 20
c = C(10, 20)
assert c.x == 10 and c.y == 21
z = Z(10, 20)
assert z.x == 10 and z.y == 20

assert c.foo(10) == 11

PrintList().v_list([1,2,3])
[out]
yo!
1
yo!
2
yo!
3
yo!

[case testSubclassException]
class Failure(Exception):
    def __init__(self, x: int) -> None:
        self.x = x

def foo() -> None:
    raise Failure(10)

def heyo() -> int:
    try:
        foo()
    except Failure as e:
        return e.x
    return -1

[file driver.py]
from native import foo, heyo, Failure
try:
    foo()
except Failure as e:
    assert str(e) == '10'
    assert e.x == 10
heyo()

[case testSubclassDict]
from typing import Dict
class WelpDict(Dict[str, int]):
    def __init__(self) -> None:
        self.emarhavil = 3
    def foo(self) -> int:
        return self.emarhavil

def welp() -> int:
    x = WelpDict()
    x['a'] = 10
    x['b'] = 15
    x.emarhavil = 5
    return x['a'] + x['b'] + x.emarhavil + x.foo()

[file driver.py]
from native import welp
assert welp() == 35

[case testSubclassPy]
from b import B, V
class A(B):
    def __init__(self, x: int, y: int) -> None:
        super().__init__(y)
        self.x = x

    def foo(self, x: int) -> int:
        print("hi", x)
        return x+1

class C(V[int]):
    def f(self) -> int: return 10

assert isinstance(C(), V)

def f(x: A) -> None:
    print(x.x)
    print(x.y)
    print(x.foo(20))

[file b.py]
from typing import Generic, TypeVar
T = TypeVar('T')

class B:
    def __init__(self, y: int) -> None:
        self.y = y
    def foo(self, x: int) -> int:
        print("parent!")
        return x + self.y
    def bar(self) -> None:
        print("hello!", self.y)

class V(Generic[T]):
    def f(self) -> T:
        raise Exception('unimplemented')
[file driver.py]
import native
a = native.A(10, 20)
a.foo(10)
a.bar()
native.f(a)
[out]
hi 10
hello! 20
10
20
hi 20
21

[case testDisallowSubclassFromPy]
# We'll want to allow this at some point but right now we need to
# disallow it because it doesn't work.
class A:
    pass
[file b.py]
from native import A

# It would be better if we disallowed it at class decl time but it is
# really easy to do in __new__

class B(A):
    pass

[file driver.py]
from b import B
try:
    B()
except TypeError:
    pass
else:
    assert False, "instantiating was supposed to fail"

[case testClassVariable]
MYPY = False
if MYPY:
    from typing import ClassVar
class A:
    x = 10  # type: ClassVar[int]

def g(x: int) -> None:
    A.x = 10
def f() -> int:
    return A.x
[file driver.py]
from native import A, f
assert f() == 10
A.x = 200
assert f() == 200

[case testDefaultVars]
from typing import Optional
class A:
    x = 10
    w: object = 10
    def lol(self) -> None:
        self.x = 100

LOL = 'lol'
class B(A):
    y = LOL
    z = None  # type: Optional[str]
    b = True
    bogus = None  # type: int

def g() -> None:
    a = A()
    assert a.x == 10
    a.x = 20
    assert a.x == 20
    b = B()
    assert b.x == 10
    b.x = 20
    assert b.x == 20
    assert b.y == 'lol'
    b.y = 'rofl'
    assert b.y == 'rofl'
    assert b.z is None
[file driver.py]
from native import *
g()

a = A()
assert a.x == 10
a.x = 20
assert a.x == 20
b = B()
assert b.x == 10
b.x = 20
assert b.x == 20
assert b.y == 'lol'
b.y = 'rofl'
assert b.y == 'rofl'
assert b.z is None
# N.B: this doesn't match cpython
assert not hasattr(b, 'bogus')

[case testProtocol]
from typing_extensions import Protocol

class Proto(Protocol):
    def foo(self, x: int) -> None:
        pass

    def bar(self, x: int) -> None:
        pass

class A:
    def foo(self, x: int) -> None:
        print("A:", x)

    def bar(self, *args: int, **kwargs: int) -> None:
        print("A:", args, kwargs)

class B(A, Proto):
    def foo(self, x: int) -> None:
        print("B:", x)

    def bar(self, *args: int, **kwargs: int) -> None:
        print("B:", args, kwargs)

def f(x: Proto) -> None:
    x.foo(20)
    x.bar(x=20)

[file driver.py]
from native import A, B, f

f(A())
f(B())

# ... this exploits a bug in glue methods to distinguish whether we
# are making a direct call or a pycall...
[out]
A: 20
A: () {'x': 20}
B: 20
B: (20,) {}

[case testMethodOverrideDefault1]
class A:
    def foo(self, x: int) -> None:
        pass
class B(A):
    def foo(self, x: int, y: int = 10) -> None:
        print(x, y)

def a(x: A) -> None:
    x.foo(1)
def b(x: B) -> None:
    x.foo(2)
    x.foo(2, 3)

[file driver.py]
from native import B, a, b
a(B())
b(B())
[out]
1 10
2 10
2 3

[case testMethodOverrideDefault2]
class A:
    def foo(self, *, x: int = 0) -> None:
        pass
    def bar(self, *, x: int = 0, y: int = 0) -> None:
        pass
    def baz(self, x: int = 0) -> None:
        pass
class B(A):
    def foo(self, *, y: int = 0, x: int = 0) -> None:
        print(x, y)
    def bar(self, *, y: int = 0, x: int = 0) -> None:
        print(x, y)
    def baz(self, x: int = 0, *, y: int = 0) -> None:
        print(x, y)

def a(x: A) -> None:
    x.foo(x=1)
    x.bar(x=1, y=2)
    x.bar(x=2, y=1)
    x.baz()
    x.baz(1)
    x.baz(x=2)

[file driver.py]
from native import B, a
a(B())
[out]
1 0
1 2
2 1
0 0
1 0
2 0

[case testMethodOverrideDefault3]
class A:
    @classmethod
    def foo(cls, *, x: int = 0) -> None:
        pass
    @staticmethod
    def bar(*, x: int = 0) -> None:
        pass
    @staticmethod
    def baz() -> object:
        pass
class B(A):
    @classmethod
    def foo(cls, *, y: int = 0, x: int = 0) -> None:
        print(x, y)
        print(cls.__name__)  # type: ignore
    @staticmethod
    def bar(*, y: int = 0, x: int = 0) -> None:
        print(x, y)
    @staticmethod
    def baz() -> int:
        return 10

# This is just to make sure that this stuff works even when the
# methods might be overridden.
class C(B):
    @classmethod
    def foo(cls, *, y: int = 0, x: int = 0) -> None:
        pass
    @staticmethod
    def bar(*, y: int = 0, x: int = 0) -> None:
        pass
    @staticmethod
    def baz() -> int:
        return 10

def a(x: A) -> None:
    x.foo(x=1)
    x.bar(x=1)
    print(x.baz())

[file driver.py]
from native import B, a
a(B())
[out]
1 0
B
1 0
10

[case testOverride]
class A:
    def f(self) -> int:
        return 0
    def g(self) -> int:
        return 1

class B(A):
    def g(self) -> int:
        return 2

class C(B):
    def f(self) -> int:
        return 3

def test() -> None:
    ba: A = B()
    ca: A = C()
    assert ba.f() == 0
    assert ba.g() == 2
    assert ca.f() == 3
    assert ca.g() == 2
    cc = C()
    assert cc.f() == 3
    assert cc.g() == 2
    print('ok')
[file driver.py]
import native
native.test()
[out]
ok

[case testNoMetaclass]
from foo import Base

class Nothing(Base):  # type: ignore
    pass

[file foo.py]
from typing import Any
class Meta(type):
    pass

class _Base(metaclass=Meta):
    pass
Base = _Base  # type: Any

[file driver.py]
try:
    import native
except TypeError as e:
    assert(str(e) == "mypyc classes can't have a metaclass")

[case testMetaclass]
from meta import Meta
import six

class Nothing1(metaclass=Meta):
    pass

def ident(x): return x

@ident
class Test:
    pass

class Nothing2(six.with_metaclass(Meta, Test)):
    pass

@six.add_metaclass(Meta)
class Nothing3:
    pass

[file meta.py]
from typing import Any
class Meta(type):
    def __new__(mcs, name, bases, dct):
        dct['X'] = 10
        return super().__new__(mcs, name, bases, dct)


[file driver.py]
from native import Nothing1, Nothing2, Nothing3
assert Nothing1.X == 10
assert Nothing2.X == 10
assert Nothing3.X == 10

[case testPickling]
from mypy_extensions import trait
from typing import Any, TypeVar, Generic

def dec(x: Any) -> Any:
    return x

class A:
    x: int
    y: str

class B(A):
    z: bool

    def __init__(self, x: int, y: str, z: bool) -> None:
        self.x = x
        self.y = y
        self.z = z

@trait
class T:
    a: str

class C(B, T):
    w: object

    # property shouldn't go in
    @property
    def foo(self) -> int:
        return 0

@dec
class D:
    x: int

class E(D):
    y: int


U = TypeVar('U')

class F(Generic[U]):
    y: int

class G(F[int]):
    pass

[file driver.py]
from native import A, B, T, C, D, E, F, G

import copy
import pickle

assert A.__mypyc_attrs__ == ('x', 'y')
assert B.__mypyc_attrs__ == ('z', 'x', 'y')
assert T.__mypyc_attrs__ == ('a',)
assert C.__mypyc_attrs__ == ('w', 'z', 'x', 'y', 'a')
assert not hasattr(D, '__mypyc_attrs__')
assert E.__mypyc_attrs__ == ('y', '__dict__')
assert F.__mypyc_attrs__ == ('y', '__dict__')
assert G.__mypyc_attrs__ == ('y', '__dict__')

b = B(10, '20', False)
assert b.__getstate__() == {'z': False, 'x': 10, 'y': '20'}
b2 = copy.copy(b)
assert b is not b2 and b.y == b2.y

b3 = pickle.loads(pickle.dumps(b))
assert b is not b3 and b.y == b3.y

e = E()
e.x = 10
e.y = 20

assert e.__getstate__() == {'y': 20, '__dict__': {'x': 10}}
e2 = pickle.loads(pickle.dumps(e))
assert e is not e2 and e.x == e2.x and e.y == e2.y


[case testInterpretedParentInit]
from interp import C
from typing import TypeVar

T = TypeVar('T')

def dec(x: T) -> T:
    return x

@dec
class A:
    def __init__(self, x: int) -> None:
        self.x = x

class B(A):
    s = 'test'

def b(x: int) -> B: return B(x)

class D(C):
    s = 'test'

def d(x: int) -> D: return D(x)


[file interp.py]
class C:
    def __init__(self, x: int) -> None:
        self.x = x

[file driver.py]
from native import b, d, B, D

def test(f, v):
    x = f(v)
    assert x.x == v
    assert x.s == 'test'

test(b, 20)
test(d, 30)
test(B, -1)
test(D, -2)

[case testInterpretedInherit]
from typing import TypeVar, Any, overload
from mypy_extensions import mypyc_attr, trait

T = TypeVar('T')
def dec(x: T) -> T: return x

@mypyc_attr(allow_interpreted_subclasses=True)
class Top:
    def spam(self) -> str:
        return "grandparent"

@mypyc_attr(allow_interpreted_subclasses=True)
@trait
class Trait:
    def trait_method(self) -> str:
        return "trait"

@mypyc_attr(allow_interpreted_subclasses=True)
class Foo(Top, Trait):
    def __init__(self, x: int) -> None:
        self.x = x

    def foo(self) -> str:
        return "parent foo: " + self.bar(self.x)

    def bar(self, x: int) -> str:
        return "parent bar: {}".format(x + self.x)

    @dec
    def decorated(self) -> str:
        return "decorated parent"

    @property
    def read_property(self) -> str:
        return "parent prop"

    @overload
    def overloaded(self, index: int) -> int: ...

    @overload
    def overloaded(self, index: str) -> str: ...

    def overloaded(self, index: Any) -> Any:
        return index

def foo(x: Foo) -> str:
    return x.foo()

def bar(x: Foo, y: int) -> str:
    return x.bar(y)

def spam(x: Top) -> str:
    return x.spam()

def decorated(x: Foo) -> str:
    return x.decorated()

def prop(x: Foo) -> str:
    return x.read_property

def trait_method(x: Trait) -> str:
    return x.trait_method()

def overloaded(x: Foo, s: str) -> str:
    return x.overloaded(s)

[file interp.py]
from typing import Any
from native import Foo

class Bar(Foo):
    def bar(self, x: int) -> str:
        return "child bar: {}".format(x + self.x)

    def spam(self) -> str:
        assert super().spam() == "grandparent"
        return "child"

    @property
    def read_property(self) -> str:
        return "child prop"

    def decorated(self) -> str:
        return "decorated child"

    def trait_method(self) -> str:
        return "child"

    def overloaded(self, index: Any) -> Any:
        return index + index


class InterpBase:
    def eggs(self) -> str:
        return "eggs"

class Baz(InterpBase, Bar):
    def __init__(self) -> None:
        super().__init__(1000)
        self.z = self.read_property

[file driver.py]
from native import Foo, foo, bar, spam, decorated, overloaded, prop, trait_method
from interp import Bar, Baz
from unittest.mock import patch
from testutil import assertRaises

x = Foo(10)
y = Bar(20)
z = Baz()

assert isinstance(y, Bar)
assert y.x == 20
assert y.bar(10) == "child bar: 30"
assert y.foo() == "parent foo: child bar: 40"
assert foo(y) == "parent foo: child bar: 40"
assert bar(y, 30) == "child bar: 50"
y.x = 30
assert bar(y, 30) == "child bar: 60"

assert spam(y) == "child"
assert y.read_property == "child prop"
assert prop(x) == "parent prop"
assert prop(y) == "child prop"
assert y.decorated() == "decorated child"
assert decorated(y) == "decorated child"
assert y.overloaded("test") == "testtest"
assert overloaded(y, "test") == "testtest"

assert y.trait_method() == "child"
assert trait_method(y) == "child"

assert z.bar(10) == "child bar: 1010"
assert bar(z, 10) == "child bar: 1010"
assert z.z == "child prop"
assert z.eggs() == "eggs"

with patch("interp.Bar.spam", lambda self: "monkey patched"):
    assert y.spam() == "monkey patched"
    spam(y) == "monkey patched"

with patch("interp.Bar.spam", lambda self: 20):
    assert y.spam() == 20
    with assertRaises(TypeError, "str object expected; got int"):
        spam(y)

with assertRaises(TypeError, "int object expected; got str"):
    y.x = "test"

[case testProperty]
from typing import Callable
from mypy_extensions import trait
class Temperature:
    @property
    def celsius(self) -> float:
        return 5.0 * (self.farenheit - 32.0) / 9.0

    def __init__(self, farenheit: float) -> None:
        self.farenheit = farenheit

    def print_temp(self) -> None:
        print("F:", self.farenheit, "C:", self.celsius)

    @property
    def rankine(self) -> float:
        raise NotImplementedError

class Access:
    @property
    def number_of_accesses(self) -> int:
        self._count += 1
        return self._count
    def __init__(self) -> None:
        self._count = 0

from typing import Callable
class BaseProperty:
    @property
    def doc(self) -> str:
        return "Represents a sequence of values. Updates itself by next, which is a new value."

    @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

    def __init__(self, incr_func: Callable[[int], int], value: int) -> None:
        BaseProperty.__init__(self, value)
        self._incr_func = incr_func

    @property
    def next(self) -> DerivedProperty:
        return DerivedProperty(self._incr_func, self._incr_func(self.value))

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

def print_first_n(n: int, thing: BaseProperty) -> None:
    vals = []
    cur_thing = thing
    for _ in range(n):
        vals.append(cur_thing.value)
        cur_thing = cur_thing.next
    print ('', vals)

@trait
class Trait:
    @property
    def value(self) -> int:
        return 3

class Printer(Trait):
    def print_value(self) -> None:
        print(self.value)

[file driver.py]
from native import Temperature, Access
import traceback
x = Temperature(32.0)
try:
    print (x.rankine)
except NotImplementedError as e:
    traceback.print_exc()
print (x.celsius)
x.print_temp()

y = Temperature(212.0)
print (y.celsius)
y.print_temp()

z = Access()
print (z.number_of_accesses)
print (z.number_of_accesses)
print (z.number_of_accesses)
print (z.number_of_accesses)

from native import BaseProperty, DerivedProperty, AgainProperty, print_first_n
a = BaseProperty(7)
b = DerivedProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7)
c = AgainProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7)

def py_print_first_n(n: int, thing: BaseProperty) -> None:
    vals = []
    cur_thing = thing
    for _ in range(n):
        vals.append(cur_thing.value)
        cur_thing = cur_thing.next
    print ('', vals)

py_print_first_n(20, a)
py_print_first_n(20, b)
py_print_first_n(20, c)

print(a.next.next.next.bad_value)
print(b.next.next.next.bad_value)
print(c.next.next.next.bad_value)

print_first_n(20, a)
print_first_n(20, b)
print_first_n(20, c)

print (a.doc)
print (b.doc)
print (c.doc)

from native import Printer
Printer().print_value()
print (Printer().value)
[out]
Traceback (most recent call last):
  File "driver.py", line 5, in <module>
    print (x.rankine)
  File "native.py", line 16, in rankine
    raise NotImplementedError
NotImplementedError
0.0
F: 32.0 C: 0.0
100.0
F: 212.0 C: 100.0
1
2
3
4
 [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
 [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1]
 [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4]
10
34
26
 [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
 [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1]
 [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4]
Represents a sequence of values. Updates itself by next, which is a new value.
Represents a sequence of values. Updates itself by next, which is a new value.
Represents a sequence of values. Updates itself by next, which is a new value.
3
3

[case testPropertySetters]

from mypy_extensions import trait

class Foo():
    def __init__(self) -> None:
        self.attr = "unmodified"

class A:
    def __init__(self) -> None:
        self._x = 0
        self._foo = Foo()

    @property
    def x(self) -> int:
        return self._x

    @x.setter
    def x(self, val : int) -> None:
        self._x = val

    @property
    def foo(self) -> Foo:
        return self._foo

    @foo.setter
    def foo(self, val : Foo) -> None:
        self._foo = val

# Overrides base property setters and getters
class B(A):
    def __init__(self) -> None:
        self._x = 10

    @property
    def x(self) -> int:
        return self._x + 1

    @x.setter
    def x(self, val : int) -> None:
        self._x = val + 1

#Inerits base property setters and getters
class C(A):
    def __init__(self) -> None:
        A.__init__(self)

@trait
class D():
    def __init__(self) -> None:
        self._x = 0

    @property
    def x(self) -> int:
        return self._x

    @x.setter
    def x(self, val : int) -> None:
        self._x = val

#Inherits trait property setters and getters
class E(D):
    def __init__(self) -> None:
        D.__init__(self)

#Overrides trait property setters and getters
class F(D):
    def __init__(self) -> None:
        self._x = 10

    @property
    def x(self) -> int:
        return self._x + 10

    @x.setter
    def x(self, val : int) -> None:
        self._x = val + 10

# # Property setter and getter are subtypes of base property setters and getters
# # class G(A):
# #   def __init__(self) -> None:
# #       A.__init__(self)

# #   @property
# #   def y(self) -> int:
# #       return self._y

# #   @y.setter
# #   def y(self, val : object) -> None:
# #       self._y = val

[file other.py]
# Run in both interpreted and compiled mode

from native import A, B, C, D, E, F

a = A()
assert a.x == 0
assert a._x == 0
a.x = 1
assert a.x == 1
assert a._x == 1
a._x = 0
assert a.x == 0
assert a._x == 0
b = B()
assert b.x == 11
assert b._x == 10
b.x = 11
assert b.x == 13
b._x = 11
assert b.x == 12
c = C()
assert c.x == 0
c.x = 1000
assert c.x == 1000
e = E()
assert e.x == 0
e.x = 1000
assert e.x == 1000
f = F()
assert f.x == 20
f.x = 30
assert f.x == 50

[file driver.py]
# Run the tests in both interpreted and compiled mode
import other
import other_interpreted

[out]

[case testSubclassAttributeAccess]
from mypy_extensions import trait

class A:
    v = 0

class B(A):
    v = 1

class C(B):
    v = 2

[file driver.py]
from native import A, B, C

a = A()
b = B()
c = C()
