def testDeclareClassImplements() -> None: class I1(Interface): def M1(self): "" class I2(Interface): def M2(self): "" class C0: "" class C1: def M1(self): "" class C2: def M2(self): "" @ImplementsInterface(I2) class C2B: def M2(self): "" class C12B(C1, C2B): "" with pytest.raises(AssertionError): DeclareClassImplements(C0, I1) assert IsImplementation(C1, I1, requires_declaration=False) == True DeclareClassImplements(C1, I1) assert IsImplementation(C1, I1) == True AssertImplements(C1, I1) # C1 is parent of C12B, and, above, it was declared that C1 implements I1, # so C12B should automatically implement I1. assert IsImplementation(C12B, I1) == True # automatic assert (IsImplementation(C12B, I2) == True ) # inheritance for Implements still works automatically DeclareClassImplements(C12B, I1) assert IsImplementation(C12B, I1) == True # now it implements assert IsImplementation(C12B, I2) == True DeclareClassImplements(C2, I2) assert IsImplementation(C2, I2) == True AssertImplements(C2, I2) # Exception: if I define a class *after* using DeclareClassImplements in the base, it works: class C12(C1, C2): "" AssertImplements(C12, I1) AssertImplements(C12, I2)
def testNull() -> None: AssertImplements( Null(), _InterfM2, requires_declaration=False) # Not raises BadImplementationError class ExtendedNull(Null): "" AssertImplements( ExtendedNull(), _InterfM2, requires_declaration=False) # Not raises BadImplementationError
def __init__(self, image: IArray, domain: IArray) -> None: """ :param image: This is the image of this curve :param domain: This is the domain of this curve """ AssertImplements(image, IArray) AssertImplements(domain, IArray) self._CheckImageAndDomainLength(image, domain) self._image = image self._domain = domain
def testDecorators(register_callback: bool): """Interfaces and the foundation decorators/callbacks need to play nice together.""" class IFoo(Interface): def GetValues(self, unit: str) -> List[float]: ... @classmethod def GetCaption(cls) -> str: ... @ImplementsInterface(IFoo) class AbstractFoo: @Implements(IFoo.GetValues) @Abstract def GetValues(self, unit: str) -> List[float]: ... @classmethod @Implements(IFoo.GetCaption) @Abstract def GetCaption(cls) -> str: ... class Foo(AbstractFoo): @Override(AbstractFoo.GetValues) def GetValues(self, unit: str) -> List[float]: return [0.1, 10.0] @classmethod @Override(AbstractFoo.GetCaption) def GetCaption(cls) -> str: return "Foo" from oop_ext.foundation import callback if register_callback: def AfterCaption(*args): pass # Ensure methods overwritten by callbacks don't interfere with interface # signature detection: Callback.After overwrites the method object on the class, # with potentially a different signature. callback.After(Foo.GetCaption, AfterCaption) AssertImplements(Foo, IFoo) AssertImplements(Foo(), IFoo) assert Foo.GetCaption() == "Foo" assert Foo().GetValues("m") == [0.1, 10.0]
def testInterfaceCheckRequiresInterface() -> None: class M3: def m3(self, *args, **kwargs): "" with pytest.raises(InterfaceError): AssertImplements(M3(), M3) # type:ignore[arg-type] with pytest.raises(InterfaceError): IsImplementation(M3(), M3) # type:ignore[arg-type] assert IsImplementation(M3(), _InterfM3, requires_declaration=False) assert not IsImplementation(M3(), _InterfM3, requires_declaration=True) with pytest.raises(AssertionError): AssertImplements(M3(), _InterfM3, requires_declaration=True)
def testGetImplementedInterfaces2() -> None: @ImplementsInterface(_InterfM1) class A: def m1(self): "" @ImplementsInterface(_InterfM2) class B(A): def m2(self): "" assert 2 == len(GetImplementedInterfaces(B())) with pytest.raises(AssertionError): AssertImplements(A(), _InterfM2) AssertImplements(B(), _InterfM2)
def testNoCheck() -> None: @ImplementsInterface(_InterfM1, no_check=True) class NoCheck: pass no_check = NoCheck() with pytest.raises(AssertionError): AssertImplements(no_check, _InterfM1)
def SetDefaultUnitSystemClass(self, class_: Type[IUnitSystem]) -> None: """ Set the default unit system class. :param class_: The unit system class that will be used when creating new unit systems. """ AssertImplements(class_, IUnitSystem) self._default_unit_system_class = class_
def testImplementorWithAny() -> None: """ You don't need to explicitly declare that you implement an Interface. This is just a smoke test """ class M3: def m3(self, *args, **kwargs): "" AssertImplements(M3(), _InterfM3, requires_declaration=False)
def testReadOnlyAttribute() -> None: class IZoo(Interface): zoo = ReadOnlyAttribute(int) @ImplementsInterface(IZoo) class Zoo: def __init__(self, value): self.zoo = value a_zoo = Zoo(value=99) AssertImplements(a_zoo, IZoo)
def testNoName() -> None: class I(Interface): def MyMethod(self, foo): "" class C: def MyMethod(self, bar): "" with pytest.raises(AssertionError): AssertImplements(C(), I)
def testIsImplementationOfAny() -> None: class A: def m3(self, arg1, arg2): "" a_obj = A() AssertImplements(a_obj, _InterfM3, requires_declaration=False) assert IsImplementationOfAny(A, [_InterfM1, _InterfM2, _InterfM3, _InterfM4], requires_declaration=False) assert not IsImplementationOfAny(A, [_InterfM1, _InterfM2, _InterfM4], requires_declaration=False)
def testCallbackAndInterfaces() -> None: """ Tests if the interface "AssertImplements" works with "callbacked" methods. """ @ImplementsInterface(_InterfM1) class My: def m1(self): "" def MyCallback(): "" from oop_ext.foundation.callback import After o = My() AssertImplements(o, _InterfM1) After(o.m1, MyCallback) AssertImplements(o, _InterfM1) AssertImplements(o, _InterfM1) # Not raises BadImplementationError
def testClassMethodBug(mocker) -> None: """ Issue #20 """ class IFoo(Interface): @classmethod def foo(cls): "" @ImplementsInterface(IFoo) class FooImplementation: @classmethod def foo(cls): "" mocker.spy(FooImplementation, "foo") AssertImplements(FooImplementation, IFoo, requires_declaration=True)
def testAssertImplementsDoesNotDirObject() -> None: """ AssertImplements does not attempt to __getattr__ methods from an object, it only considers methods that are actually bound to the class. """ class M1: def __getattr__(self, attr): assert attr == "m1" # This test only accepts this attribute class MyMethod(Method): def __call__(self): "" return MyMethod() m1 = M1() m1.m1() with pytest.raises(AssertionError): AssertImplements(m1, _InterfM1)
def testPassNoneInAssertImplementsFullChecking() -> None: with pytest.raises(AssertionError): AssertImplements(None, _InterfM1) with pytest.raises(AssertionError): AssertImplements(10, _InterfM1)