Merge "Allow checks to provide a extension matcher"
This commit is contained in:
commit
392d4c9eaf
|
@ -75,6 +75,7 @@ class CheckCarriageReturn(LineCheck):
|
|||
|
||||
class CheckValidity(ContentCheck):
|
||||
REPORTS = frozenset(["D000"])
|
||||
EXT_MATCHER = re.compile(r"(.*)[.]rst", re.I)
|
||||
|
||||
# Only used when running in sphinx mode.
|
||||
SPHINX_IGNORES_REGEX = [
|
||||
|
@ -107,6 +108,11 @@ class CheckValidity(ContentCheck):
|
|||
class CheckMaxLineLength(ContentCheck):
|
||||
REPORTS = frozenset(["D001"])
|
||||
|
||||
def __init__(self, cfg):
|
||||
super(CheckMaxLineLength, self).__init__(cfg)
|
||||
self._max_line_length = self._cfg['max_line_length']
|
||||
self._allow_long_titles = self._cfg['allow_long_titles']
|
||||
|
||||
def _extract_node_lines(self, doc):
|
||||
|
||||
def extract_lines(node, start_line):
|
||||
|
@ -185,10 +191,14 @@ class CheckMaxLineLength(ContentCheck):
|
|||
directives.append((i, find_directive_end(i, lines)))
|
||||
return directives
|
||||
|
||||
def report_iter(self, parsed_file):
|
||||
doc = parsed_file.document
|
||||
lines = list(parsed_file.lines_iter())
|
||||
def _txt_checker(self, parsed_file):
|
||||
for i, line in enumerate(parsed_file.lines_iter()):
|
||||
if len(line) > self._max_line_length:
|
||||
yield (i + 1, 'D001', 'Line too long')
|
||||
|
||||
def _rst_checker(self, parsed_file):
|
||||
lines = list(parsed_file.lines_iter())
|
||||
doc = parsed_file.document
|
||||
nodes_lines, first_line = self._extract_node_lines(doc)
|
||||
directives = self._extract_directives(lines)
|
||||
|
||||
|
@ -225,10 +235,8 @@ class CheckMaxLineLength(ContentCheck):
|
|||
docutils_nodes.subtitle,
|
||||
docutils_nodes.section,
|
||||
)
|
||||
max_line_length = self._cfg['max_line_length']
|
||||
allow_long_titles = self._cfg['allow_long_titles']
|
||||
for i, line in enumerate(lines):
|
||||
if len(line) > max_line_length:
|
||||
if len(line) > self._max_line_length:
|
||||
in_directive = False
|
||||
for (start, end) in directives:
|
||||
if i >= start and i <= end:
|
||||
|
@ -245,6 +253,14 @@ class CheckMaxLineLength(ContentCheck):
|
|||
nodes = find_containing_nodes(i + 1)
|
||||
if any_types(nodes, skip_types):
|
||||
continue
|
||||
if allow_long_titles and any_types(nodes, title_types):
|
||||
if self._allow_long_titles and any_types(nodes, title_types):
|
||||
continue
|
||||
yield (i + 1, 'D001', 'Line too long')
|
||||
|
||||
def report_iter(self, parsed_file):
|
||||
if parsed_file.extension.lower() != '.rst':
|
||||
checker_func = self._txt_checker
|
||||
else:
|
||||
checker_func = self._rst_checker
|
||||
for issue in checker_func(parsed_file):
|
||||
yield issue
|
||||
|
|
10
doc8/main.py
10
doc8/main.py
|
@ -231,6 +231,16 @@ def main():
|
|||
check_name = ".".join([c.__class__.__module__,
|
||||
c.__class__.__name__])
|
||||
error_counts.setdefault(check_name, 0)
|
||||
try:
|
||||
extension_matcher = c.EXT_MATCHER
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if not extension_matcher.match(f.extension):
|
||||
print(" Skipping check '%s' since it does not understand"
|
||||
" parsing a file with extension '%s'"
|
||||
% (check_name, f.extension))
|
||||
continue
|
||||
try:
|
||||
reports = set(c.REPORTS)
|
||||
except AttributeError:
|
||||
|
|
|
@ -35,6 +35,7 @@ class ParsedFile(object):
|
|||
self._encoding = encoding
|
||||
self._doc = None
|
||||
self._errors = None
|
||||
self._extension = os.path.splitext(filename)[1]
|
||||
|
||||
@property
|
||||
def errors(self):
|
||||
|
@ -78,6 +79,10 @@ class ParsedFile(object):
|
|||
line = line[0:-1]
|
||||
yield line
|
||||
|
||||
@property
|
||||
def extension(self):
|
||||
return self._extension
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return self._filename
|
||||
|
|
|
@ -73,20 +73,21 @@ test
|
|||
content += "\n\n"
|
||||
content += ("a" * 60) + " " + ("b" * 60)
|
||||
content += "\n"
|
||||
conf = {
|
||||
'max_line_length': 79,
|
||||
'allow_long_titles': True,
|
||||
}
|
||||
for ext in ['.rst', '.txt']:
|
||||
with tempfile.NamedTemporaryFile(suffix=ext) as fh:
|
||||
fh.write(content)
|
||||
fh.flush()
|
||||
|
||||
with tempfile.NamedTemporaryFile() as fh:
|
||||
fh.write(content)
|
||||
fh.flush()
|
||||
parsed_file = parser.ParsedFile(fh.name)
|
||||
conf = {
|
||||
'max_line_length': 79,
|
||||
'allow_long_titles': True,
|
||||
}
|
||||
check = checks.CheckMaxLineLength(conf)
|
||||
errors = list(check.report_iter(parsed_file))
|
||||
self.assertEqual(1, len(errors))
|
||||
(line, code, msg) = errors[0]
|
||||
self.assertIn(code, check.REPORTS)
|
||||
parsed_file = parser.ParsedFile(fh.name)
|
||||
check = checks.CheckMaxLineLength(conf)
|
||||
errors = list(check.report_iter(parsed_file))
|
||||
self.assertEqual(1, len(errors))
|
||||
(line, code, msg) = errors[0]
|
||||
self.assertIn(code, check.REPORTS)
|
||||
|
||||
def test_unsplittable_length(self):
|
||||
content = """
|
||||
|
@ -102,15 +103,20 @@ test
|
|||
content += "\n\n"
|
||||
content += "a" * 100
|
||||
content += "\n"
|
||||
conf = {
|
||||
'max_line_length': 79,
|
||||
'allow_long_titles': True,
|
||||
}
|
||||
# This number is different since rst parsing is aware that titles
|
||||
# are allowed to be over-length, while txt parsing is not aware of
|
||||
# this fact (since it has no concept of title sections).
|
||||
extensions = [(0, '.rst'), (1, '.txt')]
|
||||
for expected_errors, ext in extensions:
|
||||
with tempfile.NamedTemporaryFile(suffix=ext) as fh:
|
||||
fh.write(content)
|
||||
fh.flush()
|
||||
|
||||
with tempfile.NamedTemporaryFile() as fh:
|
||||
fh.write(content)
|
||||
fh.flush()
|
||||
parsed_file = parser.ParsedFile(fh.name)
|
||||
conf = {
|
||||
'max_line_length': 79,
|
||||
'allow_long_titles': True,
|
||||
}
|
||||
check = checks.CheckMaxLineLength(conf)
|
||||
errors = list(check.report_iter(parsed_file))
|
||||
self.assertEqual(0, len(errors))
|
||||
parsed_file = parser.ParsedFile(fh.name)
|
||||
check = checks.CheckMaxLineLength(conf)
|
||||
errors = list(check.report_iter(parsed_file))
|
||||
self.assertEqual(expected_errors, len(errors))
|
||||
|
|
Loading…
Reference in New Issue