Skip to content

Commit 59a270e

Browse files
samueljlieberAntoineVDV
authored andcommitted
[IMP] test/rst_style, Makefile: add optional review checkers
task-2801043 closes #5354 X-original-commit: 8eec0e7 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
1 parent 50ec641 commit 59a270e

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,13 @@ static: $(HTML_BUILD_DIR)/_static/style.css
8484
cp -r extensions/odoo_theme/static/* $(HTML_BUILD_DIR)/_static/
8585
cp -r static/* $(HTML_BUILD_DIR)/_static/
8686

87+
# Called by runbot for the ci/documentation_guideline check.
8788
test:
8889
@python tests/main.py $(SOURCE_DIR)/administration $(SOURCE_DIR)/applications $(SOURCE_DIR)/contributing $(SOURCE_DIR)/developer $(SOURCE_DIR)/services redirects
90+
91+
# Similar as `test`, but called only manually by content reviewers to trigger extra checks.
92+
review:
93+
@read -p "Enter content path: " path; read -p "Enter max line length (default: 100): " line_length; \
94+
if [ -z "$$path" ]; then echo "Error: Path cannot be empty"; exit 1; fi; \
95+
if [ -z "$$line_length" ]; then line_length=100; fi; \
96+
python tests/main.py -e line-too-long -e early-line-breaks --max-line-length=$$line_length $(SOURCE_DIR)/$$path

tests/checkers/rst_style.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
'^(' + '|'.join(rf'\{char}+' for char in FORBIDDEN_HEADING_CHARS) + ')\n$'
1717
)
1818
GIT_CONFLICT_MARKERS = ['<' * 7, '>' * 7]
19+
ALLOWED_EARLY_BREAK_RE = re.compile(r'^\s*(\.\. |:\S+:\s+)', re.IGNORECASE) # Contains markup.
1920

2021

2122
@sphinxlint.checker('.rst')
@@ -103,6 +104,48 @@ def check_heading_spacing(file, lines, options=None):
103104
yield heading_lno + 1, "the heading should be followed by a blank line"
104105

105106

107+
@sphinxlint.checker('.rst', enabled=False)
108+
def check_early_line_breaks(file, lines, options=None):
109+
""" Checks that no line breaks early, i.e., before using as much of the max length as possible.
110+
111+
Note: `make review` only
112+
"""
113+
114+
def is_valid_line(line_, forbidden_starting_chars_):
115+
""" Allowed to break early - handle tables and bullets """
116+
return not ALLOWED_EARLY_BREAK_RE.search(line_) \
117+
and not HEADING_DELIMITER_RE.search(line_) \
118+
and not line_.startswith('\n') \
119+
and not line_.lstrip().startswith(forbidden_starting_chars_) \
120+
and len(line_) <= options.max_line_length
121+
122+
def get_next_line_first_word(next_line_):
123+
""" Return the first word of the next line """
124+
if next_line_.startswith(' '):
125+
next_line_dict = {
126+
'*': lambda x: x.split('* ', 1)[0],
127+
'-': lambda x: x.split('- ', 1)[0],
128+
'#.': lambda x: x.split('#. ', 1)[0],
129+
'default': lambda x: x.split(' ', 1)[0]
130+
}
131+
return next_line_dict.get(next_line_.lstrip()[:2], next_line_dict["default"])(
132+
next_line_.lstrip()
133+
)
134+
else:
135+
return next_line_.split(' ', 1)[0]
136+
137+
for lno, line in enumerate(lines):
138+
if lno + 1 < len(lines):
139+
next_line = lines[lno + 1]
140+
if (is_valid_line(line, ('+', '|'))
141+
and is_valid_line(next_line, ('+', '|', '- ', '* ', '#. '))
142+
):
143+
current_line_remaining_space = options.max_line_length - len(line)
144+
next_line_first_word = get_next_line_first_word(next_line)
145+
if current_line_remaining_space > len(next_line_first_word):
146+
yield lno + 1, f"consider moving \"{next_line_first_word}\" to line {lno + 1}"
147+
148+
106149
@sphinxlint.checker('.rst', '.py', '.js', '.xml', '.css', '.sass', '.less', '.po', '.pot')
107150
def check_git_conflict_markers(file, lines, options=None):
108151
""" Check that there are no conflict markers. """

tests/main.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ def run_additional_checks(argv=None):
2323

2424

2525
"""
26-
The following checkers are selected.
27-
28-
Base checkers:
26+
The following checkers are selected for `make test`.
2927
- backtick-before-role: Search for roles preceded by a backtick.
3028
- bad-dedent: Check for mis-alignment in indentation in code blocks.
3129
- carriage-return: Check for carriage returns (\r) in lines.
@@ -49,12 +47,13 @@ def run_additional_checks(argv=None):
4947
- role-without-backticks: Search roles without backticks.
5048
- trailing-whitespace: Check for trailing whitespaces at end of lines.
5149
- unbalanced-inline-literals-delimiters: Search for unbalanced inline literals delimiters.
50+
---
51+
- all the checkers defined in checkers/* files.
5252
53-
Optional checkers:
54-
- line-too-long: Check for line length; this checker is not run by default.
53+
The following checkers are only selected for `make review`.
54+
- line-too-long: Check for line length.
55+
- early-line-break: Check for early line breaks.
5556
56-
Custom checkers:
57-
- all the checkers defined in checkers/* files
5857
"""
5958
if __name__ == '__main__':
6059
# Patch sphinxlint's global constants to include our custom directives and parse their content.

0 commit comments

Comments
 (0)