Skip to content

Commit 5413d12

Browse files
committed
Get extra known directives from config file
1 parent a0f3b3d commit 5413d12

File tree

2 files changed

+52
-17
lines changed

2 files changed

+52
-17
lines changed

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ classifiers = [
2020
"Programming Language :: Python :: 3",
2121
]
2222
requires-python = ">= 3.7"
23+
dependencies = [
24+
"tomli>=2; python_version < '3.11'",
25+
]
2326
dynamic = ["version"]
2427

2528
[project.urls]

sphinxlint.py

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,16 @@
2121
from os.path import join, splitext, exists, isfile
2222
from collections import Counter
2323
from itertools import chain
24+
from typing import Any
2425
import multiprocessing
2526

27+
if sys.version_info[:2] >= (3, 11):
28+
import tomllib
29+
else:
30+
try:
31+
import tomli as tomllib
32+
except ImportError:
33+
tomllib = None
2634

2735
# The following chars groups are from docutils:
2836
closing_delimiters = "\\\\.,;!?"
@@ -103,26 +111,10 @@
103111
]
104112
# fmt: on
105113

106-
107-
all_directives = "(" + "|".join(directives) + ")"
108114
before_role = r"(^|(?<=[\s(/'{\[*-]))"
109115
simplename = r"(?:(?!_)\w)+(?:[-._+:](?:(?!_)\w)+)*"
110116
role_head = rf"({before_role}:{simplename}:)" # A role, with a clean start
111117

112-
# Find comments that look like a directive, like:
113-
# .. versionchanged 3.6
114-
# or
115-
# .. versionchanged: 3.6
116-
# as it should be:
117-
# .. versionchanged:: 3.6
118-
seems_directive_re = re.compile(rf"^\s*(?<!\.)\.\. {all_directives}([^a-z:]|:(?!:))")
119-
120-
# Find directive prefixed with three dots instead of two, like:
121-
# ... versionchanged:: 3.6
122-
# instead of:
123-
# .. versionchanged:: 3.6
124-
three_dot_directive_re = re.compile(rf"\.\.\. {all_directives}::")
125-
126118
# Find role used with double backticks instead of simple backticks like:
127119
# :const:``None``
128120
# instead of:
@@ -159,6 +151,10 @@
159151
leaked_markup_re = re.compile(r"[a-z]::\s|`|\.\.\s*\w+:")
160152

161153

154+
def get_all_directives() -> str:
155+
return "(" + "|".join(directives) + ")"
156+
157+
162158
checkers = {}
163159

164160
checker_props = {"severity": 1, "falsepositives": False, "rst_only": True}
@@ -244,6 +240,22 @@ def check_default_role(file, lines):
244240
@checker(".rst", severity=2)
245241
def check_directives(file, lines):
246242
"""Check for mis-constructed directives."""
243+
all_directives = get_all_directives()
244+
245+
# Find comments that look like a directive, like:
246+
# .. versionchanged 3.6
247+
# or
248+
# .. versionchanged: 3.6
249+
# as it should be:
250+
# .. versionchanged:: 3.6
251+
seems_directive_re = re.compile(rf"^\s*(?<!\.)\.\. {all_directives}([^a-z:]|:(?!:))")
252+
253+
# Find directive prefixed with three dots instead of two, like:
254+
# ... versionchanged:: 3.6
255+
# instead of:
256+
# .. versionchanged:: 3.6
257+
three_dot_directive_re = re.compile(rf"\.\.\. {all_directives}::")
258+
247259
for lno, line in enumerate(lines, start=1):
248260
if seems_directive_re.search(line):
249261
yield lno, "comment seems to be intended as a directive"
@@ -386,7 +398,7 @@ def hide_non_rst_blocks(lines, hidden_block_cb=None):
386398

387399

388400
def type_of_explicit_markup(line):
389-
if re.match(rf"\.\. {all_directives}::", line):
401+
if re.match(rf"\.\. {get_all_directives()}::", line):
390402
return "directive"
391403
if re.match(r"\.\. \[[0-9]+\] ", line):
392404
return "footnote"
@@ -479,6 +491,22 @@ def parse_args(argv=None):
479491
return args
480492

481493

494+
def _read_toml(filename: str) -> dict[str, Any]:
495+
if tomllib is None:
496+
return {}
497+
with open(filename, "rb") as f:
498+
return tomllib.load(f)
499+
500+
501+
def get_config() -> dict[str, Any]:
502+
if isfile("sphinx.toml"):
503+
return _read_toml("sphinx.toml").get("lint", {})
504+
if isfile("pyproject.toml"):
505+
table = _read_toml("pyproject.toml")
506+
return table.get("tool", {}).get("sphinx", {}).get("lint", {})
507+
return {}
508+
509+
482510
def is_disabled(msg, disabled_messages):
483511
return any(disabled in msg for disabled in disabled_messages)
484512

@@ -542,6 +570,10 @@ def check_file(filename, allow_false_positives=False, severity=1, disabled=()):
542570

543571
def main(argv=None):
544572
args = parse_args(argv)
573+
config = get_config()
574+
575+
# Append extra directives
576+
directives.extend(config.get("known_directives", []))
545577

546578
for path in args.paths:
547579
if not exists(path):

0 commit comments

Comments
 (0)