mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
IfcTester can now read from XML strings in addition to opening files on disk
This commit is contained in:
@@ -50,11 +50,7 @@ class IdsXmlValidationError(Exception):
|
|||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
@overload
|
def open(filepath: str, validate: bool = False) -> Ids:
|
||||||
def open(filepath: str, validate: Literal[False] = False) -> Ids: ...
|
|
||||||
@overload
|
|
||||||
def open(filepath: str, validate: Literal[True]) -> None: ...
|
|
||||||
def open(filepath: str, validate=False) -> Union[Ids, None]:
|
|
||||||
try:
|
try:
|
||||||
if validate:
|
if validate:
|
||||||
get_schema().validate(filepath)
|
get_schema().validate(filepath)
|
||||||
@@ -66,6 +62,19 @@ def open(filepath: str, validate=False) -> Union[Ids, None]:
|
|||||||
return Ids().parse(decode)
|
return Ids().parse(decode)
|
||||||
|
|
||||||
|
|
||||||
|
def from_string(xml: str, validate: bool = False) -> Ids:
|
||||||
|
tree = ET.ElementTree(ET.fromstring(xml))
|
||||||
|
try:
|
||||||
|
if validate:
|
||||||
|
get_schema().validate(tree)
|
||||||
|
decode = get_schema().decode(
|
||||||
|
tree, strip_namespaces=True, namespaces={"": "http://standards.buildingsmart.org/IDS"}
|
||||||
|
)
|
||||||
|
except XMLSchemaValidationError as e:
|
||||||
|
raise IdsXmlValidationError(e, "Provided XML appears to be invalid. See details above.")
|
||||||
|
return Ids().parse(decode)
|
||||||
|
|
||||||
|
|
||||||
def get_schema():
|
def get_schema():
|
||||||
global schema
|
global schema
|
||||||
if schema is None:
|
if schema is None:
|
||||||
|
|||||||
@@ -65,6 +65,15 @@ class TestIds:
|
|||||||
"specifications": {"specification": []},
|
"specifications": {"specification": []},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def test_reading_an_ids_from_an_xml_string(self):
|
||||||
|
specs = ids.Ids()
|
||||||
|
spec = ids.Specification(name="Name")
|
||||||
|
spec.applicability.append(ids.Entity(name="IFCWALL"))
|
||||||
|
specs.specifications.append(spec)
|
||||||
|
xml = specs.to_string()
|
||||||
|
specs2 = ids.from_string(xml)
|
||||||
|
assert len(specs2.specifications) == 1
|
||||||
|
|
||||||
def test_create_an_ids_with_all_possible_information(self):
|
def test_create_an_ids_with_all_possible_information(self):
|
||||||
specs = ids.Ids(
|
specs = ids.Ids(
|
||||||
title="title",
|
title="title",
|
||||||
@@ -117,7 +126,7 @@ class TestIds:
|
|||||||
spec.requirements.append(ids.Attribute(name="Name", value="Waldo"))
|
spec.requirements.append(ids.Attribute(name="Name", value="Waldo"))
|
||||||
specs.specifications.append(spec)
|
specs.specifications.append(spec)
|
||||||
fn = "tmp.xml"
|
fn = "tmp.xml"
|
||||||
result = specs.to_xml(fn)
|
specs.to_xml(fn)
|
||||||
os.remove(fn)
|
os.remove(fn)
|
||||||
|
|
||||||
def test_creating_a_minimal_ids_and_validating(self):
|
def test_creating_a_minimal_ids_and_validating(self):
|
||||||
@@ -187,27 +196,11 @@ class TestIds:
|
|||||||
spec.set_usage("optional")
|
spec.set_usage("optional")
|
||||||
model = ifcopenshell.file()
|
model = ifcopenshell.file()
|
||||||
wall = model.createIfcWall(Name="Waldo")
|
wall = model.createIfcWall(Name="Waldo")
|
||||||
spec.requirements.append(description_attr := ids.Attribute(name="Description", value="Foobar"))
|
spec.requirements.append(ids.Attribute(name="Description", value="Foobar"))
|
||||||
run("A specification passes only if all requirements pass 1/2", specs, model, False, [wall], [wall])
|
run("A specification passes only if all requirements pass 1/2", specs, model, False, [wall], [wall])
|
||||||
wall.Description = "Foobar"
|
wall.Description = "Foobar"
|
||||||
run("A specification passes only if all requirements pass 2/2", specs, model, True, [wall])
|
run("A specification passes only if all requirements pass 2/2", specs, model, True, [wall])
|
||||||
|
|
||||||
# optional attribute
|
|
||||||
# description_attr.minOccurs = 0
|
|
||||||
# description_attr.maxOccurs = "unbounded"
|
|
||||||
# wall.Description = None
|
|
||||||
# run("Specification optionality and facet optionality can be combined", specs, model, True, [wall])
|
|
||||||
|
|
||||||
# double negative / required attributes
|
|
||||||
# spec.set_usage("prohibited")
|
|
||||||
# name_attr.minOccurs = 0
|
|
||||||
# name_attr.maxOccurs = 0
|
|
||||||
# description_attr.minOccurs = 0
|
|
||||||
# description_attr.maxOccurs = 0
|
|
||||||
# wall.Name = "Waldo"
|
|
||||||
# wall.Description = "Foobar"
|
|
||||||
# run("A prohibited specification and a prohibited facet results in a double negative", specs, model, True, [wall])
|
|
||||||
|
|
||||||
# specs independency
|
# specs independency
|
||||||
specs = ids.Ids(title="Title")
|
specs = ids.Ids(title="Title")
|
||||||
spec = ids.Specification(name="Name")
|
spec = ids.Specification(name="Name")
|
||||||
|
|||||||
Reference in New Issue
Block a user