mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
ifcopenshell.validate to validate guids #5808
This commit is contained in:
@@ -36,6 +36,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import functools
|
import functools
|
||||||
|
import types
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from typing import Union, Iterator, Any, Optional
|
from typing import Union, Iterator, Any, Optional
|
||||||
@@ -403,8 +404,8 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
|||||||
if hasattr(logger, "set_state"):
|
if hasattr(logger, "set_state"):
|
||||||
logger.set_state("instance", inst)
|
logger.set_state("instance", inst)
|
||||||
|
|
||||||
if hasattr(inst, "GlobalId"):
|
guid: Union[str, None, types.EllipsisType]
|
||||||
guid = inst.GlobalId
|
if (guid := getattr(inst, "GlobalId", ...)) is not ...:
|
||||||
if guid is not None and guid in used_guids:
|
if guid is not None and guid in used_guids:
|
||||||
rule = "Rule IfcRoot.UR1:\n The attribute GlobalId should be unique"
|
rule = "Rule IfcRoot.UR1:\n The attribute GlobalId should be unique"
|
||||||
previous_element = used_guids[guid]
|
previous_element = used_guids[guid]
|
||||||
@@ -417,7 +418,19 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
|||||||
annotate_inst_attr_pos(previous_element, 0),
|
annotate_inst_attr_pos(previous_element, 0),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
used_guids[guid] = inst
|
if guid is not None:
|
||||||
|
if (validation_error := validate_guid(guid)) is None:
|
||||||
|
used_guids[guid] = inst
|
||||||
|
else:
|
||||||
|
rule = "IfcGloballyUniqueId base64 validation:\n The attribute GlobalId should be valid base64 encoded 128-bit number."
|
||||||
|
previous_element = None
|
||||||
|
logger.error(
|
||||||
|
"On instance:\n %s\n %s\n%s\nViolated by:\n %s\n",
|
||||||
|
inst,
|
||||||
|
annotate_inst_attr_pos(inst, 0),
|
||||||
|
rule,
|
||||||
|
validation_error,
|
||||||
|
)
|
||||||
|
|
||||||
entity, attrs = get_entity_attributes(schema, inst.is_a())
|
entity, attrs = get_entity_attributes(schema, inst.is_a())
|
||||||
|
|
||||||
@@ -528,6 +541,28 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
|||||||
ifcopenshell.express.rule_executor.run(f, logger)
|
ifcopenshell.express.rule_executor.run(f, logger)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_guid(guid: str) -> Union[str, None]:
|
||||||
|
"""Check if a given guid is valid.
|
||||||
|
|
||||||
|
Don't check for `None` as `None` guid will trigger "non-optional" validation error either way.
|
||||||
|
|
||||||
|
:return: `None` if guid is valid, otherwise a string with an error message.
|
||||||
|
"""
|
||||||
|
if len(guid) != 22:
|
||||||
|
return "Guid length should be 22 characters."
|
||||||
|
if guid[0] not in "0123":
|
||||||
|
return "Guid first character must be either a 0, 1, 2, or 3."
|
||||||
|
try:
|
||||||
|
ifcopenshell.guid.expand(guid)
|
||||||
|
except:
|
||||||
|
allowed_characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$"
|
||||||
|
if any(c for c in guid if c not in allowed_characters):
|
||||||
|
return "Guid contains invalid characters, allowed characters: '%s'." % allowed_characters
|
||||||
|
# NOTE: are there actually cases where guid won't expand, besides invalid characters?
|
||||||
|
return "Couldn't decompress guid, it's not base64 encoded."
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def validate_ifc_header(f: ifcopenshell.file, logger: Logger) -> None:
|
def validate_ifc_header(f: ifcopenshell.file, logger: Logger) -> None:
|
||||||
header: W.IfcSpfHeader = f.wrapped_data.header
|
header: W.IfcSpfHeader = f.wrapped_data.header
|
||||||
AGGREGATE_TYPE = "LIST [ 1 : ? ] OF STRING (256)"
|
AGGREGATE_TYPE = "LIST [ 1 : ? ] OF STRING (256)"
|
||||||
|
|||||||
Reference in New Issue
Block a user