From 6080409c638c041946e3f85af82b791d1b6bd795 Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Sun, 12 Jul 2026 22:52:08 +0300 Subject: [PATCH] Fix ci-bonsai-daily: classification operators honor obj argument Four classification operators (AddManualClassificationReference, RemoveClassificationReference, AddClassificationReference, AddClassificationReferenceFromBSDD) ignored their own obj StringProperty in the obj_type == "Object" branch and used context.selected_objects / context.active_object instead. But bim.assign_class runs first and clears/replaces the selection (it recreates the object for IfcElementType targets), so active_object is None by the time these operators run - which is why the BDD scenarios pass obj='IfcWallType/Cube' explicitly. The operators just never read it, so they crashed on context.active_object.name being None. Apply the same precedence AssignClass itself uses: explicit self.obj first, then selected objects, then a guarded active_object, else empty (which already no-ops via the `if products:` guard). Fixes the crash and makes the operators honor the passed argument. Verified in headless Blender: the 5 classification BDD scenarios (add/enable-editing/disable-editing/remove/edit classification reference) go from 5 failed to passing (6 passed incl. sibling). This change was made with the assistance of an AI tool. Co-Authored-By: Claude Fable 5 --- .../bim/module/classification/operator.py | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/classification/operator.py b/src/bonsai/bonsai/bim/module/classification/operator.py index 77b77ba541..9ede249614 100644 --- a/src/bonsai/bonsai/bim/module/classification/operator.py +++ b/src/bonsai/bonsai/bim/module/classification/operator.py @@ -77,10 +77,14 @@ class AddManualClassificationReference(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): if self.obj_type == "Object": - if context.selected_objects: + if self.obj: + objects = [self.obj] + elif context.selected_objects: objects = [o.name for o in context.selected_objects] - else: + elif context.active_object: objects = [context.active_object.name] + else: + objects = [] else: objects = [self.obj] props = tool.Classification.get_classification_reference_props() @@ -284,12 +288,15 @@ class RemoveClassificationReference(bpy.types.Operator, tool.Ifc.Operator): obj_type: bpy.props.StringProperty() def _execute(self, context): - obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object if self.obj_type == "Object": - if context.selected_objects: + if self.obj: + objects = [self.obj] + elif context.selected_objects: objects = [o.name for o in context.selected_objects] - else: + elif context.active_object: objects = [context.active_object.name] + else: + objects = [] else: objects = [self.obj] @@ -348,10 +355,14 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): if self.obj_type == "Object": - if context.selected_objects: + if self.obj: + objects = [self.obj] + elif context.selected_objects: objects = [o.name for o in context.selected_objects] - else: + elif context.active_object: objects = [context.active_object.name] + else: + objects = [] else: objects = [self.obj] props = tool.Classification.get_classification_props() @@ -389,10 +400,14 @@ class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): if self.obj_type == "Object": - if context.selected_objects: + if self.obj: + objects = [self.obj] + elif context.selected_objects: objects = [o.name for o in context.selected_objects] - else: + elif context.active_object: objects = [context.active_object.name] + else: + objects = [] else: objects = [self.obj] bprops = tool.Bsdd.get_bsdd_props()