From df3d07e952cc184bffbc3da3816c6b9a1ce3e85c Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Sun, 30 Aug 2026 15:25:13 +0300 Subject: [PATCH] fix(ifctester): accept tuple results when chaining facet filters Facet.filter() implementations broad-phase query with ifc_file.by_type(), then check isinstance(elements, list) to decide whether a previous facet already narrowed the candidate set. In v0.9.0, file.by_type() returns a tuple instead of a list, so that check silently failed and every facet after the first re-scanned the whole model instead of the already-narrowed (possibly empty) set. This let a prohibited Entity+Attribute applicability match instances of the wrong class, e.g. an IfcSlab satisfying an "IFCWALL" Entity facet's chain. Accept tuples too, matching how by_type() results are actually returned now. --- src/ifctester/ifctester/facet.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ifctester/ifctester/facet.py b/src/ifctester/ifctester/facet.py index ce8e7e034f..e732193955 100644 --- a/src/ifctester/ifctester/facet.py +++ b/src/ifctester/ifctester/facet.py @@ -201,7 +201,7 @@ class Entity(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] = None ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) if isinstance(self.name, str): @@ -280,7 +280,7 @@ class Attribute(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) results = [] @@ -415,7 +415,7 @@ class Classification(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) return ifc_file.by_type("IfcObjectDefinition") @@ -480,7 +480,7 @@ class PartOf(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) return list(ifc_file) # Lazy @@ -673,7 +673,7 @@ class Property(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) if ifc_file.schema == "IFC2X3": return ifc_file.by_type("IfcObjectDefinition") @@ -946,7 +946,7 @@ class Material(Facet): def filter( self, ifc_file: ifcopenshell.file, elements: Optional[list[ifcopenshell.entity_instance]] ) -> list[ifcopenshell.entity_instance]: - if isinstance(elements, list): + if isinstance(elements, (list, tuple)): return super().filter(ifc_file, elements) return ifc_file.by_type("IfcObjectDefinition")