Skip to content

Commit

Permalink
fix: support simple Ruff extend (#312)
Browse files Browse the repository at this point in the history
* fix: support simple Ruff extend

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* Update src/sp_repo_review/checks/ruff.py

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
  • Loading branch information
henryiii committed Nov 17, 2023
1 parent 120f130 commit 6e33351
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 7 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ testpaths = ["tests"]


[tool.mypy]
mypy_path = ["src"]
files = ["src", "tests"]
python_version = "3.10"
warn_unused_configs = true
Expand Down
28 changes: 21 additions & 7 deletions src/sp_repo_review/checks/ruff.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,31 @@
## R2xx: Ruff deprecations


def merge(start: dict[str, Any], add: dict[str, Any]) -> dict[str, Any]:
merged = start.copy()
for key, value in add.items():
merged[key] = (
merge(start.get(key, {}), value) if isinstance(value, dict) else value
)
return merged


def ruff(pyproject: dict[str, Any], root: Traversable) -> dict[str, Any] | None:
"""
Returns the ruff configuration, or None if the configuration doesn't exist.
Respects ``ruff.toml`` and ``.ruff.toml`` in addition to
``pyproject.toml``.
``pyproject.toml``. Respects the extend option.
"""
paths = [root.joinpath(".ruff.toml"), root.joinpath("ruff.toml")]
for path in paths:
if path.is_file():
with path.open("rb") as f:
return tomllib.load(f)
contents = tomllib.load(f)
if contents.get("extend", "") == "pyproject.toml":
extend = pyproject.get("tool", {}).get("ruff", {})
return merge(extend, contents)
return contents

return pyproject.get("tool", {}).get("ruff", None) # type: ignore[no-any-return]


Expand All @@ -35,13 +49,13 @@ class Ruff:
class RF001(Ruff):
"Has Ruff config"

requires = {"PY001"}
requires = set()

@staticmethod
def check(ruff: dict[str, Any] | None) -> bool:
"""
Must have `[tool.ruff]` section in `pyproject.toml`. Other forms of
configuration are not supported by this check.
Must have `[tool.ruff]` section in `pyproject.toml` or
`ruff.toml`/`.ruff.toml`.
"""

return ruff is not None
Expand Down Expand Up @@ -102,8 +116,8 @@ def check(cls: type[RF1xxMixin], ruff: dict[str, Any]) -> bool:
Must select the {self.name} `{self.code}` checks. Recommended:
```toml
[tool.ruff]
select = [
[tool.ruff.lint]
extend-select = [
"{self.code}", # {self.name}
]
```
Expand Down
5 changes: 5 additions & 0 deletions tests/packages/ruff_extend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[tool.repo-review]
select = ["RF", "PY001"]

[tool.ruff.lint]
select = ["ALL"]
2 changes: 2 additions & 0 deletions tests/packages/ruff_extend/ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extend = "pyproject.toml"
target-version = "3.8"
9 changes: 9 additions & 0 deletions tests/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@ def test_local():
package = DIR.parent
results = process(package)
assert results


@pytest.mark.parametrize("name", ["ruff_extend"])
def test_examples(name: str) -> None:
package = DIR / "packages" / name
_, results = process(package)

failures = [r for r in results if r.result is not None and not r.result]
assert not failures
16 changes: 16 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from __future__ import annotations

from sp_repo_review.checks.ruff import merge


def test_merge():
a = {"a": 1, "b": [1], "c": {"aa": 2, "bb": [2]}, "d": {"one": 1}}
b = {"b": [3], "c": {"bb": [4], "cc": 5}, "e": {"two": 2}}

assert merge(a, b) == {
"a": 1,
"b": [3],
"c": {"aa": 2, "bb": [4], "cc": 5},
"d": {"one": 1},
"e": {"two": 2},
}

0 comments on commit 6e33351

Please sign in to comment.