ifctester.Specification.set_usage convenience method

sets minOccurs and maxOccurs according to the agreement mentioned in the latest ids.xsd
https://github.com/buildingSMART/IDS/blob/6d71cdf3547a0383c6cfbbead81a7cef7521ac3a/Development/ids.xsd#L67-L72
This commit is contained in:
Andrej730
2024-04-01 12:12:19 +05:00
parent 7be396474c
commit 5c398428c3
2 changed files with 25 additions and 19 deletions
+15 -4
View File
@@ -264,11 +264,11 @@ class Specification:
is_pass = bool(result) is_pass = bool(result)
if facet.cardinality == "prohibited": if facet.cardinality == "prohibited":
is_pass = not is_pass is_pass = not is_pass
if self.maxOccurs != 0: # This is a required or optional specification if self.maxOccurs != 0: # This is a required or optional specification
if not is_pass: if not is_pass:
self.failed_entities.add(element) self.failed_entities.add(element)
facet.failures.append({"element": element, "reason": str(result)}) facet.failures.append({"element": element, "reason": str(result)})
else: # This is a prohibited specification else: # This is a prohibited specification
if is_pass: if is_pass:
self.failed_entities.add(element) self.failed_entities.add(element)
facet.failures.append({"element": element, "reason": str(result)}) facet.failures.append({"element": element, "reason": str(result)})
@@ -279,12 +279,12 @@ class Specification:
if not facet.status: if not facet.status:
self.status = False self.status = False
if self.minOccurs != 0: # Required specification if self.minOccurs != 0: # Required specification
if not self.applicable_entities: if not self.applicable_entities:
self.status = False self.status = False
for facet in self.requirements: for facet in self.requirements:
facet.status = False facet.status = False
elif self.maxOccurs == 0: # Prohibited specification elif self.maxOccurs == 0: # Prohibited specification
if self.applicable_entities and not self.requirements: if self.applicable_entities and not self.requirements:
self.status = False self.status = False
@@ -295,3 +295,14 @@ class Specification:
return "optional" return "optional"
elif self.maxOccurs == 0: elif self.maxOccurs == 0:
return "prohibited" return "prohibited"
def set_usage(self, usage: Cardinality) -> None:
if usage == "optional":
self.minOccurs = 0
self.maxOccurs = "unbounded"
elif usage == "prohibited":
self.minOccurs = 0
self.maxOccurs = 0
else: # required
self.minOccurs = 1
self.maxOccurs = "unbounded"
+10 -15
View File
@@ -146,7 +146,7 @@ class TestIds:
) )
spec.ifcVersion = [] spec.ifcVersion = []
spec.minOccurs = 1 spec.set_usage("required")
model = ifcopenshell.file() model = ifcopenshell.file()
waldo = model.createIfcWall(Name="Waldo") waldo = model.createIfcWall(Name="Waldo")
run("Required specifications need at least one applicable entity 1/2", specs, model, True, [waldo]) run("Required specifications need at least one applicable entity 1/2", specs, model, True, [waldo])
@@ -154,13 +154,12 @@ class TestIds:
waldo = model.createIfcSlab(Name="Waldo") waldo = model.createIfcSlab(Name="Waldo")
run("Required specifications need at least one applicable entity 2/2", specs, model, False) run("Required specifications need at least one applicable entity 2/2", specs, model, False)
spec.minOccurs = 0 spec.set_usage("optional")
model = ifcopenshell.file() model = ifcopenshell.file()
waldo = model.createIfcSlab(Name="Waldo") waldo = model.createIfcSlab(Name="Waldo")
run("Optional specifications may still pass if nothing is applicable", specs, model, True) run("Optional specifications may still pass if nothing is applicable", specs, model, True)
spec.minOccurs = 0 spec.set_usage("prohibited")
spec.maxOccurs = 0
model = ifcopenshell.file() model = ifcopenshell.file()
wall = model.createIfcSlab(Name="Waldo") wall = model.createIfcSlab(Name="Waldo")
run("Prohibited specifications fail if at least one entity passes all requirements 1/3", specs, model, True) run("Prohibited specifications fail if at least one entity passes all requirements 1/3", specs, model, True)
@@ -185,8 +184,7 @@ class TestIds:
[wall], [wall],
) )
spec.minOccurs = 0 spec.set_usage("optional")
spec.maxOccurs = "unbounded"
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(description_attr := ids.Attribute(name="Description", value="Foobar"))
@@ -201,8 +199,7 @@ class TestIds:
# run("Specification optionality and facet optionality can be combined", specs, model, True, [wall]) # run("Specification optionality and facet optionality can be combined", specs, model, True, [wall])
# double negative / required attributes # double negative / required attributes
# spec.minOccurs = 0 # spec.set_usage("prohibited")
# spec.maxOccurs = 0
# name_attr.minOccurs = 0 # name_attr.minOccurs = 0
# name_attr.maxOccurs = 0 # name_attr.maxOccurs = 0
# description_attr.minOccurs = 0 # description_attr.minOccurs = 0
@@ -292,7 +289,7 @@ class TestSpecification:
spec = ids.Specification(name="Name") spec = ids.Specification(name="Name")
spec.applicability.append(ids.Entity(name="IFCWALL")) spec.applicability.append(ids.Entity(name="IFCWALL"))
test_ids.specifications.append(spec) test_ids.specifications.append(spec)
spec.minOccurs = 1 spec.set_usage("required")
run( run(
"A specification that is required and has at least one applicable entity but no requirements shall pass", "A specification that is required and has at least one applicable entity but no requirements shall pass",
test_ids, test_ids,
@@ -305,7 +302,7 @@ class TestSpecification:
test_ids = ids.Ids(title="Title") test_ids = ids.Ids(title="Title")
spec = ids.Specification(name="Name") spec = ids.Specification(name="Name")
test_ids.specifications.append(spec) test_ids.specifications.append(spec)
spec.minOccurs = 1 spec.set_usage("required")
run( run(
"A specification that is required but has no applicable entities or requirements shall fail", "A specification that is required but has no applicable entities or requirements shall fail",
test_ids, test_ids,
@@ -319,7 +316,7 @@ class TestSpecification:
spec = ids.Specification(name="Name") spec = ids.Specification(name="Name")
spec.applicability.append(ids.Entity(name="IFCWALL")) spec.applicability.append(ids.Entity(name="IFCWALL"))
test_ids.specifications.append(spec) test_ids.specifications.append(spec)
spec.minOccurs = 0 spec.set_usage("optional")
run( run(
"A specification that is optional and has at least one applicable entity but no requirements shall pass", "A specification that is optional and has at least one applicable entity but no requirements shall pass",
test_ids, test_ids,
@@ -333,8 +330,7 @@ class TestSpecification:
spec = ids.Specification(name="Name") spec = ids.Specification(name="Name")
spec.applicability.append(ids.Entity(name="IFCWALL")) spec.applicability.append(ids.Entity(name="IFCWALL"))
test_ids.specifications.append(spec) test_ids.specifications.append(spec)
spec.minOccurs = 0 spec.set_usage("prohibited")
spec.maxOccurs = 0
run( run(
"A specification that is prohibited and has at least one applicable entity but no requirements shall fail", "A specification that is prohibited and has at least one applicable entity but no requirements shall fail",
test_ids, test_ids,
@@ -347,8 +343,7 @@ class TestSpecification:
test_ids = ids.Ids(title="Title") test_ids = ids.Ids(title="Title")
spec = ids.Specification(name="Name") spec = ids.Specification(name="Name")
test_ids.specifications.append(spec) test_ids.specifications.append(spec)
spec.minOccurs = 0 spec.set_usage("prohibited")
spec.maxOccurs = 0
run( run(
"A specification that is prohibited but has no applicable entities or requirements shall pass", "A specification that is prohibited but has no applicable entities or requirements shall pass",
test_ids, test_ids,