From 6e932ec2fb97a1b6cdc549e4b09be63f82167928 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 28 Nov 2023 10:45:49 +1100 Subject: [PATCH] Fix #3974. Bug where orphaned histories would be left in API remove operations. --- .../api/aggregate/assign_object.py | 3 ++ .../api/aggregate/unassign_object.py | 7 ++- .../classification/remove_classification.py | 6 +++ .../api/classification/remove_reference.py | 6 +++ .../api/constraint/remove_constraint.py | 6 +++ .../api/constraint/remove_metric.py | 3 ++ .../api/constraint/unassign_constraint.py | 6 +++ .../api/control/unassign_control.py | 7 ++- .../ifcopenshell/api/cost/remove_cost_item.py | 11 ++++ .../api/cost/remove_cost_schedule.py | 5 ++ .../api/document/remove_information.py | 1 + .../api/document/remove_reference.py | 6 +++ .../api/document/unassign_document.py | 4 ++ .../api/geometry/connect_element.py | 4 ++ .../ifcopenshell/api/geometry/connect_path.py | 4 ++ .../api/geometry/disconnect_element.py | 6 +++ .../api/geometry/disconnect_path.py | 4 ++ .../ifcopenshell/api/group/unassign_group.py | 4 ++ .../api/library/remove_library.py | 6 +++ .../api/library/remove_reference.py | 6 +++ .../api/library/unassign_reference.py | 6 +++ .../ifcopenshell/api/nest/assign_object.py | 4 ++ .../ifcopenshell/api/nest/change_nest.py | 12 ++++- .../ifcopenshell/api/nest/unassign_object.py | 17 ++++--- .../ifcopenshell/api/owner/unassign_actor.py | 7 ++- .../api/resource/remove_resource.py | 14 +++++ .../api/resource/unassign_resource.py | 8 ++- .../api/sequence/assign_lag_time.py | 17 ++----- .../ifcopenshell/api/sequence/remove_task.py | 51 +++++++++++-------- .../api/sequence/remove_work_calendar.py | 12 +++-- .../api/sequence/remove_work_plan.py | 4 ++ .../api/sequence/remove_work_schedule.py | 17 ++++--- .../api/sequence/unassign_process.py | 16 +++--- .../api/sequence/unassign_product.py | 16 +++--- .../sequence/unassign_recurrence_pattern.py | 4 +- .../api/sequence/unassign_sequence.py | 10 ++-- .../api/spatial/assign_container.py | 4 ++ .../api/spatial/dereference_structure.py | 4 ++ .../api/spatial/remove_container.py | 4 ++ .../api/spatial/unassign_container.py | 4 ++ .../remove_structural_analysis_model.py | 9 ++++ .../remove_structural_connection_condition.py | 7 ++- .../structural/remove_structural_load_case.py | 7 +++ .../remove_structural_load_group.py | 8 +++ .../unassign_structural_analysis_model.py | 4 ++ .../api/style/remove_surface_style.py | 1 + .../ifcopenshell/api/void/add_filling.py | 12 +++-- .../ifcopenshell/api/void/add_opening.py | 4 ++ .../ifcopenshell/api/void/remove_filling.py | 6 +++ .../ifcopenshell/api/void/remove_opening.py | 6 +++ 50 files changed, 314 insertions(+), 86 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py b/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py index f8a1c3c261..751307fc06 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py @@ -109,7 +109,10 @@ class Usecase: decomposes.RelatedObjects = related_objects ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": decomposes}) else: + history = decomposes.OwnerHistory self.file.remove(decomposes) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) if is_decomposed_by: related_objects = set(is_decomposed_by.RelatedObjects) diff --git a/src/ifcopenshell-python/ifcopenshell/api/aggregate/unassign_object.py b/src/ifcopenshell-python/ifcopenshell/api/aggregate/unassign_object.py index 6b991051f1..b4c4c42a79 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/aggregate/unassign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/aggregate/unassign_object.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -65,7 +66,11 @@ class Usecase: if not rel.is_a("IfcRelAggregates"): continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["product"]) rel.RelatedObjects = related_objects diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py index 0bd10eddd1..2cf46cb091 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, classification=None): @@ -48,7 +51,10 @@ class Usecase: self.file.remove(self.settings["classification"]) for rel in self.file.by_type("IfcRelAssociatesClassification"): if not rel.RelatingClassification: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) for rel in self.file.by_type("IfcExternalReferenceRelationship"): if not rel.RelatingReference: self.file.remove(rel) diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py index b64dc41e47..48b55b3740 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, reference=None, product=None): @@ -59,7 +62,10 @@ class Usecase: if len(related_objects): rel.RelatedObjects = related_objects else: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: for rel in self.file.by_type("IfcExternalReferenceRelationship"): if rel.RelatingReference == self.settings["reference"] and rel.RelatedResourceObjects: diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py index e0c9c1776a..d2d797ce0f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, constraint=None): @@ -46,4 +49,7 @@ class Usecase: self.file.remove(self.settings["constraint"]) for rel in self.file.by_type("IfcRelAssociatesConstraint"): if not rel.RelatingConstraint: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py index 229f198920..86ab642b7a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_metric.py @@ -50,7 +50,10 @@ class Usecase: self.file.remove(self.settings["metric"]) for rel in self.file.by_type("IfcRelAssociatesConstraint"): if not rel.RelatingConstraint: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) for resource_rel in self.file.by_type("IfcResourceConstraintRelationship"): if not resource_rel.RelatingConstraint: self.file.remove(resource_rel) diff --git a/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py index 2972268fb5..66b3bc94b9 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, product=None, constraint=None): @@ -40,4 +43,7 @@ class Usecase: def execute(self): for rel in self.settings["product"].HasAssociations: if rel.is_a("IfcRelAssociatesConstraint") and rel.RelatingConstraint == self.settings["constraint"]: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/control/unassign_control.py b/src/ifcopenshell-python/ifcopenshell/api/control/unassign_control.py index ce734ab92d..33ee89db4d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/control/unassign_control.py +++ b/src/ifcopenshell-python/ifcopenshell/api/control/unassign_control.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -61,7 +62,11 @@ class Usecase: if not rel.is_a("IfcRelAssignsToControl") or rel.RelatingControl != self.settings["relating_control"]: continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_item.py b/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_item.py index 8d4f9c5e8d..eaadf832d7 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_item.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_item.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -51,7 +53,16 @@ class Usecase: for related_object in inverse.RelatedObjects: ifcopenshell.api.run("cost.remove_cost_item", self.file, cost_item=related_object) elif inverse.RelatedObjects == tuple(self.settings["cost_item"]): + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) elif inverse.is_a("IfcRelAssignsToControl"): + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + history = self.settings["cost_item"].OwnerHistory self.file.remove(self.settings["cost_item"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_schedule.py index b1ebfbd738..79438a5461 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_schedule.py +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/remove_cost_schedule.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -53,4 +55,7 @@ class Usecase: for related_object in inverse.RelatedObjects if related_object.is_a("IfcCostItem") ] + history = self.settings["cost_schedule"].OwnerHistory self.file.remove(self.settings["cost_schedule"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/remove_information.py b/src/ifcopenshell-python/ifcopenshell/api/document/remove_information.py index a1dd69b51c..bf26837822 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/document/remove_information.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/remove_information.py @@ -55,6 +55,7 @@ class Usecase: for rel in self.settings["information"].IsPointedTo or []: if rel.RelatedDocuments == (self.settings["information"],): + # This relationship is non-rooted self.file.remove(rel) for rel in self.settings["information"].DocumentInfoForObjects or []: diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/remove_reference.py b/src/ifcopenshell-python/ifcopenshell/api/document/remove_reference.py index 5426608257..3a73f692bb 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/document/remove_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/remove_reference.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, reference=None): @@ -41,5 +44,8 @@ class Usecase: def execute(self): for rel in self.settings["reference"].DocumentRefForObjects or []: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) self.file.remove(self.settings["reference"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py index 7a1b72132f..5a08c13262 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell +import ifcopenshell.util.element class Usecase: @@ -59,6 +60,9 @@ class Usecase: for rel in self.settings["product"].HasAssociations: if rel.is_a("IfcRelAssociatesDocument") and rel.RelatingDocument == self.settings["document"]: if len(rel.RelatedObjects) == 1: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: rel.RelatedObjects = [o for o in rel.RelatedObjects if o != self.settings["product"]] diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_element.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_element.py index 80760f6b15..9339752d4c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_element.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_element.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -44,7 +45,10 @@ class Usecase: if incompatible_connections: for connection in set(incompatible_connections): + history = connection.OwnerHistory self.file.remove(connection) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) for rel in self.settings["relating_element"].ConnectedTo: if rel.is_a() == "IfcRelConnectsElements" and rel.RelatedElement == self.settings["related_element"]: diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py index efec41fee2..1a610a7d2c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/connect_path.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -77,7 +78,10 @@ class Usecase: if incompatible_connections: for connection in set(incompatible_connections): + history = connection.OwnerHistory self.file.remove(connection) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) return self.file.createIfcRelConnectsPathElements( ifcopenshell.guid.new(), diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_element.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_element.py index 793c96a71c..680b3e85e7 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_element.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_element.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, **settings): @@ -48,4 +51,7 @@ class Usecase: if incompatible_connections: for connection in set(incompatible_connections): + history = connection.OwnerHistory self.file.remove(connection) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_path.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_path.py index ff8a75404c..8e52c7e4ff 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_path.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/disconnect_path.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -51,4 +52,7 @@ class Usecase: ] for connection in set(connections): + history = connection.OwnerHistory self.file.remove(connection) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py index cf4fc385bf..161b4b5fb5 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -60,4 +61,7 @@ class Usecase: rel.RelatedObjects = list(related_objects) ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) else: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/library/remove_library.py b/src/ifcopenshell-python/ifcopenshell/api/library/remove_library.py index f6af4d6c3b..931d9153d6 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/library/remove_library.py +++ b/src/ifcopenshell-python/ifcopenshell/api/library/remove_library.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, library=None): @@ -45,4 +48,7 @@ class Usecase: self.file.remove(self.settings["library"]) for rel in self.file.by_type("IfcRelAssociatesLibrary"): if not rel.RelatingLibrary: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/library/remove_reference.py b/src/ifcopenshell-python/ifcopenshell/api/library/remove_reference.py index 88e267a1c2..c1b15847fc 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/library/remove_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/library/remove_reference.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, reference=None): @@ -43,5 +46,8 @@ class Usecase: def execute(self): for rel in self.settings["reference"].LibraryRefForObjects: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) self.file.remove(self.settings["reference"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/library/unassign_reference.py b/src/ifcopenshell-python/ifcopenshell/api/library/unassign_reference.py index 8fef53ebc3..639a3dd35b 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/library/unassign_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/library/unassign_reference.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, reference=None, product=None): @@ -62,7 +65,10 @@ class Usecase: for rel in rels: if self.settings["product"] in rel.RelatedObjects: if len(rel.RelatedObjects) == 1: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) continue related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["product"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py b/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py index b88be0f912..8f0b916fec 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/nest/assign_object.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -115,7 +116,10 @@ class Usecase: nests.RelatedObjects = related_objects ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": nests}) else: + history = nests.OwnerHistory self.file.remove(nests) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) if is_nested_by: related_objects = list(is_nested_by.RelatedObjects) diff --git a/src/ifcopenshell-python/ifcopenshell/api/nest/change_nest.py b/src/ifcopenshell-python/ifcopenshell/api/nest/change_nest.py index 33ac1ce7c2..98ba363050 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/nest/change_nest.py +++ b/src/ifcopenshell-python/ifcopenshell/api/nest/change_nest.py @@ -18,6 +18,8 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element + class Usecase: def __init__(self, file, item=None, new_parent=None): @@ -35,5 +37,13 @@ class Usecase: nests.RelatedObjects = related_objects ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": nests}) else: + history = nests.OwnerHistory self.file.remove(nests) - ifcopenshell.api.run("nest.assign_object", self.file, related_object=self.settings["item"], relating_object=self.settings["new_parent"]) \ No newline at end of file + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + ifcopenshell.api.run( + "nest.assign_object", + self.file, + related_object=self.settings["item"], + relating_object=self.settings["new_parent"], + ) diff --git a/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py b/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py index 97391d8619..bff97fd07a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/nest/unassign_object.py @@ -18,17 +18,18 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: def __init__(self, file, related_object=None): """Unassigns a related_object from its nest. - + An object (the whole within a decomposition) is Nested by zero or one more smaller objects. This function will remove this nesting relationship. - + If the object is not part of a nesting relationship, nothing will happen. - + :param related_object: The child of the nesting relationship, typically an IfcElement. :type related_object: ifcopenshell.entity_instance.entity_instance @@ -56,11 +57,13 @@ class Usecase: if not rel.is_a("IfcRelNests"): continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects - ifcopenshell.api.run( - "owner.update_owner_history", self.file, **{"element": rel} - ) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) return rel diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/unassign_actor.py b/src/ifcopenshell-python/ifcopenshell/api/owner/unassign_actor.py index 06b428cd05..aadb6426c9 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/unassign_actor.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/unassign_actor.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -65,7 +66,11 @@ class Usecase: if not rel.is_a("IfcRelAssignsToActor") or rel.RelatingActor != self.settings["relating_actor"]: continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/remove_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/remove_resource.py index e4511708c8..db8153a3e0 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/remove_resource.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/remove_resource.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -47,10 +49,16 @@ class Usecase: self.file, resource=related_object, ) + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) elif inverse.is_a("IfcRelAssignsToControl"): if len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["resource"]) @@ -65,7 +73,10 @@ class Usecase: resource=self.settings["resource"], ) elif inverse.RelatedObjects == tuple(self.settings["resource"]): + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) if self.settings["resource"].Usage: self.file.remove(self.settings["resource"].Usage) if self.settings["resource"].BaseQuantity: @@ -74,4 +85,7 @@ class Usecase: self.file, resource=self.settings["resource"], ) + history = self.settings["resource"].OwnerHistory self.file.remove(self.settings["resource"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/unassign_resource.py b/src/ifcopenshell-python/ifcopenshell/api/resource/unassign_resource.py index ea07bcf44c..50c8661ecd 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/unassign_resource.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/unassign_resource.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -69,7 +71,11 @@ class Usecase: ): continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py index 97e644e05d..cc1abf7409 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/assign_lag_time.py @@ -20,9 +20,7 @@ import ifcopenshell.util.date class Usecase: - def __init__( - self, file, rel_sequence=None, lag_value=None, duration_type="WORKTIME" - ): + def __init__(self, file, rel_sequence=None, lag_value=None, duration_type="WORKTIME"): """Assign a lag time to a sequence relationship between tasks A task sequence (e.g. finish to start) may optionally have a lag time @@ -94,22 +92,15 @@ class Usecase: def execute(self): lag_value = self.file.createIfcDuration( - ifcopenshell.util.date.datetime2ifc( - self.settings["lag_value"], "IfcDuration" - ) + ifcopenshell.util.date.datetime2ifc(self.settings["lag_value"], "IfcDuration") ) lag_time = self.file.create_entity( - "IfcLagTime", - **{ - "DurationType": self.settings["duration_type"], - "LagValue": lag_value, - } + "IfcLagTime", DurationType=self.settings["duration_type"], LagValue=lag_value ) if self.settings["rel_sequence"].is_a("IfcRelSequence"): if ( self.settings["rel_sequence"].TimeLag - and len(self.file.get_inverse(self.settings["rel_sequence"].TimeLag)) - == 1 + and len(self.file.get_inverse(self.settings["rel_sequence"].TimeLag)) == 1 ): self.file.remove(self.settings["rel_sequence"].TimeLag) self.settings["rel_sequence"].TimeLag = lag_time diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_task.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_task.py index a7e7708b08..4c0ee504f4 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_task.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_task.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -67,15 +69,19 @@ class Usecase: self.file.remove(self.settings["task"].TaskTime) for inverse in self.file.get_inverse(self.settings["task"]): if inverse.is_a("IfcRelSequence"): + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) elif inverse.is_a("IfcRelNests"): if inverse.RelatingObject == self.settings["task"]: for related_object in inverse.RelatedObjects: - ifcopenshell.api.run( - "sequence.remove_task", self.file, task=related_object - ) + ifcopenshell.api.run("sequence.remove_task", self.file, task=related_object) elif not inverse.RelatedObjects: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) elif self.settings["task"] in inverse.RelatedObjects: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["task"]) @@ -84,17 +90,16 @@ class Usecase: else: inverse.RelatedObjects = related_objects elif inverse.is_a("IfcRelAssignsToControl"): - if ( - inverse.RelatingControl == self.settings["task"] - or len(inverse.RelatedObjects) == 1 - ): + if inverse.RelatingControl == self.settings["task"] or len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["task"]) inverse.RelatedObjects = related_objects elif inverse.is_a("IfcRelDefinesByProperties"): - print(inverse.RelatingPropertyDefinition.Name) ifcopenshell.api.run( "pset.remove_pset", self.file, @@ -102,32 +107,38 @@ class Usecase: pset=inverse.RelatingPropertyDefinition, ) elif inverse.is_a("IfcRelAssignsToProcess"): - if ( - inverse.RelatingProcess == self.settings["task"] - or len(inverse.RelatedObjects) == 1 - ): + if inverse.RelatingProcess == self.settings["task"] or len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) elif inverse.is_a("IfcRelAssignsToProduct"): - if ( - inverse.RelatingProduct == self.settings["task"] - or len(inverse.RelatedObjects) == 1 - ): + if inverse.RelatingProduct == self.settings["task"] or len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["task"]) inverse.RelatedObjects = related_objects elif inverse.is_a("IfcRelAssignsToObject"): - if ( - inverse.RelatingObject == self.settings["task"] - or len(inverse.RelatedObjects) == 1 - ): + if inverse.RelatingObject == self.settings["task"] or len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["task"]) inverse.RelatedObjects = related_objects elif inverse.is_a("IfcRelAssignsToProcess"): + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + history = self.settings["task"].OwnerHistory self.file.remove(self.settings["task"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_calendar.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_calendar.py index 8fb24bc48e..a630c3f42e 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_calendar.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_calendar.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell +import ifcopenshell.util.element class Usecase: @@ -54,13 +55,14 @@ class Usecase: ) if self.settings["work_calendar"].Controls: for rel in self.settings["work_calendar"].Controls: - for object in rel.RelatedObjects: + for related_object in rel.RelatedObjects: ifcopenshell.api.run( "control.unassign_control", self.file, - **{ - "relating_control": self.settings["work_calendar"], - "related_object": object, - } + relating_control=self.settings["work_calendar"], + related_object=related_object, ) + history = self.settings["work_calendar"].OwnerHistory self.file.remove(self.settings["work_calendar"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py index 7a89293d26..cb8c638799 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell +import ifcopenshell.util.element class Usecase: @@ -52,4 +53,7 @@ class Usecase: definition=self.settings["work_plan"], relating_context=self.file.by_type("IfcContext")[0], ) + history = self.settings["work_plan"].OwnerHistory self.file.remove(self.settings["work_plan"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_schedule.py index aee6b94f1c..935c9f1832 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_schedule.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_schedule.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -65,22 +67,23 @@ class Usecase: ) for inverse in self.file.get_inverse(self.settings["work_schedule"]): if inverse.is_a("IfcRelDefinesByObject"): - if ( - inverse.RelatingObject == self.settings["work_schedule"] - or len(inverse.RelatedObjects) == 1 - ): + if inverse.RelatingObject == self.settings["work_schedule"] or len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) else: related_objects = list(inverse.RelatedObjects) related_objects.remove(self.settings["work_schedule"]) inverse.RelatedObjects = related_objects elif inverse.is_a("IfcRelAssignsToControl"): [ - ifcopenshell.api.run( - "sequence.remove_task", self.file, task=related_object - ) + ifcopenshell.api.run("sequence.remove_task", self.file, task=related_object) for related_object in inverse.RelatedObjects if related_object.is_a("IfcTask") ] + history = self.settings["work_schedule"].OwnerHistory self.file.remove(self.settings["work_schedule"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_process.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_process.py index d60c891bad..2d7a5fb10f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_process.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_process.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -63,17 +64,16 @@ class Usecase: def execute(self): for rel in self.settings["related_object"].HasAssignments or []: - if ( - not rel.is_a("IfcRelAssignsToProcess") - or rel.RelatingProcess != self.settings["relating_process"] - ): + if not rel.is_a("IfcRelAssignsToProcess") or rel.RelatingProcess != self.settings["relating_process"]: continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects - ifcopenshell.api.run( - "owner.update_owner_history", self.file, **{"element": rel} - ) + ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel) return rel diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_product.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_product.py index c4d372f686..a4dcfd6968 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_product.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -63,17 +64,16 @@ class Usecase: def execute(self): for rel in self.settings["related_object"].HasAssignments or []: - if ( - not rel.is_a("IfcRelAssignsToProduct") - or rel.RelatingProduct != self.settings["relating_product"] - ): + if not rel.is_a("IfcRelAssignsToProduct") or rel.RelatingProduct != self.settings["relating_product"]: continue if len(rel.RelatedObjects) == 1: - return self.file.remove(rel) + history = rel.OwnerHistory + self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + return related_objects = list(rel.RelatedObjects) related_objects.remove(self.settings["related_object"]) rel.RelatedObjects = related_objects - ifcopenshell.api.run( - "owner.update_owner_history", self.file, **{"element": rel} - ) + ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel) return rel diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_recurrence_pattern.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_recurrence_pattern.py index 5c46e3e51c..7a13495289 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_recurrence_pattern.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_recurrence_pattern.py @@ -16,8 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . -import ifcopenshell.api - class Usecase: def __init__(self, file, recurrence_pattern=None): @@ -53,4 +51,6 @@ class Usecase: self.settings = {"recurrence_pattern": recurrence_pattern} def execute(self): + for time_period in self.settings["recurrence_pattern"].TimePeriods or []: + self.file.remove(time_period) self.file.remove(self.settings["recurrence_pattern"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_sequence.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_sequence.py index 481a77831b..85afb4cd23 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_sequence.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/unassign_sequence.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -65,9 +66,8 @@ class Usecase: def execute(self): for rel in self.settings["related_process"].IsSuccessorFrom or []: if rel.RelatingProcess == self.settings["relating_process"]: + history = rel.OwnerHistory self.file.remove(rel) - ifcopenshell.api.run( - "sequence.cascade_schedule", - self.file, - task=self.settings["related_process"], - ) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + ifcopenshell.api.run("sequence.cascade_schedule", self.file, task=self.settings["related_process"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py index d21e91f6f0..28c594ab74 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element import ifcopenshell.util.placement @@ -120,7 +121,10 @@ class Usecase: contained_in_structure[0].RelatedElements = related_elements ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contained_in_structure[0]}) else: + history = contained_in_structure[0].OwnerHistory self.file.remove(contained_in_structure[0]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) if contains_elements: related_elements = list(contains_elements[0].RelatedElements) diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py index a919d2195d..b47a9f976f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/dereference_structure.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -77,4 +78,7 @@ class Usecase: rel.RelatedElements = related_elements ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) else: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py index 55bdf637ee..48a2f6dc38 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -70,4 +71,7 @@ class Usecase: contained_in_structure[0].RelatedElements = related_elements ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contained_in_structure[0]}) else: + history = contained_in_structure[0].OwnerHistory self.file.remove(contained_in_structure[0]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py index b82d575473..7c46bd3e49 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/unassign_container.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -67,4 +68,7 @@ class Usecase: rel.RelatedElements = related_elements ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel) else: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py index ab4f5558aa..b4148687aa 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, structural_analysis_model=None): @@ -34,5 +37,11 @@ class Usecase: def execute(self): for rel in self.settings["structural_analysis_model"].IsGroupedBy or []: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + history = self.settings["structural_analysis_model"].OwnerHistory self.file.remove(self.settings["structural_analysis_model"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py index e6e60ef48c..a09618575f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -38,6 +40,9 @@ class Usecase: ifcopenshell.api.run( "structural.remove_structural_boundary_condition", self.file, - **{"connection": self.settings["relation"].RelatedStructuralConnection} + connection=self.settings["relation"].RelatedStructuralConnection ) + history = self.settings["relation"].OwnerHistory self.file.remove(self.settings["relation"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_case.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_case.py index 2b724675f8..c9aa1b2c5d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_case.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_case.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -34,5 +36,10 @@ class Usecase: def execute(self): # TODO: do a deep purge for rel in self.settings["load_case"].IsGroupedBy or []: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + history = self.settings["load_case"].OwnerHistory self.file.remove(self.settings["load_case"]) + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_group.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_group.py index fb97b71b92..937af21bca 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_load_group.py @@ -16,7 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -35,5 +37,11 @@ class Usecase: # TODO: do a deep purge for inverse in self.file.get_inverse(self.settings["load_group"]): if inverse.is_a("IfcRelAssignsToGroup") and len(inverse.RelatedObjects) == 1: + history = inverse.OwnerHistory self.file.remove(inverse) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) + history = self.settings["load_group"].OwnerHistory self.file.remove(self.settings["load_group"]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py index 3f8af320e7..0dd7bf8ca4 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element class Usecase: @@ -48,4 +49,7 @@ class Usecase: rel.RelatedObjects = list(related_objects) ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) else: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py index 809862c8ed..5e17b2b06d 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/remove_surface_style.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell import ifcopenshell.util.element diff --git a/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py b/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py index 3f8ed9340d..b457ab5d3a 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell +import ifcopenshell.util.element class Usecase: @@ -108,13 +109,14 @@ class Usecase: if fills_voids: if fills_voids[0].RelatingOpeningElement == self.settings["opening"]: return + history = fills_voids[0].OwnerHistory self.file.remove(fills_voids[0]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) self.file.create_entity( "IfcRelFillsElement", - **{ - "GlobalId": ifcopenshell.guid.new(), - "RelatingOpeningElement": self.settings["opening"], - "RelatedBuildingElement": self.settings["element"], - } + GlobalId=ifcopenshell.guid.new(), + RelatingOpeningElement=self.settings["opening"], + RelatedBuildingElement=self.settings["element"], ) diff --git a/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py b/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py index e3abf67a9d..de479a1d39 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py @@ -18,6 +18,7 @@ import ifcopenshell import ifcopenshell.api +import ifcopenshell.util.element import ifcopenshell.util.placement @@ -108,7 +109,10 @@ class Usecase: if voids_elements: if voids_elements[0].RelatingBuildingElement == self.settings["element"]: return + history = voids_elements[0].OwnerHistory self.file.remove(voids_elements[0]) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) self.file.create_entity( "IfcRelVoidsElement", diff --git a/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py b/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py index f8cefdfc9e..d277960a5f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py @@ -16,6 +16,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with IfcOpenShell. If not, see . +import ifcopenshell +import ifcopenshell.util.element + class Usecase: def __init__(self, file, element=None): @@ -56,5 +59,8 @@ class Usecase: def execute(self): for rel in self.file.by_type("IfcRelFillsElement"): if rel.RelatedBuildingElement == self.settings["element"]: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) break diff --git a/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py b/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py index 9be088dc52..6ed1079b41 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py @@ -49,8 +49,14 @@ class Usecase: def execute(self): for rel in self.settings["opening"].VoidsElements: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) if self.settings["opening"].is_a("IfcOpeningElement"): for rel in self.settings["opening"].HasFillings: + history = rel.OwnerHistory self.file.remove(rel) + if history: + ifcopenshell.util.element.remove_deep2(self.file, history) ifcopenshell.api.run("root.remove_product", self.file, product=self.settings["opening"])