blob: 54f5343bc7bb8f32238249fc8cb270b85e81ab4b [file] [log] [blame] [edit]
[case testEmptyClass]
class Empty: pass
def f(e: Empty) -> Empty:
return e
class EmptyEllipsis: ...
def g(e: EmptyEllipsis) -> EmptyEllipsis:
return e
[file driver.py]
from native import Empty, EmptyEllipsis, f, g
print(isinstance(Empty, type))
print(Empty)
print(str(Empty())[:20])
e = Empty()
print(f(e) is e)
print(isinstance(EmptyEllipsis, type))
print(EmptyEllipsis)
print(str(EmptyEllipsis())[:28])
e2 = EmptyEllipsis()
print(g(e2) is e2)
[out]
True
<class 'native.Empty'>
<native.Empty object
True
True
<class 'native.EmptyEllipsis'>
<native.EmptyEllipsis object
True
[case testClassWithFields]
class C:
x: int
y: int
z: 'D'
class D:
pass
[file driver.py]
from native import C
from testutil import assertRaises
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')
with assertRaises(AttributeError, "'C' object attribute 'x' cannot be deleted"):
del c.x
assert hasattr(c, 'x')
assert hasattr(c, 'y')
with assertRaises(AttributeError, "'C' object attribute 'y' cannot be deleted"):
del c.y
assert hasattr(c, 'y')
c.x = 10**30+2
print(c.x)
assert hasattr(c, 'x')
[out]
1
2
1000000000000000000000000000000
1000000000000000000000000000001
1000000000000000000000000000002
[case testTypedDictWithFields]
import collections
import json
from typing import TypedDict
class C(TypedDict):
x: collections.deque
spam: json.JSONDecoder
[file driver.py]
from native import C
from collections import deque
from json import JSONDecoder
print(C.__annotations__["x"] is deque)
print(C.__annotations__["spam"] is JSONDecoder)
[typing fixtures/typing-full.pyi]
[out]
True
True
[case testClassWithDeletableAttributes]
from typing import Any, cast
from testutil import assertRaises
class C:
__deletable__ = ['x', 'y']
x: int
y: int
z: int
def test_delete() -> None:
c = C()
c.x = 1
c.y = 2
c.z = 3
del c.x
del c.y
assert c.z == 3
with assertRaises(AttributeError, "attribute 'x' of 'C' undefined"):
c.x
with assertRaises(AttributeError, "attribute 'y' of 'C' undefined"):
c.y
def test_delete_any() -> None:
c: Any = C()
c.x = 1
c.y = 2
c.z = 3
del c.x
del c.y
with assertRaises(AttributeError, "'C' object attribute 'z' cannot be deleted"):
del c.z
assert c.z == 3
with assertRaises(AttributeError):
c.x
with assertRaises(AttributeError):
c.y
class Base:
__deletable__ = ['a']
a: int
b: int
class Deriv(Base):
__deletable__ = ('c',)
c: str
d: str
def test_delete_with_inheritance() -> None:
d = Deriv()
d.a = 0
d.b = 1
d.c = 'X'
d.d = 'Y'
del d.a
with assertRaises(AttributeError):
d.a
del d.c
with assertRaises(AttributeError):
d.c
assert d.b == 1
assert d.d == 'Y'
def test_delete_with_inheritance_any() -> None:
d: Any = Deriv()
d.a = 0
d.b = 1
d.c = 'X'
d.d = 'Y'
del d.a
with assertRaises(AttributeError):
d.a
del d.c
with assertRaises(AttributeError):
d.c
with assertRaises(AttributeError):
del d.b
assert d.b == 1
with assertRaises(AttributeError):
del d.d
assert d.d == 'Y'
def decorator(cls):
return cls
@decorator
class NonExt:
x: int
y: int
# No effect in a non-native class
__deletable__ = ['x']
def test_non_ext() -> None:
n = NonExt()
n.x = 2
n.y = 3
del n.x
del n.y
with assertRaises(AttributeError):
n.x
with assertRaises(AttributeError):
n.y
def test_non_ext_any() -> None:
n: Any = NonExt()
n.x = 2
n.y = 3
del n.x
del n.y
with assertRaises(AttributeError):
n.x
with assertRaises(AttributeError):
n.y
[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)
@decorator
class Var:
x = 'xy'
def get_class_var() -> str:
return Var.x
[file driver.py]
from native import A, Overload, get, get_class_var
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
assert get_class_var() == 'xy'
[case testEnum]
from enum import Enum
class TestEnum(Enum):
_order_ = "a b"
a = 1
b = 2
@classmethod
def test(cls) -> int:
return 3
assert TestEnum.test() == 3
import enum
class Pokemon(enum.Enum):
magikarp = 1
squirtle = 2
slowbro = 3
assert Pokemon.magikarp.value == 1
assert Pokemon.squirtle.name == 'squirtle'
[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
e: int
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
from testutil import assertRaises
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
c3 = C()
with assertRaises(AttributeError, "attribute 'a' of 'C' undefined"):
c3.a
with assertRaises(AttributeError, "attribute 'b' of 'C' undefined"):
c3.b
with assertRaises(AttributeError, "attribute 'c' of 'C' undefined"):
c3.c
with assertRaises(AttributeError, "attribute 'd' of 'C' undefined"):
c3.d
with assertRaises(AttributeError, "attribute 'e' of 'C' undefined"):
c3.e
[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 testClassKwargs]
class X:
def __init__(self, msg: str, **variables: int) -> None:
self.msg = msg
self.variables = variables
[file driver.py]
import traceback
from native import X
x = X('hello', a=0, b=1)
assert x.msg == 'hello'
assert x.variables == {'a': 0, 'b': 1}
try:
X('hello', msg='hello')
except TypeError as e:
print(f"{type(e).__name__}: {e}")
[out]
TypeError: argument for __init__() given by name ('msg') and position (1)
[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]
from typing import ClassVar, Any, final
from mypy_extensions import mypyc_attr
from interp import make_interpreted_subclass
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
@classmethod
def call_other(cls, x: int) -> int:
return cls.quux(x, 3)
class D(C):
def f(self) -> int:
return super().foo(1) + super().bar(2) + super().baz(10) + super().quux(10)
def ctest1() -> int:
return C.foo(1) + C.bar(2) + C.baz(10) + C.quux(10) + C.quux(y=10, x=9)
def ctest2() -> int:
c = C()
return c.foo(1) + c.bar(2) + c.baz(10)
CAny: Any = C
def test_classmethod_using_any() -> None:
assert CAny.foo(10) == 20
assert CAny.bar(10) == 19
def test_classmethod_on_instance() -> None:
c = C()
assert c.foo(10) == 20
assert c.bar(10) == 19
assert c.call_other(1) == 2
def test_classmethod_misc() -> None:
assert ctest1() == 23
assert ctest2() == 22
assert C.call_other(2) == 1
def test_classmethod_using_super() -> None:
d = D()
assert d.f() == 22
@final
class F1:
@classmethod
def f(cls, x: int) -> int:
return cls.g(x)
@classmethod
def g(cls, x: int) -> int:
return x + 1
class F2: # Implicitly final (no subclasses)
@classmethod
def f(cls, x: int) -> int:
return cls.g(x)
@classmethod
def g(cls, x: int) -> int:
return x + 1
def test_classmethod_of_final_class() -> None:
assert F1.f(5) == 6
assert F2.f(7) == 8
@mypyc_attr(allow_interpreted_subclasses=True)
class CI:
@classmethod
def f(cls, x: int) -> int:
return cls.g(x)
@classmethod
def g(cls, x: int) -> int:
return x + 1
def test_classmethod_with_allow_interpreted() -> None:
assert CI.f(4) == 5
sub = make_interpreted_subclass(CI)
assert sub.f(4) == 7
[file interp.py]
def make_interpreted_subclass(base):
class Sub(base):
@classmethod
def g(cls, x: int) -> int:
return x + 3
return Sub
[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:
super(C, self).__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 testSubclassUnsupportedException]
from mypy_extensions import mypyc_attr
@mypyc_attr(native_class=False)
class MyError(ZeroDivisionError):
pass
@mypyc_attr(native_class=False)
class MyError2(ZeroDivisionError):
def __init__(self, s: str) -> None:
super().__init__(s + "!")
self.x = s.upper()
def f() -> None:
raise MyError("foobar")
def test_non_native_exception_subclass_basics() -> None:
e = MyError()
assert isinstance(e, MyError)
assert isinstance(e, ZeroDivisionError)
assert isinstance(e, Exception)
e = MyError("x")
assert repr(e) == "MyError('x')"
e2 = MyError2("ab")
assert repr(e2) == "MyError2('ab!')", repr(e2)
assert e2.x == "AB"
def test_raise_non_native_exception_subclass_1() -> None:
try:
f()
except MyError:
x = True
else:
assert False
assert x
def test_raise_non_native_exception_subclass_2() -> None:
try:
f()
except ZeroDivisionError:
x = True
else:
assert False
assert x
[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 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 = -1) -> None:
pass
def bar(self, *, x: int = -1, y: int = -1) -> None:
pass
def baz(self, x: int = -1) -> 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 testMethodOverrideDefault4]
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)
def test_override() -> None:
z: Foo = Bar()
z.f(1, z=50)
z.f()
[out]
stuff (1,) {'z': 50}
stuff () {}
[case testMethodOverrideDefault5]
from testutil import make_python_function
from mypy_extensions import mypyc_attr
from typing import TypeVar, Any
@mypyc_attr(allow_interpreted_subclasses=True)
class Foo:
def f(self, x: int=20, *, z: int=10) -> None:
print("Foo", x, z)
@make_python_function
def baz_f(self: Any, *args: int, **kwargs: int) -> None:
print("Baz", args, kwargs)
def test_override() -> None:
# Make an "interpreted" subtype of Foo
type2: Any = type
Bar = type2('Bar', (Foo,), {})
Baz = type2('Baz', (Foo,), {'f': baz_f})
y: Foo = Bar()
y.f(1, z=2)
y.f()
z: Foo = Baz()
z.f(1, z=2)
z.f()
[out]
Foo 1 2
Foo 20 10
Baz (1,) {'z': 2}
Baz () {}
[case testMethodOverrideDefault6]
from typing import Optional
class Foo:
def f(self, x: int=20) -> None:
pass
class Bar(Foo):
def f(self, x: Optional[int]=None) -> None:
print(x)
def test_override() -> None:
z: Foo = Bar()
z.f(1)
z.f()
[out]
1
None
[case testMethodOverrideDefault7]
from typing import TypeVar, Any
class Foo:
def f(self, x: int, *args: int, **kwargs: int) -> None:
print("Foo", x, args, kwargs)
class Bar(Foo):
def f(self, *args: int, **kwargs: int) -> None:
print("Bar", args, kwargs)
def test_override() -> None:
z: Foo = Bar()
z.f(1, z=2)
z.f(1, 2, 3)
# z.f(x=5) # Not tested because we (knowingly) do the wrong thing and pass it as positional
[out]
Bar (1,) {'z': 2}
Bar (1, 2, 3) {}
--Bar () {'x': 5}
[case testMethodOverrideDefault8]
from typing import TypeVar, Any
class Foo:
def f(self, *args: int, **kwargs: int) -> None:
print("Foo", args, kwargs)
class Bar(Foo):
def f(self, x: int = 10, *args: int, **kwargs: int) -> None:
print("Bar", x, args, kwargs)
def test_override() -> None:
z: Foo = Bar()
z.f(1, z=2)
z.f(1, 2, 3)
z.f()
[out]
Bar 1 () {'z': 2}
Bar 1 (2, 3) {}
Bar 10 () {}
[case testMethodOverrideDefault9]
from testutil import make_python_function
from mypy_extensions import mypyc_attr
from typing import TypeVar, Any
@mypyc_attr(allow_interpreted_subclasses=True)
class Foo:
def f(self, x: int=20, y: int=40) -> None:
print("Foo", x, y)
# This sort of argument renaming is dodgy and not really sound but we
# shouldn't break it when they aren't actually used by name...
# (They *ought* to be positional only!)
@make_python_function
def baz_f(self, a: int=30, y: int=50) -> None:
print("Baz", a, y)
def test_override() -> None:
# Make an "interpreted" subtype of Foo
type2: Any = type
Baz = type2('Baz', (Foo,), {'f': baz_f})
z: Foo = Baz()
z.f()
z.f(y=1)
z.f(1, 2)
# Not tested because we don't (and probably won't) match cpython here
# from testutil import assertRaises
# with assertRaises(TypeError):
# z.f(x=7)
[out]
Baz 30 50
Baz 30 1
Baz 1 2
[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
class Nothing(metaclass=Meta):
pass
def ident(x): return x
@ident
class Test:
pass
[file meta.py]
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 Nothing
assert Nothing.X == 10
[case testPickling]
from mypy_extensions import trait, mypyc_attr
from typing import Any, TypeVar, Generic
def dec(x: Any) -> Any:
return x
@mypyc_attr(allow_interpreted_subclasses=True)
class A:
x: int
y: str
@mypyc_attr(allow_interpreted_subclasses=True)
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.fahrenheit - 32.0) / 9.0
def __init__(self, fahrenheit: float) -> None:
self.fahrenheit = fahrenheit
def print_temp(self) -> None:
print("F:", self.fahrenheit, "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
[out version>=3.11]
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
# Inherits 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
# No inheritance, just plain setter/getter
class G:
def __init__(self, x: int) -> None:
self._x = x
@property
def x(self) -> int:
return self._x
@x.setter
def x(self, x: int) -> None:
self._x = x
class H:
def __init__(self, g: G) -> None:
self.g = g
self.g.x = 5 # Should not be treated as initialization
[file other.py]
# Run in both interpreted and compiled mode
from native import A, B, C, D, E, F, G
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
g = G(4)
g.x = 20
assert g.x == 20
[file driver.py]
# Run the tests in both interpreted and compiled mode
import other
import other_interpreted
[out]
[case testAttributeOverridesProperty]
from typing import Any
from mypy_extensions import trait
@trait
class T1:
@property
def x(self) -> int: ...
@property
def y(self) -> int: ...
class C1(T1):
x: int = 1
y: int = 4
def test_read_only_property_in_trait_implemented_as_attribute() -> None:
c = C1()
c.x = 5
assert c.x == 5
assert c.y == 4
c.y = 6
assert c.y == 6
t: T1 = C1()
assert t.y == 4
t = c
assert t.x == 5
assert t.y == 6
a: Any = c
assert a.x == 5
assert a.y == 6
a.x = 7
a.y = 8
assert a.x == 7
assert a.y == 8
class B2:
@property
def x(self) -> int:
return 11
@property
def y(self) -> int:
return 25
class C2(B2):
x: int = 1
y: int = 4
def test_read_only_property_in_class_implemented_as_attribute() -> None:
c = C2()
c.x = 5
assert c.x == 5
assert c.y == 4
c.y = 6
assert c.y == 6
b: B2 = C2()
assert b.y == 4
b = c
assert b.x == 5
assert b.y == 6
a: Any = c
assert a.x == 5
assert a.y == 6
a.x = 7
a.y = 8
assert a.x == 7
assert a.y == 8
@trait
class T3:
@property
def x(self) -> int: ...
@property
def y(self) -> int: ...
class B3:
x: int = 1
y: int = 4
class C3(B3, T3):
pass
def test_read_only_property_implemented_as_attribute_indirectly() -> None:
c = C3()
c.x = 5
assert c.x == 5
assert c.y == 4
c.y = 6
assert c.y == 6
t: T3 = C3()
assert t.y == 4
t = c
assert t.x == 5
assert t.y == 6
a: Any = c
assert a.x == 5
assert a.y == 6
a.x = 7
a.y = 8
assert a.x == 7
assert a.y == 8
@trait
class T4:
@property
def x(self) -> int: ...
@x.setter
def x(self, v1: int) -> None: ...
@property
def y(self) -> int: ...
@y.setter
def y(self, v2: int) -> None: ...
class C4(T4):
x: int = 1
y: int = 4
def test_read_write_property_implemented_as_attribute() -> None:
c = C4()
c.x = 5
assert c.x == 5
assert c.y == 4
c.y = 6
assert c.y == 6
t: T4 = C4()
assert t.y == 4
t.x = 5
assert t.x == 5
t.y = 6
assert t.y == 6
a: Any = c
assert a.x == 5
assert a.y == 6
a.x = 7
a.y = 8
assert a.x == 7
assert a.y == 8
@trait
class T5:
@property
def x(self) -> int: ...
@x.setter
def x(self, v1: int) -> None: ...
@property
def y(self) -> int: ...
@y.setter
def y(self, v2: int) -> None: ...
class B5:
x: int = 1
y: int = 4
class BB5(B5):
pass
class C5(BB5, T5):
pass
def test_read_write_property_indirectly_implemented_as_attribute() -> None:
c = C5()
c.x = 5
assert c.x == 5
assert c.y == 4
c.y = 6
assert c.y == 6
t: T5 = C5()
assert t.y == 4
t.x = 5
assert t.x == 5
t.y = 6
assert t.y == 6
a: Any = c
assert a.x == 5
assert a.y == 6
a.x = 7
a.y = 8
assert a.x == 7
assert a.y == 8
[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()
[case testCopyAlwaysDefinedAttributes]
import copy
from typing import Union
class A: pass
class C:
def __init__(self, n: int = 0) -> None:
self.n = n
self.s = ""
self.t = ("", 0)
self.u: Union[str, bytes] = ''
self.a = A()
def test_copy() -> None:
c1 = C()
c1.n = 1
c1.s = "x"
c2 = copy.copy(c1)
assert c2.n == 1
assert c2.s == "x"
assert c2.t == ("", 0)
assert c2.u == ''
assert c2.a is c1.a
[case testNonNativeCallsToDunderNewAndInit]
from typing import Any
from testutil import assertRaises
count_c = 0
class C:
def __init__(self) -> None:
self.x = 'a' # Always defined attribute
global count_c
count_c += 1
def get(self) -> str:
return self.x
def test_no_init_args() -> None:
global count_c
count_c = 0
# Use Any to get non-native semantics
cls: Any = C
# __new__ implicitly calls __init__ for native classes
obj = cls.__new__(cls)
assert obj.get() == 'a'
assert count_c == 1
# Make sure we don't call __init__ twice
obj2 = cls()
assert obj2.get() == 'a'
assert count_c == 2
count_d = 0
class D:
def __init__(self, x: str) -> None:
self.x = x # Always defined attribute
global count_d
count_d += 1
def get(self) -> str:
return self.x
def test_init_arg() -> None:
global count_d
count_d = 0
# Use Any to get non-native semantics
cls: Any = D
# __new__ implicitly calls __init__ for native classes
obj = cls.__new__(cls, 'abc')
assert obj.get() == 'abc'
assert count_d == 1
# Make sure we don't call __init__ twice
obj2 = cls('x')
assert obj2.get() == 'x'
assert count_d == 2
# Keyword args should work
obj = cls.__new__(cls, x='abc')
assert obj.get() == 'abc'
assert count_d == 3
def test_invalid_init_args() -> None:
# Use Any to get non-native semantics
cls: Any = D
with assertRaises(TypeError):
cls()
with assertRaises(TypeError):
cls(y='x')
with assertRaises(TypeError):
cls(1)
[case testTryDeletingAlwaysDefinedAttribute]
from typing import Any
from testutil import assertRaises
class C:
def __init__(self) -> None:
self.x = 0
class D(C):
pass
def test_try_deleting_always_defined_attr() -> None:
c: Any = C()
with assertRaises(AttributeError):
del c.x
d: Any = D()
with assertRaises(AttributeError):
del d.x
[case testAlwaysDefinedAttributeAndAllowInterpretedSubclasses]
from mypy_extensions import mypyc_attr
from m import define_interpreted_subclass
@mypyc_attr(allow_interpreted_subclasses=True)
class Base:
x = 5
y: int
def __init__(self, s: str) -> None:
self.s = s
class DerivedNative(Base):
def __init__(self) -> None:
super().__init__('x')
self.z = 3
def test_native_subclass() -> None:
o = DerivedNative()
assert o.x == 5
assert o.s == 'x'
assert o.z == 3
def test_interpreted_subclass() -> None:
define_interpreted_subclass(Base)
[file m.py]
from testutil import assertRaises
def define_interpreted_subclass(b):
class DerivedInterpreted1(b):
def __init__(self):
# Don't call base class __init__
pass
d1 = DerivedInterpreted1()
assert d1.x == 5
with assertRaises(AttributeError):
d1.y
with assertRaises(AttributeError):
d1.s
with assertRaises(AttributeError):
del d1.x
class DerivedInterpreted1(b):
def __init__(self):
super().__init__('y')
d2 = DerivedInterpreted1()
assert d2.x == 5
assert d2.s == 'y'
with assertRaises(AttributeError):
d2.y
with assertRaises(AttributeError):
del d2.x
[case testBaseClassSometimesDefinesAttribute]
class C:
def __init__(self, b: bool) -> None:
if b:
self.x = [1]
class D(C):
def __init__(self, b: bool) -> None:
super().__init__(b)
self.x = [2]
def test_base_class() -> None:
c = C(True)
assert c.x == [1]
c = C(False)
try:
c.x
except AttributeError:
return
assert False
def test_subclass() -> None:
d = D(True)
assert d.x == [2]
d = D(False)
assert d.x == [2]
[case testSerializableClass]
from mypy_extensions import mypyc_attr
from typing import Any
import copy
from testutil import assertRaises
@mypyc_attr(serializable=True)
class Base:
def __init__(self, s: str) -> None:
self.s = s
class Derived(Base):
def __init__(self, s: str, n: int) -> None:
super().__init__(s)
self.n = n
def test_copy_base() -> None:
o = Base('xyz')
o2 = copy.copy(o)
assert isinstance(o2, Base)
assert o2 is not o
assert o2.s == 'xyz'
def test_copy_derived() -> None:
d = Derived('xyz', 5)
d2 = copy.copy(d)
assert isinstance(d2, Derived)
assert d2 is not d
assert d2.s == 'xyz'
assert d2.n == 5
class NonSerializable:
def __init__(self, s: str) -> None:
self.s = s
@mypyc_attr(serializable=True)
class SerializableSub(NonSerializable):
def __init__(self, s: str, n: int) -> None:
super().__init__(s)
self.n = n
def test_serializable_sub_class() -> None:
n = NonSerializable('xyz')
assert n.s == 'xyz'
with assertRaises(TypeError):
copy.copy(n)
s = SerializableSub('foo', 6)
s2 = copy.copy(s)
assert s2 is not s
assert s2.s == 'foo'
assert s2.n == 6
def test_serializable_sub_class_call_new() -> None:
t: Any = SerializableSub
sub: SerializableSub = t.__new__(t)
with assertRaises(AttributeError):
sub.s
with assertRaises(AttributeError):
sub.n
base: NonSerializable = sub
with assertRaises(AttributeError):
base.s
[case testClassWithInherited__call__]
class Base:
def __call__(self) -> int:
return 1
class Derived(Base):
pass
def test_inherited() -> None:
assert Derived()() == 1
[case testClassWithFinalAttribute]
from typing import Final
class C:
A: Final = -1
a: Final = [A]
def test_final_attribute() -> None:
assert C.A == -1
assert C.a == [-1]
[case testClassWithFinalDecorator]
from typing import final
@final
class C:
def a(self) -> int:
return 1
def test_class_final_attribute() -> None:
assert C().a() == 1
[case testClassWithFinalDecoratorCtor]
from typing import final
@final
class C:
def __init__(self) -> None:
self.a = 1
def b(self) -> int:
return 2
@property
def c(self) -> int:
return 3
def test_class_final_attribute() -> None:
assert C().a == 1
assert C().b() == 2
assert C().c == 3
[case testClassWithFinalDecoratorInheritedWithProperties]
from typing import final
class B:
def a(self) -> int:
return 2
@property
def b(self) -> int:
return self.a() + 2
@property
def c(self) -> int:
return 3
def test_class_final_attribute_basic() -> None:
assert B().a() == 2
assert B().b == 4
assert B().c == 3
@final
class C(B):
def a(self) -> int:
return 1
@property
def b(self) -> int:
return self.a() + 1
def fn(cl: B) -> int:
return cl.a()
def test_class_final_attribute_inherited() -> None:
assert C().a() == 1
assert fn(C()) == 1
assert B().a() == 2
assert fn(B()) == 2
assert B().b == 4
assert C().b == 2
assert B().c == 3
assert C().c == 3
[case testClassWithFinalAttributeAccess]
from typing import Final
class C:
a: Final = {'x': 'y'}
b: Final = C.a
def test_final_attribute() -> None:
assert C.a['x'] == 'y'
assert C.b['x'] == 'y'
assert C.a is C.b
[case testClassDerivedFromIntEnum]
from enum import IntEnum, auto
class Player(IntEnum):
MIN = auto()
print(f'{Player.MIN = }')
[file driver.py]
from native import Player
[out]
Player.MIN = <Player.MIN: 1>
[case testStaticCallsWithUnpackingArgs]
from typing import Tuple
class Foo:
@staticmethod
def static(a: int, b: int, c: int) -> Tuple[int, int, int]:
return (c+1, a+2, b+3)
@classmethod
def clsmethod(cls, a: int, b: int, c: int) -> Tuple[int, int, int]:
return (c+1, a+2, b+3)
print(Foo.static(*[10, 20, 30]))
print(Foo.static(*(40, 50), *[60]))
assert Foo.static(70, 80, *[90]) == Foo.clsmethod(70, *(80, 90))
[file driver.py]
import native
[out]
(31, 12, 23)
(61, 42, 53)
[case testDataclassInitVar]
import dataclasses
@dataclasses.dataclass
class C:
init_v: dataclasses.InitVar[int]
v: float = dataclasses.field(init=False)
def __post_init__(self, init_v):
self.v = init_v + 0.1
[file driver.py]
import native
print(native.C(22).v)
[out]
22.1
[case testLastParentEnum]
from enum import Enum
class ColorCode(str, Enum):
OKGREEN = "okgreen"
[file driver.py]
import native
print(native.ColorCode.OKGREEN.value)
[out]
okgreen
[case testAttrWithSlots]
import attr
@attr.s(slots=True)
class A:
ints: list[int] = attr.ib()
[file driver.py]
import native
print(native.A(ints=[1, -17]).ints)
[out]
\[1, -17]
[case testDataclassClassReference]
from __future__ import annotations
from dataclasses import dataclass
class BackwardDefinedClass:
pass
@dataclass
class Data:
bitem: BackwardDefinedClass
bitems: 'BackwardDefinedClass'
fitem: ForwardDefinedClass
fitems: 'ForwardDefinedClass'
class ForwardDefinedClass:
pass
def test_function():
d = Data(
bitem=BackwardDefinedClass(),
bitems=BackwardDefinedClass(),
fitem=ForwardDefinedClass(),
fitems=ForwardDefinedClass(),
)
assert(isinstance(d.bitem, BackwardDefinedClass))
assert(isinstance(d.bitems, BackwardDefinedClass))
assert(isinstance(d.fitem, ForwardDefinedClass))
assert(isinstance(d.fitems, ForwardDefinedClass))
[case testDelForDictSubclass-xfail]
# The crash in issue mypy#19175 is fixed.
# But, for classes that derive from built-in Python classes, user-defined __del__ method is not
# being invoked.
class DictSubclass(dict):
def __del__(self):
print("deleting DictSubclass...")
[file driver.py]
import native
native.DictSubclass()
[out]
deleting DictSubclass...
[case testDel]
class A:
def __del__(self):
print("deleting A...")
class B:
def __del__(self):
print("deleting B...")
class C(B):
def __init__(self):
self.a = A()
def __del__(self):
print("deleting C...")
super().__del__()
class D(A):
pass
# Just make sure that this class compiles (see issue mypy#19175). testDelForDictSubclass tests for
# correct output.
class NormDict(dict):
def __del__(self) -> None:
pass
[file driver.py]
import native
native.C()
native.D()
[out]
deleting C...
deleting B...
deleting A...
deleting A...
[case testDelCircular]
import dataclasses
import typing
i: int = 1
@dataclasses.dataclass
class C:
var: typing.Optional["C"] = dataclasses.field(default=None)
def __del__(self):
global i
print(f"deleting C{i}...")
i = i + 1
[file driver.py]
import native
import gc
c1 = native.C()
c2 = native.C()
c1.var = c2
c2.var = c1
del c1
del c2
gc.collect()
[out]
deleting C1...
deleting C2...
[case testDelException]
# The error message in the expected output of this test does not match CPython's error message due to the way mypyc compiles Python classes. If the error message is fixed, the expected output of this test will also change.
class F:
def __del__(self):
if True:
raise Exception("e2")
[file driver.py]
import native
f = native.F()
del f
[out]
Exception ignored in: <slot wrapper '__del__' of 'F' objects>
Traceback (most recent call last):
File "native.py", line 5, in __del__
raise Exception("e2")
Exception: e2
[case testMypycAttrNativeClass]
from mypy_extensions import mypyc_attr
from testutil import assertRaises
@mypyc_attr(native_class=False)
class AnnontatedNonExtensionClass:
pass
class DerivedClass(AnnontatedNonExtensionClass):
pass
class ImplicitExtensionClass():
pass
@mypyc_attr(native_class=True)
class AnnotatedExtensionClass():
pass
def test_function():
setattr(AnnontatedNonExtensionClass, 'attr_class', 5)
assert(hasattr(AnnontatedNonExtensionClass, 'attr_class') == True)
assert(getattr(AnnontatedNonExtensionClass, 'attr_class') == 5)
delattr(AnnontatedNonExtensionClass, 'attr_class')
assert(hasattr(AnnontatedNonExtensionClass, 'attr_class') == False)
inst = AnnontatedNonExtensionClass()
setattr(inst, 'attr_instance', 6)
assert(hasattr(inst, 'attr_instance') == True)
assert(getattr(inst, 'attr_instance') == 6)
delattr(inst, 'attr_instance')
assert(hasattr(inst, 'attr_instance') == False)
setattr(DerivedClass, 'attr_class', 5)
assert(hasattr(DerivedClass, 'attr_class') == True)
assert(getattr(DerivedClass, 'attr_class') == 5)
delattr(DerivedClass, 'attr_class')
assert(hasattr(DerivedClass, 'attr_class') == False)
derived_inst = DerivedClass()
setattr(derived_inst, 'attr_instance', 6)
assert(hasattr(derived_inst, 'attr_instance') == True)
assert(getattr(derived_inst, 'attr_instance') == 6)
delattr(derived_inst, 'attr_instance')
assert(hasattr(derived_inst, 'attr_instance') == False)
ext_inst = ImplicitExtensionClass()
with assertRaises(AttributeError):
setattr(ext_inst, 'attr_instance', 6)
explicit_ext_inst = AnnotatedExtensionClass()
with assertRaises(AttributeError):
setattr(explicit_ext_inst, 'attr_instance', 6)
[case testMypycAttrNativeClassDunder]
from mypy_extensions import mypyc_attr
from typing import Generic, Optional, TypeVar
_T = TypeVar("_T")
get_count = set_count = del_count = 0
@mypyc_attr(native_class=False)
class Bar(Generic[_T]):
# Note the lack of __deletable__
def __init__(self) -> None:
self.value: str = 'start'
def __get__(self, instance: _T, owner: Optional[type[_T]] = None) -> str:
global get_count
get_count += 1
return self.value
def __set__(self, instance: _T, value: str) -> None:
global set_count
set_count += 1
self.value = value
def __delete__(self, instance: _T) -> None:
global del_count
del_count += 1
del self.value
@mypyc_attr(native_class=False)
class Foo(object):
bar: Bar = Bar()
[file driver.py]
import native
f = native.Foo()
assert(hasattr(f, 'bar'))
assert(native.get_count == 1)
assert(f.bar == 'start')
assert(native.get_count == 2)
f.bar = 'test'
assert(f.bar == 'test')
assert(native.set_count == 1)
del f.bar
assert(not hasattr(f, 'bar'))
assert(native.del_count == 1)
[case testMypycAttrNativeClassMeta]
from mypy_extensions import mypyc_attr
from typing import ClassVar, TypeVar
_T = TypeVar("_T")
@mypyc_attr(native_class=False)
class M(type):
count: ClassVar[int] = 0
def make(cls: type[_T]) -> _T:
M.count += 1
return cls()
# implicit native_class=False
# see testMypycAttrNativeClassMetaError for when trying to set it True
class A(metaclass=M):
pass
[file driver.py]
import native
a: native.A = native.A.make()
assert(native.A.count == 1)
class B(native.A):
pass
b: B = B.make()
assert(B.count == 2)
[case testTypeVarNarrowing]
from typing import TypeVar
class B:
def __init__(self, x: int) -> None:
self.x = x
class C(B):
def __init__(self, x: int, y: str) -> None:
self.x = x
self.y = y
T = TypeVar("T", bound=B)
def f(x: T) -> T:
if isinstance(x, C):
print("C", x.y)
return x
print("B", x.x)
return x
[file driver.py]
from native import f, B, C
f(B(1))
f(C(1, "yes"))
[out]
B 1
C yes