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 json
|
||||
import functools
|
||||
import types
|
||||
|
||||
from collections import namedtuple
|
||||
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"):
|
||||
logger.set_state("instance", inst)
|
||||
|
||||
if hasattr(inst, "GlobalId"):
|
||||
guid = inst.GlobalId
|
||||
guid: Union[str, None, types.EllipsisType]
|
||||
if (guid := getattr(inst, "GlobalId", ...)) is not ...:
|
||||
if guid is not None and guid in used_guids:
|
||||
rule = "Rule IfcRoot.UR1:\n The attribute GlobalId should be unique"
|
||||
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),
|
||||
)
|
||||
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())
|
||||
|
||||
@@ -528,6 +541,28 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
||||
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:
|
||||
header: W.IfcSpfHeader = f.wrapped_data.header
|
||||
AGGREGATE_TYPE = "LIST [ 1 : ? ] OF STRING (256)"
|
||||
|
||||
Reference in New Issue
Block a user