Skip to content

Commit 145d4d9

Browse files
committed
Add directivegetter
1 parent 5d1890d commit 145d4d9

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

sphinxlint/directivegetter.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
import sys
5+
from typing import TYPE_CHECKING
6+
7+
from docutils.parsers.rst.directives import _directive_registry, _directives
8+
from docutils.parsers.rst.languages import en
9+
from sphinx.builders.dummy import DummyBuilder
10+
11+
if TYPE_CHECKING:
12+
from collections.abc import Iterator, Iterable
13+
14+
from sphinx.application import Sphinx
15+
16+
DOCUTILS_DIRECTIVES = frozenset(_directive_registry.keys() | en.directives.keys())
17+
SPHINX_DIRECTIVES = frozenset({
18+
# reStructuredText content:
19+
# ~~~~~~~~~~~~~~~~~~~~~~~~~
20+
# Added by Sphinx:
21+
'acks', 'centered', 'codeauthor', 'default-domain', 'deprecated(?!-removed)',
22+
'describe', 'highlight', 'hlist', 'index', 'literalinclude', 'moduleauthor',
23+
'object', 'only', 'rst-class', 'sectionauthor', 'seealso', 'tabularcolumns',
24+
'toctree', 'versionadded', 'versionchanged',
25+
# Added by Sphinx (since removed):
26+
'highlightlang', # removed in Sphinx 4.0
27+
# Added by Sphinx (Standard domain):
28+
'cmdoption', 'envvar', 'glossary', 'option', 'productionlist', 'program',
29+
# Added by Sphinx (Python domain):
30+
'py:attribute', 'py:class', 'py:classmethod', 'py:currentmodule', 'py:data',
31+
'py:decorator', 'py:decoratormethod', 'py:exception', 'py:function',
32+
'py:method', 'py:module', 'py:property', 'py:staticmethod',
33+
'attribute', 'class', 'classmethod', 'currentmodule', 'data',
34+
'decorator', 'decoratormethod', 'exception', 'function',
35+
'method', 'module', 'property', 'staticmethod',
36+
# Added by Sphinx (C domain):
37+
'c:alias', 'c:enum', 'c:enumerator', 'c:function', 'c:macro', 'c:member',
38+
'c:struct', 'c:type', 'c:union', 'c:var',
39+
'cfunction', 'cmacro', 'cmember', 'ctype', 'cvar',
40+
# Added by Sphinx (sphinx.ext.todo):
41+
'todo', 'todolist',
42+
# Added in Sphinx's own documentation only:
43+
'confval', 'event',
44+
45+
# Arbitrary content:
46+
# ~~~~~~~~~~~~~~~~~~
47+
# Added by Sphinx (core):
48+
'cssclass',
49+
# Added by Sphinx (Standard domain):
50+
'productionlist',
51+
# Added by Sphinx (C domain):
52+
'c:namespace', 'c:namespace-pop', 'c:namespace-push',
53+
# Added by Sphinx (sphinx.ext.autodoc):
54+
'autoattribute', 'autoclass', 'autodata', 'autodecorator', 'autoexception',
55+
'autofunction', 'automethod', 'automodule', 'autonewtypedata',
56+
'autonewvarattribute', 'autoproperty',
57+
# Added by Sphinx (sphinx.ext.doctest):
58+
'doctest', 'testcleanup', 'testcode', 'testoutput', 'testsetup',
59+
60+
})
61+
CORE_DIRECTIVES = DOCUTILS_DIRECTIVES | SPHINX_DIRECTIVES
62+
63+
64+
def tomlify_directives(directives: Iterable[str], comment: str) -> Iterator[str]:
65+
yield f" # {comment}:"
66+
yield from (f' "{directive}",' for directive in sorted(directives))
67+
68+
69+
def write_directives(directives: Iterable[str]):
70+
lines = [
71+
"[tool.sphinx-lint]",
72+
"known_directives = [",
73+
tomlify_directives(directives, "Added by extensions or in conf.py"),
74+
"]",
75+
"", # final blank line
76+
]
77+
with open("sphinx.toml", "w", encoding="utf-8") as file:
78+
file.write("\n".join(lines))
79+
80+
81+
class DirectiveCollectorBuilder(DummyBuilder):
82+
name = "directive_collector"
83+
84+
def get_outdated_docs(self) -> str:
85+
return "nothing, just getting list of directives"
86+
87+
def read(self) -> list[str]:
88+
write_directives({*_directives} - CORE_DIRECTIVES)
89+
return []
90+
91+
def write(self, *args, **kwargs) -> None:
92+
pass
93+
94+
95+
def setup(app: Sphinx) -> dict[str, bool]:
96+
"""Plugin for Sphinx"""
97+
app.add_builder(DirectiveCollectorBuilder)
98+
return {"parallel_read_safe": True, "parallel_write_safe": True}
99+
100+
101+
def collect_directives():
102+
from sphinx import application
103+
from sphinx.application import Sphinx
104+
105+
try:
106+
source_dir, build_dir, *opts = sys.argv[1:]
107+
except ValueError:
108+
raise RuntimeError("Two arguments (source dir and build dir) are required.")
109+
110+
application.builtin_extensions = (
111+
*application.builtin_extensions,
112+
"directivegetter" # set up this file as an extension
113+
)
114+
app = Sphinx(
115+
str(Path(source_dir)),
116+
str(Path(source_dir)),
117+
str(Path(build_dir)),
118+
str(Path(build_dir, "doctrees")),
119+
"directive_collector",
120+
)
121+
app.build(force_all=True)
122+
raise SystemExit(app.statuscode)
123+
124+
125+
if __name__ == "__main__":
126+
collect_directives()

0 commit comments

Comments
 (0)