2323import inspect
2424import importlib
2525import doctest
26- import textwrap
26+ import pydoc
2727try :
2828 from io import StringIO
2929except ImportError :
3939from numpydoc .docscrape import NumpyDocString
4040
4141
42+ PRIVATE_CLASSES = ['NDFrame' , 'IndexOpsMixin' ]
43+
44+
4245def _to_original_callable (obj ):
4346 while True :
4447 if inspect .isfunction (obj ) or inspect .isclass (obj ):
@@ -72,8 +75,7 @@ class Docstring:
7275 def __init__ (self , method_name , method_obj ):
7376 self .method_name = method_name
7477 self .method_obj = method_obj
75- self .raw_doc = method_obj .__doc__ or ''
76- self .raw_doc = textwrap .dedent (self .raw_doc )
78+ self .raw_doc = pydoc .getdoc (method_obj )
7779 self .doc = NumpyDocString (self .raw_doc )
7880
7981 def __len__ (self ):
@@ -127,7 +129,12 @@ def doc_parameters(self):
127129
128130 @property
129131 def signature_parameters (self ):
130- if not inspect .isfunction (self .method_obj ):
132+ if not (inspect .isfunction (self .method_obj )
133+ or inspect .isclass (self .method_obj )):
134+ return tuple ()
135+ if (inspect .isclass (self .method_obj )
136+ and self .method_name .split ('.' )[- 1 ] in {'dt' , 'str' , 'cat' }):
137+ # accessor classes have a signature, but don't want to show this
131138 return tuple ()
132139 params = tuple (inspect .signature (self .method_obj ).parameters .keys ())
133140 if params and params [0 ] in ('self' , 'cls' ):
@@ -149,7 +156,8 @@ def parameter_mismatches(self):
149156 extra = set (doc_params ) - set (signature_params )
150157 if extra :
151158 errs .append ('Unknown parameters {!r}' .format (extra ))
152- if not missing and not extra and signature_params != doc_params :
159+ if (not missing and not extra and signature_params != doc_params
160+ and not (not signature_params and not doc_params )):
153161 errs .append ('Wrong parameters order. ' +
154162 'Actual: {!r}. ' .format (signature_params ) +
155163 'Documented: {!r}' .format (doc_params ))
@@ -180,6 +188,10 @@ def deprecated(self):
180188 bool (pattern .search (self .summary )) or
181189 bool (pattern .search (self .extended_summary )))
182190
191+ @property
192+ def mentioned_private_classes (self ):
193+ return [klass for klass in PRIVATE_CLASSES if klass in self .raw_doc ]
194+
183195 @property
184196 def examples_errors (self ):
185197 flags = doctest .NORMALIZE_WHITESPACE | doctest .IGNORE_EXCEPTION_DETAIL
@@ -311,6 +323,11 @@ def validate_one(func_name):
311323 for param_err in param_errs :
312324 errs .append ('\t {}' .format (param_err ))
313325
326+ mentioned_errs = doc .mentioned_private_classes
327+ if mentioned_errs :
328+ errs .append ('Private classes ({}) should not be mentioned in public '
329+ 'docstring.' .format (mentioned_errs ))
330+
314331 examples_errs = ''
315332 if not doc .examples :
316333 errs .append ('No examples section found' )
0 commit comments