mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
ifcopenshell.validate to validate ifc header #4119
This commit is contained in:
@@ -43,6 +43,7 @@ from logging import Logger, Handler
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.ifcopenshell_wrapper
|
||||
import ifcopenshell.ifcopenshell_wrapper as W
|
||||
import ifcopenshell.express.rule_executor
|
||||
|
||||
named_type = ifcopenshell.ifcopenshell_wrapper.named_type
|
||||
@@ -95,11 +96,13 @@ simple_type_python_mapping = {
|
||||
}
|
||||
|
||||
|
||||
def annotate_inst_attr_pos(inst: ifcopenshell.entity_instance, pos: int) -> str:
|
||||
def annotate_inst_attr_pos(
|
||||
inst: Union[ifcopenshell.entity_instance, W.HeaderEntity], pos: int, entity_str: str = ""
|
||||
) -> str:
|
||||
def get_pos() -> Iterator[int]:
|
||||
depth = 0
|
||||
idx = -1
|
||||
for c in str(inst):
|
||||
for c in entity_str or str(inst):
|
||||
if c == "(":
|
||||
depth += 1
|
||||
if depth == 1:
|
||||
@@ -389,6 +392,8 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
||||
|
||||
log_internal_cpp_errors(f, filename, logger)
|
||||
|
||||
validate_ifc_header(f, logger)
|
||||
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema_identifier)
|
||||
used_guids: dict[str, ifcopenshell.entity_instance] = dict()
|
||||
|
||||
@@ -521,6 +526,61 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
||||
ifcopenshell.express.rule_executor.run(f, logger)
|
||||
|
||||
|
||||
def validate_ifc_header(f: ifcopenshell.file, logger: Logger) -> None:
|
||||
header: W.IfcSpfHeader = f.wrapped_data.header
|
||||
AGGREGATE_TYPE = "LIST [ 1 : ? ] OF STRING (256)"
|
||||
STRING_TYPE = "STRING (256)"
|
||||
|
||||
def log_error(header_entity: W.HeaderEntity, name: str, index: int, expected_type: str, provided_type: str) -> None:
|
||||
logger.error(
|
||||
(
|
||||
"For instance:\n %s\n %s\n"
|
||||
"Attribute '%s' has invalid type:\n"
|
||||
" Expected: %s\n Current value type: %s\n"
|
||||
),
|
||||
(s := header_entity.toString()),
|
||||
annotate_inst_attr_pos(header_entity, index, s),
|
||||
name,
|
||||
expected_type,
|
||||
provided_type,
|
||||
)
|
||||
|
||||
def validate_attribute(header_entity: W.HeaderEntity, name: str, index: int, *, aggregate: bool = False) -> None:
|
||||
value = getattr(header_entity, name)
|
||||
if aggregate:
|
||||
if not isinstance(value, tuple):
|
||||
log_error(header_entity, name, index, AGGREGATE_TYPE, type(value).__name__)
|
||||
return
|
||||
if not value:
|
||||
log_error(header_entity, name, index, AGGREGATE_TYPE, "EMPTY LIST")
|
||||
return
|
||||
if not all(isinstance(last_value := v, str) for v in value):
|
||||
log_error(
|
||||
header_entity,
|
||||
name,
|
||||
index,
|
||||
AGGREGATE_TYPE,
|
||||
f"LIST with {type(last_value).__name__} (value: {last_value})",
|
||||
)
|
||||
return
|
||||
|
||||
if not isinstance(value, str):
|
||||
log_error(header_entity, name, index, STRING_TYPE, type(value).__name__)
|
||||
|
||||
# Ignore header.file_schema as file won't load to IfcOpenShell with invalid file_schema.
|
||||
file_description: W.FileDescription = header.file_description
|
||||
validate_attribute(file_description, "description", 0, aggregate=True)
|
||||
validate_attribute(file_description, "implementation_level", 1)
|
||||
file_name: W.FileName = header.file_name
|
||||
validate_attribute(file_name, "name", 0)
|
||||
validate_attribute(file_name, "time_stamp", 1)
|
||||
validate_attribute(file_name, "author", 2, aggregate=True)
|
||||
validate_attribute(file_name, "organization", 3, aggregate=True)
|
||||
validate_attribute(file_name, "preprocessor_version", 4)
|
||||
validate_attribute(file_name, "originating_system", 5)
|
||||
validate_attribute(file_name, "authorization", 6)
|
||||
|
||||
|
||||
class LogDetectionHandler(Handler):
|
||||
message_logged = False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user