Skip to content

Commit ed144c8

Browse files
author
Jon Wayne Parrott
authored
Reformat docutils messages into more human-friendly output. (#92)
1 parent d0864f3 commit ed144c8

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

readme_renderer/integration/distutils.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,47 @@
1515

1616
import cgi
1717
import io
18+
import re
1819

1920
import distutils.log
2021
from distutils.command.check import check as _check
22+
import six
2123

2224
from ..rst import render
2325

2426

27+
# Regular expression used to capture and reformat doctuils warnings into
28+
# something that a human can understand. This is loosely borrowed from
29+
# Sphinx: https://github.com/sphinx-doc/sphinx/blob
30+
# /c35eb6fade7a3b4a6de4183d1dd4196f04a5edaf/sphinx/util/docutils.py#L199
31+
_REPORT_RE = re.compile(
32+
r'^<string>:(?P<line>(?:\d+)?): '
33+
r'\((?P<level>DEBUG|INFO|WARNING|ERROR|SEVERE)/(\d+)?\) '
34+
r'(?P<message>.*)', re.DOTALL | re.MULTILINE)
35+
36+
37+
@six.python_2_unicode_compatible
38+
class _WarningStream(object):
39+
def __init__(self):
40+
self.output = io.StringIO()
41+
42+
def write(self, text):
43+
matched = _REPORT_RE.search(text)
44+
45+
if not matched:
46+
self.output.write(text)
47+
return
48+
49+
self.output.write(
50+
u"line {line}: {level_text}: {message}\n".format(
51+
level_text=matched.group('level').capitalize(),
52+
line=matched.group('line'),
53+
message=matched.group('message').rstrip('\r\n')))
54+
55+
def __str__(self):
56+
return self.output.getvalue()
57+
58+
2559
class Check(_check):
2660
def check_restructuredtext(self):
2761
"""
@@ -45,18 +79,14 @@ def check_restructuredtext(self):
4579
"The project's long_description is either missing or empty.")
4680
return
4781

48-
stream = io.StringIO()
82+
stream = _WarningStream()
4983
markup = render(data, stream=stream)
5084

51-
for line in stream.getvalue().splitlines():
52-
if line.startswith("<string>"):
53-
line = line[8:]
54-
self.warn(line)
55-
5685
if markup is None:
5786
self.warn(
5887
"The project's long_description has invalid markup which will "
59-
"not be rendered on PyPI.")
88+
"not be rendered on PyPI. The following syntax errors were "
89+
"detected:\n%s" % stream)
6090
return
6191

6292
self.announce(

tests/test_integration_distutils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ def test_invalid_rst():
2929

3030
# Should warn once for the syntax error, and finally to warn that the
3131
# overall syntax is invalid
32-
checker.warn.call_count = 2
33-
message_one = checker.warn.call_args_list[0][0][0]
34-
assert 'start-string without end-string' in message_one
35-
message_two = checker.warn.call_args_list[1][0][0]
36-
assert 'invalid markup' in message_two
32+
checker.warn.assert_called_once_with(mock.ANY)
33+
message = checker.warn.call_args[0][0]
34+
assert 'invalid markup' in message
35+
assert 'line 1: Warning:' in message
36+
assert 'start-string without end-string' in message
3737

3838
# Should not have announced that it was valid.
3939
checker.announce.assert_not_called()

0 commit comments

Comments
 (0)