From 4d00c5115abbc4ed0b460dc1b304f30faafa0481 Mon Sep 17 00:00:00 2001 From: huyenngn Date: Wed, 27 Nov 2024 10:42:41 +0100 Subject: [PATCH] feat: Add support for python lambda filter --- .../collectors/custom.py | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/capellambse_context_diagrams/collectors/custom.py b/capellambse_context_diagrams/collectors/custom.py index 7787445..af2c852 100644 --- a/capellambse_context_diagrams/collectors/custom.py +++ b/capellambse_context_diagrams/collectors/custom.py @@ -116,9 +116,41 @@ def _fix_box_heights(self) -> None: box = self.boxes[uuid] box.height = max([box.height] + list(min_heights.values())) + def _safely_eval_filter(self, obj: m.ModelElement, filter: str) -> bool: + if not filter.startswith("lambda"): + raise ValueError(f"Filter '{filter}' is not a lambda expression.") + + import capellambse + + allowed_builtins = { + "True": True, + "False": False, + "isinstance": isinstance, + "len": len, + "sum": sum, + "min": min, + "max": max, + "abs": abs, + "round": round, + "capellambse": capellambse, + } + try: + result = eval(filter, {"__builtins__": allowed_builtins})(obj) + except Exception as e: + raise ValueError( + f"Filter '{filter}' raised an exception: {e}" + ) from e + if not isinstance(result, bool): + raise ValueError( + f"Filter '{filter}' did not return a boolean value." + ) + return result + def _matches_filters( - self, obj: m.ModelElement, filters: dict[str, t.Any] + self, obj: m.ModelElement, filters: dict[str, t.Any] | str ) -> bool: + if isinstance(filters, str): + return self._safely_eval_filter(obj, filters) for key, value in filters.items(): if getattr(obj, key) != value: return False