11import collections
2- import itertools
32import os
4- import sys
53
64import astroid
75import astroid .builder
108from . import _astroid_utils
119
1210
13- if sys .version_info < (3 , 10 ): # PY310
14- from stdlib_list import in_stdlib
15- else :
16-
17- def in_stdlib (module_name : str ) -> bool :
18- return module_name in sys .stdlib_module_names
19-
20-
2111def _prepare_docstring (doc ):
2212 return "\n " .join (sphinx .util .docstrings .prepare_docstring (doc ))
2313
@@ -117,55 +107,69 @@ def _parse_assign(self, node):
117107
118108 return [data ]
119109
120- def parse_classdef (self , node , data = None ):
110+ def _parse_classdef (self , node , use_name_stacks ):
111+ if use_name_stacks :
112+ qual_name = self ._get_qual_name (node .name )
113+ full_name = self ._get_full_name (node .name )
114+
115+ self ._qual_name_stack .append (node .name )
116+ self ._full_name_stack .append (node .name )
117+ else :
118+ qual_name = node .qname ()[len (node .root ().qname ()) + 1 :]
119+ full_name = node .qname ()
120+
121121 type_ = "class"
122122 if _astroid_utils .is_exception (node ):
123123 type_ = "exception"
124124
125- basenames = list (_astroid_utils .get_full_basenames (node ))
126-
127125 data = {
128126 "type" : type_ ,
129127 "name" : node .name ,
130- "qual_name" : self . _get_qual_name ( node . name ) ,
131- "full_name" : self . _get_full_name ( node . name ) ,
132- "bases" : basenames ,
128+ "qual_name" : qual_name ,
129+ "full_name" : full_name ,
130+ "bases" : list ( _astroid_utils . get_full_basenames ( node )) ,
133131 "doc" : _prepare_docstring (_astroid_utils .get_class_docstring (node )),
134132 "from_line_no" : node .fromlineno ,
135133 "to_line_no" : node .tolineno ,
136134 "children" : [],
135+ "is_abstract" : _astroid_utils .is_abstract_class (node ),
137136 }
138137
139- self ._qual_name_stack .append (node .name )
140- self ._full_name_stack .append (node .name )
141- overridden = set ()
142138 overloads = {}
139+ for child in node .get_children ():
140+ children_data = self .parse (child )
141+ for child_data in children_data :
142+ if _parse_child (child_data , overloads ):
143+ data ["children" ].append (child_data )
144+
145+ data ["children" ] = list (self ._resolve_inheritance (data ))
146+
147+ return data
148+
149+ def _resolve_inheritance (self , * mro_data ):
150+ overridden = set ()
143151 children = {}
144- for base in itertools . chain ( iter (( node ,)), node . ancestors () ):
152+ for i , cls_data in enumerate ( mro_data ):
145153 seen = set ()
146154 base_children = []
155+ overloads = {}
147156
148- # Don't document members inherited from standard library classes
149- # unless that class is abstract.
150- base_module = base .qname ().split ("." , 1 )[0 ]
151- if in_stdlib (base_module ) and not _astroid_utils .is_abstract_class (base ):
152- continue
153-
154- for child in base .get_children ():
155- children_data = self .parse (child )
156- for child_data in children_data :
157- name = child_data ["name" ]
157+ for child_data in cls_data ["children" ]:
158+ name = child_data ["name" ]
158159
159- existing_child = children .get (name )
160- if existing_child and not existing_child ["doc" ]:
161- existing_child ["doc" ] = child_data ["doc" ]
160+ existing_child = children .get (name )
161+ if existing_child and not existing_child ["doc" ]:
162+ existing_child ["doc" ] = child_data ["doc" ]
162163
163- if name in overridden :
164- continue
164+ if name in overridden :
165+ continue
165166
166- seen .add (name )
167- if _parse_child (node , child_data , overloads , base ):
168- base_children .append (child_data )
167+ seen .add (name )
168+ if _parse_child (child_data , overloads ):
169+ base_children .append (child_data )
170+ child_data ["inherited" ] = i != 0
171+ if child_data ["inherited" ]:
172+ child_data ["inherited_from" ] = cls_data
169173
170174 overridden .update (seen )
171175
@@ -185,7 +189,29 @@ def parse_classdef(self, node, data=None):
185189
186190 children [base_child ["name" ]] = base_child
187191
188- data ["children" ].extend (children .values ())
192+ return children .values ()
193+
194+ def _relevant_ancestors (self , node ):
195+ for base in node .ancestors ():
196+ if base .qname () in (
197+ "__builtins__.object" ,
198+ "builtins.object" ,
199+ "builtins.type" ,
200+ ):
201+ continue
202+
203+ yield base
204+
205+ def parse_classdef (self , node ):
206+ data = self ._parse_classdef (node , use_name_stacks = True )
207+
208+ ancestors = self ._relevant_ancestors (node )
209+ ancestor_data = [
210+ self ._parse_classdef (base , use_name_stacks = False ) for base in ancestors
211+ ]
212+ if ancestor_data :
213+ data ["children" ] = list (self ._resolve_inheritance (data , * ancestor_data ))
214+
189215 self ._qual_name_stack .pop ()
190216 self ._full_name_stack .pop ()
191217
@@ -227,7 +253,7 @@ def parse_functiondef(self, node):
227253 "qual_name" : self ._get_qual_name (node .name ),
228254 "full_name" : self ._get_full_name (node .name ),
229255 "args" : _astroid_utils .get_args_info (node .args ),
230- "doc" : _prepare_docstring (_astroid_utils . get_func_docstring ( node ) ),
256+ "doc" : _prepare_docstring (node . doc_node . value if node . doc_node else "" ),
231257 "from_line_no" : node .fromlineno ,
232258 "to_line_no" : node .tolineno ,
233259 "return_annotation" : _astroid_utils .get_return_annotation (node ),
@@ -302,7 +328,7 @@ def parse_module(self, node):
302328 children_data = self .parse (child )
303329
304330 for child_data in children_data :
305- if _parse_child (node , child_data , overloads ):
331+ if _parse_child (child_data , overloads ):
306332 data ["children" ].append (child_data )
307333
308334 return data
@@ -352,7 +378,7 @@ def parse(self, node):
352378 return data
353379
354380
355- def _parse_child (node , child_data , overloads , base = None ) -> bool :
381+ def _parse_child (child_data , overloads ) -> bool :
356382 if child_data ["type" ] in ("function" , "method" , "property" ):
357383 name = child_data ["name" ]
358384 if name in overloads :
@@ -369,7 +395,4 @@ def _parse_child(node, child_data, overloads, base=None) -> bool:
369395 if child_data ["is_overload" ] and name not in overloads :
370396 overloads [name ] = child_data
371397
372- if base :
373- child_data ["inherited" ] = base is not node
374-
375398 return True
0 commit comments