diff --git a/pybind11_stubgen/parser/errors.py b/pybind11_stubgen/parser/errors.py index fba88945..7af14ac9 100644 --- a/pybind11_stubgen/parser/errors.py +++ b/pybind11_stubgen/parser/errors.py @@ -33,3 +33,14 @@ def __init__(self, name: QualifiedName): def __str__(self): return f"Can't find/import '{self.name}'" + + +class InspectError(ParserError): + def __init__(self, path: QualifiedName, class_: type, msg: str): + super().__init__() + self.path = path + self.class_ = class_ + self.msg = msg + + def __str__(self): + return f"Can't get members of type {self.class_} at {self.path}: {self.msg}" diff --git a/pybind11_stubgen/parser/mixins/parse.py b/pybind11_stubgen/parser/mixins/parse.py index dbf6f159..5ea97753 100644 --- a/pybind11_stubgen/parser/mixins/parse.py +++ b/pybind11_stubgen/parser/mixins/parse.py @@ -7,6 +7,7 @@ from typing import Any from pybind11_stubgen.parser.errors import ( + InspectError, InvalidExpressionError, InvalidIdentifierError, NameResolutionError, @@ -45,26 +46,31 @@ class ParserDispatchMixin(IParser): def handle_class(self, path: QualifiedName, class_: type) -> Class | None: base_classes = class_.__bases__ result = Class(name=path[-1], bases=self.handle_bases(path, base_classes)) - for name, member in inspect.getmembers(class_): - obj = self.handle_class_member( - QualifiedName([*path, Identifier(name)]), class_, member - ) - if isinstance(obj, Docstring): - result.doc = obj - elif isinstance(obj, Alias): - result.aliases.append(obj) - elif isinstance(obj, Field): - result.fields.append(obj) - elif isinstance(obj, Class): - result.classes.append(obj) - elif isinstance(obj, list): # list[Method] - result.methods.extend(obj) - elif isinstance(obj, Property): - result.properties.append(obj) - elif obj is None: - pass - else: - raise AssertionError() + try: + members = inspect.getmembers(class_) + except TypeError as e: + self.report_error(InspectError(path, class_, str(e))) + else: + for name, member in members: + obj = self.handle_class_member( + QualifiedName([*path, Identifier(name)]), class_, member + ) + if isinstance(obj, Docstring): + result.doc = obj + elif isinstance(obj, Alias): + result.aliases.append(obj) + elif isinstance(obj, Field): + result.fields.append(obj) + elif isinstance(obj, Class): + result.classes.append(obj) + elif isinstance(obj, list): # list[Method] + result.methods.extend(obj) + elif isinstance(obj, Property): + result.properties.append(obj) + elif obj is None: + pass + else: + raise AssertionError() return result def handle_class_member(