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

Commit d3ea9a0

Browse files
StrusNurdok
authored andcommitted
Fix D401 and D404 checks not working for docstrings containing only one word and ending with non-alpha character (#421) (#422)
* Fix D401 and D404 checks not working for docstrings containing only one word and ending with non-alpha character (#421) * Add test and information in release notes. (#421) * Fix too long test documentation. (#421) * Move regex for stripping non-alphanumeric characters outside of strip_non_alphanumeric function. (#421)
1 parent 667d9be commit d3ea9a0

File tree

5 files changed

+35
-7
lines changed

5 files changed

+35
-7
lines changed

docs/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Bug Fixes
3131
* Fix decorator parsing (#411).
3232
* Google-style sections no longer cause false errors when used with
3333
Numpy-style sections (#388, #424).
34+
* Fix D401 and D404 checks not working for docstrings containing only one word and ending with non-alpha character (#421)
3435

3536
4.0.1 - August 14th, 2019
3637
-------------------------

src/pydocstyle/checker.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from .parser import (Package, Module, Class, NestedClass, Definition, AllError,
1515
Method, Function, NestedFunction, Parser, StringIO,
1616
ParseError)
17-
from .utils import log, is_blank, pairwise, common_prefix_length
17+
from .utils import log, is_blank, pairwise, common_prefix_length, strip_non_alphanumeric
1818
from .wordlists import IMPERATIVE_VERBS, IMPERATIVE_BLACKLIST, stem
1919

2020

@@ -437,7 +437,7 @@ def check_imperative_mood(self, function, docstring): # def context
437437
if docstring and not function.is_test:
438438
stripped = ast.literal_eval(docstring).strip()
439439
if stripped:
440-
first_word = stripped.split()[0]
440+
first_word = strip_non_alphanumeric(stripped.split()[0])
441441
check_word = first_word.lower()
442442

443443
if check_word in IMPERATIVE_BLACKLIST:
@@ -499,10 +499,16 @@ def check_starts_with_this(self, function, docstring):
499499
with "This class is [..]" or "This module contains [..]".
500500
501501
"""
502-
if docstring:
503-
first_word = ast.literal_eval(docstring).split()[0]
504-
if first_word.lower() == 'this':
505-
return violations.D404()
502+
if not docstring:
503+
return
504+
505+
stripped = ast.literal_eval(docstring).strip()
506+
if not stripped:
507+
return
508+
509+
first_word = strip_non_alphanumeric(stripped.split()[0])
510+
if first_word.lower() == 'this':
511+
return violations.D404()
506512

507513
@staticmethod
508514
def _is_docstring_section(context):

src/pydocstyle/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""General shared utilities."""
2+
import ast
23
import logging
4+
import re
35
from typing import Iterable, Any, Tuple
46
from itertools import tee, zip_longest
57

@@ -8,6 +10,9 @@
810
__version__ = '4.0.1'
911
log = logging.getLogger(__name__)
1012

13+
#: Regular expression for stripping non-alphanumeric characters
14+
NON_ALPHANUMERIC_STRIP_RE = re.compile(r'[\W_]+')
15+
1116

1217
def is_blank(string: str) -> bool:
1318
"""Return True iff the string contains only whitespaces."""
@@ -37,4 +42,9 @@ def common_prefix_length(a: str, b: str) -> int:
3742
for common, (ca, cb) in enumerate(zip(a, b)):
3843
if ca != cb:
3944
return common
40-
return min(len(a), len(b))
45+
return min(len(a), len(b))
46+
47+
48+
def strip_non_alphanumeric(string: str) -> str:
49+
"""Strip string from any non-alphanumeric characters."""
50+
return NON_ALPHANUMERIC_STRIP_RE.sub('', string)

src/tests/test_cases/test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,12 @@ def sdgfsdg23245():
309309
"""Constructor for a foo."""
310310

311311

312+
@expect("D401: First line should be in imperative mood; try rephrasing "
313+
"(found 'Constructor')")
314+
def sdgfsdg23245777():
315+
"""Constructor."""
316+
317+
312318
@expect('D402: First line should not be the function\'s "signature"')
313319
def foobar():
314320
"""Signature: foobar()."""

src/tests/test_utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ def test_differ_length():
2626
def test_empty_string():
2727
"""Test common prefix length of two strings, one of them empty."""
2828
assert utils.common_prefix_length('abcd', '') == 0
29+
30+
31+
def test_strip_non_alphanumeric():
32+
"""Test strip of a string leaves only alphanumeric characters."""
33+
assert utils.strip_non_alphanumeric(" 1abcd1...") == "1abcd1"

0 commit comments

Comments
 (0)