mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 14:33:28 +00:00
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:
@@ -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)
|
||||||
|
|||||||
@@ -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():
|
||||||
|
|||||||
Reference in New Issue
Block a user