diff --git a/src/ifcopenshell-python/ifcopenshell/util/selector.py b/src/ifcopenshell-python/ifcopenshell/util/selector.py index 6ec36b1878..419937aac3 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/selector.py +++ b/src/ifcopenshell-python/ifcopenshell/util/selector.py @@ -24,8 +24,9 @@ import lark class Selector: @classmethod - def parse(cls, ifc_file, query): + def parse(cls, ifc_file, query, elements=None): cls.file = ifc_file + cls.elements = elements l = lark.Lark( """start: query (lfunction query)* @@ -157,7 +158,10 @@ class Selector: elif class_selector.children[0] == "FMHEM": elements = ifcopenshell.util.fm.get_fmhem_types(cls.file) else: - elements = cls.file.by_type(class_selector.children[0]) + if cls.elements is None: + elements = cls.file.by_type(class_selector.children[0]) + else: + elements = [e for e in cls.elements if e.is_a(class_selector.children[0])] if len(class_selector.children) > 1 and class_selector.children[1].data == "filter": return cls.filter_elements(elements, class_selector.children[1]) return elements diff --git a/src/ifcopenshell-python/test/bootstrap.py b/src/ifcopenshell-python/test/bootstrap.py index a5b6905f31..b87d30855b 100644 --- a/src/ifcopenshell-python/test/bootstrap.py +++ b/src/ifcopenshell-python/test/bootstrap.py @@ -28,6 +28,8 @@ class IFC4: self.file = ifcopenshell.api.run("project.create_file") ifcopenshell.api.owner.settings.get_user = lambda ifc: (ifc.by_type("IfcPersonAndOrganization") or [None])[0] ifcopenshell.api.owner.settings.get_application = lambda ifc: (ifc.by_type("IfcApplication") or [None])[0] + ifcopenshell.api.pre_listeners = {} + ifcopenshell.api.post_listeners = {} class IFC2X3: @@ -36,3 +38,5 @@ class IFC2X3: self.file = ifcopenshell.api.run("project.create_file", version="IFC2X3") ifcopenshell.api.owner.settings.get_user = lambda ifc: ifc.createIfcPersonAndOrganization() ifcopenshell.api.owner.settings.get_application = lambda ifc: ifc.createIfcApplication() + ifcopenshell.api.pre_listeners = {} + ifcopenshell.api.post_listeners = {} diff --git a/src/ifcopenshell-python/test/util/test_selector.py b/src/ifcopenshell-python/test/util/test_selector.py index c7805f3871..3c138098cc 100644 --- a/src/ifcopenshell-python/test/util/test_selector.py +++ b/src/ifcopenshell-python/test/util/test_selector.py @@ -112,9 +112,9 @@ class TestSelector(test.bootstrap.IFC4): element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") ifcopenshell.api.run("type.assign_type", self.file, related_object=element, relating_type=element_type) element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") - element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") - ifcopenshell.api.run("type.assign_type", self.file, related_object=element2, relating_type=element_type) - assert subject.Selector.parse(self.file, "* .IfcWallType") == [element, element2] + element_type2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("type.assign_type", self.file, related_object=element2, relating_type=element_type2) + assert set(subject.Selector.parse(self.file, "* .IfcWallType")) == {element, element2} def test_getting_decomposition_of_a_filtered_type(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") @@ -122,4 +122,10 @@ class TestSelector(test.bootstrap.IFC4): building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) - assert subject.Selector.parse(self.file, "@ .IfcBuilding") == [element, subelement] + assert set(subject.Selector.parse(self.file, "@ .IfcBuilding")) == {element, subelement} + + def test_selecting_elements_from_a_prefiltered_list(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSlab") + assert subject.Selector.parse(self.file, ".IfcWall", elements=[element]) + assert not subject.Selector.parse(self.file, ".IfcWall", elements=[element2])