def __getattr__(self, name):
        """Get a COM attribute."""
        if name.startswith("__") and name.endswith("__"):
            raise AttributeError(name)
        # check for propget or method
        descr = self.__bind(name, DISPATCH_METHOD | DISPATCH_PROPERTYGET)
        if descr is None:
            raise AttributeError(name)
        if descr.invkind == DISPATCH_PROPERTYGET:
            # DISPATCH_PROPERTYGET
            if descr.funckind == FUNC_DISPATCH:
                if descr.cParams == 0:
                    return self._comobj._invoke(descr.memid, descr.invkind, 0)
            elif descr.funckind == FUNC_PUREVIRTUAL:
                # FUNC_PUREVIRTUAL descriptions contain the property
                # itself as a parameter.
                if descr.cParams == 1:
                    return self._comobj._invoke(descr.memid, descr.invkind, 0)
            else:
                raise RuntimeError("funckind %d not yet implemented" % descr.funckind)
            put = self.__bind(name, DISPATCH_PROPERTYPUT)
            putref = self.__bind(name, DISPATCH_PROPERTYPUTREF)
            return NamedProperty(self, descr, put, putref)
        else:
            # DISPATCH_METHOD
            def caller(*args):
                return self._comobj._invoke(descr.memid, descr.invkind, 0, *args)
            try:
                caller.__name__ = name
            except __HOLE__:
                # In Python 2.3, __name__ is readonly
                pass
            return caller
dataset/ETHPy150Open enthought/comtypes/comtypes/client/lazybind.py/Dispatch.__getattr__