@@ -173,6 +173,18 @@ def is_method(self) -> bool:
173173 function_type = type (lambda : None )
174174 return self .parent_is_class () and isinstance (self .obj , function_type )
175175
176+ def is_method_descriptor (self ) -> bool :
177+ """
178+ Tell if this node's object is a method descriptor.
179+
180+ Built-in methods (e.g. those implemented in C/Rust) are often
181+ method descriptors, rather than normal methods.
182+
183+ Returns:
184+ If this node's object is a method descriptor.
185+ """
186+ return inspect .ismethoddescriptor (self .obj )
187+
176188 def is_staticmethod (self ) -> bool :
177189 """
178190 Tell if this node's object is a staticmethod.
@@ -360,6 +372,8 @@ def get_object_documentation(self, dotted_path: str, members: Optional[Union[Set
360372 root_object = self .get_staticmethod_documentation (leaf )
361373 elif leaf .is_classmethod ():
362374 root_object = self .get_classmethod_documentation (leaf )
375+ elif leaf .is_method_descriptor ():
376+ root_object = self .get_regular_method_documentation (leaf )
363377 elif leaf .is_method ():
364378 root_object = self .get_regular_method_documentation (leaf )
365379 elif leaf .is_function ():
@@ -792,7 +806,7 @@ def get_regular_method_documentation(self, node: ObjectNode) -> Method:
792806
793807 def get_method_documentation (self , node : ObjectNode , properties : Optional [List [str ]] = None ) -> Method :
794808 """
795- Get the documentation for a method.
809+ Get the documentation for a method or method descriptor .
796810
797811 Arguments:
798812 node: The node representing the method and its parents.
@@ -803,6 +817,7 @@ def get_method_documentation(self, node: ObjectNode, properties: Optional[List[s
803817 """
804818 method = node .obj
805819 path = node .dotted_path
820+ signature : Optional [inspect .Signature ]
806821 source : Optional [Source ]
807822
808823 try :
@@ -819,12 +834,23 @@ def get_method_documentation(self, node: ObjectNode, properties: Optional[List[s
819834 else :
820835 properties .append ("async" )
821836
837+ try :
838+ # for "built-in" functions, e.g. those implemented in C,
839+ # inspect.signature() uses the __text_signature__ attribute, which
840+ # provides a limited but still useful amount of signature information.
841+ # "built-in" functions with no __text_signature__ will
842+ # raise a ValueError().
843+ signature = inspect .signature (method )
844+ except ValueError as error :
845+ self .errors .append (f"Couldn't read signature for '{ path } ': { error } " )
846+ signature = None
847+
822848 return Method (
823849 name = node .name ,
824850 path = path ,
825851 file_path = node .file_path ,
826852 docstring = inspect .getdoc (method ),
827- signature = inspect . signature ( method ) ,
853+ signature = signature ,
828854 properties = properties or [],
829855 source = source ,
830856 )
0 commit comments