diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-10-27 17:15:20 +0100 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2017-10-27 17:50:20 +0100 |
commit | 0dac630fe6a852016d4b79e8bee6af4b70e7e0f7 (patch) | |
tree | 85bf5c7943ef781038a682a4661443e28a4de89d | |
parent | dcf0d7279c3d2a0fa15560eef34eca4babb92437 (diff) | |
download | buildstream-sam/compose-list-exception.tar.gz |
Catch attempts to compose a listsam/compose-list-exception
Attempting to compose a list property would result in an unhandled
exception:
AttributeError: 'CommentedSeq' object has no attribute 'get'
We now at least detect the situation and produce an exception that
the frontend will report neatly:
Error loading pipeline: element.bst [line 11 column 4]: Only values of type 'dict' can be composed.
I was getting this error from an attempt to conditionally extend the
sources list:
sources:
(?):
arch == "x86_64":
- url: http://example.com/x86_64
The correct way to do this is to move the conditional into the parent
dict, e.g.:
(?):
arch == "x86_64":
sources:
- url: https://example.com/x86_64
It would be nice if the error message could hint at how the user can do
what they want, but it doesn't seem possible in this case.
-rw-r--r-- | buildstream/_yaml.py | 10 | ||||
-rw-r--r-- | tests/format/list-directive-type-error/element.bst | 6 | ||||
-rw-r--r-- | tests/format/list-directive-type-error/project.conf | 7 | ||||
-rw-r--r-- | tests/format/listdirectiveerrors.py | 15 |
4 files changed, 35 insertions, 3 deletions
diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py index bba59c73c..8aa2ec714 100644 --- a/buildstream/_yaml.py +++ b/buildstream/_yaml.py @@ -743,13 +743,17 @@ def composite_dict(target, source, path=None): # Like composite_dict(), but raises an all purpose LoadError for convenience # def composite(target, source): - provenance = node_get_provenance(source) + if not hasattr(source, 'get'): + raise LoadError(LoadErrorReason.ILLEGAL_COMPOSITE, + "Only values of type 'dict' can be composed.") + + source_provenance = node_get_provenance(source) try: composite_dict(target, source) except CompositeTypeError as e: error_prefix = "" - if provenance: - error_prefix = "[%s]: " % str(provenance) + if source_provenance: + error_prefix = "[%s]: " % str(source_provenance) raise LoadError(LoadErrorReason.ILLEGAL_COMPOSITE, "%sExpected '%s' type for configuration '%s', instead received '%s'" % (error_prefix, diff --git a/tests/format/list-directive-type-error/element.bst b/tests/format/list-directive-type-error/element.bst new file mode 100644 index 000000000..4ac7d95bb --- /dev/null +++ b/tests/format/list-directive-type-error/element.bst @@ -0,0 +1,6 @@ +kind: autotools + +sources: + (?): + - arch == "x86_64": + - url: https://example.com/x86_64 diff --git a/tests/format/list-directive-type-error/project.conf b/tests/format/list-directive-type-error/project.conf new file mode 100644 index 000000000..dde56d7b8 --- /dev/null +++ b/tests/format/list-directive-type-error/project.conf @@ -0,0 +1,7 @@ +name: test + +options: + arch: + type: arch + description: Example architecture option + values: [ x86_32, x86_64 ] diff --git a/tests/format/listdirectiveerrors.py b/tests/format/listdirectiveerrors.py index 001b8a49d..9f2cfaaca 100644 --- a/tests/format/listdirectiveerrors.py +++ b/tests/format/listdirectiveerrors.py @@ -39,3 +39,18 @@ def test_element_error(cli, datafiles, target): assert result.exception assert isinstance(result.exception, LoadError) assert result.exception.reason == LoadErrorReason.TRAILING_LIST_DIRECTIVE + + +@pytest.mark.datafiles(DATA_DIR) +def test_project_error(cli, datafiles): + project = os.path.join(datafiles.dirname, datafiles.basename, 'list-directive-type-error') + result = cli.run(project=project, silent=True, args=[ + 'show', + '--deps', 'none', + '--format', '%{vars}', + 'element.bst']) + + assert result.exit_code != 0 + assert result.exception + assert isinstance(result.exception, LoadError) + assert result.exception.reason == LoadErrorReason.ILLEGAL_COMPOSITE |