From d764c0af23d1eddb22640901bb9e216d3eb956b9 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 8 Apr 2024 15:47:31 +0500 Subject: [PATCH] temporary support for deprecated api arguments #4531 --- .../ifcopenshell/api/__init__.py | 29 +++++++ .../test/api/group/test_unassign_group.py | 2 +- .../api/spatial/test_unassign_container.py | 9 +- src/ifcopenshell-python/test/api/test_api.py | 85 +++++++++++++++++++ 4 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/ifcopenshell-python/test/api/test_api.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/__init__.py b/src/ifcopenshell-python/ifcopenshell/api/__init__.py index 1b2af5b09f..905ebeaaf4 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/api/__init__.py @@ -24,12 +24,37 @@ import importlib import ifcopenshell import ifcopenshell.api from typing import Callable, Any, Optional +from functools import partial pre_listeners = {} post_listeners = {} +def batching_argument_deprecation(usecase_path: str, settings: dict, prev_argument: str, new_argument: str) -> dict: + if prev_argument in settings: + print( + f"WARNING. `{prev_argument}` argument is deprecated for API method " + f'"{usecase_path}" and should be replaced with `{new_argument}`.' + ) + settings = settings | {new_argument: [settings[prev_argument]]} + settings.pop(prev_argument) + return settings + + +ARGUMENTS_DEPRECATION = { + "spatial.assign_container": partial( + batching_argument_deprecation, prev_argument="product", new_argument="products" + ), + "spatial.unassign_container": partial( + batching_argument_deprecation, prev_argument="product", new_argument="products" + ), + "group.unassign_group": partial(batching_argument_deprecation, prev_argument="product", new_argument="products"), + "layer.assign_layer": partial(batching_argument_deprecation, prev_argument="item", new_argument="items"), + "layer.unassign_layer": partial(batching_argument_deprecation, prev_argument="item", new_argument="items"), +} + + def run( usecase_path: str, ifc_file: Optional[ifcopenshell.file] = None, @@ -40,6 +65,10 @@ def run( for listener in pre_listeners.get(usecase_path, {}).values(): listener(usecase_path, ifc_file, settings) + # see #4531 + if usecase_path in ARGUMENTS_DEPRECATION: + settings = ARGUMENTS_DEPRECATION[usecase_path](usecase_path, settings) + # TODO: settings serialization for client-server systems # def serialise_entity_instance(entity): # return {"cast_type": "entity_instance", "value": entity.id(), "Name": getattr(entity, "Name", None)} diff --git a/src/ifcopenshell-python/test/api/group/test_unassign_group.py b/src/ifcopenshell-python/test/api/group/test_unassign_group.py index edc2ecbca0..d7b1179f03 100644 --- a/src/ifcopenshell-python/test/api/group/test_unassign_group.py +++ b/src/ifcopenshell-python/test/api/group/test_unassign_group.py @@ -21,7 +21,7 @@ import ifcopenshell.api class TestAssignGroup(test.bootstrap.IFC4): - def test_unassignment(self): + def test_group_unassignment(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") element3 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") diff --git a/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py b/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py index cbd591c0a1..4c06d4251d 100644 --- a/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py +++ b/src/ifcopenshell-python/test/api/spatial/test_unassign_container.py @@ -29,7 +29,9 @@ class TestAssignContainer(test.bootstrap.IFC4): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") - ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element) + ifcopenshell.api.run( + "spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element + ) ifcopenshell.api.run("spatial.unassign_container", self.file, products=[subelement, subelement2]) assert not self.file.by_type("IfcRelContainedInSpatialStructure") @@ -37,8 +39,9 @@ class TestAssignContainer(test.bootstrap.IFC4): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") - ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element) - ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement2], relating_structure=element) + ifcopenshell.api.run( + "spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element + ) ifcopenshell.api.run("spatial.unassign_container", self.file, products=[subelement]) rel = self.file.by_type("IfcRelContainedInSpatialStructure")[0] assert list(rel.RelatedElements) == [subelement2] diff --git a/src/ifcopenshell-python/test/api/test_api.py b/src/ifcopenshell-python/test/api/test_api.py new file mode 100644 index 0000000000..0a2cd611de --- /dev/null +++ b/src/ifcopenshell-python/test/api/test_api.py @@ -0,0 +1,85 @@ +# IfcOpenShell - IFC toolkit and geometry engine +# Copyright (C) 2021 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 +import ifcopenshell.util.element +from datetime import datetime + + +def deprecation_check(test): + def new_test(self): + assert datetime.now().date() < datetime(2024, 6, 1).date(), "API arguments are completely deprecated" + test(self) + + return new_test + + +class TestTemporarySupportForDeprecatedAPIArguments(test.bootstrap.IFC4): + @deprecation_check + def test_assigning_a_container(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") + subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + rel = ifcopenshell.api.run( + "spatial.assign_container", self.file, product=subelement, relating_structure=element + ) + assert ifcopenshell.util.element.get_container(subelement) == element + assert rel.is_a("IfcRelContainedInSpatialStructure") + + @deprecation_check + def test_unassigning_a_container_with_other_elements(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") + subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + ifcopenshell.api.run( + "spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element + ) + ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement) + rel = self.file.by_type("IfcRelContainedInSpatialStructure")[0] + assert list(rel.RelatedElements) == [subelement2] + + @deprecation_check + def test_group_unassignment(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcPump") + group = ifcopenshell.api.run("group.add_group", self.file) + ifcopenshell.api.run("group.assign_group", self.file, products=[element, element2], group=group) + ifcopenshell.api.run("group.unassign_group", self.file, product=element2, group=group) + + assert len(rels := self.file.by_type("IfcRelAssignsToGroup")) == 1 + rel = rels[0] + assert rel.RelatingGroup == group + assert rel.RelatedObjects == (element,) + + @deprecation_check + def test_assign_layer_to_items(self): + item = self.file.createIfcExtrudedAreaSolid() + layer = self.file.createIfcPresentationLayerAssignment() + + ifcopenshell.api.run("layer.assign_layer", self.file, item=item, layer=layer) + assert layer.AssignedItems == (item,) + + @deprecation_check + def test_unassign_layer_from_items(self): + items = [self.file.createIfcExtrudedAreaSolid() for i in range(3)] + layer = self.file.createIfcPresentationLayerAssignment() + + ifcopenshell.api.run("layer.assign_layer", self.file, items=items, layer=layer) + ifcopenshell.api.run("layer.unassign_layer", self.file, item=items[2], layer=layer) + assert len(layer.AssignedItems) == 2 + assert set(layer.AssignedItems) == set(items[:2])