From 3703c77aa9014aeff71ea455710cc627cd5c562c Mon Sep 17 00:00:00 2001 From: Dominik Holland Date: Thu, 27 Jan 2022 10:42:52 +0100 Subject: Improve error handling when parsing annotation files The System.lookup() function is now throwing an exception when the name couldn't be found, instead of just returning None. This exception is catched in the FileSystem object and printed on stderr. In strict mode, any annotation error results in exiting the generator. Fixes: #90 --- qface/generator.py | 17 +++++++++++++---- qface/idl/domain.py | 6 +++--- tests/in/broken_tuner_annotations.yaml | 3 +++ tests/in/invalid_tuner_annotations.yaml | 3 +++ tests/in/tuner_annotations.yaml | 3 +++ tests/test_tags.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 tests/in/broken_tuner_annotations.yaml create mode 100644 tests/in/invalid_tuner_annotations.yaml create mode 100644 tests/in/tuner_annotations.yaml diff --git a/qface/generator.py b/qface/generator.py index d84a04c..297c2ef 100644 --- a/qface/generator.py +++ b/qface/generator.py @@ -345,10 +345,15 @@ class FileSystem(object): return meta = FileSystem.load_yaml(document) click.secho('merge: {0}'.format(document.name), fg='blue') - for identifier, data in meta.items(): - symbol = system.lookup(identifier) - if symbol: - merge(symbol.tags, data) + try: + for identifier, data in meta.items(): + symbol = system.lookup(identifier) + if symbol: + merge(symbol.tags, data) + except Exception as e: + click.secho('Error parsing annotation {0}: {1}'.format(document, e), fg='red', err=True) + if FileSystem.strict: + sys.exit(-1) @staticmethod def parse(input, identifier: str = None, use_cache=False, clear_cache=True, pattern="*.qface", profile=EProfile.FULL): @@ -391,6 +396,8 @@ class FileSystem(object): if not document.exists(): if required: click.secho('yaml document does not exists: {0}'.format(document), fg='red', err=True) + if FileSystem.strict: + sys.exit(-1) return {} try: return yaml.load(document.text(), Loader=Loader) @@ -399,4 +406,6 @@ class FileSystem(object): if hasattr(exc, 'problem_mark'): error = '{0}:{1}'.format(error, exc.problem_mark.line+1) click.secho('{0}: error: {1}'.format(error, str(exc)), fg='red', err=True) + if FileSystem.strict: + sys.exit(-1) return {} diff --git a/qface/idl/domain.py b/qface/idl/domain.py index 7949e6c..fbd0175 100644 --- a/qface/idl/domain.py +++ b/qface/idl/domain.py @@ -55,10 +55,10 @@ class System(object): return self._moduleMap[name] # . (module_name, type_name, fragment_name) = self.split_typename(name) - if not module_name and type_name: - click.secho('not able to lookup symbol: {0}'.format(name), fg='red') - return None + if not module_name in self._moduleMap: + raise Exception('not able to lookup symbol: {0}'.format(name)) module = self._moduleMap[module_name] + # The module lookup calls this function again if the type_name doesn't exist return module.lookup(type_name, fragment_name) @staticmethod diff --git a/tests/in/broken_tuner_annotations.yaml b/tests/in/broken_tuner_annotations.yaml new file mode 100644 index 0000000..a05536a --- /dev/null +++ b/tests/in/broken_tuner_annotations.yaml @@ -0,0 +1,3 @@ +com.pelagicore.ivi.tuner.Tuner{ + extra: + extraA: true diff --git a/tests/in/invalid_tuner_annotations.yaml b/tests/in/invalid_tuner_annotations.yaml new file mode 100644 index 0000000..564aaf4 --- /dev/null +++ b/tests/in/invalid_tuner_annotations.yaml @@ -0,0 +1,3 @@ +com.pelagicore.ivi.tuner.Tunerrrrrrrr: + extra: + extraA: true diff --git a/tests/in/tuner_annotations.yaml b/tests/in/tuner_annotations.yaml new file mode 100644 index 0000000..bff1d8b --- /dev/null +++ b/tests/in/tuner_annotations.yaml @@ -0,0 +1,3 @@ +com.pelagicore.ivi.tuner.Tuner: + extra: + extraA: true diff --git a/tests/test_tags.py b/tests/test_tags.py index 82f2c90..0e70143 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -1,4 +1,6 @@ from qface.generator import FileSystem +from unittest.mock import patch +from io import StringIO import logging import logging.config from path import Path @@ -57,5 +59,31 @@ def test_flag(): assert interface.attribute('config', 'c') == 'C' # use value from IDL assert interface.tags['data'] == [1, 2, 3] # array annotatiom +def test_merge_annotation(): + system = loadTuner() + interface = system.lookup('com.pelagicore.ivi.tuner.Tuner') + assert interface + assert interface.attribute('config', 'private') is True + assert interface.attribute('extra', 'extraA') is None + FileSystem.merge_annotations(system, inputPath / 'tuner_annotations.yaml') + assert interface.attribute('extra', 'extraA') is True + +@patch('sys.stderr', new_callable=StringIO) +def test_merge_broken_annotation(mock_stderr): + system = loadTuner() + interface = system.lookup('com.pelagicore.ivi.tuner.Tuner') + assert interface + FileSystem.merge_annotations(system, inputPath / 'broken_tuner_annotations.yaml') + + assert interface.attribute('extra', 'extraA') is None + assert mock_stderr.getvalue().__contains__("tests/in/broken_tuner_annotations.yaml:2: error: mapping values are not allowed") +@patch('sys.stderr', new_callable=StringIO) +def test_merge_invalid_annotation(mock_stderr): + system = loadTuner() + interface = system.lookup('com.pelagicore.ivi.tuner.Tuner') + assert interface + FileSystem.merge_annotations(system, inputPath / 'invalid_tuner_annotations.yaml') + assert interface.attribute('extra', 'extraA') is None + assert mock_stderr.getvalue() == "Error parsing annotation tests/in/invalid_tuner_annotations.yaml: not able to lookup symbol: Tunerrrrrrrr\n" -- cgit v1.2.1