From 75d4e115f82238c78d311d0f2fc8a8ffdcad6052 Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Mon, 12 Aug 2024 15:33:33 +0200 Subject: [PATCH] fix(model): Strictly check RoleTagAccessor's classes Previously when retrieving objects using a RoleTagAccessor that has a non-empty `classes` argument, objects that didn't match the specified classes were simply filtered out and ignored. This caused two problems: 1. It made it more difficult to spot potential metamodel mismatches with upstream Capella. 2. The implementation (using `ElementList.filter`) decoupled the list from the model and therefore prevented modifying the model through it. This commit changes the implementation to strictly verify that the actual classes match those expected by the metamodel, and will raise an exception in case of any mismatch. Part of the fix to #446. --- capellambse/model/_descriptors.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/capellambse/model/_descriptors.py b/capellambse/model/_descriptors.py index e11d74c7f..25b8715d6 100644 --- a/capellambse/model/_descriptors.py +++ b/capellambse/model/_descriptors.py @@ -1787,7 +1787,14 @@ def __get__(self, obj, objtype=None): elts = list(obj._element.iterchildren(self.role_tag)) rv = self._make_list(obj, elts) if self.classes: - rv = rv.filter(lambda i: isinstance(i, self.classes)) + for i in rv: + if not isinstance(i, self.classes): + expected = ", ".join(i.__name__ for i in self.classes) + raise RuntimeError( + f"Unexpected element of type {type(i).__name__}" + f" in {self._qualname} on {obj._short_repr_()}," + f" expected one of: {expected}" + ) if self.alternate is not None: assert isinstance(rv, _obj.ElementList) assert not isinstance(rv, _obj.MixedElementList)