Python: how to check whether an object implements a given UNO interface?

Really thought there’d be a simple answer here.

I found this page. This didn’t seem applicable to my case.

And I found XInterface.queryInterface() from consulting the docs.

But this doesn’t work with this, where I want to check whether something implements XComponent:

def documentEventOccured(self, event):
    if event.EventName == 'OnSubComponentOpened':
        # this print out shows that event.Supplement does indeed implement com.sun.star.lang.XComponent
        print(f'doc event.Supplement {event.Supplement}')
        print(f'event.Supplement.queryInterface(XComponent) {event.Supplement.queryInterface(XComponent)}')

This gives:

uno.com.sun.star.uno.RuntimeException: Couldn’t convert <class ‘uno.com.sun.star.lang.XComponent’> to a UNO type; caught exception: <class ‘AttributeError’>: type object ‘com.sun.star.lang.XComponent’ has no attribute ‘getTypes’, traceback follows
no traceback available

So, despite the name, it would appear that queryInterface is not for checking interfaces (at least not those of the kind beginning X…). How might I check that an object implements a particular UNO interface such as XComponent?

Incidentally I also tried a vanilla Python isinstance test:

print(f'isinstance(event.Supplement, XComponent) {isinstance(event.Supplement, XComponent)}')
… False.

Here is how I do in OOO Development Tools (OooDev)

@classmethod
def is_uno_interfaces(cls, component: object, *args: str | UnoInterface) -> bool:
    if len(args) == 0:
        return False
    result = True
    for arg in args:
        try:
            if isinstance(arg, str):
                t = uno.getClass(arg)
            else:
                t = arg
            obj = cls.qi(t, component)
            if obj is None:
                result = False
                break
        except Exception:
            result = False
            break
    return result

@staticmethod
def qi(atype: Type[T], obj: XTypeProvider, raise_err: bool = False) -> T | None:
    result = None
    if uno.isInterface(atype) and hasattr(obj, "queryInterface"):
        uno_t = uno.getTypeByName(atype.__pyunointerface__)
        result = obj.queryInterface(uno_t)
    if raise_err is True and result is None:
        raise mEx.MissingInterfaceError(atype)
    return result

Source Code Link

Thanks. A pretty complicated answer. I reduced it down to a simple function:

def is_uno_interface(comp, uno_interface):
    if isinstance(uno_interface, str):
        uno_interface = uno.getClass(uno_interface)
    if not uno.isInterface(uno_interface):
        raise Exception(f'{uno_interface} is not a UNO interface')
    if not hasattr(comp, 'queryInterface'):
        raise Exception(f'comp {comp} does not have attribute "queryInterface": not a UNO object')
    uno_type = uno.getTypeByName(uno_interface.__pyunointerface__)
    return comp.queryInterface(uno_type) != None

… the key obviously being uno.getTypeByName(uno_interface.__pyunointerface__).

1 Like