Skip to content

Commit

Permalink
Merge pull request #20 from svenevs/silence_rtd
Browse files Browse the repository at this point in the history
remove color printing and doxygen output on RTD
  • Loading branch information
svenevs committed Feb 16, 2018
2 parents 5e57391 + 1a27c0e commit 8b3ea01
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 28 deletions.
2 changes: 2 additions & 0 deletions docs/reference_exhale_configs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,8 @@ Utility Variables

.. autodata:: exhale.configs._app_src_dir

.. autodata:: exhale.configs._on_rtd

Secondary Sphinx Entry Point
----------------------------------------------------------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions exhale/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,13 @@
checks in different places.
'''

_on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
'''
**Do not modify**. Signals whether or not the build is taking place on ReadTheDocs. If
it is, then colorization of output is disabled, as well as the Doxygen output (where
applicable) is directed to ``/dev/null`` as capturing it can cause the ``subprocess``
buffers to overflow.
'''

########################################################################################
## #
Expand Down
64 changes: 38 additions & 26 deletions exhale/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import codecs
import tempfile
import textwrap
from subprocess import PIPE, Popen
from subprocess import PIPE, Popen, STDOUT

__name__ = "deploy"
__docformat__ = "reStructuredText"
Expand Down Expand Up @@ -88,26 +88,34 @@ def _generate_doxygen(doxygen_input):

doxyfile = doxygen_input == "Doxyfile"
try:
# TL;DR: strictly enforce that (verbose) doxygen output doesn't cause the
# `communicate` to hang due to buffer overflows.
#
# See excellent synopsis:
# https://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/
_, tmp_out_path = tempfile.mkstemp(prefix="exhale_launched_doxygen_buff")
_, tmp_err_path = tempfile.mkstemp(prefix="exhale_launched_doxygen_buff")
tmp_out = codecs.open(tmp_out_path, "r+", "utf-8") # read/write (read after communicate)
tmp_err = codecs.open(tmp_err_path, "r+", "utf-8")

# Setup the arguments to launch doxygen
if doxyfile:
args = ["doxygen"]
kwargs = {}
else:
args = ["doxygen", "-"]
kwargs = {"stdin": PIPE}
# Write to the tempfiles over PIPE to avoid buffer overflowing
kwargs["stdout"] = tmp_out
kwargs["stderr"] = tmp_err

if configs._on_rtd:
# On RTD, any capturing of Doxygen output can cause buffer overflows for
# even medium sized projects. So it is disregarded entirely to ensure the
# build will complete (otherwise, it silently fails after `cat conf.py`)
devnull_file = open(os.devnull, "w")
kwargs["stdout"] = devnull_file
kwargs["stderr"] = STDOUT
else:
# TL;DR: strictly enforce that (verbose) doxygen output doesn't cause the
# `communicate` to hang due to buffer overflows.
#
# See excellent synopsis:
# https://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/
_, tmp_out_path = tempfile.mkstemp(prefix="exhale_launched_doxygen_buff")
_, tmp_err_path = tempfile.mkstemp(prefix="exhale_launched_doxygen_buff")
tmp_out_file = codecs.open(tmp_out_path, "r+", "utf-8") # read/write (read after communicate)
tmp_err_file = codecs.open(tmp_err_path, "r+", "utf-8")
# Write to the tempfiles over PIPE to avoid buffer overflowing
kwargs["stdout"] = tmp_out_file
kwargs["stderr"] = tmp_err_file

# Note: overload of args / kwargs, Popen is expecting a list as the first
# parameter (aka no *args, just args)!
Expand All @@ -127,12 +135,12 @@ def _generate_doxygen(doxygen_input):
doxygen_proc.communicate(**comm_kwargs)

# Print out what was written to the tmpfiles by doxygen
if not configs.exhaleSilentDoxygen:
if not configs._on_rtd and not configs.exhaleSilentDoxygen:
# Doxygen output (some useful information, mostly just enumeration of the
# configurations you gave it {usefule for debugging...})
# configurations you gave it {useful for debugging...})
if os.path.getsize(tmp_out_path) > 0:
tmp_out.seek(0)
print(tmp_out.read())
tmp_out_file.seek(0)
print(tmp_out_file.read())
# Doxygen error (e.g. any warnings, or invalid input)
if os.path.getsize(tmp_err_path) > 0:
# Making them stick out, ideally users would reduce this output to 0 ;)
Expand All @@ -141,14 +149,18 @@ def _generate_doxygen(doxygen_input):
# Hack: empty string to utils.info will not give us anything, inserting
# a null character will xD
prefix = utils.info("\0", utils.AnsiColors.BOLD_YELLOW, sys.stderr)
tmp_err.seek(0)
sys.stderr.write(utils.prefix(prefix, tmp_err.read()))

# Delete the tmpfiles
tmp_out.close()
tmp_err.close()
os.remove(tmp_out_path)
os.remove(tmp_err_path)
tmp_err_file.seek(0)
sys.stderr.write(utils.prefix(prefix, tmp_err_file.read()))

# Close the file handles opened for communication with subprocess
if configs._on_rtd:
devnull_file.close()
else:
# Delete the tmpfiles
tmp_out_file.close()
tmp_err_file.close()
os.remove(tmp_out_path)
os.remove(tmp_err_path)

# Make sure we had a valid execution of doxygen
exit_code = doxygen_proc.returncode
Expand Down
4 changes: 2 additions & 2 deletions exhale/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ def _use_color(msg, ansi_fmt, output_stream):
:data:`~exhale.configs.alwaysColorize` and whether or not the
``output_stream`` is a TTY.
'''
if not configs.alwaysColorize and not output_stream.isatty():
if configs._on_rtd or (not configs.alwaysColorize and not output_stream.isatty()):
log = msg
else:
log = colorize(msg, ansi_fmt)
Expand Down Expand Up @@ -630,7 +630,7 @@ def verbose_log(msg, ansi_fmt=None):


def __fancy(text, language, fmt):
if __USE_PYGMENTS:
if not configs._on_rtd and __USE_PYGMENTS:
try:
lang_lex = lexers.find_lexer_class_by_name(language)
fmt = formatters.get_formatter_by_name(fmt)
Expand Down

0 comments on commit 8b3ea01

Please sign in to comment.