Fixed issue reassigning class to type class with userdefined type #4018

When PredefinedType is not found in the related enum reassign_class is considering it USERDEFINED and trying to set .ObjectType. The problem was it was doing for type classes also, when it should have set .ElementType instead.

Why it crashed BlenderBIM - in IfcClassData.data["has_entity"] we store currently active IFC entity which is recreated during `ifcopenshell.util.schema.reassign_class` making old entity invalid. Since `root.reassign_class` was failing in the process, related BBIM operator was failing too, IfcClassData wasn't updated and removed entity was accessed from UI leading to crash.
This commit is contained in:
Andrej730
2023-11-21 12:34:53 +05:00
parent 0d757027e3
commit 6ee4edd0a0
2 changed files with 20 additions and 4 deletions
@@ -73,13 +73,21 @@ class Usecase:
element = ifcopenshell.util.schema.reassign_class(
self.file, self.settings["product"], self.settings["ifc_class"]
)
is_type = element.is_a("IfcTypeProduct")
if self.settings["predefined_type"] and hasattr(element, "PredefinedType"):
try:
element.PredefinedType = self.settings["predefined_type"]
except:
# PredefinedType wasn't in the respective enum, assume it's actually USERDEFINED
# and set .ElementType / .ObjectType to the provided predefined type
element.PredefinedType = "USERDEFINED"
element.ObjectType = self.settings["predefined_type"]
if element.is_a("IfcTypeProduct"):
if is_type:
element.ElementType = self.settings["predefined_type"]
else:
element.ObjectType = self.settings["predefined_type"]
# reassign classes for occurences connected to the type
if is_type:
for occurrence in ifcopenshell.util.element.get_types(element) or []:
ifc_class = ifcopenshell.util.type.get_applicable_entities(self.settings["ifc_class"])[0]
ifcopenshell.api.run(
@@ -87,6 +95,6 @@ class Usecase:
self.file,
product=occurrence,
ifc_class=ifc_class,
predefined_type= self.settings["predefined_type"]
predefined_type=self.settings["predefined_type"],
)
return element
@@ -35,10 +35,18 @@ class TestReassignClass(test.bootstrap.IFC4):
)
assert new.PredefinedType == "FLOOR"
def test_falling_back_to_userdefined_if_the_predefined_type_cannot_be_reassigned(self):
def test_falling_back_to_userdefined_if_the_predefined_type_cannot_be_reassigned_for_occurrence_class(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
new = ifcopenshell.api.run(
"root.reassign_class", self.file, product=element, ifc_class="IfcSlab", predefined_type="FOO"
)
assert new.PredefinedType == "USERDEFINED"
assert new.ObjectType == "FOO"
def test_falling_back_to_userdefined_if_the_predefined_type_cannot_be_reassigned_for_type_class(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
new = ifcopenshell.api.run(
"root.reassign_class", self.file, product=element, ifc_class="IfcSlabType", predefined_type="FOO"
)
assert new.PredefinedType == "USERDEFINED"
assert new.ElementType == "FOO"