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

Commit

Permalink
Add disable_skip_errors flag to ConventionChecker API (#485)
Browse files Browse the repository at this point in the history
* Add disable_skip_errors flag to ConventionChecker API

Added to ConventionChecker.check_source() and ConventionChecker.check().
This allows other systems that integrate pydocstyle,
such as flake8-docstyle, to request errors that are otherwise
skipped due to # noqa comments.

Added test for skip_errors feature in general and with this flag.

Fixes #484

* Update release notes

* rename argument to ignore inline noqa comments

* Add docstring description of new argument

* Move release note

Co-authored-by: Sambhav Kothari <sambhavs.email@gmail.com>
  • Loading branch information
plinss and samj1912 committed Aug 29, 2020
1 parent fd3aef5 commit 779e247
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docs/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Release Notes
Current Development Version
---------------------------

New Features

* Add flag to disable `# noqa` comment processing in API (#485).

5.1.1 - August 29th, 2020
---------------------------
Expand Down
15 changes: 9 additions & 6 deletions src/pydocstyle/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class ConventionChecker:
".+" # Followed by 1 or more characters - which is the docstring for the parameter
)

def check_source(self, source, filename, ignore_decorators=None):
def check_source(self, source, filename, ignore_decorators=None, ignore_inline_noqa=False):
module = parse(StringIO(source), filename)
for definition in module:
for this_check in self.checks:
Expand All @@ -114,15 +114,15 @@ def check_source(self, source, filename, ignore_decorators=None):
decorator_skip = ignore_decorators is not None and any(
len(ignore_decorators.findall(dec.name)) > 0
for dec in definition.decorators)
if not skipping_all and not decorator_skip:
if (ignore_inline_noqa or not skipping_all) and not decorator_skip:
error = this_check(self, definition,
definition.docstring)
else:
error = None
errors = error if hasattr(error, '__iter__') else [error]
for error in errors:
if error is not None and error.code not in \
definition.skipped_error_codes:
if error is not None and (ignore_inline_noqa or error.code not in \
definition.skipped_error_codes):
partition = this_check.__doc__.partition('.\n')
message, _, explanation = partition
error.set_context(explanation=explanation,
Expand Down Expand Up @@ -932,7 +932,7 @@ def check_docstring_sections(self, definition, docstring):
parse = Parser()


def check(filenames, select=None, ignore=None, ignore_decorators=None):
def check(filenames, select=None, ignore=None, ignore_decorators=None, ignore_inline_noqa=False):
"""Generate docstring errors that exist in `filenames` iterable.
By default, the PEP-257 convention is checked. To specifically define the
Expand All @@ -949,6 +949,8 @@ def check(filenames, select=None, ignore=None, ignore_decorators=None):
convenience, you may use `pydocstyle.violations.conventions.pep257` as
a base set to add or remove errors from.
`ignore_inline_noqa` controls if `# noqa` comments are respected or not.
Examples
---------
>>> check(['pydocstyle.py'])
Expand Down Expand Up @@ -978,7 +980,8 @@ def check(filenames, select=None, ignore=None, ignore_decorators=None):
with tk.open(filename) as file:
source = file.read()
for error in ConventionChecker().check_source(source, filename,
ignore_decorators):
ignore_decorators,
ignore_inline_noqa):
code = getattr(error, 'code', None)
if code in checked_codes:
yield error
Expand Down
30 changes: 30 additions & 0 deletions src/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,36 @@ def function_with_bad_docstring(foo):
assert error_codes == expected_error_codes - ignored


def test_skip_errors():
"""Test that `ignore`d errors are not reported in the API."""
function_to_check = textwrap.dedent('''
def function_with_bad_docstring(foo): # noqa: D400, D401, D403, D415
""" does spacinwithout a period in the end
no blank line after one-liner is bad. Also this - """
return foo
''')
expected_error_codes = {'D100', 'D205', 'D209', 'D210', 'D213'}
mock_open = mock.mock_open(read_data=function_to_check)
from pydocstyle import checker
with mock.patch.object(
checker.tk, 'open', mock_open, create=True):
# Passing a blank ignore here explicitly otherwise
# checkers takes the pep257 ignores by default.
errors = tuple(checker.check(['filepath'], ignore={}))
error_codes = {error.code for error in errors}
assert error_codes == expected_error_codes

skipped_error_codes = {'D400', 'D401', 'D403', 'D415'}
# We need to recreate the mock, otherwise the read file is empty
mock_open = mock.mock_open(read_data=function_to_check)
with mock.patch.object(
checker.tk, 'open', mock_open, create=True):
errors = tuple(checker.check(['filepath'], ignore={},
ignore_inline_noqa=True))
error_codes = {error.code for error in errors}
assert error_codes == expected_error_codes | skipped_error_codes


def test_run_as_named_module():
"""Test that pydocstyle can be run as a "named module".
Expand Down

0 comments on commit 779e247

Please sign in to comment.