mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
ifcopenshell.validate - fix IfcApplication.UR2 validation
Previously we were checking for just ApplicationFullName, without considering Version. https://github.com/buildingSMART/IFC4.3.x-development/issues/966
This commit is contained in:
@@ -116,12 +116,14 @@ simple_type_python_mapping = {
|
|||||||
|
|
||||||
|
|
||||||
def annotate_inst_attr_pos(
|
def annotate_inst_attr_pos(
|
||||||
inst: Union[ifcopenshell.entity_instance, W.HeaderEntity], pos: int, entity_str: str = ""
|
inst: Union[ifcopenshell.entity_instance, W.HeaderEntity],
|
||||||
|
pos: Union[int, tuple[int, ...]],
|
||||||
|
entity_str: str = "",
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Add a caret annotation to the entity string at the given attribute index.
|
"""Add a caret annotation to the entity string at the given attribute index.
|
||||||
|
|
||||||
:param inst: Instance to annotate.
|
:param inst: Instance to annotate.
|
||||||
:param pos: Attribute index to annotate.
|
:param pos: Attribute index or a tuple of them to annotate.
|
||||||
:param entity_str: Entity string to annotate. If not provided, ``str(inst)`` is used.
|
:param entity_str: Entity string to annotate. If not provided, ``str(inst)`` is used.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -132,7 +134,12 @@ def annotate_inst_attr_pos(
|
|||||||
# ^^^^^^^^
|
# ^^^^^^^^
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if isinstance(pos, int):
|
||||||
|
pos = (pos,)
|
||||||
|
|
||||||
def get_pos() -> Iterator[int]:
|
def get_pos() -> Iterator[int]:
|
||||||
|
# -1 - outside of entity attributes or on comma.
|
||||||
|
# >=0 - current attribute index
|
||||||
depth = 0
|
depth = 0
|
||||||
idx = -1
|
idx = -1
|
||||||
for c in entity_str or str(inst):
|
for c in entity_str or str(inst):
|
||||||
@@ -156,7 +163,7 @@ def annotate_inst_attr_pos(
|
|||||||
else:
|
else:
|
||||||
yield idx
|
yield idx
|
||||||
|
|
||||||
return "".join(" ^"[i == pos] for i in get_pos())
|
return "".join(" ^"[i in pos] for i in get_pos())
|
||||||
|
|
||||||
|
|
||||||
def format(val: Any) -> str:
|
def format(val: Any) -> str:
|
||||||
@@ -680,11 +687,11 @@ def validate_ifc_header(
|
|||||||
|
|
||||||
|
|
||||||
def validate_ifc_applications(f: ifcopenshell.file, logger: Union[Logger, json_logger]) -> None:
|
def validate_ifc_applications(f: ifcopenshell.file, logger: Union[Logger, json_logger]) -> None:
|
||||||
used_names: dict[str, ifcopenshell.entity_instance] = dict()
|
used_names: dict[tuple[str, str], ifcopenshell.entity_instance] = dict()
|
||||||
used_ids: dict[str, ifcopenshell.entity_instance] = dict()
|
used_ids: dict[str, ifcopenshell.entity_instance] = dict()
|
||||||
|
|
||||||
for inst in f.by_type("IfcApplication"):
|
for inst in f.by_type("IfcApplication"):
|
||||||
app_name: str = inst.ApplicationFullName
|
app_name: tuple[str, str] = (inst.ApplicationFullName, inst.Version)
|
||||||
app_id: str = inst.ApplicationIdentifier
|
app_id: str = inst.ApplicationIdentifier
|
||||||
|
|
||||||
if app_name is not None:
|
if app_name is not None:
|
||||||
@@ -693,15 +700,15 @@ def validate_ifc_applications(f: ifcopenshell.file, logger: Union[Logger, json_l
|
|||||||
else:
|
else:
|
||||||
if isinstance(logger, json_logger):
|
if isinstance(logger, json_logger):
|
||||||
logger.set_state("instance", inst)
|
logger.set_state("instance", inst)
|
||||||
rule = "Rule IfcApplication.UR2:\n The attribute ApplicationFullName should be unique"
|
rule = "Rule IfcApplication.UR2:\n The combination of attributes ApplicationFullName and Version should be unique"
|
||||||
previous_element = used_names[app_name]
|
previous_element = used_names[app_name]
|
||||||
logger.error(
|
logger.error(
|
||||||
"On instance:\n %s\n %s\n%s\nViolated by:\n %s\n %s",
|
"On instance:\n %s\n %s\n%s\nViolated by:\n %s\n %s",
|
||||||
inst,
|
inst,
|
||||||
annotate_inst_attr_pos(inst, 2),
|
annotate_inst_attr_pos(inst, (1, 2)),
|
||||||
rule,
|
rule,
|
||||||
previous_element,
|
previous_element,
|
||||||
annotate_inst_attr_pos(previous_element, 2),
|
annotate_inst_attr_pos(previous_element, (1, 2)),
|
||||||
)
|
)
|
||||||
|
|
||||||
if app_id is not None:
|
if app_id is not None:
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
ISO-10303-21;
|
||||||
|
HEADER;
|
||||||
|
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||||
|
FILE_NAME('','2022-10-01T16:31:47',(''),(''),'IfcOpenShell 0.7.0','IfcOpenShell 0.7.0','');
|
||||||
|
FILE_SCHEMA(('IFC4'));
|
||||||
|
ENDSEC;
|
||||||
|
DATA;
|
||||||
|
#1=IFCORGANIZATION('IfcOpenShell','IfcOpenShell','',$,$);
|
||||||
|
#2=IFCAPPLICATION(#1,'0.0.0','Bonsai','Bonsai1');
|
||||||
|
#3=IFCAPPLICATION(#1,'0.0.1','Bonsai','Bonsai2');
|
||||||
|
ENDSEC;
|
||||||
|
END-ISO-10303-21;
|
||||||
Reference in New Issue
Block a user