Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Commit

Permalink
Fix indentation error while parsing class methods
Browse files Browse the repository at this point in the history
In order to determine the missing arguments, we currently
use ast.parse to parse partial source code. This parsing
might lead to syntax errors. We catch the syntax error and
make the parsing more resilient to errors in the source code.

Fixes #437
  • Loading branch information
samj1912 committed May 8, 2020
1 parent ebc5466 commit eb8d312
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/release_notes.rst
Expand Up @@ -15,6 +15,8 @@ Bug Fixes

* Update convention support documentation (#386, #393)
* Detect inner asynchronous functions for D202 (#467)
* Fix indentation error while parsing class methods (#441).


5.0.2 - January 8th, 2020
---------------------------
Expand Down
15 changes: 13 additions & 2 deletions src/pydocstyle/checker.py
Expand Up @@ -1007,9 +1007,20 @@ def is_def_arg_private(arg_name):
"""Return a boolean indicating if the argument name is private."""
return arg_name.startswith("_")

def get_function_args(function_string):
def get_function_args(function_source):
"""Return the function arguments given the source-code string."""
function_arg_node = ast.parse(textwrap.dedent(function_string)).body[0].args
# We are stripping the whitespace from the left of the
# function source.
# This is so that if the docstring has incorrectly
# indented lines, which are at a lower indent than the
# function source, we still dedent the source correctly
# and the AST parser doesn't throw an error.
try:
function_arg_node = ast.parse(function_source.lstrip()).body[0].args
except SyntaxError:
# If we still get a syntax error, we don't want the
# the checker to crash. Instead we just return a blank list.
return []
arg_nodes = function_arg_node.args
kwonly_arg_nodes = function_arg_node.kwonlyargs
return [arg_node.arg for arg_node in chain(arg_nodes, kwonly_arg_nodes)]
4 changes: 2 additions & 2 deletions src/tests/test_cases/expected.py
Expand Up @@ -4,13 +4,13 @@ class Expectation:
def __init__(self):
self.expected = set()

def expect(self, *args, arg_count=0):
def expect(self, *args, arg_count=0, func_name=""):
"""Decorator that expects a certain PEP 257 violation."""
# The `arg_count` parameter helps the decorator
# with functions that have positional arguments.
if len(args) == 1:
def decorate(f):
self.expected.add((f.__name__, args[0]))
self.expected.add((func_name or f.__name__, args[0]))
f(*[None]*arg_count)
return f
return decorate
Expand Down
40 changes: 39 additions & 1 deletion src/tests/test_cases/sections.py
Expand Up @@ -274,6 +274,25 @@ def missing_colon_google_style_section(): # noqa: D406, D407
"""


@expect("D417: Missing argument descriptions in the docstring "
"(argument(s) y are missing descriptions in "
"'bar' docstring)", func_name="bar")
def _test_nested_functions():
x = 1

def bar(y=2): # noqa: D207, D213, D406, D407
"""Nested function test for docstrings.
Will this work when referencing x?
Args:
x: Test something
that is broken.
"""
print(x)


@expect(_D213)
@expect("D417: Missing argument descriptions in the docstring "
"(argument(s) y are missing descriptions in "
Expand Down Expand Up @@ -340,13 +359,15 @@ def test_missing_args_static_method(a, x, y, _test, z=3): # noqa: D213, D407
@expect("D417: Missing argument descriptions in the docstring "
"(argument(s) y are missing descriptions in "
"'test_missing_numpy_args' docstring)")
@expect("D207: Docstring is under-indented")
def test_missing_numpy_args(_private_arg=0, x=1, y=2): # noqa: D406, D407
"""Toggle the gizmo.
Parameters
----------
x : int
The greatest integer.
The greatest integer in the history \
of the entire world.
"""

Expand Down Expand Up @@ -425,3 +446,20 @@ def test_mixing_numpy_and_google(danger): # noqa: D213
Zoneeeeee!
"""


class TestIncorrectIndent: # noqa: D203
"""Test class."""

@expect("D417: Missing argument descriptions in the docstring "
"(argument(s) y are missing descriptions in "
"'test_incorrect_indent' docstring)", arg_count=3)
def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407
"""Reproducing issue #437.
Testing this incorrectly indented docstring.
Args:
x: Test argument.
"""

0 comments on commit eb8d312

Please sign in to comment.