| [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() |