fix get_applicable_entities / get_applicable_types missing schema #6108

This commit is contained in:
Andrej730
2025-02-07 17:52:28 +05:00
committed by Dion Moult
parent a28070afef
commit 59dd105e99
11 changed files with 65 additions and 31 deletions
@@ -176,12 +176,12 @@ class Usecase:
element = self.reassign_class(element, ifc_class, predefined_type)
if element.is_a("IfcTypeProduct"):
for occurrence in ifcopenshell.util.element.get_types(element):
ifc_class_ = ifcopenshell.util.type.get_applicable_entities(ifc_class)[0]
ifc_class_ = ifcopenshell.util.type.get_applicable_entities(ifc_class, self.file.schema)[0]
self.reassign_class(occurrence, ifc_class_, predefined_type)
else:
element_type = ifcopenshell.util.element.get_type(element)
if element_type:
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class)))
ifc_class_ = next(iter(ifcopenshell.util.type.get_applicable_types(ifc_class, self.file.schema)))
element_type = self.reassign_class(element_type, ifc_class_, predefined_type)
ifc_class = element.is_a()
for occurrence in ifcopenshell.util.element.get_types(element_type):
@@ -19,11 +19,12 @@
import re
import pathlib
import ifcopenshell
import ifcopenshell.ifcopenshell_wrapper as W
import ifcopenshell.util.schema
import ifcopenshell.util.type
from ifcopenshell.entity_instance import entity_instance
from functools import lru_cache
from typing import List, Optional, Literal
from typing import Optional, Literal
templates: dict[str, "PsetQto"] = {}
@@ -62,10 +63,16 @@ class PsetQto:
@lru_cache()
def get_applicable(
self, ifc_class="", predefined_type="", pset_only=False, qto_only=False
) -> List[entity_instance]:
self,
ifc_class="",
predefined_type="",
pset_only=False,
qto_only=False,
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
) -> list[entity_instance]:
any_class = not ifc_class
if not any_class:
entity: W.entity
entity = self.schema.declaration_by_name(ifc_class)
result = []
for template in self.templates:
@@ -77,18 +84,32 @@ class PsetQto:
if prop_set.TemplateType and prop_set.TemplateType.startswith("PSET_"):
continue
if any_class or self.is_applicable(
entity, prop_set.ApplicableEntity or "IfcRoot", predefined_type, prop_set.TemplateType
entity, prop_set.ApplicableEntity or "IfcRoot", predefined_type, prop_set.TemplateType, schema
):
result.append(prop_set)
return result
@lru_cache()
def get_applicable_names(self, ifc_class: str, predefined_type="", pset_only=False, qto_only=False) -> List[str]:
def get_applicable_names(
self,
ifc_class: str,
predefined_type: str = "",
pset_only: bool = False,
qto_only: bool = False,
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
) -> list[str]:
"""Return names instead of objects for other use eg. enum"""
return [prop_set.Name for prop_set in self.get_applicable(ifc_class, predefined_type, pset_only, qto_only)]
return [
prop_set.Name for prop_set in self.get_applicable(ifc_class, predefined_type, pset_only, qto_only, schema)
]
def is_applicable(
self, entity: entity_instance, applicables: str, predefined_type="", template_type="NOTDEFINED"
self,
entity: W.entity,
applicables: str,
predefined_type: str = "",
template_type: str = "NOTDEFINED",
schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4",
) -> bool:
"""applicables can have multiple possible patterns :
IfcBoilerType (IfcClass)
@@ -118,7 +139,7 @@ class PsetQto:
# This will be fixed in IFC4.3
template_type = template_type or ""
if "TYPE" in template_type and ifcopenshell.util.schema.is_a(entity, "IfcTypeObject"):
types = ifcopenshell.util.type.get_applicable_types(applicable_class, "IFC4")
types = ifcopenshell.util.type.get_applicable_types(applicable_class, schema)
if not types:
# Abstract classes will not have an "applicable type" but
# the implementer agreement still applies to them.
@@ -51,7 +51,7 @@ for schema in mapped_schemas:
type_to_entity_map[schema][element_type] = [e for e in elements if guessed_element in e]
def get_applicable_types(ifc_class: str, schema="IFC4") -> list[str]:
def get_applicable_types(ifc_class: str, schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4") -> list[str]:
"""Get applicable types IFC classes for the occurrence IFC class.
E.g. "IfcWindow" -> ["IfcWindowType"].
@@ -60,7 +60,7 @@ def get_applicable_types(ifc_class: str, schema="IFC4") -> list[str]:
return entity_to_type_map[schema].get(ifc_class, [])
def get_applicable_entities(ifc_type_class: str, schema="IFC4") -> list[str]:
def get_applicable_entities(ifc_type_class: str, schema: ifcopenshell.util.schema.IFC_SCHEMA = "IFC4") -> list[str]:
"""Get applicable occurrence IFC classes for the type IFC class.
E.g. "IfcWindowType" -> ["IfcWindow"].
@@ -24,7 +24,7 @@ from ifcopenshell import util
class TestPsetQto:
@classmethod
def setup_class(cls):
cls.pset_qto = util.pset.PsetQto("IFC4")
cls.pset_qto = pset.PsetQto("IFC4")
def test_get_applicables(self):
for i in range(1000):