From 2da5f2d61ea6a1b4b8a6d41ed8ea88df0c550a8f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 6 Dec 2024 16:30:43 +0500 Subject: [PATCH] set_element_value - optimizations setting enum values 1) Identify from previous pset value whether prop was an enum (by checking if previous value is a list), instead of searching through prop templates 2) Compare previous and new enum values - if they match, skip editing IFC. --- .../ifcopenshell/util/selector.py | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/util/selector.py b/src/ifcopenshell-python/ifcopenshell/util/selector.py index 0a7fff0c0e..c54d3037a6 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/selector.py +++ b/src/ifcopenshell-python/ifcopenshell/util/selector.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import re +import types import lark import numpy as np import ifcopenshell.api.pset @@ -466,7 +467,12 @@ class SetElementValueException(Exception): ... def set_element_value( ifc_file: ifcopenshell.file, - element: Union[ifcopenshell.entity_instance, Iterable[ifcopenshell.entity_instance], None], + element: Union[ + ifcopenshell.entity_instance, + dict[str, Any], + Iterable[ifcopenshell.entity_instance], + None, + ], query: Union[str, list[str]], value: Any, *, @@ -656,14 +662,30 @@ def set_element_value( ifcopenshell.api.pset.edit_qto(ifc_file, qto=pset, properties={prop: float(value)}) elif pset.is_a("IfcPropertySet") and element.get(key, None) != value: - def process_pset_prop_value(pset: ifcopenshell.entity_instance, prop: str, value: Any) -> Any: + def process_pset_prop_value( + pset: ifcopenshell.entity_instance, prop: str, value: Any + ) -> Union[Any, types.EllipsisType]: """Try to process value for edit_pset. `edit_pset` is expecting a sequence of values for enum properties, not just a string of some-symbol-separated values. + + Return `...` if property can be skipped as it has the same value. """ if not isinstance(value, str): return value + + current_value = element.get(key, ...) + # Check if previous value is a list as a fast way to identify enum properties. + if not isinstance(current_value, (types.EllipsisType, list)): + return value + + if isinstance(current_value, list): + # Value won't change, safe to skip editing IFC. + enum_values = value.split(concat) + if len(enum_values) == len(current_value) and set(enum_values) == set(current_value): + return ... + template = ifcopenshell.util.pset.get_template(ifc_file.schema) pset_template = template.get_by_name(pset.Name) if pset_template is None: @@ -704,6 +726,8 @@ def set_element_value( return value value = process_pset_prop_value(pset, key, value) + if value == ...: + return ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={key: value}) elif pset.is_a("IfcElementQuantity"): try: