python-interface
python-interface copied to clipboard
Check if interface is implemented
nice module! is there a way to check at runtime if an interface is implemented by a class / instace?
Hi @21stio. Thanks for your interest in inferface!
There isn't currently a public API for checking if an object/class implements an interface. The closest thing is Interface.verify(type)
, which is what gets called at class creation time when you declare that you implement an interface, but that function is fairly expensive when it fails, because it spends a lot of effort building nice error messages.
I think it makes sense to add a function that just gives back a boolean indicating whether an object/type implements an interface (though I confess I haven't actually needed such a function yet in using interface, which is why it currently doesn't exist). What would you expect the behavior of such a function to be? If we added a function named something like check_implements
(actual name TBD), I can think of a few potential axes of variation.
- Would
check_implements(obj, IFace)
expectobj
to be a type or an instance? Would we want separate methods for objects and types (analogous to the built-inisinstance
/issubclass
functions)? - Would
check_implements
just verify that the object it receives was declared as implementingIFace
, or would it dynamically verify that the interface is actually implemented? The former would likely be much faster, but I could imagine use-cases for both behaviors.
This module makes perfect sense! I too would really like that boolean check method. My suggestion:
-
instance_implements(obj, IFace)
andclass_implements(cls, IFace)
(analogous to the built-in isinstance/issubclass functions) - Since the actual implementation is checked at class creation, wouldn't it suffice to do the former check, i.e. check that it was declared as implementing
IFace
?
I just ended up using classes with methods that throw NotImplemented when not being overwritten. This validation only happens when the method is called tho.
Like this you have full is_instance support, ides let you override methods etc.
just my 2 cents
Since the actual implementation is checked at class creation, wouldn't it suffice to do the former check, i.e. check that it was declared as implementing IFace?
That would work in most cases, but it wouldn't work if you dynamically added or removed interface methods from an object's type after the type was created (class decorators like the new dataclass decorator in the stdlib often do this, for example).
@dremok @21stio I'd be curious to see if you have concrete examples where you think this functionality would be useful. My general belief is that idiomatic usage of interface shouldn't require runtime interface checks. My usage pattern usually looks like:
class SomeInterface(Interface):
pass
class SomeImplementation(implements(SomeInterface)):
....
class SomeOtherImplementation(implements(SomeInterface)):
...
def some_function(arg): # expects arg to implement SomeInterface
# Call interface methods on arg.
For this kind of usage, the only thing I could imagine wanting to do with instance_implements
and class_implements
is use them for assertions, but it's generally more idiomatic to just try to use the object and fail with an AttributeError/TypeError if the received object is incorrect.
@ssanderson Ah, you're right about dynamically added methods, didn't think about that.
Assertion is exactly what I was planning on using these methods for. I have a unit test which calls a method which returns a list of stuff, where the objects are implementing different interfaces. Then I wanted to do different assertions depending on the interface type. But I guess I should really redesign, or just ask for forgiveness instead of permission...
that's exactly the same use case I had
Hi @21stio. Thanks for your interest in inferface!
There isn't currently a public API for checking if an object/class implements an interface. The closest thing is
Interface.verify(type)
, which is what gets called at class creation time when you declare that you implement an interface, but that function is fairly expensive when it fails, because it spends a lot of effort building nice error messages.I think it makes sense to add a function that just gives back a boolean indicating whether an object/type implements an interface (though I confess I haven't actually needed such a function yet in using interface, which is why it currently doesn't exist). What would you expect the behavior of such a function to be? If we added a function named something like
check_implements
(actual name TBD), I can think of a few potential axes of variation.
- Would
check_implements(obj, IFace)
expectobj
to be a type or an instance? Would we want separate methods for objects and types (analogous to the built-inisinstance
/issubclass
functions)?- Would
check_implements
just verify that the object it receives was declared as implementingIFace
, or would it dynamically verify that the interface is actually implemented? The former would likely be much faster, but I could imagine use-cases for both behaviors.
I was actually expecting that the standard isinstance function would work for checking if an object implements a certain interface
Hi,
Am I reviving a dead thread? Hope @ssanderson is still around to react.
In any case, one example I can come up with that does require such a checking method: when external code that wasn't written using your Interface needs to be checked if it has the necessary methods. Imagine some public protocol that has several implementations that need to work together - your code may use Interface but someone else's code doesn't. This is pretty straightforward with the subclasshook/check that's used with abc.
BtW, I really like your implementation of interfaces. I was not satisfied with abc and kept thinking why a better implementation didn't exist, then one day I searched around a bit and found this project. Awesome!
In any case, one example I can come up with that does require such a checking method: when external code that wasn't written using your Interface needs to be checked if it has the necessary methods. Imagine some public protocol that has several implementations that need to work together - your code may use Interface but someone else's code doesn't. This is pretty straightforward with the subclasshook/check that's used with abc.
I think checking implementations on types that are outside your control is a reasonable use-case. Something like the following seems reasonable to me, for example:
class MyInterface(Interface):
# Declare methods
class MyImpl(implements(MyInterface)):
# Implement methods.
from not_my_module import OtherImpl
# Raises a TypeError if OtherImpl isn't a valid implementation of MyInterface.
expect_type_implements(OtherImpl, MyInterface)
I'm less confident that runtime checking on instances is a reasonable thing to support, e.g.:
class MyInterface(Interface):
...
def my_function(obj):
"""``obj`` must implement MyInterface
"""
expect_instance_implements(obj, MyInterface)
# Use interface methods.
BtW, I really like your implementation of interfaces.
Thanks!