mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
#2082. You can now use the selector to filter by strict data types.
This commit is contained in:
@@ -36,7 +36,7 @@ class Selector:
|
|||||||
class_selector: "." WORD filter ?
|
class_selector: "." WORD filter ?
|
||||||
filter: "[" filter_key (comparison filter_value)? "]"
|
filter: "[" filter_key (comparison filter_value)? "]"
|
||||||
filter_key: WORD | pset_or_qto
|
filter_key: WORD | pset_or_qto
|
||||||
filter_value: ESCAPED_STRING
|
filter_value: ESCAPED_STRING | SIGNED_FLOAT | SIGNED_INT | BOOLEAN | NULL
|
||||||
pset_or_qto: /[A-Za-z0-9_]+/ "." /[A-Za-z0-9_]+/
|
pset_or_qto: /[A-Za-z0-9_]+/ "." /[A-Za-z0-9_]+/
|
||||||
lfunction: and | or
|
lfunction: and | or
|
||||||
inverse_relationship: types | contains_elements | boundedby
|
inverse_relationship: types | contains_elements | boundedby
|
||||||
@@ -52,6 +52,8 @@ class Selector:
|
|||||||
equal: "="
|
equal: "="
|
||||||
morethan: ">"
|
morethan: ">"
|
||||||
lessthan: "<"
|
lessthan: "<"
|
||||||
|
BOOLEAN: "TRUE" | "FALSE"
|
||||||
|
NULL: "NULL"
|
||||||
|
|
||||||
// Embed common.lark for packaging
|
// Embed common.lark for packaging
|
||||||
DIGIT: "0".."9"
|
DIGIT: "0".."9"
|
||||||
@@ -168,10 +170,20 @@ class Selector:
|
|||||||
comparison = value = None
|
comparison = value = None
|
||||||
if len(filter_rule.children) > 1:
|
if len(filter_rule.children) > 1:
|
||||||
comparison = filter_rule.children[1].children[0].data
|
comparison = filter_rule.children[1].children[0].data
|
||||||
value = filter_rule.children[2].children[0][1:-1]
|
token_type = filter_rule.children[2].children[0].type
|
||||||
|
if token_type == "ESCAPED_STRING":
|
||||||
|
value = str(filter_rule.children[2].children[0][1:-1])
|
||||||
|
elif token_type == "SIGNED_INT":
|
||||||
|
value = int(filter_rule.children[2].children[0])
|
||||||
|
elif token_type == "SIGNED_FLOAT":
|
||||||
|
value = float(filter_rule.children[2].children[0])
|
||||||
|
elif token_type == "BOOLEAN":
|
||||||
|
value = filter_rule.children[2].children[0] == "TRUE"
|
||||||
|
elif token_type == "NULL":
|
||||||
|
value = None
|
||||||
for element in elements:
|
for element in elements:
|
||||||
element_value = cls.get_element_value(element, key)
|
element_value = cls.get_element_value(element, key)
|
||||||
if element_value is None:
|
if element_value is None and value is not None:
|
||||||
continue
|
continue
|
||||||
if not comparison or cls.filter_element(element, element_value, comparison, value):
|
if not comparison or cls.filter_element(element, element_value, comparison, value):
|
||||||
results.append(element)
|
results.append(element)
|
||||||
@@ -217,7 +229,7 @@ class Selector:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def filter_element(cls, element, element_value, comparison, value):
|
def filter_element(cls, element, element_value, comparison, value):
|
||||||
if comparison == "equal":
|
if comparison == "equal":
|
||||||
return str(element_value) == value
|
return element_value == value
|
||||||
elif comparison == "contains":
|
elif comparison == "contains":
|
||||||
return value in str(element_value)
|
return value in str(element_value)
|
||||||
elif comparison == "morethan":
|
elif comparison == "morethan":
|
||||||
|
|||||||
@@ -45,3 +45,31 @@ class TestSelector(test.bootstrap.IFC4):
|
|||||||
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
||||||
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": "Bar"})
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": "Bar"})
|
||||||
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo="Bar"]') == [element]
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo="Bar"]') == [element]
|
||||||
|
|
||||||
|
def test_selecting_by_integer_property(self):
|
||||||
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": 42})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=42]') == [element]
|
||||||
|
|
||||||
|
def test_selecting_by_float_property(self):
|
||||||
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": 4.2})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=4.2]') == [element]
|
||||||
|
|
||||||
|
def test_selecting_by_boolean_property(self):
|
||||||
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": True})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=TRUE]') == [element]
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": False})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=FALSE]') == [element]
|
||||||
|
|
||||||
|
def test_selecting_by_null_property(self):
|
||||||
|
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||||
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": "Bar"})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=NULL]') == []
|
||||||
|
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Foo": None})
|
||||||
|
assert subject.Selector.parse(self.file, '.IfcElement[Foo_Bar.Foo=NULL]') == [element]
|
||||||
|
|||||||
Reference in New Issue
Block a user