From fd989733c720793187b08f40148bde6e5b883eac Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 10 Apr 2023 22:26:58 +1000 Subject: [PATCH] Fix bug where unassigning a document was too aggressive and deleted relationships where it shouldn't. --- .../api/document/unassign_document.py | 5 ++- .../test/api/document/test_assign_document.py | 39 ++++++++++++++++++ .../api/document/test_unassign_document.py | 40 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/ifcopenshell-python/test/api/document/test_assign_document.py create mode 100644 src/ifcopenshell-python/test/api/document/test_unassign_document.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py index ebe513d193..7a1b72132f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py @@ -58,4 +58,7 @@ class Usecase: def execute(self): for rel in self.settings["product"].HasAssociations: if rel.is_a("IfcRelAssociatesDocument") and rel.RelatingDocument == self.settings["document"]: - self.file.remove(rel) + if len(rel.RelatedObjects) == 1: + self.file.remove(rel) + else: + rel.RelatedObjects = [o for o in rel.RelatedObjects if o != self.settings["product"]] diff --git a/src/ifcopenshell-python/test/api/document/test_assign_document.py b/src/ifcopenshell-python/test/api/document/test_assign_document.py new file mode 100644 index 0000000000..6c76f844b4 --- /dev/null +++ b/src/ifcopenshell-python/test/api/document/test_assign_document.py @@ -0,0 +1,39 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2023 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import test.bootstrap +import ifcopenshell.api + + +class TestAssignDocument(test.bootstrap.IFC4): + def test_assigning_a_document(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + reference = ifcopenshell.api.run("document.add_reference", self.file, information=None) + ifcopenshell.api.run("document.assign_document", self.file, product=element, document=reference) + assert element.HasAssociations[0].RelatingDocument == reference + + def test_assigning_multiple_documents(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + reference = ifcopenshell.api.run("document.add_reference", self.file, information=None) + ifcopenshell.api.run("document.assign_document", self.file, product=element, document=reference) + ifcopenshell.api.run("document.assign_document", self.file, product=element2, document=reference) + assert len(self.file.by_type("IfcRelAssociatesDocument")) == 1 + assert element.HasAssociations[0].RelatingDocument == reference + assert element2.HasAssociations[0].RelatingDocument == reference + assert element.HasAssociations[0] == element.HasAssociations[0] diff --git a/src/ifcopenshell-python/test/api/document/test_unassign_document.py b/src/ifcopenshell-python/test/api/document/test_unassign_document.py new file mode 100644 index 0000000000..8f227dd2b2 --- /dev/null +++ b/src/ifcopenshell-python/test/api/document/test_unassign_document.py @@ -0,0 +1,40 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2023 Dion Moult +# +# This file is part of IfcOpenShell. +# +# IfcOpenShell is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcOpenShell is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcOpenShell. If not, see . + +import test.bootstrap +import ifcopenshell.api + + +class TestUnassignDocument(test.bootstrap.IFC4): + def test_unassigning_a_document(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + reference = ifcopenshell.api.run("document.add_reference", self.file, information=None) + ifcopenshell.api.run("document.assign_document", self.file, product=element, document=reference) + ifcopenshell.api.run("document.unassign_document", self.file, product=element, document=reference) + assert not element.HasAssociations + assert not len(self.file.by_type("IfcRelAssociatesDocument")) + + def test_unassigning_a_document_used_by_multiple_entities(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + reference = ifcopenshell.api.run("document.add_reference", self.file, information=None) + ifcopenshell.api.run("document.assign_document", self.file, product=element, document=reference) + ifcopenshell.api.run("document.assign_document", self.file, product=element2, document=reference) + ifcopenshell.api.run("document.unassign_document", self.file, product=element, document=reference) + assert not element.HasAssociations + assert element2.HasAssociations[0].RelatingDocument == reference