diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py index c3577a43e0..0ec81a87d7 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py @@ -65,13 +65,29 @@ class Usecase: representations = self.settings["product"].Representation.Representations or [] else: representations = [] - + + # remove object placements object_placement = self.settings["product"].ObjectPlacement - if object_placement and self.file.get_total_inverses(object_placement) == 1: - self.settings["product"].ObjectPlacement = None # remove the inverse for remove_deep2 to work - ifcopenshell.util.element.remove_deep2(self.file, object_placement) + if object_placement: + if self.file.get_total_inverses(object_placement) == 1: + self.settings["product"].ObjectPlacement = None # remove the inverse for remove_deep2 to work + ifcopenshell.util.element.remove_deep2(self.file, object_placement) + elif self.settings["product"].is_a("IfcTypeProduct"): representations = [rm.MappedRepresentation for rm in self.settings["product"].RepresentationMaps or []] + + # remove psets + psets = self.settings["product"].HasPropertySets or [] + for pset in psets: + if self.file.get_total_inverses(pset) != 1: + continue + ifcopenshell.api.run( + "pset.remove_pset", + self.file, + product=self.settings["product"], + pset=pset, + ) + for representation in representations: ifcopenshell.api.run( "geometry.unassign_representation", diff --git a/src/ifcopenshell-python/test/api/root/test_remove_product.py b/src/ifcopenshell-python/test/api/root/test_remove_product.py index d45b306e76..eb8a0d6631 100644 --- a/src/ifcopenshell-python/test/api/root/test_remove_product.py +++ b/src/ifcopenshell-python/test/api/root/test_remove_product.py @@ -54,6 +54,24 @@ class TestRemoveProduct(test.bootstrap.IFC4): ifcopenshell.api.run("root.remove_product", self.file, product=element1) assert len(self.file.by_type("IfcObjectPlacement")) == 0 + def test_removing_element_type_psets(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar") + ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": "Bar"}) + + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + element2.HasPropertySets = (pset,) + + # make sure it won't remove the pset if it's connected elsewhere + ifcopenshell.api.run("root.remove_product", self.file, product=element2) + assert len(self.file.by_type("IfcPropertySet")) == 1 + assert len(self.file.by_type("IfcPropertySingleValue")) == 1 + + # if it's the product is the only inverse for pset, it should remove the pset + ifcopenshell.api.run("root.remove_product", self.file, product=element) + assert len(self.file.by_type("IfcPropertySet")) == 0 + assert len(self.file.by_type("IfcPropertySingleValue")) == 0 + def test_removing_all_representations_of_an_element(self): ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") ifcopenshell.api.run("unit.assign_unit", self.file)