Fix incorrect handling of prohibited specifications

This commit is contained in:
Dion Moult
2024-03-30 00:13:02 +11:00
parent 1ab24e8362
commit 0065c5fba8
2 changed files with 27 additions and 24 deletions
+19 -19
View File
@@ -259,31 +259,31 @@ class Specification:
self.applicable_entities.append(element)
for facet in self.requirements:
result = facet(element)
if not bool(result):
self.failed_entities.add(element)
facet.failures.append({"element": element, "reason": str(result)})
for facet in self.requirements:
if facet.cardinality == "required":
facet.status = not bool(facet.failures)
elif facet.cardinality == "optional":
facet.status = True
elif facet.cardinality == "prohibited":
facet.status = bool(facet.failures)
is_pass = bool(result)
if facet.cardinality == "prohibited":
is_pass = not is_pass
if self.maxOccurs != 0: # This is a required or optional specification
if not is_pass:
self.failed_entities.add(element)
facet.failures.append({"element": element, "reason": str(result)})
else: # This is a prohibited specification
if is_pass:
self.failed_entities.add(element)
facet.failures.append({"element": element, "reason": str(result)})
self.status = True
if self.minOccurs != 0:
for facet in self.requirements:
facet.status = not bool(facet.failures)
if not facet.status:
self.status = False
if self.minOccurs != 0: # Required specification
if not self.applicable_entities:
self.status = False
for facet in self.requirements:
facet.status = False
elif self.failed_entities:
self.status = False
elif self.minOccurs == 0 and self.maxOccurs != 0:
if self.failed_entities:
self.status = False
elif self.maxOccurs == 0:
if (len(self.applicable_entities)) > 0:
elif self.maxOccurs == 0: # Prohibited specification
if self.applicable_entities and not self.requirements:
self.status = False
def get_usage(self):
+8 -5
View File
@@ -36,7 +36,7 @@ def run(name, ids, ifc, expected, applicable_entities=None, failed_entities=None
all_applicable.update(spec.applicable_entities)
for requirement in spec.requirements:
if requirement.status is False:
all_failures.update(requirement.failed_entities)
all_failures.update([f["element"] for f in requirement.failures])
assert set(all_applicable) == set(applicable_entities)
assert set(all_failures) == set(failed_entities)
@@ -162,9 +162,9 @@ class TestIds:
"Prohibited specifications fail if at least one entity passes all requirements 2/3",
specs,
model,
False,
[wall],
True,
[wall],
[],
)
model = ifcopenshell.file()
wall = model.createIfcWall(Name="Waldo")
@@ -174,6 +174,7 @@ class TestIds:
model,
False,
[wall],
[wall],
)
spec.minOccurs = 0
@@ -238,8 +239,10 @@ class TestIds:
assert spec.status == False
assert set(spec.applicable_entities) == {wall, waldo}
assert spec.requirements[0].failed_entities == [wall]
assert spec2.requirements[0].failed_entities == [wall]
assert len(spec.requirements[0].failures) == 1
assert len(spec2.requirements[0].failures) == 1
assert spec.requirements[0].failures[0]["element"] == wall
assert spec2.requirements[0].failures[0]["element"] == wall
class TestSpecification: