Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if interface is implemented #5

Open
ppwfx opened this issue Nov 8, 2017 · 11 comments
Open

Check if interface is implemented #5

ppwfx opened this issue Nov 8, 2017 · 11 comments

Comments

@ppwfx
Copy link

ppwfx commented Nov 8, 2017

nice module! is there a way to check at runtime if an interface is implemented by a class / instace?

@ssanderson
Copy link
Owner

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.

  1. Would check_implements(obj, IFace) expect obj to be a type or an instance? Would we want separate methods for objects and types (analogous to the built-in isinstance/issubclass functions)?
  2. Would check_implements just verify that the object it receives was declared as implementing IFace, 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.

@dremok
Copy link

dremok commented Feb 13, 2018

This module makes perfect sense!
I too would really like that boolean check method. My suggestion:

  1. instance_implements(obj, IFace) and class_implements(cls, IFace) (analogous to the built-in isinstance/issubclass functions)
  2. 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?

@ppwfx
Copy link
Author

ppwfx commented Feb 13, 2018

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

@ssanderson
Copy link
Owner

ssanderson commented Feb 13, 2018

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).

@ssanderson
Copy link
Owner

ssanderson commented Feb 13, 2018

@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.

@dremok
Copy link

dremok commented Feb 14, 2018

@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...

@ppwfx
Copy link
Author

ppwfx commented Feb 14, 2018

that's exactly the same use case I had

@FastGeert
Copy link

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.

  1. Would check_implements(obj, IFace) expect obj to be a type or an instance? Would we want separate methods for objects and types (analogous to the built-in isinstance/issubclass functions)?
  2. Would check_implements just verify that the object it receives was declared as implementing IFace, 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

@zEdS15B3GCwq
Copy link

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!

@ssanderson
Copy link
Owner

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.

@ssanderson
Copy link
Owner

BtW, I really like your implementation of interfaces.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants