Skip to content

Commit

Permalink
B021: f-string used as docstring. (#230)
Browse files Browse the repository at this point in the history
* B021: f-string used as docstring.

* Update README.rst

* Update bugbear.py

Co-authored-by: Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>

* There are more docstrings than just triple double quotes!

Co-authored-by: Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
  • Loading branch information
jpy-git and Zac-HD committed Mar 20, 2022
1 parent 3206da7 commit c5223e0
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.rst
Expand Up @@ -134,6 +134,9 @@ data available in ``ex``.

**B020**: Loop control variable overrides iterable it iterates

**B021**: f-string used as docstring. This will be interpreted by python
as a joined string rather than a docstring.


Opinionated warnings
~~~~~~~~~~~~~~~~~~~~
Expand Down
18 changes: 18 additions & 0 deletions bugbear.py
Expand Up @@ -350,11 +350,13 @@ def visit_FunctionDef(self, node):
self.check_for_b902(node)
self.check_for_b006(node)
self.check_for_b018(node)
self.check_for_b021(node)
self.generic_visit(node)

def visit_ClassDef(self, node):
self.check_for_b903(node)
self.check_for_b018(node)
self.check_for_b021(node)
self.generic_visit(node)

def visit_Try(self, node):
Expand Down Expand Up @@ -685,6 +687,16 @@ def check_for_b018(self, node):
):
self.errors.append(B018(subnode.lineno, subnode.col_offset))

def check_for_b021(self, node):
if (
node.body
and isinstance(node.body[0], ast.Expr)
and isinstance(node.body[0].value, ast.JoinedStr)
):
self.errors.append(
B021(node.body[0].value.lineno, node.body[0].value.col_offset)
)


@attr.s
class NameFinder(ast.NodeVisitor):
Expand Down Expand Up @@ -892,6 +904,12 @@ def visit(self, node):
+ "with each iterable value."
)
)
B021 = Error(
message=(
"B021 f-string used as docstring."
"This will be interpreted by python as a joined string rather than a docstring."
)
)

# Warnings disabled by default.
B901 = Error(
Expand Down
76 changes: 76 additions & 0 deletions tests/b021.py
@@ -0,0 +1,76 @@
"""
Should emit:
B021 - on lines 14, 22, 30, 38, 46, 54, 62, 70, 73
"""

VARIABLE = "world"


def foo1():
"""hello world!"""


def foo2():
f"""hello {VARIABLE}!"""


class bar1:
"""hello world!"""


class bar2:
f"""hello {VARIABLE}!"""


def foo1():
"""hello world!"""


def foo2():
f"""hello {VARIABLE}!"""


class bar1:
"""hello world!"""


class bar2:
f"""hello {VARIABLE}!"""


def foo1():
"hello world!"


def foo2():
f"hello {VARIABLE}!"


class bar1:
"hello world!"


class bar2:
f"hello {VARIABLE}!"


def foo1():
"hello world!"


def foo2():
f"hello {VARIABLE}!"


class bar1:
"hello world!"


class bar2:
f"hello {VARIABLE}!"


def baz():
f"""I'm probably a docstring: {VARIABLE}!"""
print(f"""I'm a normal string""")
f"""Don't detect me!"""
18 changes: 18 additions & 0 deletions tests/test_bugbear.py
Expand Up @@ -30,6 +30,7 @@
B017,
B018,
B020,
B021,
B901,
B902,
B903,
Expand Down Expand Up @@ -262,6 +263,23 @@ def test_b020(self):
),
)

def test_b021_classes(self):
filename = Path(__file__).absolute().parent / "b021.py"
bbc = BugBearChecker(filename=str(filename))
errors = list(bbc.run())
expected = self.errors(
B021(14, 4),
B021(22, 4),
B021(30, 4),
B021(38, 4),
B021(46, 4),
B021(54, 4),
B021(62, 4),
B021(70, 4),
B021(74, 4),
)
self.assertEqual(errors, expected)

def test_b901(self):
filename = Path(__file__).absolute().parent / "b901.py"
bbc = BugBearChecker(filename=str(filename))
Expand Down

0 comments on commit c5223e0

Please sign in to comment.