blob: ab1dcb926c34fddd9e9101de334565c3ecb17d31 [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 testBufferRoundTrip_native_libs]
from typing import Final
from mypy_extensions import u8
from native_internal import (
Buffer, write_bool, read_bool, write_str, read_str, write_float, read_float,
write_int, read_int, write_tag, read_tag
)
Tag = u8
TAG_A: Final[Tag] = 33
TAG_B: Final[Tag] = 255
TAG_SPECIAL: Final[Tag] = 239
def test_buffer_basic() -> None:
b = Buffer(b"foo")
assert b.getvalue() == b"foo"
def test_buffer_roundtrip() -> None:
b = Buffer()
write_str(b, "foo")
write_bool(b, True)
write_str(b, "bar" * 1000)
write_bool(b, False)
write_float(b, 0.1)
write_int(b, 0)
write_int(b, 1)
write_tag(b, TAG_A)
write_tag(b, TAG_SPECIAL)
write_tag(b, TAG_B)
write_int(b, 2)
write_int(b, 2 ** 85)
write_int(b, 255)
write_int(b, -1)
write_int(b, -255)
write_int(b, 1234512344)
write_int(b, 1234512345)
b = Buffer(b.getvalue())
assert read_str(b) == "foo"
assert read_bool(b) is True
assert read_str(b) == "bar" * 1000
assert read_bool(b) is False
assert read_float(b) == 0.1
assert read_int(b) == 0
assert read_int(b) == 1
assert read_tag(b) == TAG_A
assert read_tag(b) == TAG_SPECIAL
assert read_tag(b) == TAG_B
assert read_int(b) == 2
assert read_int(b) == 2 ** 85
assert read_int(b) == 255
assert read_int(b) == -1
assert read_int(b) == -255
assert read_int(b) == 1234512344
assert read_int(b) == 1234512345
def test_buffer_int_size() -> None:
for i in (-10, -9, 0, 116, 117):
b = Buffer()
write_int(b, i)
assert len(b.getvalue()) == 1
b = Buffer(b.getvalue())
assert read_int(b) == i
for i in (-12345, -12344, -11, 118, 12344, 12345):
b = Buffer()
write_int(b, i)
assert len(b.getvalue()) <= 9 # sizeof(size_t) + 1
b = Buffer(b.getvalue())
assert read_int(b) == i
def test_buffer_str_size() -> None:
for s in ("", "a", "a" * 127):
b = Buffer()
write_str(b, s)
assert len(b.getvalue()) == len(s) + 1
b = Buffer(b.getvalue())
assert read_str(b) == s
[file driver.py]
from native import *
test_buffer_basic()
test_buffer_roundtrip()
test_buffer_int_size()
test_buffer_str_size()
def test_buffer_basic_interpreted() -> None:
b = Buffer(b"foo")
assert b.getvalue() == b"foo"
def test_buffer_roundtrip_interpreted() -> None:
b = Buffer()
write_str(b, "foo")
write_bool(b, True)
write_str(b, "bar" * 1000)
write_bool(b, False)
write_float(b, 0.1)
write_int(b, 0)
write_int(b, 1)
write_tag(b, 33)
write_tag(b, 239)
write_tag(b, 255)
write_int(b, 2)
write_int(b, 2 ** 85)
write_int(b, 255)
write_int(b, -1)
write_int(b, -255)
write_int(b, 1234512344)
write_int(b, 1234512345)
b = Buffer(b.getvalue())
assert read_str(b) == "foo"
assert read_bool(b) is True
assert read_str(b) == "bar" * 1000
assert read_bool(b) is False
assert read_float(b) == 0.1
assert read_int(b) == 0
assert read_int(b) == 1
assert read_tag(b) == 33
assert read_tag(b) == 239
assert read_tag(b) == 255
assert read_int(b) == 2
assert read_int(b) == 2 ** 85
assert read_int(b) == 255
assert read_int(b) == -1
assert read_int(b) == -255
assert read_int(b) == 1234512344
assert read_int(b) == 1234512345
def test_buffer_int_size_interpreted() -> None:
for i in (-10, -9, 0, 116, 117):
b = Buffer()
write_int(b, i)
assert len(b.getvalue()) == 1
b = Buffer(b.getvalue())
assert read_int(b) == i
for i in (-12345, -12344, -11, 118, 12344, 12345):
b = Buffer()
write_int(b, i)
assert len(b.getvalue()) <= 9 # sizeof(size_t) + 1
b = Buffer(b.getvalue())
assert read_int(b) == i
def test_buffer_str_size_interpreted() -> None:
for s in ("", "a", "a" * 127):
b = Buffer()
write_str(b, s)
assert len(b.getvalue()) == len(s) + 1
b = Buffer(b.getvalue())
assert read_str(b) == s
test_buffer_basic_interpreted()
test_buffer_roundtrip_interpreted()
test_buffer_int_size_interpreted()
test_buffer_str_size_interpreted()
[case testEnumMethodCalls]
from enum import Enum
from typing import overload, Optional, Union
class C:
def foo(self, x: Test) -> bool:
assert Test.ONE.is_one()
assert x.next(2) == Test.THREE
assert x.prev(2) == Test.ONE
assert x.enigma(22)
assert x.enigma("22") == 22
return x.is_one(inverse=True)
class Test(Enum):
ONE = 1
TWO = 2
THREE = 3
def is_one(self, *, inverse: bool = False) -> bool:
if inverse:
return self != Test.ONE
return self == Test.ONE
@classmethod
def next(cls, val: int) -> Test:
return cls(val + 1)
@staticmethod
def prev(val: int) -> Test:
return Test(val - 1)
@overload
def enigma(self, val: int) -> bool: ...
@overload
def enigma(self, val: Optional[str] = None) -> int: ...
def enigma(self, val: Union[int, str, None] = None) -> Union[int, bool]:
if isinstance(val, int):
return self.is_one()
return 22
[file driver.py]
from native import Test, C
assert Test.ONE.is_one()
assert Test.TWO.is_one(inverse=True)
assert not C().foo(Test.ONE)
assert Test.next(2) == Test.THREE
assert Test.prev(2) == Test.ONE
assert Test.ONE.enigma(22)
assert Test.ONE.enigma("22") == 22
[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: <native.F object at 0x000000000000>
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
[case testTypeObjectName]
from typing import Any
import re
from dynamic import E, foo, Thing
class C: pass
class D(C): pass
def type_name(t: type[object]) -> str:
return t.__name__
def any_name(x: Any) -> str:
return x.__name__
def assert_type_name(x: Any) -> None:
assert type_name(x) == getattr(x, "__name__")
assert any_name(x) == getattr(x, "__name__")
def assert_any_name(x: Any) -> None:
assert any_name(x) == getattr(x, "__name__")
def test_type_name() -> None:
assert_type_name(C)
assert_type_name(D)
assert_type_name(int)
assert_type_name(E)
assert_type_name(re.Pattern)
def test_module_name() -> None:
assert_any_name(re)
def test_function_name() -> None:
assert_any_name(any_name)
assert_any_name(foo)
def test_obj_name() -> None:
assert_any_name(Thing())
[file dynamic.py]
class E: pass
def foo(): pass
class Thing:
def __init__(self):
self.__name__ = "xyz"
[case testTypeOfObject]
from typing import Any
from dynamic import Dyn
class Foo: pass
class Bar(Foo): pass
def generic_type(x) -> type[object]:
return x.__class__
def test_built_in_type() -> None:
i: Any = int
l: Any = list
assert type(i()) is i().__class__
assert type(i()) is int
assert type(l()) is list
n = 5
assert n.__class__ is i
def test_native_class() -> None:
f_any: Any = Foo()
b_any: Any = Bar()
f: Foo = f_any
b: Foo = b_any
if int("1"): # use int("1") to avoid constant folding
assert type(f) is Foo
assert type(b) is Bar
if int("2"):
assert f.__class__ is Foo
assert b.__class__ is Bar
if int("3"):
assert f_any.__class__ is Foo
assert b_any.__class__ is Bar
if int("4"):
assert type(f_any) is Foo
assert type(b_any) is Bar
def test_python_class() -> None:
d = Dyn()
assert type(d) is Dyn
assert d.__class__ is Dyn
[file dynamic.py]
class Dyn: pass
[case testDunderNew]
from __future__ import annotations
from typing import Any, Union
from testutil import assertRaises
class Add:
l: IntLike
r: IntLike
def __new__(cls, l: IntLike, r: IntLike) -> Any:
return (
l if r == 0 else
r if l == 0 else
super().__new__(cls)
)
def __init__(self, l: IntLike, r: IntLike):
self.l = l
self.r = r
IntLike = Union[int, Add]
class RaisesException:
def __new__(cls, val: int) -> RaisesException:
if val == 0:
raise RuntimeError("Invalid value!")
return super().__new__(cls)
def __init__(self, val: int) -> None:
self.val = val
class ClsArgNotPassed:
def __new__(cls) -> Any:
return super().__new__(str)
def test_dunder_new() -> None:
add_instance: Any = Add(1, 5)
assert type(add_instance) == Add
assert add_instance.l == 1
assert add_instance.r == 5
# TODO: explicit types should not be needed but mypy does not use
# the return type of __new__ which makes mypyc add casts to Add.
right_int: Any = Add(0, 5)
assert type(right_int) == int
assert right_int == 5
left_int: Any = Add(1, 0)
assert type(left_int) == int
assert left_int == 1
with assertRaises(RuntimeError, "Invalid value!"):
raised = RaisesException(0)
not_raised = RaisesException(1)
assert not_raised.val == 1
with assertRaises(TypeError, "object.__new__(str) is not safe, use str.__new__()"):
str_as_cls = ClsArgNotPassed()
[case testDunderNewInInterpreted]
from __future__ import annotations
from typing import Any, Union
class Add:
l: IntLike
r: IntLike
def __new__(cls, l: IntLike, r: IntLike) -> Any:
print(f'running __new__ with {l} and {r}')
return (
l if r == 0 else
r if l == 0 else
super().__new__(cls)
)
def __init__(self, l: IntLike, r: IntLike):
self.l = l
self.r = r
def __repr__(self) -> str:
return f'({self.l} + {self.r})'
IntLike = Union[int, Add]
class RaisesException:
def __new__(cls, val: int) -> RaisesException:
if val == 0:
raise RuntimeError("Invalid value!")
return super().__new__(cls)
def __init__(self, val: int) -> None:
self.val = val
class ClsArgNotPassed:
def __new__(cls) -> Any:
return super().__new__(str)
[file driver.py]
from native import Add, ClsArgNotPassed, RaisesException
from testutil import assertRaises
print(f'{Add(1, 5)=}')
print(f'{Add(0, 5)=}')
print(f'{Add(1, 0)=}')
with assertRaises(RuntimeError, "Invalid value!"):
raised = RaisesException(0)
not_raised = RaisesException(1)
assert not_raised.val == 1
with assertRaises(TypeError, "object.__new__(str) is not safe, use str.__new__()"):
str_as_cls = ClsArgNotPassed()
[out]
running __new__ with 1 and 5
Add(1, 5)=(1 + 5)
running __new__ with 0 and 5
Add(0, 5)=5
running __new__ with 1 and 0
Add(1, 0)=1
[case testObjectDunderNew]
from __future__ import annotations
from typing import Any, Union
from testutil import assertRaises
class Add:
l: IntLike
r: IntLike
def __new__(cls, l: IntLike, r: IntLike) -> Any:
return (
l if r == 0 else
r if l == 0 else
object.__new__(cls)
)
def __init__(self, l: IntLike, r: IntLike):
self.l = l
self.r = r
IntLike = Union[int, Add]
class RaisesException:
def __new__(cls, val: int) -> RaisesException:
if val == 0:
raise RuntimeError("Invalid value!")
return object.__new__(cls)
def __init__(self, val: int) -> None:
self.val = val
class ClsArgNotPassed:
def __new__(cls) -> Any:
return object.__new__(str)
class SkipsBase(Add):
def __new__(cls) -> Any:
obj = object.__new__(cls)
obj.l = 0
obj.r = 0
return obj
def test_dunder_new() -> None:
add_instance: Any = Add(1, 5)
assert type(add_instance) == Add
assert add_instance.l == 1
assert add_instance.r == 5
# TODO: explicit types should not be needed but mypy does not use
# the return type of __new__ which makes mypyc add casts to Add.
right_int: Any = Add(0, 5)
assert type(right_int) == int
assert right_int == 5
left_int: Any = Add(1, 0)
assert type(left_int) == int
assert left_int == 1
with assertRaises(RuntimeError, "Invalid value!"):
_ = RaisesException(0)
not_raised = RaisesException(1)
assert not_raised.val == 1
with assertRaises(TypeError, "object.__new__(str) is not safe, use str.__new__()"):
_ = ClsArgNotPassed()
skip = SkipsBase.__new__(SkipsBase)
assert type(skip) == SkipsBase
assert skip.l == 0
assert skip.r == 0
[case testObjectDunderNewInInterpreted]
from __future__ import annotations
from typing import Any, Union
class Add:
l: IntLike
r: IntLike
def __new__(cls, l: IntLike, r: IntLike) -> Any:
print(f'running __new__ with {l} and {r}')
return (
l if r == 0 else
r if l == 0 else
object.__new__(cls)
)
def __init__(self, l: IntLike, r: IntLike):
self.l = l
self.r = r
def __repr__(self) -> str:
return f'({self.l} + {self.r})'
IntLike = Union[int, Add]
class RaisesException:
def __new__(cls, val: int) -> RaisesException:
if val == 0:
raise RuntimeError("Invalid value!")
return object.__new__(cls)
def __init__(self, val: int) -> None:
self.val = val
class ClsArgNotPassed:
def __new__(cls) -> Any:
return object.__new__(str)
class SkipsBase(Add):
def __new__(cls) -> Any:
obj = object.__new__(cls)
obj.l = 0
obj.r = 0
return obj
[file driver.py]
from native import Add, ClsArgNotPassed, RaisesException, SkipsBase
from testutil import assertRaises
print(f'{Add(1, 5)=}')
print(f'{Add(0, 5)=}')
print(f'{Add(1, 0)=}')
with assertRaises(RuntimeError, "Invalid value!"):
raised = RaisesException(0)
not_raised = RaisesException(1)
assert not_raised.val == 1
with assertRaises(TypeError, "object.__new__(str) is not safe, use str.__new__()"):
str_as_cls = ClsArgNotPassed()
skip = SkipsBase.__new__(SkipsBase)
assert type(skip) == SkipsBase
assert skip.l == 0
assert skip.r == 0
[out]
running __new__ with 1 and 5
Add(1, 5)=(1 + 5)
running __new__ with 0 and 5
Add(0, 5)=5
running __new__ with 1 and 0
Add(1, 0)=1
[case testInheritedDunderNew]
from __future__ import annotations
from mypy_extensions import mypyc_attr
from typing_extensions import Self
from m import interpreted_subclass
@mypyc_attr(allow_interpreted_subclasses=True)
class Base:
val: int
def __new__(cls, val: int) -> Self:
obj = super().__new__(cls)
obj.val = val + 1
return obj
def __init__(self, val: int) -> None:
self.init_val = val
class Sub(Base):
def __new__(cls, val: int) -> Self:
return super().__new__(cls, val + 1)
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val = self.init_val * 2
class SubWithoutNew(Base):
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val = self.init_val * 2
class BaseWithoutInterpretedSubclasses:
val: int
def __new__(cls, val: int) -> Self:
obj = super().__new__(cls)
obj.val = val + 1
return obj
def __init__(self, val: int) -> None:
self.init_val = val
class SubNoInterpreted(BaseWithoutInterpretedSubclasses):
def __new__(cls, val: int) -> Self:
return super().__new__(cls, val + 1)
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val = self.init_val * 2
class SubNoInterpretedWithoutNew(BaseWithoutInterpretedSubclasses):
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val = self.init_val * 2
def test_inherited_dunder_new() -> None:
b = Base(42)
assert type(b) == Base
assert b.val == 43
assert b.init_val == 42
s = Sub(42)
assert type(s) == Sub
assert s.val == 44
assert s.init_val == 84
s2 = SubWithoutNew(42)
assert type(s2) == SubWithoutNew
assert s2.val == 43
assert s2.init_val == 84
def test_inherited_dunder_new_without_interpreted_subclasses() -> None:
b = BaseWithoutInterpretedSubclasses(42)
assert type(b) == BaseWithoutInterpretedSubclasses
assert b.val == 43
assert b.init_val == 42
s = SubNoInterpreted(42)
assert type(s) == SubNoInterpreted
assert s.val == 44
assert s.init_val == 84
s2 = SubNoInterpretedWithoutNew(42)
assert type(s2) == SubNoInterpretedWithoutNew
assert s2.val == 43
assert s2.init_val == 84
def test_interpreted_subclass() -> None:
interpreted_subclass(Base)
[file m.py]
from __future__ import annotations
from typing_extensions import Self
def interpreted_subclass(base) -> None:
b = base(42)
assert type(b) == base
assert b.val == 43
assert b.init_val == 42
class InterpretedSub(base):
def __new__(cls, val: int) -> Self:
return super().__new__(cls, val + 1)
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val : int = self.init_val * 2
s = InterpretedSub(42)
assert type(s) == InterpretedSub
assert s.val == 44
assert s.init_val == 84
class InterpretedSubWithoutNew(base):
def __init__(self, val: int) -> None:
super().__init__(val)
self.init_val : int = self.init_val * 2
s2 = InterpretedSubWithoutNew(42)
assert type(s2) == InterpretedSubWithoutNew
assert s2.val == 43
assert s2.init_val == 84
[typing fixtures/typing-full.pyi]
[case testDunderNewInitArgMismatch]
from __future__ import annotations
from testutil import assertRaises
class Test0:
@classmethod
def __new__(cls, val: int = 42) -> Test0:
obj = super().__new__(cls)
obj.val = val
return obj
def __init__(self) -> None:
self.val = 0
class Test1:
def __new__(cls, val: int) -> Test1:
obj = super().__new__(cls)
obj.val = val
return obj
def __init__(self) -> None:
self.val = 0
class Test2:
def __new__(cls) -> Test2:
obj = super().__new__(cls)
return obj
def __init__(self, val: int) -> None:
self.val = val
def test_arg_mismatch() -> None:
t0 = Test0()
assert t0.val == 0
t0 = Test0.__new__(1)
assert t0.val == 1
with assertRaises(TypeError, "__new__() missing required argument 'val'"):
t1 = Test1()
t1 = Test1.__new__(Test1, 2)
assert t1.val == 2
with assertRaises(TypeError, "__new__() takes at most 0 arguments"):
t2 = Test2(42)
t2 = Test2.__new__(Test2)
with assertRaises(AttributeError, "attribute 'val' of 'Test2' undefined"):
print(t2.val)
[case testDunderNewInitArgMismatchInInterpreted]
from __future__ import annotations
class Test0:
# TODO: It should be possible to annotate '@classmethod' here
# but when it's added calling __new__ in interpreted code
# without the explicit type param results in a TypeError.
def __new__(cls, val: int = 42) -> Test0:
obj = super().__new__(cls)
obj.val = val
return obj
def __init__(self) -> None:
self.val = 0
class Test1:
def __new__(cls, val: int) -> Test1:
obj = super().__new__(cls)
obj.val = val
return obj
def __init__(self) -> None:
self.val = 0
class Test2:
def __new__(cls) -> Test2:
obj = super().__new__(cls)
return obj
def __init__(self, val: int) -> None:
self.val = val
[file driver.py]
from native import Test0, Test1, Test2
from testutil import assertRaises
t0 = Test0()
assert t0.val == 0
t0 = Test0.__new__(Test0, 1)
assert t0.val == 1
with assertRaises(TypeError, "__new__() missing required argument 'val'"):
t1 = Test1()
t1 = Test1.__new__(Test1, 2)
assert t1.val == 2
with assertRaises(TypeError, "__new__() takes at most 0 arguments"):
t2 = Test2(42)
t2 = Test2.__new__(Test2)
with assertRaises(AttributeError, "attribute 'val' of 'Test2' undefined"):
print(t2.val)
[case testDunderNewAttributeAccess]
from __future__ import annotations
from mypy_extensions import u8
from testutil import assertRaises
class Test:
native: int
generic: object
bitfield: u8
default: int = 5
def __new__(cls, native: int, generic: object, bitfield: u8) -> Test:
obj = super().__new__(cls)
with assertRaises(AttributeError, "attribute 'native' of 'Test' undefined"):
print(obj.native)
with assertRaises(AttributeError, "attribute 'generic' of 'Test' undefined"):
print(obj.generic)
with assertRaises(AttributeError, "attribute 'bitfield' of 'Test' undefined"):
print(obj.bitfield)
obj.native = native
obj.generic = generic
obj.bitfield = bitfield
obj.native = obj.native + 1
obj.generic = obj.generic.__str__()
obj.bitfield = obj.bitfield & 0x0F
obj.default = obj.default * 2
return obj
def test_attribute_access() -> None:
t = Test(42, {}, 0xCC)
assert t.native == 43
assert t.generic == "{}"
assert t.bitfield == 0x0C
assert t.default == 10
[case testDunderNewAttributeAccessInInterpreted]
from __future__ import annotations
from mypy_extensions import u8
from testutil import assertRaises
class Test:
native: int
generic: object
bitfield: u8
default: int = 5
def __new__(cls, native: int, generic: object, bitfield: u8) -> Test:
obj = super().__new__(cls)
with assertRaises(AttributeError, "attribute 'native' of 'Test' undefined"):
print(obj.native)
with assertRaises(AttributeError, "attribute 'generic' of 'Test' undefined"):
print(obj.generic)
with assertRaises(AttributeError, "attribute 'bitfield' of 'Test' undefined"):
print(obj.bitfield)
obj.native = native
obj.generic = generic
obj.bitfield = bitfield
obj.native = obj.native + 1
obj.generic = obj.generic.__str__()
obj.bitfield = obj.bitfield & 0x0F
obj.default = obj.default * 2
return obj
[file driver.py]
from native import Test
t = Test(42, {}, 0xCC)
assert t.native == 43
assert t.generic == "{}"
assert t.bitfield == 0x0C
assert t.default == 10
[case testUntransformedDunderNewCalls]
from testutil import assertRaises
from typing import Any
class TestStrCls:
def __new__(cls):
return str.__new__(cls)
@classmethod
def factory(cls):
return str.__new__(cls)
class TestStrStr:
def __new__(cls):
return str.__new__(str)
@classmethod
def factory(cls):
return str.__new__(str)
class TestStrInt:
def __new__(cls):
return str.__new__(int)
@classmethod
def factory(cls):
return str.__new__(int)
def test_untransformed_dunder_new() -> None:
with assertRaises(TypeError, "str.__new__(TestStrCls): TestStrCls is not a subtype of str"):
i = TestStrCls()
j: Any = TestStrStr()
assert j == ""
with assertRaises(TypeError, "str.__new__(int): int is not a subtype of str"):
k = TestStrInt()
with assertRaises(TypeError, "str.__new__(TestStrCls): TestStrCls is not a subtype of str"):
i = TestStrCls.factory()
j = TestStrStr.factory()
assert j == ""
with assertRaises(TypeError, "str.__new__(int): int is not a subtype of str"):
k = TestStrInt.factory()
[case testPerTypeFreeList]
from __future__ import annotations
from mypy_extensions import mypyc_attr
a = []
@mypyc_attr(free_list_len=1)
class Foo:
def __init__(self, x: int) -> None:
self.x = x
a.append(x)
def test_alloc() -> None:
x: Foo | None
y: Foo | None
x = Foo(1)
assert x.x == 1
x = None
x = Foo(2)
assert x.x == 2
y = Foo(3)
assert x.x == 2
assert y.x == 3
x = None
y = None
assert a == [1, 2, 3]
x = Foo(4)
assert x.x == 4
y = Foo(5)
assert x.x == 4
assert y.x == 5
@mypyc_attr(free_list_len=1)
class Base:
def __init__(self, x: str) -> None:
self.x = x
class Deriv(Base):
def __init__(self, x: str, y: str) -> None:
super().__init__(x)
self.y = y
@mypyc_attr(free_list_len=1)
class Deriv2(Base):
def __init__(self, x: str, y: str) -> None:
super().__init__(x)
self.y = y
def test_inheritance() -> None:
x: Base | None
y: Base | None
x = Base('x' + str())
y = Base('y' + str())
y = None
d = Deriv('a' + str(), 'b' + str())
assert type(d) is Deriv
assert d.x == 'a'
assert d.y == 'b'
assert x.x == 'x'
y = Base('z' + str())
assert d.x == 'a'
assert d.y == 'b'
assert y.x == 'z'
x = None
y = None
def test_inheritance_2() -> None:
x: Base | None
y: Base | None
d: Deriv2 | None
x = Base('x' + str())
y = Base('y' + str())
y = None
d = Deriv2('a' + str(), 'b' + str())
assert type(d) is Deriv2
assert d.x == 'a'
assert d.y == 'b'
assert x.x == 'x'
d = None
d = Deriv2('c' + str(), 'd' + str())
assert type(d) is Deriv2
assert d.x == 'c'
assert d.y == 'd'
assert x.x == 'x'
y = Base('z' + str())
assert type(y) is Base
assert d.x == 'c'
assert d.y == 'd'
assert y.x == 'z'
x = None
y = None
d = None
[case testDunderGetAttr]
from mypy_extensions import mypyc_attr
from typing import ClassVar
class GetAttr:
class_var = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str) -> object:
return self.extra_attrs.get(attr)
class GetAttrDefault:
class_var: ClassVar[str] = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str, default: int = 8, mult: int = 1) -> object:
return self.extra_attrs.get(attr, default * mult)
class GetAttrInherited(GetAttr):
subclass_var = "y"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int, sub_attr: int):
super().__init__(extra_attrs, regular_attr)
self.sub_attr = sub_attr
class GetAttrOverridden(GetAttr):
subclass_var: ClassVar[str] = "y"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int, sub_attr: int):
super().__init__(extra_attrs, regular_attr)
self.sub_attr = sub_attr
def __getattr__(self, attr: str) -> str:
return attr
@mypyc_attr(native_class=False)
class GetAttrNonNative:
class_var = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str) -> object:
return self.extra_attrs.get(attr)
def test_getattr() -> None:
i = GetAttr({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == None
assert i.__class__ == GetAttr
i.extra_attrs["regular_attr"] = (4, 4, 4)
assert i.__getattr__("regular_attr") == (4, 4, 4)
assert getattr(i, "regular_attr") == 42
assert i.regular_attr == 42
def test_getattr_default() -> None:
i = GetAttrDefault({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == 8
assert i.__getattr__("class_var") == 8
assert i.__getattr__("four", 4, 3) == 12
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == 8
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == 8
assert i.__class__ == GetAttrDefault
i.extra_attrs["class_var"] = (4, 4, 4)
assert i.__getattr__("class_var") == (4, 4, 4)
assert getattr(i, "class_var") == "x"
assert i.class_var == "x"
def test_getattr_inherited() -> None:
i = GetAttrInherited({"one": 1, "two": "two", "three": 3.14}, 42, 24)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("sub_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("subclass_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "sub_attr") == 24
assert getattr(i, "class_var") == "x"
assert getattr(i, "subclass_var") == "y"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.sub_attr == 24
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.four == None
assert i.__class__ == GetAttrInherited
i.extra_attrs["sub_attr"] = (4, 4, 4)
assert i.__getattr__("sub_attr") == (4, 4, 4)
assert getattr(i, "sub_attr") == 24
assert i.sub_attr == 24
base_ref: GetAttr = i
assert getattr(base_ref, "sub_attr") == 24
assert base_ref.sub_attr == 24
assert getattr(base_ref, "subclass_var") == "y"
assert base_ref.subclass_var == "y"
assert getattr(base_ref, "new") == None
assert base_ref.new == None
assert base_ref.__class__ == GetAttrInherited
def test_getattr_overridden() -> None:
i = GetAttrOverridden({"one": 1, "two": "two", "three": 3.14}, 42, 24)
assert i.__getattr__("one") == "one"
assert i.__getattr__("regular_attr") == "regular_attr"
assert i.__getattr__("sub_attr") == "sub_attr"
assert i.__getattr__("class_var") == "class_var"
assert i.__getattr__("subclass_var") == "subclass_var"
assert i.__getattr__("four") == "four"
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "sub_attr") == 24
assert getattr(i, "class_var") == "x"
assert getattr(i, "subclass_var") == "y"
assert getattr(i, "four") == "four"
assert i.three == "three"
assert i.regular_attr == 42
assert i.sub_attr == 24
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.four == "four"
assert i.__class__ == GetAttrOverridden
i.extra_attrs["subclass_var"] = (4, 4, 4)
assert i.__getattr__("subclass_var") == "subclass_var"
assert getattr(i, "subclass_var") == "y"
assert i.subclass_var == "y"
base_ref: GetAttr = i
assert getattr(base_ref, "sub_attr") == 24
assert base_ref.sub_attr == 24
assert getattr(base_ref, "subclass_var") == "y"
assert base_ref.subclass_var == "y"
assert getattr(base_ref, "new") == "new"
assert base_ref.new == "new"
assert base_ref.__class__ == GetAttrOverridden
def test_getattr_nonnative() -> None:
i = GetAttr({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == None
assert i.__class__ == GetAttr
i.extra_attrs["regular_attr"] = (4, 4, 4)
assert i.__getattr__("regular_attr") == (4, 4, 4)
assert getattr(i, "regular_attr") == 42
assert i.regular_attr == 42
[typing fixtures/typing-full.pyi]
[case testDunderGetAttrInterpreted]
from mypy_extensions import mypyc_attr
from typing import ClassVar
class GetAttr:
class_var = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str) -> object:
return self.extra_attrs.get(attr)
class GetAttrDefault:
class_var: ClassVar[str] = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str, default: int = 8, mult: int = 1) -> object:
return self.extra_attrs.get(attr, default * mult)
class GetAttrInherited(GetAttr):
subclass_var = "y"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int, sub_attr: int):
super().__init__(extra_attrs, regular_attr)
self.sub_attr = sub_attr
class GetAttrOverridden(GetAttr):
subclass_var: ClassVar[str] = "y"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int, sub_attr: int):
super().__init__(extra_attrs, regular_attr)
self.sub_attr = sub_attr
def __getattr__(self, attr: str) -> str:
return attr
@mypyc_attr(native_class=False)
class GetAttrNonNative:
class_var = "x"
def __init__(self, extra_attrs: dict[str, object], regular_attr: int):
self.extra_attrs = extra_attrs
self.regular_attr = regular_attr
def __getattr__(self, attr: str) -> object:
return self.extra_attrs.get(attr)
[file driver.py]
from native import GetAttr, GetAttrDefault, GetAttrInherited, GetAttrOverridden, GetAttrNonNative
def test_getattr() -> None:
i = GetAttr({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == None
assert i.__class__ == GetAttr
i.extra_attrs["regular_attr"] = (4, 4, 4)
assert i.__getattr__("regular_attr") == (4, 4, 4)
assert getattr(i, "regular_attr") == 42
assert i.regular_attr == 42
def test_getattr_default() -> None:
i = GetAttrDefault({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == 8
assert i.__getattr__("class_var") == 8
assert i.__getattr__("four", 4, 3) == 12
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == 8
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == 8
assert i.__class__ == GetAttrDefault
i.extra_attrs["class_var"] = (4, 4, 4)
assert i.__getattr__("class_var") == (4, 4, 4)
assert getattr(i, "class_var") == "x"
assert i.class_var == "x"
def test_getattr_inherited() -> None:
i = GetAttrInherited({"one": 1, "two": "two", "three": 3.14}, 42, 24)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("sub_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("subclass_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "sub_attr") == 24
assert getattr(i, "class_var") == "x"
assert getattr(i, "subclass_var") == "y"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.sub_attr == 24
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.four == None
assert i.__class__ == GetAttrInherited
i.extra_attrs["sub_attr"] = (4, 4, 4)
assert i.__getattr__("sub_attr") == (4, 4, 4)
assert getattr(i, "sub_attr") == 24
assert i.sub_attr == 24
base_ref: GetAttr = i
assert getattr(base_ref, "sub_attr") == 24
assert base_ref.sub_attr == 24
assert getattr(base_ref, "subclass_var") == "y"
assert base_ref.subclass_var == "y"
assert getattr(base_ref, "new") == None
assert base_ref.new == None
assert base_ref.__class__ == GetAttrInherited
def test_getattr_overridden() -> None:
i = GetAttrOverridden({"one": 1, "two": "two", "three": 3.14}, 42, 24)
assert i.__getattr__("one") == "one"
assert i.__getattr__("regular_attr") == "regular_attr"
assert i.__getattr__("sub_attr") == "sub_attr"
assert i.__getattr__("class_var") == "class_var"
assert i.__getattr__("subclass_var") == "subclass_var"
assert i.__getattr__("four") == "four"
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "sub_attr") == 24
assert getattr(i, "class_var") == "x"
assert getattr(i, "subclass_var") == "y"
assert getattr(i, "four") == "four"
assert i.three == "three"
assert i.regular_attr == 42
assert i.sub_attr == 24
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.four == "four"
assert i.__class__ == GetAttrOverridden
i.extra_attrs["subclass_var"] = (4, 4, 4)
assert i.__getattr__("subclass_var") == "subclass_var"
assert getattr(i, "subclass_var") == "y"
assert i.subclass_var == "y"
base_ref: GetAttr = i
assert getattr(base_ref, "sub_attr") == 24
assert base_ref.sub_attr == 24
assert getattr(base_ref, "subclass_var") == "y"
assert base_ref.subclass_var == "y"
assert getattr(base_ref, "new") == "new"
assert base_ref.new == "new"
assert base_ref.__class__ == GetAttrOverridden
def test_getattr_nonnative() -> None:
i = GetAttr({"one": 1, "two": "two", "three": 3.14}, 42)
assert i.__getattr__("one") == 1
assert i.__getattr__("regular_attr") == None
assert i.__getattr__("class_var") == None
assert i.__getattr__("four") == None
assert getattr(i, "two") == "two"
assert getattr(i, "regular_attr") == 42
assert getattr(i, "class_var") == "x"
assert getattr(i, "four") == None
assert i.three == 3.14
assert i.regular_attr == 42
assert i.class_var == "x"
assert i.four == None
assert i.__class__ == GetAttr
i.extra_attrs["regular_attr"] = (4, 4, 4)
assert i.__getattr__("regular_attr") == (4, 4, 4)
assert getattr(i, "regular_attr") == 42
assert i.regular_attr == 42
test_getattr()
test_getattr_default()
test_getattr_inherited()
test_getattr_overridden()
test_getattr_nonnative()
[typing fixtures/typing-full.pyi]
[case testDunderSetAttr]
from mypy_extensions import mypyc_attr
from testutil import assertRaises
from typing import ClassVar
class SetAttr:
_attributes: dict[str, object]
regular_attr: int
class_var: ClassVar[str] = "x"
const: int = 42
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__setattr__("_attributes", extra_attrs)
super().__setattr__("regular_attr", regular_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "regular_attr":
super().__setattr__("regular_attr", val)
elif key == "class_var" or key == "const":
raise AttributeError()
else:
self._attributes[key] = val
def __getattr__(self, key: str) -> object:
return self._attributes.get(key)
class SetAttrInherited(SetAttr):
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__init__(regular_attr, extra_attrs)
class SetAttrOverridden(SetAttr):
sub_attr: int
subclass_var: ClassVar[str] = "y"
def __init__(self, regular_attr: int, sub_attr: int, extra_attrs: dict[str, object]) -> None:
super().__init__(regular_attr, extra_attrs)
object.__setattr__(self, "sub_attr", sub_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "sub_attr":
object.__setattr__(self, "sub_attr", val)
elif key == "subclass_var":
raise AttributeError()
else:
super().__setattr__(key, val)
def __delattr__(self, key: str) -> None:
del self._attributes[key]
@mypyc_attr(native_class=False)
class SetAttrNonNative:
_attributes: dict[str, object]
regular_attr: int
class_var: ClassVar[str] = "x"
const: int = 42
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__setattr__("_attributes", extra_attrs)
super().__setattr__("regular_attr", regular_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "regular_attr":
super().__setattr__("regular_attr", val)
elif key == "class_var" or key == "const":
raise AttributeError()
else:
self._attributes[key] = val
def __getattr__(self, key: str) -> object:
return self._attributes.get(key)
class NoSetAttr:
def __init__(self, attr: int) -> None:
self.attr = attr
def object_setattr(self, attr: str, val: object) -> None:
object.__setattr__(self, attr, val)
def super_setattr(self, attr: str, val: object) -> None:
super().__setattr__(attr, val)
@mypyc_attr(native_class=False)
class NoSetAttrNonNative:
def __init__(self, attr: int) -> None:
self.attr = attr
def object_setattr(self, attr: str, val: object) -> None:
object.__setattr__(self, attr, val)
def super_setattr(self, attr: str, val: object) -> None:
super().__setattr__(attr, val)
def __getattr__(self, attr: str) -> object:
pass
def test_setattr() -> None:
i = SetAttr(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_setattr_inherited() -> None:
i = SetAttrInherited(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_setattr_overridden() -> None:
i = SetAttrOverridden(99, 1, {"one": 1})
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.regular_attr == 99
assert i.sub_attr == 1
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
i.__setattr__("sub_attr", 2)
assert i.sub_attr == 2
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("subclass_var", "a")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
setattr(i, "sub_attr", 3)
assert i.sub_attr == 3
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "subclass_var", "b")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
i.sub_attr = 4
assert i.sub_attr == 4
with assertRaises(AttributeError):
i.const = 45
del i.four
assert "four" not in i._attributes
delattr(i, "three")
assert "three" not in i._attributes
i.__delattr__("two")
assert "two" not in i._attributes
base_ref: SetAttr = i
setattr(base_ref, "sub_attr", 5)
assert base_ref.sub_attr == 5
base_ref.sub_attr = 6
assert base_ref.sub_attr == 6
with assertRaises(AttributeError):
setattr(base_ref, "subclass_var", "c")
base_ref.new_attr = "new_attr"
assert base_ref.new_attr == "new_attr"
del base_ref.new_attr
assert "new_attr" not in base_ref._attributes
def test_setattr_nonnative() -> None:
i = SetAttrNonNative(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_no_setattr() -> None:
i = NoSetAttr(99)
i.super_setattr("attr", 100)
assert i.attr == 100
i.object_setattr("attr", 101)
assert i.attr == 101
object.__setattr__(i, "attr", 102)
assert i.attr == 102
with assertRaises(AttributeError):
i.super_setattr("not_attr", 100)
with assertRaises(AttributeError):
i.object_setattr("not_attr", 101)
with assertRaises(AttributeError):
object.__setattr__(i, "not_attr", 102)
def test_no_setattr_nonnative() -> None:
i = NoSetAttrNonNative(99)
i.super_setattr("attr", 100)
assert i.attr == 100
i.object_setattr("attr", 101)
assert i.attr == 101
object.__setattr__(i, "attr", 102)
assert i.attr == 102
i.super_setattr("one", 100)
assert i.one == 100
i.object_setattr("two", 101)
assert i.two == 101
object.__setattr__(i, "three", 102)
assert i.three == 102
del i.three
assert i.three == None
delattr(i, "two")
assert i.two == None
object.__delattr__(i, "one")
assert i.one == None
[typing fixtures/typing-full.pyi]
[case testDunderSetAttrInterpreted]
from mypy_extensions import mypyc_attr
from typing import ClassVar
class SetAttr:
_attributes: dict[str, object]
regular_attr: int
class_var: ClassVar[str] = "x"
const: int = 42
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__setattr__("_attributes", extra_attrs)
super().__setattr__("regular_attr", regular_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "regular_attr":
super().__setattr__("regular_attr", val)
elif key == "class_var" or key == "const":
raise AttributeError()
else:
self._attributes[key] = val
def __getattr__(self, key: str) -> object:
return self._attributes.get(key)
class SetAttrInherited(SetAttr):
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__init__(regular_attr, extra_attrs)
class SetAttrOverridden(SetAttr):
sub_attr: int
subclass_var: ClassVar[str] = "y"
def __init__(self, regular_attr: int, sub_attr: int, extra_attrs: dict[str, object]) -> None:
super().__init__(regular_attr, extra_attrs)
object.__setattr__(self, "sub_attr", sub_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "sub_attr":
object.__setattr__(self, "sub_attr", val)
elif key == "subclass_var":
raise AttributeError()
else:
super().__setattr__(key, val)
def __delattr__(self, key: str) -> None:
del self._attributes[key]
@mypyc_attr(native_class=False)
class SetAttrNonNative:
_attributes: dict[str, object]
regular_attr: int
class_var: ClassVar[str] = "x"
const: int = 42
def __init__(self, regular_attr: int, extra_attrs: dict[str, object]) -> None:
super().__setattr__("_attributes", extra_attrs)
super().__setattr__("regular_attr", regular_attr)
def __setattr__(self, key: str, val: object) -> None:
if key == "regular_attr":
super().__setattr__("regular_attr", val)
elif key == "class_var" or key == "const":
raise AttributeError()
else:
self._attributes[key] = val
def __getattr__(self, key: str) -> object:
return self._attributes.get(key)
class NoSetAttr:
def __init__(self, attr: int) -> None:
self.attr = attr
def object_setattr(self, attr: str, val: object) -> None:
object.__setattr__(self, attr, val)
def super_setattr(self, attr: str, val: object) -> None:
super().__setattr__(attr, val)
@mypyc_attr(native_class=False)
class NoSetAttrNonNative:
def __init__(self, attr: int) -> None:
self.attr = attr
def object_setattr(self, attr: str, val: object) -> None:
object.__setattr__(self, attr, val)
def super_setattr(self, attr: str, val: object) -> None:
super().__setattr__(attr, val)
def __getattr__(self, attr: str) -> object:
pass
[file driver.py]
from native import SetAttr, SetAttrInherited, SetAttrOverridden, SetAttrNonNative, NoSetAttr, NoSetAttrNonNative
from testutil import assertRaises
def test_setattr() -> None:
i = SetAttr(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_setattr_inherited() -> None:
i = SetAttrInherited(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_setattr_overridden() -> None:
i = SetAttrOverridden(99, 1, {"one": 1})
assert i.class_var == "x"
assert i.subclass_var == "y"
assert i.regular_attr == 99
assert i.sub_attr == 1
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
i.__setattr__("sub_attr", 2)
assert i.sub_attr == 2
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("subclass_var", "a")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
setattr(i, "sub_attr", 3)
assert i.sub_attr == 3
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "subclass_var", "b")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
i.sub_attr = 4
assert i.sub_attr == 4
with assertRaises(AttributeError):
i.const = 45
del i.four
assert "four" not in i._attributes
delattr(i, "three")
assert "three" not in i._attributes
i.__delattr__("two")
assert "two" not in i._attributes
base_ref: SetAttr = i
setattr(base_ref, "sub_attr", 5)
assert base_ref.sub_attr == 5
base_ref.sub_attr = 6
assert base_ref.sub_attr == 6
with assertRaises(AttributeError):
setattr(base_ref, "subclass_var", "c")
base_ref.new_attr = "new_attr"
assert base_ref.new_attr == "new_attr"
del base_ref.new_attr
assert "new_attr" not in base_ref._attributes
def test_setattr_nonnative() -> None:
i = SetAttrNonNative(99, {"one": 1})
assert i.class_var == "x"
assert i.regular_attr == 99
assert i.one == 1
assert i.two == None
assert i.const == 42
i.__setattr__("two", "2")
assert i.two == "2"
i.__setattr__("regular_attr", 101)
assert i.regular_attr == 101
with assertRaises(AttributeError):
i.__setattr__("class_var", "y")
with assertRaises(AttributeError):
i.__setattr__("const", 43)
setattr(i, "three", (3,3,3))
assert i.three == (3,3,3)
setattr(i, "regular_attr", 102)
assert i.regular_attr == 102
with assertRaises(AttributeError):
setattr(i, "class_var", "z")
with assertRaises(AttributeError):
setattr(i, "const", 44)
i.four = [4,4]
assert i.four == [4,4]
i.regular_attr = 103
assert i.regular_attr == 103
with assertRaises(AttributeError):
i.const = 45
# Doesn't work because there's no __delattr__.
with assertRaises(AttributeError):
del i.four
def test_no_setattr() -> None:
i = NoSetAttr(99)
i.super_setattr("attr", 100)
assert i.attr == 100
i.object_setattr("attr", 101)
assert i.attr == 101
object.__setattr__(i, "attr", 102)
assert i.attr == 102
with assertRaises(AttributeError):
i.super_setattr("not_attr", 100)
with assertRaises(AttributeError):
i.object_setattr("not_attr", 101)
with assertRaises(AttributeError):
object.__setattr__(i, "not_attr", 102)
def test_no_setattr_nonnative() -> None:
i = NoSetAttrNonNative(99)
i.super_setattr("attr", 100)
assert i.attr == 100
i.object_setattr("attr", 101)
assert i.attr == 101
object.__setattr__(i, "attr", 102)
assert i.attr == 102
i.super_setattr("one", 100)
assert i.one == 100
i.object_setattr("two", 101)
assert i.two == 101
object.__setattr__(i, "three", 102)
assert i.three == 102
del i.three
assert i.three == None
delattr(i, "two")
assert i.two == None
object.__delattr__(i, "one")
assert i.one == None
test_setattr()
test_setattr_inherited()
test_setattr_overridden()
test_setattr_nonnative()
test_no_setattr()
test_no_setattr_nonnative()
[typing fixtures/typing-full.pyi]
[case testDelAttrWithDeletableAttr]
from testutil import assertRaises
class DelAttr:
__deletable__ = ["del_counter"]
_attributes: dict[str, object]
del_counter: int = 0
def __init__(self) -> None:
object.__setattr__(self, "_attributes", {})
def __setattr__(self, key: str, val: object) -> None:
if key == "del_counter":
object.__setattr__(self, "del_counter", val)
else:
self._attributes[key] = val
def __delattr__(self, key: str) -> None:
if key == "del_counter":
self.del_counter += 1
else:
del self._attributes[key]
def test_deletable_attr() -> None:
i = DelAttr()
assert i.del_counter == 0
del i.del_counter
assert i.del_counter == 1
[case testDelAttrWithDeletableAttrInterpreted]
class DelAttr:
__deletable__ = ["del_counter"]
_attributes: dict[str, object]
del_counter: int = 0
def __init__(self) -> None:
object.__setattr__(self, "_attributes", {})
def __setattr__(self, key: str, val: object) -> None:
if key == "del_counter":
object.__setattr__(self, "del_counter", val)
else:
self._attributes[key] = val
def __delattr__(self, key: str) -> None:
if key == "del_counter":
self.del_counter += 1
else:
del self._attributes[key]
[file driver.py]
from native import DelAttr
from testutil import assertRaises
def test_deletable_attr() -> None:
i = DelAttr()
assert i.del_counter == 0
del i.del_counter
assert i.del_counter == 1
test_deletable_attr()