Skip to content

Commit

Permalink
Allow no type in Numpy param docstrings for mising-param-doc
Browse files Browse the repository at this point in the history
This closes pylint-dev#5222
  • Loading branch information
DanielNoord committed Oct 30, 2021
1 parent ff7eea5 commit 40ef827
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 35 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ Release date: TBA

Closes #3733

* ``mising-param-doc`` now correctly handles Numpy parameter documentation without
explicit typing

Closes #5222

* Update ``literal-comparison``` checker to ignore tuple literals

Closes #3031
Expand Down
5 changes: 5 additions & 0 deletions doc/whatsnew/2.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,8 @@ Other Changes
keyword parameters

Closes #3733

* ``mising-param-doc`` now correctly handles Numpy parameter documentation without
explicit typing

Closes #5222
39 changes: 35 additions & 4 deletions pylint/extensions/_check_docs_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"""Utility methods for docstring checking."""

import re
from typing import List
from typing import List, Set, Tuple

import astroid
from astroid import nodes
Expand Down Expand Up @@ -731,9 +731,8 @@ class NumpyDocstring(GoogleDocstring):

re_param_line = re.compile(
fr"""
\s* (\*{{0,2}}\w+) # identifier with potential asterisks
\s* :
\s* (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?)? # optional type declaration
\s* (\*{{0,2}}\w+)(\s?(:|\n)) # identifier with potential asterisks
\s* (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?\n)? # optional type declaration
\s* (.*) # optional description
""",
re.X | re.S,
Expand Down Expand Up @@ -772,6 +771,38 @@ class NumpyDocstring(GoogleDocstring):

supports_yields = True

def match_param_docs(self) -> Tuple[Set[str], Set[str]]:
"""Matches parameter documentation section to parameter documentation rules"""
params_with_doc = set()
params_with_type = set()

entries = self._parse_section(self.re_param_section)
print(entries)
entries.extend(self._parse_section(self.re_keyword_param_section))
for entry in entries:
match = self.re_param_line.match(entry)
if not match:
continue

# check if parameter has description only
re_only_desc = re.match(r"\\s* (\\*{0,2}\\w+)\\s*:?\n", entry)
if re_only_desc:
param_name = match.group(1)
param_desc = match.group(2)
param_type = None
else:
param_name = match.group(1)
param_type = match.group(3)
param_desc = match.group(4)

if param_type:
params_with_type.add(param_name)

if param_desc:
params_with_doc.add(param_name)

return params_with_doc, params_with_type

@staticmethod
def min_section_indent(section_match):
return len(section_match.group(1))
Expand Down
39 changes: 8 additions & 31 deletions tests/extensions/test_check_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,35 +292,6 @@ def function_foo(x, y, z):
):
self.checker.visit_functiondef(node)

@set_config(default_docstring_type="numpy")
def test_no_type_func_params_in_numpy_docstring(self) -> None:
"""Example of a function with NumPy style parameter without type annotation
documentation in the docstring
"""
node = astroid.extract_node(
"""
def func(arg1: bool, arg2: bool):
'''Return args.
Parameters
----------
arg1 : bool
arg1
arg2
arg2
Returns
----------
bool
bool
'''
return arg1, arg2
"""
)
with self.assertNoMessages():
self.checker.visit_functiondef(node)

@set_config(accept_no_param_doc=True)
def test_tolerate_no_param_documentation_at_all(self) -> None:
"""Example of a function with no parameter documentation at all
Expand Down Expand Up @@ -1367,13 +1338,17 @@ def my_func(named_arg, **kwargs):
def test_finds_args_without_type_numpy(self) -> None:
node = astroid.extract_node(
'''
def my_func(named_arg, *args):
def my_func(named_arg, typed_arg: bool, untyped_arg, *args):
"""The docstring
Args
----
named_arg : object
Returned
typed_arg
Other argument without numpy type annotation
untyped_arg
Other argument without any type annotation
*args :
Optional Arguments
Expand All @@ -1386,7 +1361,9 @@ def my_func(named_arg, *args):
return named_arg
'''
)
with self.assertNoMessages():
with self.assertAddsMessages(
MessageTest(msg_id="missing-type-doc", node=node, args=("untyped_arg",))
):
self.checker.visit_functiondef(node)

def test_finds_args_with_xref_type_google(self) -> None:
Expand Down

0 comments on commit 40ef827

Please sign in to comment.