Skip to content

Commit

Permalink
Fix lack of support on checking generic interfaces
Browse files Browse the repository at this point in the history
Previosly verifying non-generic classes that correctly implements generic
interfaces used to fail, as the interface holds an special method
coming from the typing.Generic inheritance (`__class_getitem__`). The
changes here solves this limitation.
  • Loading branch information
ro-oliveira95 committed Nov 21, 2023
1 parent e03adf1 commit 0c46e6c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/oop_ext/interface/_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ def AssertImplementsFullChecking(


# set of methods that might be declared in interfaces but should be not be required by implementations
_INTERFACE_METHODS_TO_IGNORE = {"__init_subclass__"}
_INTERFACE_METHODS_TO_IGNORE = {"__init_subclass__", "__class_getitem__"}


def _AssertImplementsFullChecking(
Expand Down
33 changes: 33 additions & 0 deletions src/oop_ext/interface/_tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,3 +1077,36 @@ def AfterCaption(*args):

assert Foo.GetCaption() == "Foo"
assert Foo().GetValues("m") == [0.1, 10.0]


def testGenericInterface() -> None:
"""Generic interfaces need to support checking on both generic and non-generic implementers"""
from typing import Generic, TypeVar

T = TypeVar("T", covariant=True)

class IFoo(Interface, Generic[T], TypeCheckingSupport):
def GetOutput(self) -> T: # type:ignore[empty-body]
...

@ImplementsInterface(IFoo, no_check=True) # Will check later.
class GenericFoo(Generic[T]):
def __init__(self, output: T) -> None:
self.output = output

@Implements(IFoo.GetOutput)
def GetOutput(self) -> T:
return self.output

@ImplementsInterface(IFoo, no_check=True)
class NonGenericFoo:
@Implements(IFoo.GetOutput)
def GetOutput(self) -> int:
return 1

# This works out of the box.
AssertImplements(GenericFoo, IFoo)
AssertImplements(GenericFoo[str](output="foo"), IFoo)

# This only works if we skip the verification of `__class_getitem__` method.
AssertImplements(NonGenericFoo, IFoo)

0 comments on commit 0c46e6c

Please sign in to comment.