Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions sphinxlint/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def __call__(self, parser, namespace, values, option_string=None):
sort_fields.append(SortField[field_name.upper()])
except KeyError:
raise ValueError(
f"Unsupported sort field: {field_name}, supported values are {SortField.as_supported_options()}"
f"Unsupported sort field: {field_name}, "
f"supported values are {SortField.as_supported_options()}"
) from None
setattr(namespace, self.dest, sort_fields)

Expand Down Expand Up @@ -152,8 +153,8 @@ def _check_file(todo):
def sort_errors(results, sorted_by):
"""Flattens and potentially sorts errors based on user prefernces"""
if not sorted_by:
for results in results:
yield from results
for result in results:
yield from result
return
errors = list(error for errors in results for error in errors)
# sorting is stable in python, so we can sort in reverse order to get the
Expand Down
35 changes: 21 additions & 14 deletions sphinxlint/checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def check_missing_backtick_after_role(file, lines, options=None):
Good: :fct:`foo`
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
error = rst.ROLE_MISSING_CLOSING_BACKTICK_RE.search(paragraph)
if error:
Expand All @@ -71,7 +71,7 @@ def check_missing_space_after_literal(file, lines, options=None):
Good: ``items``\ s
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = clean_paragraph(paragraph)
for role in re.finditer("``.+?``(?!`).", paragraph, flags=re.DOTALL):
Expand All @@ -92,7 +92,7 @@ def check_unbalanced_inline_literals_delimiters(file, lines, options=None):
Good: ``hello`` world
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = clean_paragraph(paragraph)
for lone_double_backtick in re.finditer("(?<!`)``(?!`)", paragraph):
Expand All @@ -117,9 +117,7 @@ def check_default_role(file, lines, options=None):
if match:
before_match = line[: match.start()]
after_match = line[match.end() :]
stripped_line = line.strip()
if (stripped_line.startswith("|") and stripped_line.endswith("|") and
stripped_line.count("|") >= 4 and "|" in match.group(0)):
if rst.line_looks_like_a_table(line):
return # we don't handle tables yet.
if re.search(rst.ROLE_TAG + "$", before_match):
# It's not a default role: it starts with a tag.
Expand Down Expand Up @@ -253,7 +251,7 @@ def check_role_with_double_backticks(file, lines, options=None):
for paragraph_lno, paragraph in paragraphs(lines):
if "`" not in paragraph:
continue
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = escape2null(paragraph)
while True:
Expand All @@ -267,7 +265,10 @@ def check_role_with_double_backticks(file, lines, options=None):
before = paragraph[: inline_literal.start()]
if re.search(rst.ROLE_TAG + "$", before):
error_offset = paragraph[: inline_literal.start()].count("\n")
yield paragraph_lno + error_offset, "role use a single backtick, double backtick found."
yield (
paragraph_lno + error_offset,
"role use a single backtick, double backtick found.",
)
paragraph = (
paragraph[: inline_literal.start()] + paragraph[inline_literal.end() :]
)
Expand All @@ -281,16 +282,22 @@ def check_missing_space_before_role(file, lines, options=None):
Good: the :fct:`sum`, :issue:`123`, :c:func:`foo`
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = clean_paragraph(paragraph)
match = rst.ROLE_GLUED_WITH_WORD_RE.search(paragraph)
if match:
error_offset = paragraph[: match.start()].count("\n")
if looks_like_glued(match):
yield paragraph_lno + error_offset, f"missing space before role ({match.group(0)})."
yield (
paragraph_lno + error_offset,
f"missing space before role ({match.group(0)}).",
)
else:
yield paragraph_lno + error_offset, f"role missing opening tag colon ({match.group(0)})."
yield (
paragraph_lno + error_offset,
f"role missing opening tag colon ({match.group(0)}).",
)


@checker(".rst", ".po")
Expand All @@ -301,7 +308,7 @@ def check_missing_space_before_default_role(file, lines, options=None):
Good: the `sum`
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = clean_paragraph(paragraph)
paragraph = rst.INTERPRETED_TEXT_RE.sub("", paragraph)
Expand All @@ -324,7 +331,7 @@ def check_hyperlink_reference_missing_backtick(file, lines, options=None):
Good: `Misc/NEWS <https://github.com/python/cpython/blob/v3.2.6/Misc/NEWS>`_
"""
for paragraph_lno, paragraph in paragraphs(lines):
if paragraph.count("|") > 4:
if rst.paragraph_looks_like_a_table(paragraph):
return # we don't handle tables yet.
paragraph = clean_paragraph(paragraph)
paragraph = rst.INTERPRETED_TEXT_RE.sub("", paragraph)
Expand Down Expand Up @@ -459,4 +466,4 @@ def check_dangling_hyphen(file, lines, options):
for lno, line in enumerate(lines):
stripped_line = line.rstrip("\n")
if re.match(r".*[a-z]-$", stripped_line):
yield lno + 1, f"Line ends with dangling hyphen"
yield lno + 1, "Line ends with dangling hyphen"
16 changes: 16 additions & 0 deletions sphinxlint/rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,19 @@ def inline_markup_gen(start_string, end_string, extra_allowed_before=""):
)

ROLE_MISSING_CLOSING_BACKTICK_RE = re.compile(rf"({ROLE_HEAD}`[^`]+?)[^`]*$")


TABLE_HEAD_RE = re.compile(r"^\+[+=-]+\+")


def line_looks_like_a_table(line):
"""Return true if the given line looks part of an rst table."""
line = line.strip()
if TABLE_HEAD_RE.match(line):
return True
return line.startswith("|") and line.endswith("|")


def paragraph_looks_like_a_table(paragraph):
"""Return true if the given paragraph looks like an rst table."""
return all(line_looks_like_a_table(line) for line in paragraph.splitlines())
7 changes: 4 additions & 3 deletions sphinxlint/sphinxlint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from collections import Counter
from dataclasses import dataclass
from os.path import splitext
from pathlib import Path
from typing import Optional

from sphinxlint.utils import hide_non_rst_blocks, po2rst

Expand Down Expand Up @@ -49,13 +51,12 @@ def check_text(filename, text, checkers, options=None):
return errors


def check_file(filename, checkers, options: CheckersOptions = None):
def check_file(filename, checkers, options: Optional[CheckersOptions] = None):
ext = splitext(filename)[1]
if not any(ext in checker.suffixes for checker in checkers):
return Counter()
try:
with open(filename, encoding="utf-8") as f:
text = f.read()
text = Path(filename).read_text(encoding="UTF-8")
if filename.endswith(".po"):
text = po2rst(text)
except OSError as err:
Expand Down
7 changes: 0 additions & 7 deletions tests/fixtures/xfail/default-role-in-tables.rst

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_enable_disable.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from random import choice
import re
from random import choice

from sphinxlint.__main__ import main

Expand Down
1 change: 0 additions & 1 deletion tests/test_filter_out_literal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from sphinxlint.utils import hide_non_rst_blocks


LITERAL = r"""
Hide non-RST Blocks
===================
Expand Down
7 changes: 3 additions & 4 deletions tests/test_sphinxlint.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from pathlib import Path

from sphinxlint.utils import paragraphs

import pytest

from sphinxlint.__main__ import main
from sphinxlint.utils import paragraphs

FIXTURE_DIR = Path(__file__).resolve().parent / "fixtures"

Expand Down Expand Up @@ -69,8 +68,8 @@ def test_sphinxlint_shall_not_pass(file, expected_errors, capsys):

@pytest.mark.parametrize("file", [str(FIXTURE_DIR / "paragraphs.rst")])
def test_paragraphs(file):
with open(file) as f:
lines = f.readlines()
with open(file, encoding="UTF-8") as ifile:
lines = ifile.readlines()
actual = paragraphs(lines)
for lno, para in actual:
firstpline = para.splitlines(keepends=True)[0]
Expand Down
3 changes: 1 addition & 2 deletions tests/test_xpass_friends.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
This is useful to avoid a sphinx-lint release to break many CIs.
"""

from pathlib import Path
import shlex
from pathlib import Path

import pytest

from sphinxlint.__main__ import main


FIXTURE_DIR = Path(__file__).resolve().parent / "fixtures"


Expand Down
26 changes: 26 additions & 0 deletions tox.ini
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, if tox is added, shall also be used in CI so we keep them aligned?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #100.

There's some non-tox things added in this PR. If they're still needed, should this PR be rebased. or this closed and those bits split out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split make sense to me...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, how about trying tox-gh see #112

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[tox]
envlist = py3{8,9,10,11,12}, mypy, black, pylint
isolated_build = True
skip_missing_interpreters = True

[testenv]
deps = pytest
commands = pytest {posargs}

[testenv:black]
deps = black
skip_install = True
commands = black --check --diff .

[testenv:mypy]
deps =
mypy
types-polib
skip_install = True
commands = mypy --exclude fixtures --ignore-missing-imports sphinxlint/ tests/

[testenv:pylint]
deps =
pylint
pytest
commands = pylint --ignore fixtures sphinxlint/ tests/ --disable missing-function-docstring,missing-module-docstring,missing-class-docstring,too-few-public-methods,too-many-return-statements --good-names=po