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