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

Commit

Permalink
Raise ParseError on fstring docstrings as they are not valid docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
samj1912 committed Sep 6, 2020
1 parent afd0030 commit 2f9f337
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 30 deletions.
23 changes: 21 additions & 2 deletions src/pydocstyle/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@
from .utils import (
common_prefix_length,
is_blank,
is_fstring,
log,
pairwise,
safe_literal_eval,
strip_non_alphanumeric,
)
from .wordlists import IMPERATIVE_BLACKLIST, IMPERATIVE_VERBS, stem
Expand All @@ -46,6 +44,27 @@ def decorator(f):
return decorator


FSTRING_REGEX = re(r'^([rR]?)[fF]')


def is_fstring(docstring):
"""Return True if docstring is an f-string."""
return FSTRING_REGEX.match(str(docstring))


def safe_literal_eval(string):
"""Safely evaluate a literal even if it is an fstring."""
try:
return ast.literal_eval(string)
except ValueError as error:
# If the docstring is a fstring, it is
# not considered a valid docstring. See
# https://bugs.python.org/issue28739
raise ParseError(
info="f-strings are not valid as docstrings."
) from error


class ConventionChecker:
"""Checker for PEP 257, NumPy and Google conventions.
Expand Down
6 changes: 5 additions & 1 deletion src/pydocstyle/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@
class ParseError(Exception):
"""An error parsing contents of a Python file."""

def __init__(self, info=""):
"""Initialize the error with a more specific message."""
self.info = info

def __str__(self):
return "Cannot parse file."
return f"Cannot parse file. {self.info}".strip()


class UnexpectedTokenError(ParseError):
Expand Down
22 changes: 0 additions & 22 deletions src/pydocstyle/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""General shared utilities."""
import ast
import logging
import re
from itertools import tee, zip_longest
Expand Down Expand Up @@ -47,24 +46,3 @@ def common_prefix_length(a: str, b: str) -> int:
def strip_non_alphanumeric(string: str) -> str:
"""Strip string from any non-alphanumeric characters."""
return NON_ALPHANUMERIC_STRIP_RE.sub('', string)


FSTRING_REGEX = re.compile(r'^([rR]?)[fF]')


def is_fstring(docstring):
"""Return True if docstring is an f-string."""
return FSTRING_REGEX.match(str(docstring))


def safe_literal_eval(string):
"""Safely evaluate a literal even if it is an fstring."""
try:
return ast.literal_eval(string)
except ValueError:
# In case we hit a value error due to an fstring
# we do a literal eval by subtituting the fstring
# with a normal string.
# We keep the first captured group if any. This includes
# the raw identifiers (r/R) and replace f/F with a blank.
return ast.literal_eval(FSTRING_REGEX.sub(r"\1", string))
5 changes: 0 additions & 5 deletions src/tests/test_cases/fstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,3 @@ def fstring_with_other_errors(arg=1, missing_arg=2):
@D303
def fstring_with_blank_doc_string():
f""" """


@expect("D103: Missing docstring in public function")
def fstring_with_ignores(): # noqa: D303
f""" """
15 changes: 15 additions & 0 deletions src/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,21 @@ def foo():
assert code == 0


def test_fstring_excluded(env):
"""Test excluding D303 fstring error."""
with env.open('example.py', 'wt') as example:
example.write(textwrap.dedent("""\
def foo(): # noqa: D303
f'''Test'''
"""))

env.write_config(add_ignore="D100")
out, err, code = env.invoke()
assert code == 1
assert out == ""
assert "f-strings are not valid as docstrings." in err


def test_empty_select_with_added_error(env):
"""Test excluding all errors but one."""
with env.open('example.py', 'wt') as example:
Expand Down

0 comments on commit 2f9f337

Please sign in to comment.