Skip to content

Commit 7f05400

Browse files
committed
Adopt Ruff and use stricter MyPy settings
1 parent be777a7 commit 7f05400

30 files changed

+447
-283
lines changed

.flake8

Lines changed: 0 additions & 4 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ jobs:
7171
runs-on: ubuntu-latest
7272
strategy:
7373
matrix:
74-
env: [flake8, mypy]
74+
env:
75+
- ruff
76+
- mypy
7577

7678
steps:
7779
- uses: actions/checkout@v3

.ruff.toml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
target-version = "py39" # Pin Ruff to Python 3.9
2+
output-format = "full"
3+
line-length = 95
4+
5+
[lint]
6+
preview = true
7+
select = [
8+
# "ANN", # flake8-annotations
9+
"C4", # flake8-comprehensions
10+
"COM", # flake8-commas
11+
"B", # flake8-bugbear
12+
"DTZ", # flake8-datetimez
13+
"E", # pycodestyle
14+
"EM", # flake8-errmsg
15+
"EXE", # flake8-executable
16+
"F", # pyflakes
17+
"FA", # flake8-future-annotations
18+
"FLY", # flynt
19+
"FURB", # refurb
20+
"G", # flake8-logging-format
21+
"I", # isort
22+
"ICN", # flake8-import-conventions
23+
"INT", # flake8-gettext
24+
"LOG", # flake8-logging
25+
"PERF", # perflint
26+
"PGH", # pygrep-hooks
27+
"PIE", # flake8-pie
28+
"PT", # flake8-pytest-style
29+
"SIM", # flake8-simplify
30+
"SLOT", # flake8-slots
31+
"TCH", # flake8-type-checking
32+
"UP", # pyupgrade
33+
"W", # pycodestyle
34+
"YTT", # flake8-2020
35+
]
36+
ignore = [
37+
"E116",
38+
"E241",
39+
"E251",
40+
]
41+
42+
[lint.per-file-ignores]
43+
"tests/*" = [
44+
"ANN", # tests don't need annotations
45+
]
46+
47+
[lint.isort]
48+
forced-separate = [
49+
"tests",
50+
]
51+
required-imports = [
52+
"from __future__ import annotations",
53+
]

pyproject.toml

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ whoosh = [
5656
"whoosh",
5757
]
5858
lint = [
59-
"flake8",
59+
"ruff==0.5.5",
6060
"mypy",
61-
"docutils-stubs",
61+
"types-docutils",
6262
]
6363

6464
[[project.authors]]
@@ -82,6 +82,49 @@ include = [
8282
]
8383

8484
[tool.mypy]
85+
python_version = "3.9"
86+
packages = [
87+
"sphinxcontrib",
88+
"tests",
89+
]
90+
exclude = [
91+
"tests/roots",
92+
]
93+
check_untyped_defs = true
94+
#disallow_any_generics = true
95+
disallow_incomplete_defs = true
96+
disallow_subclassing_any = true
97+
#disallow_untyped_calls = true
98+
disallow_untyped_decorators = true
99+
#disallow_untyped_defs = true
100+
explicit_package_bases = true
101+
extra_checks = true
102+
no_implicit_reexport = true
103+
show_column_numbers = true
104+
show_error_context = true
105+
strict_optional = true
106+
warn_redundant_casts = true
107+
warn_unused_configs = true
108+
warn_unused_ignores = true
109+
enable_error_code = [
110+
"type-arg",
111+
"redundant-self",
112+
"truthy-iterable",
113+
"ignore-without-code",
114+
"unused-awaitable",
115+
]
116+
117+
[[tool.mypy.overrides]]
118+
module = [
119+
"sqlalchemy",
120+
"sqlalchemy.orm",
121+
"sqlalchemy.sql",
122+
"whoosh",
123+
"whoosh.analysis",
124+
"whoosh.fields",
125+
"whoosh.qparser",
126+
"xapian",
127+
]
85128
ignore_missing_imports = true
86129

87130
[tool.pytest.ini_options]
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
"""A Python API to easily integrate Sphinx documentation into Web applications."""
2-
from os import path
32

3+
from __future__ import annotations
4+
5+
from os import path
46

57
__version__ = '1.2.7'
68
__version_info__ = (1, 2, 7)
79

810
package_dir = path.abspath(path.dirname(__file__))
911

1012
# must be imported last to avoid circular import
11-
from sphinxcontrib.websupport.core import WebSupport # NOQA
13+
from sphinxcontrib.websupport.core import WebSupport as WebSupport # NoQA: E402

sphinxcontrib/websupport/builder.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,28 @@
44

55
import html
66
import os
7-
from os import path
87
import posixpath
98
import shutil
9+
from os import path
1010
from typing import TYPE_CHECKING, Any
1111

1212
from docutils.io import StringOutput
13-
1413
from sphinx.jinja2glue import BuiltinTemplateLoader
15-
from sphinx.util.osutil import os_path, relative_uri, ensuredir, copyfile
16-
from sphinxcontrib.serializinghtml import PickleHTMLBuilder
14+
from sphinx.util.osutil import copyfile, ensuredir, os_path, relative_uri
1715

16+
from sphinxcontrib.serializinghtml import PickleHTMLBuilder
1817
from sphinxcontrib.websupport import package_dir
19-
from sphinxcontrib.websupport.writer import WebSupportTranslator
2018
from sphinxcontrib.websupport.utils import is_commentable
21-
19+
from sphinxcontrib.websupport.writer import WebSupportTranslator
2220

2321
if TYPE_CHECKING:
24-
from collections.abc import Iterable
22+
from collections.abc import Callable, Iterable
2523

2624
from docutils import nodes
2725
from sphinx.application import Sphinx
26+
from sphinx.builders.html._assets import _CascadingStyleSheet, _JavaScript
27+
28+
from sphinxcontrib.websupport.search import BaseSearch
2829

2930
RESOURCES = [
3031
'ajax-loader.gif',
@@ -48,34 +49,34 @@ class WebSupportBuilder(PickleHTMLBuilder):
4849
versioning_compare = True # for commentable node's uuid stability.
4950

5051
def init(self) -> None:
51-
PickleHTMLBuilder.init(self)
52+
super().init()
5253
# templates are needed for this builder, but the serializing
5354
# builder does not initialize them
5455
self.init_templates()
5556
if not isinstance(self.templates, BuiltinTemplateLoader):
56-
raise RuntimeError('websupport builder must be used with '
57-
'the builtin templates')
57+
msg = 'websupport builder must be used with the builtin templates'
58+
raise RuntimeError(msg)
5859
# add our custom JS
5960
self.add_js_file('websupport.js')
6061

6162
@property
62-
def versioning_method(self):
63+
def versioning_method(self) -> Callable[[nodes.Node], bool]: # type: ignore[override]
6364
return is_commentable
6465

6566
def set_webinfo(
6667
self,
6768
staticdir: str,
6869
virtual_staticdir: str,
69-
search: Any,
70+
search: BaseSearch,
7071
storage: str,
7172
) -> None:
7273
self.staticdir = staticdir
7374
self.virtual_staticdir = virtual_staticdir
74-
self.search = search
75+
self.search: BaseSearch = search # type: ignore[assignment]
7576
self.storage = storage
7677

7778
def prepare_writing(self, docnames: Iterable[str]) -> None:
78-
PickleHTMLBuilder.prepare_writing(self, docnames)
79+
super().prepare_writing(set(docnames))
7980
self.globalcontext['no_search_suffix'] = True
8081

8182
def write_doc(self, docname: str, doctree: nodes.document) -> None:
@@ -95,16 +96,16 @@ def write_doc(self, docname: str, doctree: nodes.document) -> None:
9596
ctx = self.get_doc_context(docname, body, metatags)
9697
self.handle_page(docname, ctx, event_arg=doctree)
9798

98-
def write_doc_serialized(self, docname: str, doctree: nodes.Node) -> None:
99+
def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
99100
self.imgpath = '/' + posixpath.join(self.virtual_staticdir, self.imagedir)
100101
self.post_process_images(doctree)
101-
title = self.env.longtitles.get(docname)
102-
title = title and self.render_partial(title)['title'] or ''
102+
title_node = self.env.longtitles.get(docname)
103+
title = title_node and self.render_partial(title_node)['title'] or ''
103104
self.index_page(docname, doctree, title)
104105

105106
def load_indexer(self, docnames: Iterable[str]) -> None:
106-
self.indexer = self.search # type: ignore
107-
self.indexer.init_indexing(changed=docnames) # type: ignore
107+
self.indexer = self.search # type: ignore[assignment]
108+
self.indexer.init_indexing(changed=list(docnames)) # type: ignore[union-attr]
108109

109110
def _render_page(
110111
self,
@@ -135,7 +136,7 @@ def pathto(otheruri: str, resource: bool = False,
135136
self.add_sidebars(pagename, ctx)
136137
ctx.update(addctx)
137138

138-
def css_tag(css) -> str:
139+
def css_tag(css: _CascadingStyleSheet) -> str:
139140
attrs = []
140141
for key, value in css.attributes.items():
141142
if value is not None:
@@ -145,10 +146,10 @@ def css_tag(css) -> str:
145146

146147
ctx['css_tag'] = css_tag
147148

148-
def js_tag(js) -> str:
149+
def js_tag(js: _JavaScript) -> str:
149150
if not hasattr(js, 'filename'):
150151
# str value (old styled)
151-
return f'<script src="{pathto(js, resource=True)}"></script>'
152+
return f'<script src="{pathto(js, resource=True)}"></script>' # type: ignore[arg-type]
152153

153154
attrs = []
154155
body = js.attributes.get('body', '')
@@ -216,7 +217,7 @@ def handle_finish(self) -> None:
216217
self.globalcontext['css'] = doc_ctx['css']
217218
self.globalcontext['script'] = doc_ctx['script']
218219

219-
PickleHTMLBuilder.handle_finish(self)
220+
super().handle_finish()
220221

221222
# move static stuff over to separate directory
222223
directories = [self.imagedir, '_static']
@@ -239,7 +240,7 @@ def copy_resources(self) -> None:
239240
shutil.copy(src, dst)
240241

241242
def dump_search_index(self) -> None:
242-
self.indexer.finish_indexing() # type: ignore
243+
self.indexer.finish_indexing() # type: ignore[union-attr]
243244

244245

245246
def setup(app: Sphinx) -> dict[str, Any]:

0 commit comments

Comments
 (0)