Skip to content

Commit 8eb63da

Browse files
committed
feat: emit empty warning only if no warnings exist
This is a bit more gymnastics than I think is warranted, but wanted to play out the example. Needing to inspect the stream proved more complex than originally expected, as each version confroms to a slightly different interface. - Updated the outpout string to be clearer - Added test for empty RST file Signed-off-by: Mike Fiedler <[email protected]>
1 parent 0889c59 commit 8eb63da

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

readme_renderer/rst.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from __future__ import absolute_import, division, print_function
1515

1616
import io
17-
from typing import Any, Dict, IO, Optional, Union
17+
from typing import Any, Dict, Optional, TextIO, Union, TYPE_CHECKING
1818

1919
from docutils.core import publish_parts
2020
from docutils.nodes import colspec, image
@@ -23,6 +23,10 @@
2323

2424
from .clean import clean
2525

26+
if TYPE_CHECKING:
27+
# Prevent a circular import
28+
from .integration.distutils import _WarningStream
29+
2630

2731
class ReadMeHTMLTranslator(HTMLTranslator): # type: ignore[misc] # docutils is incomplete, returns `Any` python/typeshed#7256 # noqa E501
2832

@@ -105,7 +109,7 @@ def emptytag(
105109

106110
def render(
107111
raw: str,
108-
stream: Optional[IO[str]] = None,
112+
stream: Optional[Union[io.StringIO, TextIO, "_WarningStream"]] = None,
109113
**kwargs: Any
110114
) -> Optional[str]:
111115
if stream is None:
@@ -129,5 +133,17 @@ def render(
129133
if rendered:
130134
return clean(rendered)
131135
else:
132-
stream.write("no output rendered")
136+
# If the warnings stream is empty, docutils had none, so add ours.
137+
138+
# We have to currently handle the legacy disutils integration check
139+
# command, as it implements its own warnings stream structure.
140+
# Once that code is removed, we can remove this conditional.
141+
if hasattr(stream, "output"):
142+
if not stream.output.getvalue(): # type: ignore[union-attr]
143+
stream.write("No content rendered from RST source.")
144+
elif isinstance(stream, io.StringIO) and not stream.getvalue():
145+
stream.write("No content rendered from RST source.")
146+
elif isinstance(stream, TextIO) and not stream.readlines():
147+
# This is `sys.stderr` from using readme_renderer CLI
148+
stream.write("No content rendered from RST source.")
133149
return None

tests/test_rst.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,31 @@ def test_rst_raw():
5555
assert '"raw" directive disabled' in warnings.getvalue()
5656

5757

58+
def test_rst_empty_file():
59+
warnings = io.StringIO()
60+
assert render("", stream=warnings) is None
61+
62+
assert "No content rendered from RST source." in warnings.getvalue()
63+
64+
5865
def test_rst_header_only():
5966
warnings = io.StringIO()
6067
assert render("""
6168
Header
6269
======
6370
""", stream=warnings) is None
6471

65-
assert "no output rendered" in warnings.getvalue()
72+
assert "No content rendered from RST source." in warnings.getvalue()
73+
74+
75+
def test_header_and_malformed_emits_docutils_warning_only():
76+
warnings = io.StringIO()
77+
assert render("""
78+
Header
79+
======
80+
81+
======
82+
""", stream=warnings) is None
83+
84+
assert len(warnings.getvalue().splitlines()) == 1
85+
assert "No content rendered from RST source." not in warnings.getvalue()

0 commit comments

Comments
 (0)