Skip to content

Commit 59dd105

Browse files
Andrej730Moult
authored andcommitted
fix get_applicable_entities / get_applicable_types missing schema #6108
1 parent a28070a commit 59dd105

11 files changed

Lines changed: 65 additions & 31 deletions

File tree

src/bonsai/bonsai/bim/module/pset/data.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ def pset_name(cls):
117117
if not element:
118118
return []
119119
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(
120-
element.is_a(), ifcopenshell.util.element.get_predefined_type(element), pset_only=True
120+
element.is_a(),
121+
ifcopenshell.util.element.get_predefined_type(element),
122+
pset_only=True,
123+
schema=tool.Ifc.get_schema(),
121124
)
122125
psetnames = cls.format_pset_enum(psets)
123126
assigned_names = ifcopenshell.util.element.get_psets(element, psets_only=True, should_inherit=False).keys()
@@ -130,7 +133,10 @@ def qto_name(cls):
130133
if not element:
131134
return []
132135
qtos = bonsai.bim.schema.ifc.psetqto.get_applicable(
133-
element.is_a(), ifcopenshell.util.element.get_predefined_type(element), qto_only=True
136+
element.is_a(),
137+
ifcopenshell.util.element.get_predefined_type(element),
138+
qto_only=True,
139+
schema=tool.Ifc.get_schema(),
134140
)
135141
return cls.format_pset_enum(qtos)
136142

@@ -188,7 +194,9 @@ def pset_name(cls):
188194
if material.ifc_definition_id:
189195
material = tool.Ifc.get().by_id(material.ifc_definition_id)
190196
category = getattr(material, "Category", None) or None
191-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(props.material_type, category, pset_only=True)
197+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(
198+
props.material_type, category, pset_only=True, schema=tool.Ifc.get_schema()
199+
)
192200
psetnames = cls.format_pset_enum(psets)
193201
assigned_names = ifcopenshell.util.element.get_psets(
194202
material, psets_only=True, should_inherit=False

src/bonsai/bonsai/bim/module/pset/prop.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def get_material_set_pset_names(self, context):
105105
if not ifc_class or "Set" not in ifc_class:
106106
return []
107107
if ifc_class not in psetnames:
108-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
108+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
109109
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
110110
return psetnames[ifc_class]
111111

@@ -117,7 +117,7 @@ def get_material_set_item_pset_names(self, context):
117117
return []
118118
ifc_class = tool.Ifc.get().by_id(ifc_definition_id).is_a()
119119
if ifc_class not in psetnames:
120-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
120+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
121121
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
122122
return psetnames[ifc_class]
123123

@@ -126,7 +126,7 @@ def get_task_qto_names(self, context):
126126
global qtonames
127127
ifc_class = "IfcTask"
128128
if ifc_class not in qtonames:
129-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True)
129+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True, schema=tool.Ifc.get_schema())
130130
qtonames[ifc_class] = blender_formatted_enum_from_psets(psets)
131131
return qtonames[ifc_class]
132132

@@ -137,7 +137,7 @@ def get_resource_pset_names(self, context):
137137
rtprops = context.scene.BIMResourceTreeProperties
138138
ifc_class = IfcStore.get_file().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a()
139139
if ifc_class not in psetnames:
140-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
140+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
141141
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
142142
return psetnames[ifc_class]
143143

@@ -148,7 +148,7 @@ def get_resource_qto_names(self, context):
148148
rtprops = context.scene.BIMResourceTreeProperties
149149
ifc_class = IfcStore.get_file().by_id(rtprops.resources[rprops.active_resource_index].ifc_definition_id).is_a()
150150
if ifc_class not in qtonames:
151-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True)
151+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True, schema=tool.Ifc.get_schema())
152152
qtonames[ifc_class] = blender_formatted_enum_from_psets(psets)
153153
return qtonames[ifc_class]
154154

@@ -157,7 +157,7 @@ def get_group_pset_names(self, context):
157157
global psetnames
158158
ifc_class = "IfcGroup"
159159
if ifc_class not in psetnames:
160-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
160+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
161161
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
162162
return psetnames[ifc_class]
163163

@@ -166,7 +166,7 @@ def get_group_qto_names(self, context):
166166
global qtonames
167167
ifc_class = "IfcGroup"
168168
if ifc_class not in qtonames:
169-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True)
169+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True, schema=tool.Ifc.get_schema())
170170
qtonames[ifc_class] = blender_formatted_enum_from_psets(psets)
171171
return qtonames[ifc_class]
172172

@@ -176,7 +176,7 @@ def get_profile_pset_names(self, context):
176176
pprops = context.scene.BIMProfileProperties
177177
ifc_class = IfcStore.get_file().by_id(pprops.profiles[pprops.active_profile_index].ifc_definition_id).is_a()
178178
if ifc_class not in psetnames:
179-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
179+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
180180
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
181181
return psetnames[ifc_class]
182182

@@ -185,7 +185,7 @@ def get_work_schedule_pset_names(self, context):
185185
global psetnames
186186
ifc_class = "IfcWorkSchedule"
187187
if ifc_class not in psetnames:
188-
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True)
188+
psets = bonsai.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True, schema=tool.Ifc.get_schema())
189189
psetnames[ifc_class] = blender_formatted_enum_from_psets(psets)
190190
return psetnames[ifc_class]
191191

src/bonsai/bonsai/bim/module/root/operator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def _execute(self, context):
9797
root_props = context.scene.BIMRootProperties
9898
ifc_product: str = root_props.ifc_product
9999
ifc_class: str = root_props.ifc_class
100-
type_ifc_class = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class)), None)
100+
type_ifc_class = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class, self.file.schema)), None)
101101

102102
predefined_type = root_props.ifc_predefined_type
103103
if predefined_type == "USERDEFINED":

src/bonsai/bonsai/bim/module/root/prop.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ def refresh_classes(self, context):
6767
self.representation_template = "OBJ"
6868
self.representation_obj = obj
6969

70+
ifc_file = tool.Ifc.get()
7071
# When switching between ElementType and Element, keep the same class and predefined type if possible
7172
if self.ifc_product == "IfcElement":
72-
ifc_class = next(iter(ifcopenshell.util.type.get_applicable_entities(old_class)), None)
73+
ifc_class = next(iter(ifcopenshell.util.type.get_applicable_entities(old_class, ifc_file.schema)), None)
7374
elif self.ifc_product == "IfcElementType":
74-
ifc_class = next(iter(ifcopenshell.util.type.get_applicable_types(old_class)), None)
75+
ifc_class = next(iter(ifcopenshell.util.type.get_applicable_types(old_class, ifc_file.schema)), None)
7576
else:
7677
return
7778
if ifc_class:

src/bonsai/bonsai/tool/pset.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ def is_pset_applicable(cls, element: ifcopenshell.entity_instance, pset_name: st
8181
predefined_type = ifcopenshell.util.element.get_predefined_type(element)
8282
return bool(
8383
pset_name
84-
in bonsai.bim.schema.ifc.psetqto.get_applicable_names(element.is_a(), predefined_type, pset_only=True)
84+
in bonsai.bim.schema.ifc.psetqto.get_applicable_names(
85+
element.is_a(), predefined_type, pset_only=True, schema=tool.Ifc.get_schema()
86+
)
8587
)
8688

8789
@classmethod

src/ifc5d/ifc5d/qto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def quantify(ifc_file: ifcopenshell.file, elements: set[ifcopenshell.entity_inst
6161
calculator = calculators[calculator]
6262
for ifc_class, qtos in queries.items():
6363
filtered_elements = set()
64-
ifc_classes = [ifc_class] + ifcopenshell.util.type.get_applicable_types(ifc_class)
64+
ifc_classes = [ifc_class] + ifcopenshell.util.type.get_applicable_types(ifc_class, ifc_file.schema)
6565
for ifc_class in ifc_classes:
6666
if ifc_class not in elements_by_classes:
6767
continue

src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,12 @@ def simple_reassignment(
176176
element = self.reassign_class(element, ifc_class, predefined_type)
177177
if element.is_a("IfcTypeProduct"):
178178
for occurrence in ifcopenshell.util.element.get_types(element):
179-
ifc_class_ = ifcopenshell.util.type.get_applicable_entities(ifc_class)[0]
179+
ifc_class_ = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0]
180180
self.reassign_class(occurrence, ifc_class_, predefined_type)
181181
else:
182182
element_type = ifcopenshell.util.element.get_type(element)
183183
if element_type:
184-
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class)))
184+
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class, self.file.schema)))
185185
element_type = self.reassign_class(element_type, ifc_class_, predefined_type)
186186
ifc_class = element.is_a()
187187
for occurrence in ifcopenshell.util.element.get_types(element_type):

src/ifcopenshell-python/ifcopenshell/util/pset.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
import re
2020
import pathlib
2121
import ifcopenshell
22+
import ifcopenshell.ifcopenshell_wrapper as W
2223
import ifcopenshell.util.schema
2324
import ifcopenshell.util.type
2425
from ifcopenshell.entity_instance import entity_instance
2526
from functools import lru_cache
26-
from typing import List, Optional, Literal
27+
from typing import Optional, Literal
2728

2829
templates: dict[str, "PsetQto"] = {}
2930

@@ -62,10 +63,16 @@ def __init__(self, schema_identifier: str, templates=None) -> None:
6263

6364
@lru_cache()
6465
def get_applicable(
65-
self, ifc_class="", predefined_type="", pset_only=False, qto_only=False
66-
) -> List[entity_instance]:
66+
self,
67+
ifc_class="",
68+
predefined_type="",
69+
pset_only=False,
70+
qto_only=False,
71+
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
72+
) -> list[entity_instance]:
6773
any_class = not ifc_class
6874
if not any_class:
75+
entity: W.entity
6976
entity = self.schema.declaration_by_name(ifc_class)
7077
result = []
7178
for template in self.templates:
@@ -77,18 +84,32 @@ def get_applicable(
7784
if prop_set.TemplateType and prop_set.TemplateType.startswith("PSET_"):
7885
continue
7986
if any_class or self.is_applicable(
80-
entity, prop_set.ApplicableEntity or "IfcRoot", predefined_type, prop_set.TemplateType
87+
entity, prop_set.ApplicableEntity or "IfcRoot", predefined_type, prop_set.TemplateType, schema
8188
):
8289
result.append(prop_set)
8390
return result
8491

8592
@lru_cache()
86-
def get_applicable_names(self, ifc_class: str, predefined_type="", pset_only=False, qto_only=False) -> List[str]:
93+
def get_applicable_names(
94+
self,
95+
ifc_class: str,
96+
predefined_type: str = "",
97+
pset_only: bool = False,
98+
qto_only: bool = False,
99+
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
100+
) -> list[str]:
87101
"""Return names instead of objects for other use eg. enum"""
88-
return [prop_set.Name for prop_set in self.get_applicable(ifc_class, predefined_type, pset_only, qto_only)]
102+
return [
103+
prop_set.Name for prop_set in self.get_applicable(ifc_class, predefined_type, pset_only, qto_only, schema)
104+
]
89105

90106
def is_applicable(
91-
self, entity: entity_instance, applicables: str, predefined_type="", template_type="NOTDEFINED"
107+
self,
108+
entity: W.entity,
109+
applicables: str,
110+
predefined_type: str = "",
111+
template_type: str = "NOTDEFINED",
112+
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
92113
) -> bool:
93114
"""applicables can have multiple possible patterns :
94115
IfcBoilerType (IfcClass)
@@ -118,7 +139,7 @@ def is_applicable(
118139
# This will be fixed in IFC4.3
119140
template_type = template_type or ""
120141
if "TYPE" in template_type and ifcopenshell.util.schema.is_a(entity, "IfcTypeObject"):
121-
types = ifcopenshell.util.type.get_applicable_types(applicable_class, "IFC4")
142+
types = ifcopenshell.util.type.get_applicable_types(applicable_class, schema)
122143
if not types:
123144
# Abstract classes will not have an "applicable type" but
124145
# the implementer agreement still applies to them.

src/ifcopenshell-python/ifcopenshell/util/type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
type_to_entity_map[schema][element_type] = [e for e in elements if guessed_element in e]
5252

5353

54-
def get_applicable_types(ifc_class: str, schema="IFC4") -> list[str]:
54+
def get_applicable_types(ifc_class: str, schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4") -> list[str]:
5555
"""Get applicable types IFC classes for the occurrence IFC class.
5656
5757
E.g. "IfcWindow" -> ["IfcWindowType"].
@@ -60,7 +60,7 @@ def get_applicable_types(ifc_class: str, schema="IFC4") -> list[str]:
6060
return entity_to_type_map[schema].get(ifc_class, [])
6161

6262

63-
def get_applicable_entities(ifc_type_class: str, schema="IFC4") -> list[str]:
63+
def get_applicable_entities(ifc_type_class: str, schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4") -> list[str]:
6464
"""Get applicable occurrence IFC classes for the type IFC class.
6565
6666
E.g. "IfcWindowType" -> ["IfcWindow"].

src/ifcopenshell-python/test/util/test_pset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
class TestPsetQto:
2525
@classmethod
2626
def setup_class(cls):
27-
cls.pset_qto = util.pset.PsetQto("IFC4")
27+
cls.pset_qto = pset.PsetQto("IFC4")
2828

2929
def test_get_applicables(self):
3030
for i in range(1000):

0 commit comments

Comments
 (0)