@@ -92,28 +92,38 @@ def test_parameter_docs(module, prefix):
9292 warnings .simplefilter ('ignore' ) # debug via sphinx, not here
9393 doc = None if obj is None else npd .FunctionDoc (obj )
9494
95+ # Parse the docstring using numpydoc
96+ doc = None if obj is None else npd .FunctionDoc (obj )
97+
9598 # Skip anything that is outside of this module
9699 if inspect .getmodule (obj ) is not None and \
97100 not inspect .getmodule (obj ).__name__ .startswith ('control' ):
98101 # Skip anything that isn't part of the control package
99102 _info (f"member '{ objname } ' is outside `control` module" , 5 )
100103 continue
101104
105+ # Skip non-top-level functions without parameter lists
106+ if prefix != "" and inspect .getmodule (obj ) != module and \
107+ doc is not None and doc ["Parameters" ] == []:
108+ _info (f"skipping { prefix } .{ name } " , 2 )
109+ continue
110+
102111 # If this is a class, recurse through methods
103112 # TODO: check top level documenation here (__init__, attributes?)
104113 if inspect .isclass (obj ):
105114 _info (f"Checking class { name } " , 1 )
106115 _check_numpydoc_style (obj , doc )
107116 # Check member functions within the class
108117 test_parameter_docs (obj , prefix + name + '.' )
118+ continue
109119
110120 # Skip anything that is inherited, hidden, deprecated, or checked
111121 if not inspect .isfunction (obj ) or \
112122 inspect .isclass (module ) and name not in module .__dict__ \
113123 or name .startswith ('_' ) or obj in function_skiplist \
114124 or obj in checked :
115- _info (f"skipping { prefix } .{ name } " , 6 )
116- continue
125+ _info (f"skipping { prefix } .{ name } " , 6 )
126+ continue
117127
118128 # Skip non-top-level functions without parameter lists
119129 if prefix != "" and inspect .getmodule (obj ) != module and \
@@ -226,6 +236,13 @@ def test_parameter_docs(module, prefix):
226236 f"{ obj } return value '{ retname } ' "
227237 "docstring missing space" )
228238
239+ # Look at the return values
240+ for val in doc ["Returns" ]:
241+ if val .name == '' and \
242+ (match := re .search ("([\w]+):" , val .type )) is not None :
243+ retname = match .group (1 )
244+ _warn (f"{ obj .__name__ } '{ retname } ' docstring missing space" )
245+
229246
230247@pytest .mark .parametrize ("module, prefix" , [
231248 (control , "" ), (control .flatsys , "flatsys." ),
@@ -262,7 +279,7 @@ def test_deprecated_functions(module, prefix):
262279
263280 # Get the docstring (skip w/ warning if there isn't one)
264281 if obj .__doc__ is None :
265- _warn (f"{ objname } is missing docstring" )
282+ _warn (f"{ module . __name__ } . { name } is missing docstring" )
266283 continue
267284 else :
268285 docstring = inspect .getdoc (obj )
@@ -273,14 +290,12 @@ def test_deprecated_functions(module, prefix):
273290 if ".. deprecated::" in doc_extended :
274291 # Make sure a FutureWarning is issued
275292 if not re .search ("FutureWarning" , source ):
276- _fail (f"{ objname } deprecated but does not issue "
277- "FutureWarning" )
293+ _fail (f"{ name } deprecated but does not issue FutureWarning" )
278294 else :
279295 if re .search (name + r"(\(\))? is deprecated" , docstring ) or \
280296 re .search (name + r"(\(\))? is deprecated" , source ):
281297 _fail (
282- f"{ objname } deprecated but with non-standard "
283- "docs/warnings" )
298+ f"{ name } deprecated but w/ non-standard docs/warnings" )
284299
285300#
286301# Tests for I/O system classes
0 commit comments