From 562b906d1775d539599f11238815faea910f28fd Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 5 Sep 2023 08:55:42 -0400 Subject: [PATCH] fix: add more examples to error messages (#273) --- docs/_includes/interactive_repo_review.html | 2 +- src/sp_repo_review/checks/mypy.py | 39 +++++++++++-- src/sp_repo_review/checks/pyproject.py | 63 ++++++++++++++++++--- src/sp_repo_review/checks/readthedocs.py | 7 +++ src/sp_repo_review/checks/ruff.py | 16 ++++-- 5 files changed, 108 insertions(+), 19 deletions(-) diff --git a/docs/_includes/interactive_repo_review.html b/docs/_includes/interactive_repo_review.html index 28236749..527f9861 100644 --- a/docs/_includes/interactive_repo_review.html +++ b/docs/_includes/interactive_repo_review.html @@ -21,7 +21,7 @@ header={false} deps={[ "sp-repo-review==2023.08.23", - "repo-review==0.9.3", + "repo-review==0.10.0", "validate-pyproject==0.14", "scikit-build-core==0.5.0", ]} diff --git a/src/sp_repo_review/checks/mypy.py b/src/sp_repo_review/checks/mypy.py index 0ab6be8e..4549d173 100644 --- a/src/sp_repo_review/checks/mypy.py +++ b/src/sp_repo_review/checks/mypy.py @@ -38,13 +38,19 @@ class MY101(MyPy): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - Must have `strict = true` in the mypy config. MyPy is best with strict - or nearly strict configuration. If you are happy with the strictness of - your settings already, ignore this check. + Must have `strict` in the mypy config. MyPy is best with strict or + nearly strict configuration. If you are happy with the strictness of + your settings already, ignore this check or set `strict = false` + explicitly. + + ```toml + [tool.mypy] + strict = true + ``` """ match pyproject: - case {"tool": {"mypy": {"strict": True}}}: + case {"tool": {"mypy": {"strict": bool()}}}: return True case _: return False @@ -61,6 +67,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ Must have `show_error_codes = true`. This will print helpful error codes for users that clarify why something fails if you need to skip it. + + ```toml + [tool.mypy] + show_error_codes = true + ``` """ match pyproject: @@ -83,6 +94,11 @@ def check(pyproject: dict[str, Any]) -> bool: occasionally false positives (often due to platform or Python version static checks), so it's okay to ignore this check. But try it first - it can catch real bugs too. + + ```toml + [tool.mypy] + warn_unreachable = true + ``` """ match pyproject: @@ -104,6 +120,11 @@ def check(pyproject: dict[str, Any]) -> bool: Must have `"ignore-without-code"` in `enable_error_code = [...]`. This will force all skips in your project to include the error code, which makes them more readable, and avoids skipping something unintended. + + ```toml + [tool.mypy] + enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] + ``` """ match pyproject: @@ -124,6 +145,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ Must have `"redundant-expr"` in `enable_error_code = [...]`. This helps catch useless lines of code, like checking the same condition twice. + + ```toml + [tool.mypy] + enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] + ``` """ match pyproject: @@ -144,6 +170,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ Must have `"truthy-bool"` in `enable_error_code = []`. This catches mistakes in using a value as truthy if it cannot be falsey. + + ```toml + [tool.mypy] + enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] + ``` """ match pyproject: diff --git a/src/sp_repo_review/checks/pyproject.py b/src/sp_repo_review/checks/pyproject.py index fdd6e137..123737d5 100644 --- a/src/sp_repo_review/checks/pyproject.py +++ b/src/sp_repo_review/checks/pyproject.py @@ -59,9 +59,9 @@ class PP301(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - Must have a pytest configuration section in pyproject.toml. If you must - have it somewhere else (such as to support `pytest<6`), ignore this - check. + Must have a `[tool.pytest.ini_options]` configuration section in + pyproject.toml. If you must have it somewhere else (such as to support + `pytest<6`), ignore this check. """ match pyproject: @@ -81,6 +81,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ Must have a `minversion=`, and must be at least 6 (first version to support `pyproject.toml` configuration). + + ```toml + [tool.pytest.ini_options] + minversion = "7" + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "minversion" in options and float(options["minversion"]) >= 6 @@ -93,7 +98,14 @@ class PP303(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: - "The `testpaths` setting should be set (like to `['tests']`)" + """ + The `testpaths` setting should be set to a reasonable default. + + ```toml + [tool.pytest.ini_options] + testpaths = ["tests"] + ``` + """ options = pyproject["tool"]["pytest"]["ini_options"] return "testpaths" in options @@ -106,7 +118,13 @@ class PP304(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - `log_cli_level` should be set (probably to `"INFO"`) + `log_cli_level` should be set. This will allow logs to be displayed on + failures. + + ```toml + [tool.pytest.ini_options] + log_cli_level = "INFO" + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "log_cli_level" in options @@ -120,8 +138,13 @@ class PP305(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - `xfail_strict` should be set (probably to `true`). You can manually - specify if a check should be strict when setting each xfail. + `xfail_strict` should be set. You can manually specify if a check + should be strict when setting each xfail. + + ```toml + [tool.pytest.ini_options] + xfail_strict = true + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "xfail_strict" in options @@ -137,6 +160,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ `--strict-config` should be in `addopts = [...]`. This forces an error if a config setting is misspelled. + + ```toml + [tool.pytest.ini_options] + addops = ["-ra", "--strict-config", "--strict-markers"] + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "--strict-config" in options.get("addopts", []) @@ -152,6 +180,11 @@ def check(pyproject: dict[str, Any]) -> bool: """ `--strict-markers` should be in `addopts = [...]`. This forces all markers to be specified in config, avoiding misspellings. + + ```toml + [tool.pytest.ini_options] + addops = ["-ra", "--strict-config", "--strict-markers"] + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "--strict-markers" in options.get("addopts", []) @@ -164,7 +197,14 @@ class PP308(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: - "`-ra` should be in `addopts = [...]` (print summary of all fails/errors)." + """ + `-ra` should be in `addopts = [...]` (print summary of all fails/errors). + + ```toml + [tool.pytest.ini_options] + addops = ["-ra", "--strict-config", "--strict-markers"] + ``` + """ options = pyproject["tool"]["pytest"]["ini_options"] return "-ra" in options.get("addopts", []) @@ -177,8 +217,13 @@ class PP309(PyProject): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - `filterwarnings` must be set (probably to at least `['error']`). Python + `filterwarnings` must be set (probably to at least `["error"]`). Python will hide important warnings otherwise, like deprecations. + + ```toml + [tool.pytest.ini_options] + filterwarnings = ["error"] + ``` """ options = pyproject["tool"]["pytest"]["ini_options"] return "filterwarnings" in options diff --git a/src/sp_repo_review/checks/readthedocs.py b/src/sp_repo_review/checks/readthedocs.py index be26eefe..1260d2b6 100644 --- a/src/sp_repo_review/checks/readthedocs.py +++ b/src/sp_repo_review/checks/readthedocs.py @@ -84,6 +84,13 @@ def check(readthedocs: dict[str, Any]) -> bool: """ You must set `build: tools: python: "3.11"` or similar in the `.readthedocs.yaml` file for a Python project. + + ```yaml + build: + os: ubuntu-22.04 + tools: + python: "3.11" + ``` """ match readthedocs: diff --git a/src/sp_repo_review/checks/ruff.py b/src/sp_repo_review/checks/ruff.py index 49cc8151..5d2f12c6 100644 --- a/src/sp_repo_review/checks/ruff.py +++ b/src/sp_repo_review/checks/ruff.py @@ -21,7 +21,7 @@ class RF001(Ruff): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - Must have `tool.ruff` section in `pyproject.toml`. Other forms of + Must have `[tool.ruff]` section in `pyproject.toml`. Other forms of configuration are not supported by this check. """ @@ -39,8 +39,8 @@ class RF002(Ruff): @staticmethod def check(pyproject: dict[str, Any]) -> bool: """ - Must select a minimum version to target. Affects pyupgrade, - isort, and others. Can be inferred from `project.requires-python`. + Must select a minimum version to target. Affects pyupgrade, isort, and + others. Will be inferred from `project.requires-python`. """ match pyproject: @@ -61,7 +61,9 @@ class RF003(Ruff): def check(pyproject: dict[str, Any], package: Traversable) -> bool | None: """ Must specify `src` directory if it exists. + ```toml + [tool.ruff] src = ["src"] ``` """ @@ -88,8 +90,12 @@ class RF1xx(Ruff): def check(cls: type[RuffMixin], pyproject: dict[str, Any]) -> bool: """ Must select the {self.name} `{self.code}` checks. Recommended: + ```toml - select = ["{self.code}"] # {self.name} + [tool.ruff] + select = [ + "{self.code}", # {self.name} + ] ``` """ @@ -97,7 +103,7 @@ def check(cls: type[RuffMixin], pyproject: dict[str, Any]) -> bool: case {"tool": {"ruff": {"select": list(x)}}} | { "tool": {"ruff": {"extend-select": list(x)}} }: - return cls.code in x + return cls.code in x or "ALL" in x case _: return False