Skip to content

Commit 3597d31

Browse files
committed
Enable more linter categories in Ruff
1 parent a5e22d3 commit 3597d31

11 files changed

+89
-53
lines changed

.ruff.toml

+54-1
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,75 @@ docstring-code-format = true
88

99
[lint]
1010
select = [
11-
"C4", # flake8-comprehensions
11+
"ANN", # flake8-annotations
12+
"ASYNC", # flake8-async
1213
"B", # flake8-bugbear
14+
"BLE", # flake8-blind-except
15+
"C4", # flake8-comprehensions
16+
"D", # pydocstyle
17+
"D212", # Multi-line docstring summary should start at the first line
18+
"D417", # Missing argument description in the docstring for `{definition}`: `{name}`
19+
"DTZ", # flake8-datetimez
1320
"E", # pycodestyle
21+
"EM", # flake8-errmsg
22+
"EXE", # flake8-executable
1423
"F", # pyflakes
1524
"FA", # flake8-future-annotations
25+
"FIX", # flake8-fixme
1626
"FLY", # flynt
1727
"FURB", # refurb
1828
"G", # flake8-logging-format
1929
"I", # isort
30+
"ICN", # flake8-import-conventions
31+
"INT", # flake8-gettext
32+
"ISC", # flake8-implicit-str-concat
2033
"LOG", # flake8-logging
34+
"N", # pep8-naming
2135
"PERF", # perflint
2236
"PGH", # pygrep-hooks
37+
"PIE", # flake8-pie
38+
"PLC", # pylint
39+
"PLE", # pylint
40+
"PLW", # pylint
2341
"PT", # flake8-pytest-style
42+
"PTH", # flake8-use-pathlib
43+
"Q", # flake8-quotes
44+
"RET", # flake8-return
45+
"RSE", # flake8-raise
46+
"RUF", # Ruff-specific rules
47+
"S", # flake8-bandit
48+
"SIM", # flake8-simplify
49+
"SLF", # flake8-self
50+
"SLOT", # flake8-slots
51+
"T10", # flake8-debugger
2452
"TC", # flake8-type-checking
53+
"TD", # flake8-todos
54+
"TID", # flake8-tidy-imports
55+
"TRY", # tryceratops
2556
"UP", # pyupgrade
2657
"W", # pycodestyle
58+
"W", # pycodestyle
59+
"YTT", # flake8-2020
2760
]
2861
ignore = [
62+
# pydocstyle
63+
"D100", # Missing docstring in public module
64+
"D102", # Missing docstring in public method
65+
"D103", # Missing docstring in public function
66+
"D104", # Missing docstring in public package
67+
"D107", # Missing docstring in `__init__`
68+
"D400", # First line should end with a period
69+
# pycodestyle
2970
"E501", # Ignore line length errors (we use auto-formatting)
3071
]
3172

73+
[lint.per-file-ignores]
74+
"tests/*" = [
75+
"ANN", # tests don't need annotations
76+
"S101", # allow use of assert
77+
"SLF001", # allow private member access
78+
]
79+
3280
[lint.flake8-type-checking]
3381
exempt-modules = []
3482
strict = true
@@ -40,3 +88,8 @@ forced-separate = [
4088
required-imports = [
4189
"from __future__ import annotations",
4290
]
91+
92+
[lint.pydocstyle]
93+
convention = "pep257"
94+
ignore-decorators = ["typing.overload"]
95+
ignore-var-parameters = true

docs/script/generate_social_card_previews.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""
2-
A helper script to test out what social previews look like.
1+
"""A helper script to test out what social previews look like.
2+
33
I should remove this when I'm happy with the result.
44
"""
55

docs/source/conf.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,15 @@
44
# list see the documentation:
55
# https://www.sphinx-doc.org/en/master/usage/configuration.html
66

7-
# -- Path setup --------------------------------------------------------------
8-
9-
# If extensions (or modules to document with autodoc) are in another directory,
10-
# add these directories to sys.path here. If the directory is relative to the
11-
# documentation root, use os.path.abspath to make it absolute, like shown here.
12-
#
13-
147
from __future__ import annotations
158

16-
import os
179
import sys
10+
from pathlib import Path
1811
from subprocess import run
1912

20-
sys.path.insert(0, os.path.abspath("../.."))
13+
# -- Path setup --------------------------------------------------------------
2114

15+
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
2216

2317
# -- Project information -----------------------------------------------------
2418

@@ -72,5 +66,5 @@
7266
}
7367

7468
# Generate sample social media preview images
75-
path_script = os.path.abspath("../script/generate_social_card_previews.py")
76-
run(f"python {path_script}", shell=True)
69+
path_script = Path(__file__, "..", "..", "script", "generate_social_card_previews.py").resolve()
70+
run(("python", path_script), check=False) # NoQA: S603

noxfile.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""
2-
Configuration to automatically run jobs and tests via `nox`.
1+
"""Configuration to automatically run jobs and tests via `nox`.
2+
33
For example, to build the documentation with a live server:
44
55
nox -s docs -- live
@@ -21,7 +21,7 @@
2121

2222

2323
@nox.session
24-
def docs(session):
24+
def docs(session: nox.Session) -> None:
2525
"""Build the documentation. Use `-- live` to build with a live server."""
2626
session.install("-r", "docs/requirements.txt")
2727
session.install("-e", ".")
@@ -31,13 +31,13 @@ def docs(session):
3131
session.run(*split("sphinx-autobuild -b html docs/source docs/build/html"))
3232
else:
3333
session.run(
34-
*split("sphinx-build -nW --keep-going -b html docs/source docs/build/html")
34+
*split("sphinx-build -nW --keep-going -b html docs/source docs/build/html"),
3535
)
3636

3737

3838
@nox.session
39-
def test(session):
39+
def test(session: nox.Session) -> None:
4040
"""Run the test suite."""
4141
session.install("-e", ".")
4242
session.install("-r", "dev-requirements.txt")
43-
session.run(*(["pytest"] + session.posargs))
43+
session.run("pytest", *session.posargs)

sphinxext/opengraph/__init__.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import TYPE_CHECKING
66
from urllib.parse import urljoin, urlparse, urlsplit, urlunsplit
77

8-
import docutils.nodes as nodes
8+
from docutils import nodes
99

1010
from sphinxext.opengraph.descriptionparser import get_description
1111
from sphinxext.opengraph.metaparser import get_meta_description
@@ -197,7 +197,7 @@ def get_tags(
197197
image_url_parsed = urlparse(image_url)
198198
if not image_url_parsed.scheme:
199199
# Relative image path detected, relative to the source. Make absolute.
200-
if first_image:
200+
if first_image: # NoQA: SIM108
201201
root = page_url
202202
else: # ogp_image is set
203203
# ogp_image is defined as being relative to the site root.
@@ -256,7 +256,7 @@ def social_card_for_page(
256256
outdir: str | Path,
257257
config: Config,
258258
env: BuildEnvironment,
259-
):
259+
) -> str:
260260
# Description
261261
description_max_length = config_social.get(
262262
"description_max_length", DEFAULT_DESCRIPTION_LENGTH_SOCIAL_CARDS - 3
@@ -294,8 +294,7 @@ def social_card_for_page(
294294
# We use os.path.sep to standardize behavior acros *nix and Windows
295295
url = config.ogp_site_url.strip("/")
296296
image_path = str(image_path).replace(os.path.sep, "/").strip("/")
297-
image_url = f"{url}/{image_path}"
298-
return image_url
297+
return f"{url}/{image_path}"
299298

300299

301300
def html_page_context(

sphinxext/opengraph/descriptionparser.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
import string
44
from typing import TYPE_CHECKING
55

6-
import docutils.nodes as nodes
6+
from docutils import nodes
77

88
if TYPE_CHECKING:
99
from collections.abc import Set
1010

1111

1212
class DescriptionParser(nodes.NodeVisitor):
13-
"""
14-
Finds the title and creates a description from a doctree
15-
"""
13+
"""Finds the title and creates a description from a doctree."""
1614

1715
def __init__(
1816
self,

sphinxext/opengraph/metaparser.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55

66
class HTMLTextParser(HTMLParser):
7-
"""
8-
Parse HTML into text
9-
"""
7+
"""Parse HTML into text."""
108

119
def __init__(self) -> None:
1210
super().__init__()

sphinxext/opengraph/socialcards.py

+8-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pathlib import Path
77
from typing import TYPE_CHECKING
88

9-
import matplotlib
9+
import matplotlib as mpl
1010
import matplotlib.font_manager
1111
import matplotlib.image as mpimg
1212
from matplotlib import pyplot as plt
@@ -22,7 +22,7 @@
2222

2323
PltObjects: TypeAlias = tuple[Figure, Text, Text, Text, Text]
2424

25-
matplotlib.use("agg")
25+
mpl.use("agg")
2626

2727
LOGGER = logging.getLogger(__name__)
2828
HERE = Path(__file__).parent
@@ -77,11 +77,11 @@ def create_social_card(
7777
It also passes configuration through to the rendering function.
7878
If Matplotlib objects are present in the `app` environment, it reuses them.
7979
"""
80-
8180
# Add a hash to the image path based on metadata to bust caches
8281
# ref: https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/troubleshooting-cards#refreshing_images
8382
hash = hashlib.sha1(
84-
(site_name + page_title + description + str(config_social)).encode()
83+
(site_name + page_title + description + str(config_social)).encode(),
84+
usedforsecurity=False,
8585
).hexdigest()[:8]
8686

8787
# Define the file path we'll use for this image
@@ -156,8 +156,7 @@ def create_social_card(
156156
env.ogp_social_card_plt_objects = plt_objects
157157

158158
# Path relative to build folder will be what we use for linking the URL
159-
path_relative_to_build = path_images_relative / filename_image
160-
return path_relative_to_build
159+
return path_images_relative / filename_image
161160

162161

163162
def render_social_card(
@@ -236,9 +235,7 @@ def create_social_card_objects(
236235
left_margin,
237236
site_title_y_offset,
238237
"Test site title",
239-
{
240-
"size": 24,
241-
},
238+
{"size": 24},
242239
ha="left",
243240
va="top",
244241
wrap=True,
@@ -260,7 +257,7 @@ def create_social_card_objects(
260257
c=page_title_color,
261258
)
262259

263-
txt_page._get_wrap_line_width = _set_page_title_line_width
260+
txt_page._get_wrap_line_width = _set_page_title_line_width # NoQA: SLF001
264261

265262
# description
266263
# Just below site title, smallest font and many lines.
@@ -280,7 +277,7 @@ def create_social_card_objects(
280277
wrap=True,
281278
c=description_color,
282279
)
283-
txt_description._get_wrap_line_width = _set_description_line_width
280+
txt_description._get_wrap_line_width = _set_description_line_width # NoQA: SLF001
284281

285282
# url
286283
# Aligned to the left of the mini image

sphinxext/opengraph/titleparser.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55

66
class HTMLTextParser(HTMLParser):
7-
"""
8-
Parse HTML into text
9-
"""
7+
"""Parse HTML into text."""
108

119
def __init__(self) -> None:
1210
super().__init__()

tests/conftest.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111

1212
@pytest.fixture(scope="session")
1313
def rootdir():
14-
if sphinx.version_info[:2] >= (7, 0):
15-
return Path(__file__).parent.resolve() / "roots"
16-
else:
14+
if sphinx.version_info[:2] < (7, 2):
1715
from sphinx.testing.path import path
1816

1917
return path(__file__).parent.abspath() / "roots"
2018

19+
return Path(__file__).parent.resolve() / "roots"
20+
2121

2222
@pytest.fixture
2323
def content(app):

tests/test_options.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
def get_tag(tags, tag_type, kind="property", prefix="og"):
14-
return [tag for tag in tags if tag.get(kind) == f"{prefix}:{tag_type}"][0]
14+
return next(tag for tag in tags if tag.get(kind) == f"{prefix}:{tag_type}")
1515

1616

1717
def get_tag_content(tags, tag_type, kind="property", prefix="og"):
@@ -20,9 +20,8 @@ def get_tag_content(tags, tag_type, kind="property", prefix="og"):
2020

2121

2222
def get_meta_description(tags):
23-
return [tag for tag in tags if tag.get("name") == "description"][0].get(
24-
"content", ""
25-
)
23+
tag = next(tag for tag in tags if tag.get("name") == "description")
24+
return tag.get("content", "")
2625

2726

2827
@pytest.mark.sphinx("html", testroot="simple")

0 commit comments

Comments
 (0)