Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,13 @@ repos:
- id: requirements-txt-fixer
- id: trailing-whitespace

- repo: https://github.com/adamchainz/blacken-docs
rev: "1.20.0"
hooks:
- id: blacken-docs
additional_dependencies: [black==24.*]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.15.22"
rev: "v0.16.0"
hooks:
- id: ruff-check
args: ["--fix"]
- id: ruff-format
types_or: [python, pyi, jupyter, markdown, pyproject]

- repo: https://github.com/pre-commit/pygrep-hooks
rev: "v1.10.0"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ Will not show up if using lefthook instead of pre-commit/prek.

- [`PC100`](https://learn.scientific-python.org/development/guides/style#PC100): Has pre-commit-hooks
- [`PC110`](https://learn.scientific-python.org/development/guides/style#PC110): Uses black or ruff-format
- [`PC111`](https://learn.scientific-python.org/development/guides/style#PC111): Uses blacken-docs
- [`PC111`](https://learn.scientific-python.org/development/guides/style#PC111): Formats code in docs (ruff-format or blacken-docs)
- [`PC140`](https://learn.scientific-python.org/development/guides/style#PC140): Uses a type checker
- [`PC160`](https://learn.scientific-python.org/development/guides/style#PC160): Uses a spell checker
- [`PC170`](https://learn.scientific-python.org/development/guides/style#PC170): Uses PyGrep hooks (only needed if rST present)
Expand Down
38 changes: 30 additions & 8 deletions docs/guides/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Here is the snippet to add the formatter to your `.pre-commit-config.yml`

```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.15.22"
rev: "v0.16.0"
hooks:
# id: ruff-check would go here if using both
- id: ruff-format
Expand Down Expand Up @@ -205,11 +205,31 @@ option! Most of the time, you can find a way to make the Blacked code look
better by rewriting your code; factor out long unreadable portions into a
variable, avoid writing matrices as 1D lists, etc.

:::{dropdown} Documentation / README snippets support
{rr}`PC111` If you want Black used in your documentation, you can use
blacken-docs. This can even catch syntax errors in code snippets! It supports
markdown and restructured text. Note that because black is in
`additional_dependencies`, you'll have to keep it up to date manually.
::::::{dropdown} Documentation / README snippets support
{rr}`PC111` A formatter can keep the Python snippets in your docs tidy, and
even catch syntax errors in them.

:::::{tab-set}
::::{tab-item} Ruff-format
Ruff (0.16+) formats Python code blocks in Markdown, so a single tool covers
your code and your docs. Add `markdown` to the `ruff-format` hook's `types_or`:

```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.16.0"
hooks:
- id: ruff-format
types_or: [python, pyi, jupyter, markdown, pyproject]
```

The hook only sees the file types you list, so `markdown` is needed until it is
part of the hook's default.

::::
::::{tab-item} blacken-docs
Use blacken-docs if you use Black, or want reStructuredText snippets formatted
too. Note that because black is in `additional_dependencies`, you'll have to
keep it up to date manually.

```yaml
- repo: https://github.com/adamchainz/blacken-docs
Expand All @@ -219,7 +239,9 @@ markdown and restructured text. Note that because black is in
additional_dependencies: [black==24.*]
```

:::
::::
:::::
::::::

## Ruff

Expand All @@ -234,7 +256,7 @@ pre-commit hook.

```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.15.22"
rev: "v0.16.0"
hooks:
- id: ruff-check
args: ["--fix", "--show-fixes"]
Expand Down
2 changes: 1 addition & 1 deletion docs/principles/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def get_image(
*,
normalize: bool = True,
beginning: int = 0,
end: int | None = None
end: int | None = None,
) -> np.ndarray: ...
```

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ ignore = [
"A002", # Okay for arguments to shadow builtins
"A004", # Okay for imports to shadow builtins (like print)
"COM812", # Trailing commas teach the formatter
"CPY001", # No copyright notices
"D", # Docstrings
"E501", # Line too long
"FBT", # Boolean args fine
Expand Down
45 changes: 42 additions & 3 deletions src/sp_repo_review/checks/precommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ def precommit(root: Traversable) -> dict[str, Any]:
return {}


def _formats_markdown(hook: dict[str, Any]) -> bool:
"A `ruff-format` hook that Markdown files can reach."
match hook:
case {"id": "ruff-format", "types_or": types}:
return "markdown" in types
# No `types_or` means Ruff's own default, which will include
# Markdown in a future release.
case {"id": "ruff-format"}:
return True
case _:
return False


class PreCommit:
family = "pre-commit"
requires = {"PY006"}
Expand All @@ -45,7 +58,7 @@ def describe(self) -> str:
return "one of " + ", ".join(msgs)

@classmethod
def check(cls, precommit: dict[str, Any]) -> bool | None | str:
def check(cls, precommit: dict[str, Any]) -> bool | str | None:
"Must have {self.describe} in `.pre-commit-config.yaml`"
assert cls.repos, f"{cls.__name__} must have a repo, invalid class definition"
for repo_item in precommit.get("repos", {}):
Expand Down Expand Up @@ -89,14 +102,40 @@ class PC110(PreCommit):


class PC111(PreCommit):
"Uses blacken-docs"
"Formats code in docs (ruff-format or blacken-docs)"

requires = {"PY006", "PC110"}
repos = {"https://github.com/adamchainz/blacken-docs"}
repos = {
"https://github.com/astral-sh/ruff-pre-commit",
"https://github.com/adamchainz/blacken-docs",
}
renamed = {
"https://github.com/asottile/blacken-docs": "https://github.com/adamchainz/blacken-docs"
}

@classmethod
def check(cls, precommit: dict[str, Any]) -> bool | str | None:
"""
Add `blacken-docs`, or (Ruff 0.16+) let Markdown files reach the
`ruff-format` hook in `.pre-commit-config.yaml`. Until the hook formats
Markdown by default, that means `types_or: [python, pyi, jupyter,
markdown, pyproject]`.
"""
for repo_item in precommit.get("repos", {}):
match repo_item.get("repo", "").lower(), repo_item.get("hooks", []):
case "https://github.com/adamchainz/blacken-docs", _:
return True
case "https://github.com/astral-sh/ruff-pre-commit", hooks if any(
_formats_markdown(hook) for hook in hooks
):
return True
case repo, _ if repo in cls.renamed:
return (
f"Use `{cls.renamed[repo]}` instead of `{repo}` in "
"`.pre-commit-config.yaml`"
)
return False


class PC190(PreCommit):
"Uses a linter (Ruff/Flake8)"
Expand Down
42 changes: 42 additions & 0 deletions tests/test_precommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,48 @@ def test_pc111():
assert compute_check("PC111", precommit=precommit).result


def test_pc111_ruff_markdown():
precommit = yaml.safe_load("""
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks:
- id: ruff-format
types_or: [python, pyi, jupyter, markdown, pyproject]
""")
assert compute_check("PC111", precommit=precommit).result


def test_pc111_ruff_default_types():
precommit = yaml.safe_load("""
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks:
- id: ruff-format
""")
assert compute_check("PC111", precommit=precommit).result


def test_pc111_ruff_markdown_excluded():
precommit = yaml.safe_load("""
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks:
- id: ruff-format
types_or: [python, pyi, jupyter]
""")
assert not compute_check("PC111", precommit=precommit).result


def test_pc111_ruff_check_only():
precommit = yaml.safe_load("""
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks:
- id: ruff-check
""")
assert not compute_check("PC111", precommit=precommit).result


def test_pc111_rename():
precommit = yaml.safe_load("""
repos:
Expand Down
9 changes: 2 additions & 7 deletions {{cookiecutter.project_name}}/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ ci:
exclude: ^.cruft.json|.copier-answers.yml$

repos:
- repo: https://github.com/adamchainz/blacken-docs
rev: "1.20.0"
hooks:
- id: blacken-docs
additional_dependencies: [black==26.*]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v6.0.0"
hooks:
Expand Down Expand Up @@ -43,11 +37,12 @@ repos:
args: [--prose-wrap=always]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.15.22"
rev: "v0.16.0"
hooks:
- id: ruff-check
args: ["--fix"]
- id: ruff-format
types_or: [python, pyi, jupyter, markdown, pyproject]

{%- if cookiecutter.backend in ["pybind11", "skbuild", "mesonpy"] %}

Expand Down
Loading