Fix failing product assignment test after 5a511ee

Moved code from `core`, added a warning so we could possibly narrow down #4014 in the future.
This commit is contained in:
Andrej730
2025-11-13 18:35:19 +05:00
parent b6f1119eaa
commit 339a0606c0
4 changed files with 37 additions and 12 deletions
+7 -10
View File
@@ -61,20 +61,17 @@ def edit_assigned_product(
element = ifc.get_entity(obj)
assert element
# Get ALL existing products, not just one
existing_products = []
if hasattr(element, "HasAssignments"):
for rel in element.HasAssignments:
if rel.is_a("IfcRelAssignsToProduct"):
existing_products.append(rel.RelatingProduct)
# Temporarily accomodate existing bug and check for multiple products.
existing_products = drawing.get_assigned_product_workaround(element)
if existing_products != [product]:
if product in existing_products:
assert product is not None
existing_products.remove(product)
# Only proceed if the assignment is different
if not (len(existing_products) == 1 and existing_products[0] == product):
# Unassign from ALL existing products
for existing_product in existing_products:
ifc.run("drawing.unassign_product", relating_product=existing_product, related_object=element)
# Assign to the new product
if product:
ifc.run("drawing.assign_product", relating_product=product, related_object=element)
+1
View File
@@ -343,6 +343,7 @@ class Drawing:
def get_annotation_context(cls, target_view, object_type=None): pass
def get_annotation_representation(cls, element_type): pass
def get_assigned_product(cls, element): pass
def get_assigned_product_workaround(cls, element): pass
def get_body_context(cls): pass
def get_default_drawing_path(cls, name): pass
def get_default_drawing_resource_path(cls, resource): pass
+27
View File
@@ -893,6 +893,33 @@ class Drawing(bonsai.core.tool.Drawing):
return axis
return product
@classmethod
def get_assigned_product_workaround(
cls, element: ifcopenshell.entity_instance
) -> list[ifcopenshell.entity_instance]:
"""Get all products assigned to the element.
A workaround allowing to unassign accumulated products until we properly resolve #4014.
In theory annotations should have more than one product assigned,
but there's still undefined bug causing that in some cases.
"""
assigned_products: list[ifcopenshell.entity_instance] = []
for rel in element.HasAssignments:
if not rel.is_a("IfcRelAssignsToProduct"):
continue
assigned_products.append(rel.RelatingProduct)
if len(assigned_products) > 1:
print(
f"WARNING. Detected multiple assigned products ({len(assigned_products)}) for annotation '{element}'."
"\nIf you can reproduce this, please report it to Bonsai developers "
"at https://github.com/IfcOpenShell/IfcOpenShell/issues/4014."
"\nAssigned products:\n" + "\n".join([str(p) for p in assigned_products])
)
return assigned_products
@classmethod
def import_annotations_in_group(cls, group: ifcopenshell.entity_instance) -> None:
elements = set(
+2 -2
View File
@@ -58,7 +58,7 @@ class TestDisableEditingAssignedProduct:
class TestEditAssignedProduct:
def test_text_annotation(self, ifc, drawing):
ifc.get_entity("obj").should_be_called().will_return("element")
drawing.get_assigned_product("element").should_be_called().will_return("existing_product")
drawing.get_assigned_product_workaround("element").should_be_called().will_return(["existing_product"])
ifc.run(
"drawing.unassign_product", relating_product="existing_product", related_object="element"
).should_be_called()
@@ -68,7 +68,7 @@ class TestEditAssignedProduct:
def test_non_text_annotation(self, ifc, drawing):
ifc.get_entity("obj").should_be_called().will_return("element")
drawing.get_assigned_product("element").should_be_called().will_return("existing_product")
drawing.get_assigned_product_workaround("element").should_be_called().will_return(["existing_product"])
ifc.run(
"drawing.unassign_product", relating_product="existing_product", related_object="element"
).should_be_called()