Check for stylistic and formal issues in .rst and .py files included in the documentation
Built-in checkers for detecting common reStructuredText syntax issues, Python documentation problems, and general formatting issues. Each checker is designed to catch specific types of problems that might not be visible to sphinx-build.
Decorator for registering checker functions with metadata about supported file types and default behavior.
def checker(*suffixes, **kwds):
"""
Decorator to register a function as a checker.
Parameters:
- *suffixes: file extensions this checker supports (e.g., '.rst', '.py')
- **kwds: checker properties (enabled=True/False, rst_only=True/False)
Returns:
Decorated function with checker metadata attributes
"""Global registry containing all available checker functions.
all_checkers: dict[str, CheckerFunction]
# Dictionary mapping checker names to checker functions
# Names are derived from function names by removing 'check_' prefix and replacing '_' with '-'Checkers for reStructuredText roles, inline markup, and related syntax issues.
def check_missing_backtick_after_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for roles missing their closing backticks.
Bad: :fct:`foo
Good: :fct:`foo`
Supported files: .rst, .po
"""
def check_missing_space_after_literal(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for inline literals immediately followed by a character.
Bad: ``items``s
Good: ``items``\\ s
Supported files: .rst, .po
"""
def check_unbalanced_inline_literals_delimiters(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for unbalanced inline literals delimiters.
Bad: ``hello`` world``
Good: ``hello`` world
Supported files: .rst, .po
"""
def check_default_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for default roles (disabled by default, allowed in many projects).
Bad: `print`
Good: ``print``
Supported files: .rst, .po
Enabled: False (disabled by default)
"""
def check_missing_space_after_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for roles immediately followed by a character.
Bad: :exc:`Exception`s.
Good: :exc:`Exceptions`\\ s
Supported files: .rst, .po
"""
def check_role_without_backticks(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search roles without backticks.
Bad: :func:pdb.main
Good: :func:`pdb.main`
Supported files: .rst, .po
"""
def check_backtick_before_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for roles preceded by a backtick.
Bad: `:fct:`sum`
Good: :fct:`sum`
Supported files: .rst, .po
"""
def check_role_with_double_backticks(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for roles with double backticks.
Bad: :fct:``sum``
Good: :fct:`sum`
Supported files: .rst, .po
"""
def check_missing_space_before_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for missing spaces before roles.
Bad: the:fct:`sum`, issue:`123`, c:func:`foo`
Good: the :fct:`sum`, :issue:`123`, :c:func:`foo`
Supported files: .rst, .po
"""
def check_missing_space_before_default_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for missing spaces before default role.
Bad: the`sum`
Good: the `sum`
Supported files: .rst, .po
"""
def check_missing_colon_in_role(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for missing colons in roles.
Bad: :issue`123`
Good: :issue:`123`
Supported files: .rst, .po
"""
def check_unnecessary_parentheses(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for unnecessary parentheses in :func: and :meth: roles.
Bad: :func:`test()`
Good: :func:`test`
Supported files: .rst, .po
"""Checkers for reStructuredText directive syntax issues.
def check_directive_with_three_dots(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for directives with three dots instead of two.
Bad: ... versionchanged:: 3.6
Good: .. versionchanged:: 3.6
Supported files: .rst, .po
"""
def check_directive_missing_colons(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for directive wrongly typed as comments.
Bad: .. versionchanged 3.6.
Good: .. versionchanged:: 3.6
Supported files: .rst, .po
"""Checkers for hyperlink syntax and formatting issues.
def check_missing_space_in_hyperlink(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for hyperlinks missing a space.
Bad: `Link text<https://example.com>`_
Good: `Link text <https://example.com>`_
Supported files: .rst, .po
"""
def check_missing_underscore_after_hyperlink(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for hyperlinks missing underscore after their closing backtick.
Bad: `Link text <https://example.com>`
Good: `Link text <https://example.com>`_
Supported files: .rst, .po
"""
def check_hyperlink_reference_missing_backtick(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search for missing backticks in front of hyperlink references.
Bad: Misc/NEWS <https://github.com/python/cpython/blob/v3.2.6/Misc/NEWS>`_
Good: `Misc/NEWS <https://github.com/python/cpython/blob/v3.2.6/Misc/NEWS>`_
Supported files: .rst, .po
"""def check_python_syntax(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Search invalid syntax in Python examples.
Compiles Python code and reports syntax errors.
Also checks for carriage returns in non-Windows environments.
Supported files: .py
RST-only: False (processes entire file content)
"""Checkers for common formatting problems across all supported file types.
def check_carriage_return(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for carriage returns (\\r) in lines.
Supported files: .py, .rst, .po
RST-only: False
"""
def check_horizontal_tab(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for horizontal tabs (\\t) in lines.
Supported files: .py, .rst, .po
RST-only: False
"""
def check_trailing_whitespace(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for trailing whitespaces at end of lines.
Supported files: .py, .rst, .po
RST-only: False
"""
def check_missing_final_newline(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check that the last line of the file ends with a newline.
Supported files: .py, .rst, .po
RST-only: False
"""def check_line_too_long(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for line length; this checker is not run by default.
Uses options.max_line_length for threshold.
Ignores wide tables, long interpreted text, directives, hyperlinks, and long literals.
Supported files: .rst, .po
Enabled: False (disabled by default)
RST-only: True
"""def check_bad_dedent(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for mis-alignment in indentation in code blocks.
Detects blocks that appear to be code blocks but have incorrect indentation.
Supported files: .rst, .po
RST-only: False (but processes RST structure)
"""
def check_dangling_hyphen(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for lines ending in a hyphen.
Supported files: .rst
RST-only: True
"""Checkers that are disabled by default but can be enabled when needed.
def check_leaked_markup(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check HTML files for leaked reST markup.
This only works if the HTML files have been built.
Supported files: .html
Enabled: False (disabled by default)
RST-only: False
"""
def check_triple_backticks(file: str, lines: list[str], options: CheckersOptions = None) -> Generator[tuple[int, str], None, None]:
"""
Check for triple backticks, like ```Point``` (but it's a valid syntax).
Bad: ```Point```
Good: ``Point``
Triple backticks are valid but uncommon in reStructuredText.
Supported files: .rst, .po
Enabled: False (disabled by default)
"""Each checker function has the following attributes set by the @checker decorator:
name: Checker name (derived from function name)suffixes: Tuple of supported file extensionsenabled: Boolean indicating if checker runs by defaultrst_only: Boolean indicating if checker only processes RST contentfrom sphinxlint.checkers import all_checkers
# List all checker names
for name in sorted(all_checkers.keys()):
checker = all_checkers[name]
print(f"{name}: {checker.__doc__.splitlines()[0] if checker.__doc__ else 'No description'}")
# Filter by file type
rst_checkers = [name for name, checker in all_checkers.items() if '.rst' in checker.suffixes]
print(f"RST checkers: {', '.join(sorted(rst_checkers))}")from sphinxlint.checkers import all_checkers
# Only whitespace checkers
whitespace_checkers = {
all_checkers['trailing-whitespace'],
all_checkers['horizontal-tab'],
all_checkers['carriage-return']
}
# Enable all including disabled ones
all_available = set(all_checkers.values())
# Role-related checkers only
role_checker_names = [name for name in all_checkers.keys() if 'role' in name]
role_checkers = {all_checkers[name] for name in role_checker_names}Install with Tessl CLI
npx tessl i tessl/pypi-sphinx-lint