From 94c15213f661564d49a9385e0f6802c9faabb8dd Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 21 Mar 2026 20:09:47 +1100 Subject: [PATCH] Guard against emptying IfcShapeRepresentation Items remove_representation_item now returns early if removing the item would leave Items empty. edit_text_literals returns early on empty attributes. Co-Authored-By: Claude Opus 4.6 --- src/bonsai/bonsai/tool/drawing.py | 2 ++ src/bonsai/bonsai/tool/geometry.py | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index accaaad10d..86113b9c95 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -857,6 +857,8 @@ class Drawing(bonsai.core.tool.Drawing): @classmethod def edit_text_literals(cls, obj: bpy.types.Object, literal_attributes: dict) -> None: + if not literal_attributes: + return assert (element := tool.Ifc.get_entity(obj)) assert (rep := cls.get_annotation_representation(element)) to_remove = [i for i in rep.Items if i.is_a("IfcTextLiteral")] diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index e24152d642..0d690d0308 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -1407,8 +1407,6 @@ class Geometry(bonsai.core.tool.Geometry): :param representation_item: item to remove. :param element: item's element. Is used to unmark manual booleans. """ - # NOTE: we assume it's not the last representation item - # otherwise we probably would need to remove representation too # NOTE: a lot of shared code with `geometry.remove_representation` ifc_file = tool.Ifc.get() shape_aspects: list[ifcopenshell.entity_instance] = [] @@ -1467,7 +1465,10 @@ class Geometry(bonsai.core.tool.Geometry): cls.remove_representation_items_from_shape_aspect([representation_item], shape_aspect) if representation: - representation.Items = tuple(set(representation.Items) - {representation_item}) + new_items = tuple(set(representation.Items) - {representation_item}) + if not new_items: + return + representation.Items = new_items also_consider = list(consider_inverses) ifcopenshell.util.element.remove_deep2(ifc_file, representation_item, also_consider=also_consider)