From 51aec202742f8c0be8ac3a3e365f17f5d18ff979 Mon Sep 17 00:00:00 2001 From: Allison Chilton Date: Sat, 10 Apr 2021 11:58:44 -0600 Subject: [PATCH] Add standard error to exception message The rationale is that when castxml has an error it raises a RuntimeError to the user with the message. However, the message only contains the stdout from castxml - this makes the RuntimeError contain no information about what actually went wrong. This change allows the user to add error handling to their applications based on what went wrong with castxml (such as changing their include directories, etc) --- src/pygccxml/parser/source_reader.py | 31 +++++++++++++++------------- tests/test_source_reader.py | 13 ++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/pygccxml/parser/source_reader.py b/src/pygccxml/parser/source_reader.py index d864554b..ddd679ca 100644 --- a/src/pygccxml/parser/source_reader.py +++ b/src/pygccxml/parser/source_reader.py @@ -235,7 +235,8 @@ def create_xml_file(self, source_file, destination=None): process = subprocess.Popen( args=command_line, shell=True, - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) try: results = [] @@ -246,9 +247,12 @@ def create_xml_file(self, source_file, destination=None): for line in process.stdout.readlines(): if line.strip(): results.append(line.rstrip()) + for line in process.stderr.readlines(): + if line.strip(): + results.append(line.rstrip()) exit_status = process.returncode - msg = os.linesep.join([str(s) for s in results]) + msg = os.linesep.join([str(s.decode()) for s in results]) if self.__config.ignore_gccxml_output: if not os.path.isfile(xml_file): raise RuntimeError( @@ -257,18 +261,17 @@ def create_xml_file(self, source_file, destination=None): ": %s status:%s" % (msg, exit_status)) else: - if msg or exit_status or not \ - os.path.isfile(xml_file): - if not os.path.isfile(xml_file): - raise RuntimeError( - "Error occurred while running " + - self.__config.xml_generator.upper() + - " xml file does not exist") - else: - raise RuntimeError( - "Error occurred while running " + - self.__config.xml_generator.upper() + - ": %s status:%s" % (msg, exit_status)) + if msg or exit_status: + raise RuntimeError( + "Error occurred while running " + + self.__config.xml_generator.upper() + + ": %s status:%s" % (msg, exit_status)) + if not os.path.isfile(xml_file): + raise RuntimeError( + "Error occurred while running " + + self.__config.xml_generator.upper() + + " xml file does not exist") + except Exception: utils.remove_file_no_raise(xml_file, self.__config) raise diff --git a/tests/test_source_reader.py b/tests/test_source_reader.py index 20e403a6..766b912a 100644 --- a/tests/test_source_reader.py +++ b/tests/test_source_reader.py @@ -4,6 +4,7 @@ # See http://www.boost.org/LICENSE_1_0.txt import platform +import os import pytest @@ -35,3 +36,15 @@ def test_compound_argument_type(global_ns): do_smth = global_ns.calldefs('do_smth') assert do_smth is not None do_smth.function_type() + + +def test_stderr_present_and_readable(): + with open(os.path.join('tests', 'data', TEST_FILES[0]), 'r') as f: + source_str = f.read() + + err_str = "add some stuff that should not compile" + source_str += err_str + config = autoconfig.cxx_parsers_cfg.config.clone() + with pytest.raises(RuntimeError) as e_context: + parser.parse_string(source_str, config) + assert err_str in str(e_context)