Skip to content

Replace black and flake8 with ruff #182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 13, 2025
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
8 changes: 0 additions & 8 deletions .flake8

This file was deleted.

14 changes: 6 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ repos:
rev: 1.5.0
hooks:
- id: tox-ini-fmt

- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 7.2.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.12
hooks:
- id: flake8
- id: ruff-format
alias: ruff
- id: ruff-check
alias: ruff
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.16.0
hooks:
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ recursive-include docs *.ico
recursive-include docs *.png
recursive-include docs *.py
recursive-include docs *.rst
recursive-include src *.flake8
recursive-include src *.j2
recursive-include src *.json
recursive-include src *.md
Expand Down
61 changes: 61 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ py-version = "3.10.0"

[tool.pylint."MESSAGES CONTROL"]
disable = [
"line-too-long",
# TODO(ssbarnea): remove temporary skips adding during initial adoption:
"attribute-defined-outside-init",
"consider-using-f-string",
Expand Down Expand Up @@ -126,6 +127,66 @@ filterwarnings = [
"ignore:The frontend.*:DeprecationWarning"
]

[tool.ruff]
fix = true
# Same as Black.
line-length = 88
preview = true
target-version = "py310"

[tool.ruff.lint]
ignore = [
"E501",
# temporary disabled until we fix them:
"A001",
"ANN",
"B007",
"BLE001",
"C410",
"C419",
"C901",
"CPY001",
"D",
"DOC",
"EM102",
"ERA001",
"FBT002",
"FBT003",
"FLY002",
"FURB101",
"FURB103",
"INP001",
"PERF401",
"PGH003",
"PGH004",
"PLR0912",
"PLR0915",
"PLR1702",
"PLR6104",
"PLR6301",
"PLW2901",
"PT009",
"PTH",
"RUF012",
"RUF059",
"S108",
"SIM102",
"SIM103",
"SIM105",
"SIM108",
"SLF001",
"T201",
"TRY003",
"UP031"
]
select = ["ALL"]

[tool.ruff.lint.isort]
known-first-party = ["src"]

[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.setuptools]
include-package-data = true
# These are required in actual runtime:
Expand Down
4 changes: 2 additions & 2 deletions src/doc8/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""doc8 - A docutils linter."""

from __future__ import annotations
from doc8.version import __version__
from doc8.main import doc8 # noqa

from doc8.main import doc8 # noqa
from doc8.version import __version__

__all__ = ("__version__",)
1 change: 0 additions & 1 deletion src/doc8/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@

from doc8 import main


sys.exit(main.main())
25 changes: 10 additions & 15 deletions src/doc8/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from doc8 import utils


class ContentCheck(metaclass=abc.ABCMeta):
class ContentCheck(abc.ABC):
def __init__(self, cfg):
self._cfg = cfg

Expand All @@ -30,7 +30,7 @@ def report_iter(self, parsed_file):
pass


class LineCheck(metaclass=abc.ABCMeta):
class LineCheck(abc.ABC):
def __init__(self, cfg):
self._cfg = cfg

Expand Down Expand Up @@ -83,7 +83,7 @@ def report_iter(self, parsed_file):

class CheckValidity(ContentCheck):
REPORTS = frozenset(["D000"])
EXT_MATCHER = re.compile(r"(.*)[.]rst", re.I)
EXT_MATCHER = re.compile(r"(.*)[.]rst", re.IGNORECASE)

# From docutils docs:
#
Expand All @@ -104,11 +104,11 @@ class CheckValidity(ContentCheck):
re.MULTILINE,
),
re.compile(
r'^Error in "code-block" directive:\nunknown option: "emphasize-lines"'
r'^Error in "code-block" directive:\nunknown option: "emphasize-lines"',
),
re.compile(r'^Error in "code-block" directive:\nunknown option: "linenos"'),
re.compile(
r'^Error in "code-block" directive:\nunknown option: "lineno-start"'
r'^Error in "code-block" directive:\nunknown option: "lineno-start"',
),
re.compile(r'^Error in "code-block" directive:\nunknown option: "dedent"'),
re.compile(r'^Error in "code-block" directive:\nunknown option: "force"'),
Expand All @@ -119,7 +119,7 @@ class CheckValidity(ContentCheck):
re.MULTILINE,
),
re.compile(
r'^PEP number must be a number from 0 to 9999; "\d{1,4}#[^"]*" is invalid.'
r'^PEP number must be a number from 0 to 9999; "\d{1,4}#[^"]*" is invalid.',
),
]

Expand Down Expand Up @@ -218,16 +218,14 @@ def find_directive_end(start, lines):
# for unknown directives, so we have to do it manually).
directives = []
for i, line in enumerate(lines):
if re.match(r"^\s*..\s(.*?)::\s*", line):
directives.append((i, find_directive_end(i, lines)))
elif re.match(r"^::\s*$", line):
if re.match(r"^\s*..\s(.*?)::\s*", line) or re.match(r"^::\s*$", line):
directives.append((i, find_directive_end(i, lines)))

# Find definition terms in definition lists
# This check may match the code, which is already appended
lwhitespaces = r"^\s*"
listspattern = r"^\s*(\* |- |#\. |\d+\. )"
for i in range(0, len(lines) - 1):
for i in range(len(lines) - 1):
line = lines[i]
next_line = lines[i + 1]
# if line is a blank, line is not a definition term
Expand All @@ -237,7 +235,7 @@ def find_directive_end(start, lines):
if re.match(listspattern, line):
continue
if len(re.search(lwhitespaces, line).group()) < len(
re.search(lwhitespaces, next_line).group()
re.search(lwhitespaces, next_line).group(),
):
directives.append((i, i))

Expand Down Expand Up @@ -266,10 +264,7 @@ def find_containing_nodes(num):
best_nodes = []
for n, (line_min, line_max) in contained_in:
span = line_max - line_min
if smallest_span is None:
smallest_span = span
best_nodes = [n]
elif span < smallest_span:
if smallest_span is None or span < smallest_span:
smallest_span = span
best_nodes = [n]
elif span == smallest_span:
Expand Down
58 changes: 29 additions & 29 deletions src/doc8/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import os
import sys


try:
# py3.11+
from tomllib import load as toml_load # type: ignore
Expand All @@ -45,10 +44,8 @@

from stevedore import extension

from doc8 import checks
from doc8 import checks, utils, version
from doc8 import parser as file_parser
from doc8 import utils
from doc8 import version

FILE_PATTERNS = [".rst", ".txt"]
MAX_LINE_LENGTH = 79
Expand Down Expand Up @@ -158,7 +155,8 @@
if not os.path.isfile(cfg_file):
if args["config"]:
print(
"Configuration file %s does not exist...ignoring" % (args["config"])
"Configuration file %s does not exist...ignoring"
% (args["config"]),
)
continue
if cfg_file.endswith((".ini", ".cfg")):
Expand All @@ -180,7 +178,9 @@
checks.CheckNewlineEndOfFile(cfg),
]
mgr = extension.ExtensionManager(
namespace="doc8.extension.check", invoke_on_load=True, invoke_args=(cfg.copy(),)
namespace="doc8.extension.check",
invoke_on_load=True,
invoke_args=(cfg.copy(),),
)
addons = []
for e in mgr:
Expand All @@ -194,7 +194,9 @@
else:
level = logging.ERROR
logging.basicConfig(
level=level, format="%(levelname)s: %(message)s", stream=sys.stdout
level=level,
format="%(levelname)s: %(message)s",
stream=sys.stdout,
)


Expand All @@ -205,7 +207,9 @@
ignored_paths = cfg.get("ignore_path", [])
files_ignored = 0
file_iter = utils.find_files(
cfg.get("paths", []), cfg.get("extension", []), ignored_paths
cfg.get("paths", []),
cfg.get("extension", []),
ignored_paths,
)
default_extension = cfg.get("default_extension")
file_encoding = cfg.get("file_encoding")
Expand All @@ -216,7 +220,9 @@
print(" Ignoring '%s'" % (filename))
else:
f = file_parser.parse(
filename, default_extension=default_extension, encoding=file_encoding
filename,
default_extension=default_extension,
encoding=file_encoding,
)
files.append(f)
if cfg.get("verbose"):
Expand Down Expand Up @@ -253,7 +259,7 @@
print(
" Skipping check '%s' since it does not"
" understand parsing a file with extension '%s'"
% (check_name, f.extension)
% (check_name, f.extension),
)
continue
try:
Expand All @@ -266,7 +272,7 @@
if cfg.get("verbose"):
print(
" Skipping check '%s', determined to only"
" check ignoreable codes" % check_name
" check ignoreable codes" % check_name,
)
continue
if cfg.get("verbose"):
Expand All @@ -279,13 +285,11 @@
line_num = "?"
if cfg.get("verbose"):
print(
" - {}:{}: {} {}".format(
f.filename, line_num, code, message
)
f" - {f.filename}:{line_num}: {code} {message}",
)
elif not result.capture:
print(
"{}:{}: {} {}".format(f.filename, line_num, code, message)
f"{f.filename}:{line_num}: {code} {message}",
)
result.error(check_name, f.filename, line_num, code, message)
error_counts[check_name] += 1
Expand All @@ -297,18 +301,16 @@
if cfg.get("verbose"):
print(
" - %s:%s: %s %s"
% (f.filename, line_num, code, message)
% (f.filename, line_num, code, message),
)
elif not result.capture:
print(
"{}:{}: {} {}".format(
f.filename, line_num, code, message
)
f"{f.filename}:{line_num}: {code} {message}",
)
result.error(check_name, f.filename, line_num, code, message)
error_counts[check_name] += 1
else:
raise TypeError("Unknown check type: {}, {}".format(type(c), c))
raise TypeError(f"Unknown check type: {type(c)}, {c}")

Check warning on line 313 in src/doc8/main.py

View check run for this annotation

Codecov / codecov/patch

src/doc8/main.py#L313

Added line #L313 was not covered by tests
return error_counts


Expand Down Expand Up @@ -358,20 +360,18 @@
for error in self.errors:
lines.append("%s:%s: %s %s" % error[1:])

lines.extend(
[
"=" * 8,
"Total files scanned = %s" % (self.files_selected),
"Total files ignored = %s" % (self.files_ignored),
"Total accumulated errors = %s" % (self.total_errors),
]
)
lines.extend([
"=" * 8,
"Total files scanned = %s" % (self.files_selected),
"Total files ignored = %s" % (self.files_ignored),
"Total accumulated errors = %s" % (self.total_errors),
])

if self.error_counts:
lines.append("Detailed error counts:")
for check_name in sorted(self.error_counts.keys()):
check_errors = self.error_counts[check_name]
lines.append(" - {} = {}".format(check_name, check_errors))
lines.append(f" - {check_name} = {check_errors}")

return "\n".join(lines)

Expand Down
Loading
Loading