ifctester to fail more gracefully meeting invalid .ids file

Previously Bonsai would show a wall of errors, now it's show a simple error message and redirecting to system console for the details.

Example error - https://i.imgur.com/uJJfjUW.png
Example validation error details in console - https://i.imgur.com/3mcVBUh.png

Same details but in text:
Validation error details:

failed validating {'dataType': 'IFCBOOLEAN', 'ursi': 'https://google.com', 'cardinality': 'required', 'instructions': "Make sure it's true"} with XsdAttributeGroup(['dataType', 'uri', 'cardinality', 'instructions']):

Reason: 'ursi' attribute not allowed for element

Schema component:

  <xs:extension xmlns:xs="http://www.w3.org/2001/XMLSchema" base="ids:propertyType">
      <xs:attribute name="uri" type="xs:anyURI" use="optional" />
      <xs:attribute name="cardinality" type="ids:conditionalCardinality" use="optional" default="required" />
      <xs:attribute name="instructions" type="xs:string" use="optional">
          <xs:annotation>
              <xs:documentation>Author of the IDS can leave instructions for the authors of the IFC. This text could/should be displayed in the BIM/IFC authoring tool.</xs:documentation>
          </xs:annotation>
      </xs:attribute>
  </xs:extension>

Instance type: <class 'xml.etree.ElementTree.Element'>

Instance:

  <ids:property xmlns:ids="http://standards.buildingsmart.org/IDS" dataType="IFCBOOLEAN" ursi="https://google.com" cardinality="required" instructions="Make sure it's true">
    <ids:propertySet>
      <ids:simpleValue>Pset_WallCommon</ids:simpleValue>
    </ids:propertySet>
    <ids:baseName>
      <ids:simpleValue>Combustible</ids:simpleValue>
    </ids:baseName>
    <ids:value>
      <ids:simpleValue>false</ids:simpleValue>
    </ids:value>
  </ids:property>

Path: /ids:ids/ids:specifications/ids:specification/ids:requirements/ids:property[1]
This commit is contained in:
Andrej730
2024-11-08 14:48:43 +05:00
parent 0a7ee4e360
commit f7a7626575
2 changed files with 30 additions and 6 deletions
@@ -21,6 +21,7 @@ import bpy
import time import time
import tempfile import tempfile
import webbrowser import webbrowser
import traceback
import ifctester import ifctester
import ifctester.ids import ifctester.ids
import ifctester.reporter import ifctester.reporter
@@ -72,7 +73,19 @@ class ExecuteIfcTester(bpy.types.Operator, tool.Ifc.Operator):
start = time.time() start = time.time()
output = Path(os.path.join(dirpath, "{}_{}.html".format(ifc_path, os.path.basename(specs_path)))) output = Path(os.path.join(dirpath, "{}_{}.html".format(ifc_path, os.path.basename(specs_path))))
specs = ifctester.ids.open(specs_path) try:
specs = ifctester.ids.open(specs_path)
except ifctester.ids.IdsXmlValidationError as e:
traceback.print_exc()
YELLOW = "\033[93m"
RESET = "\033[0m"
print("------------------\n" * 3)
print(f"{YELLOW}Validation error details:\n\n{str(e.xml_error)}{RESET}")
print("------------------\n" * 3)
self.report(
{"ERROR"}, "Provided IDS file appears to be invalid. Open system console to see the details."
)
return {"CANCELLED"}
print("Finished loading:", time.time() - start) print("Finished loading:", time.time() - start)
start = time.time() start = time.time()
specs.validate(ifc_data, filepath=ifc_path) specs.validate(ifc_data, filepath=ifc_path)
+16 -5
View File
@@ -20,6 +20,7 @@ from __future__ import annotations
import os import os
import datetime import datetime
import ifcopenshell import ifcopenshell
from xmlschema.validators.exceptions import XMLSchemaValidationError
from xmlschema import XMLSchema from xmlschema import XMLSchema
from xmlschema import etree_tostring from xmlschema import etree_tostring
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
@@ -43,16 +44,26 @@ cwd = os.path.dirname(os.path.realpath(__file__))
schema = None schema = None
class IdsXmlValidationError(Exception):
def __init__(self, xml_error: XMLSchemaValidationError, message: str):
self.xml_error = xml_error
super().__init__(message)
@overload @overload
def open(filepath: str, validate: Literal[False] = False) -> Ids: ... def open(filepath: str, validate: Literal[False] = False) -> Ids: ...
@overload @overload
def open(filepath: str, validate: Literal[True]) -> None: ... def open(filepath: str, validate: Literal[True]) -> None: ...
def open(filepath: str, validate=False) -> Union[Ids, None]: def open(filepath: str, validate=False) -> Union[Ids, None]:
if validate: try:
get_schema().validate(filepath) if validate:
return Ids().parse( get_schema().validate(filepath)
get_schema().decode(filepath, strip_namespaces=True, namespaces={"": "http://standards.buildingsmart.org/IDS"}) decode = get_schema().decode(
) filepath, strip_namespaces=True, namespaces={"": "http://standards.buildingsmart.org/IDS"}
)
except XMLSchemaValidationError as e:
raise IdsXmlValidationError(e, f"Provided .ids file ({filepath}) appears to be invalid. See details above.")
return Ids().parse(decode)
def get_schema(): def get_schema():