diff --git a/docs/checks.md b/docs/checks.md index e48b1e7..ef7178d 100644 --- a/docs/checks.md +++ b/docs/checks.md @@ -601,7 +601,7 @@ if x == y and x == z: # and -if x is None and y is None +if x is None and y is None: pass ``` @@ -2150,7 +2150,7 @@ Bad: from hashlib import sha512 h = sha512() -h.update(b"data) +h.update(b"data") ``` Good: @@ -2172,7 +2172,7 @@ Bad: ```python nums = [123, 456] -num = f"{num[0]}") +num = f"{num[0]}" ``` Good: diff --git a/refurb/checks/hashlib/simplify_ctor.py b/refurb/checks/hashlib/simplify_ctor.py index 390bc46..e8a279c 100644 --- a/refurb/checks/hashlib/simplify_ctor.py +++ b/refurb/checks/hashlib/simplify_ctor.py @@ -30,7 +30,7 @@ class ErrorInfo(Error): from hashlib import sha512 h = sha512() - h.update(b"data) + h.update(b"data") ``` Good: diff --git a/refurb/checks/logical/use_equal_chain.py b/refurb/checks/logical/use_equal_chain.py index 8e70710..a79d1e5 100644 --- a/refurb/checks/logical/use_equal_chain.py +++ b/refurb/checks/logical/use_equal_chain.py @@ -20,7 +20,7 @@ class ErrorInfo(Error): # and - if x is None and y is None + if x is None and y is None: pass ``` diff --git a/refurb/checks/readability/use_str_func.py b/refurb/checks/readability/use_str_func.py index d8d5c85..7ef618b 100644 --- a/refurb/checks/readability/use_str_func.py +++ b/refurb/checks/readability/use_str_func.py @@ -18,7 +18,7 @@ class ErrorInfo(Error): ``` nums = [123, 456] - num = f"{num[0]}") + num = f"{num[0]}" ``` Good: diff --git a/test/test_check_formatting.py b/test/test_check_formatting.py index eefc90a..6a7a35d 100644 --- a/test/test_check_formatting.py +++ b/test/test_check_formatting.py @@ -1,6 +1,10 @@ +import ast import re from functools import cache from pathlib import Path +from textwrap import dedent + +import pytest import refurb from refurb.error import Error @@ -55,6 +59,26 @@ def get_categories_from_docs() -> list[str]: return categories +def assert_python_snippets_are_parseable(error: type[Error]) -> None: + # This check is simple enough that it doesn't need detailed docs + if error.code == 105: + return + + docs = dedent(error(0, 0, "").__doc__ or "") + + groups = re.findall(r"```([\S\s]*?)```", docs) + assert groups, "Missing docstring" + + assert len(groups) >= 2, 'Expected at least 2 "good" and "bad" code examples in docstring' + + try: + for code in groups: + ast.parse(code.strip()) + + except SyntaxError as ex: + pytest.fail(f"Python code in docs is invalid: {ex.msg}") + + def test_checks_are_formatted_properly() -> None: error_names: set[str] = set() @@ -68,6 +92,7 @@ def test_checks_are_formatted_properly() -> None: assert_category_exists(error) assert_categories_are_sorted(error) assert_categories_are_valid(error, get_categories_from_docs()) + assert_python_snippets_are_parseable(error) assert error.name, "name field missing for class"