Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
aothms committed Sep 18, 2023
2 parents 95ff46b + 7341440 commit d8610c2
Show file tree
Hide file tree
Showing 14 changed files with 3,367 additions and 18 deletions.
6 changes: 3 additions & 3 deletions features/ALB002_Alignment-layout.feature
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ This rule verifies that (a) alignment has a nesting relationship with its layout
Given an IfcAlignmentSegment
And The element nests an IfcAlignmentHorizontal

Then The type of attribute DesignParameters should be IfcAlignmentHorizontalSegment
Then The type of attribute DesignParameters must be IfcAlignmentHorizontalSegment

Scenario: Agreement of the segments of the vertical alignment

Given an IfcAlignmentSegment
And The element nests an IfcAlignmentVertical

Then The type of attribute DesignParameters should be IfcAlignmentVerticalSegment
Then The type of attribute DesignParameters must be IfcAlignmentVerticalSegment

Scenario: Agreement of the segments of the cant alignment

Given an IfcAlignmentSegment
And The element nests an IfcAlignmentCant

Then The type of attribute DesignParameters should be IfcAlignmentCantSegment
Then The type of attribute DesignParameters must be IfcAlignmentCantSegment
14 changes: 14 additions & 0 deletions features/ALS003_Alignment-cant-shape-representation.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@implementer-agreement
@ALS
Feature: ALS003 - Alignment cant shape representation
The rule verifies that each IfcAlignmentCant uses correct representation.

Scenario: Agreement on each IfcAlignmentCant using correct representation

Given A file with Schema Identifier "IFC4X3_TC1" or "IFC4X3_ADD1" or "IFC4X3"
And An IfcAlignmentCant
And Its attribute Representation
And Its attribute Representations
Then The value of attribute RepresentationIdentifier must be Axis
And The value of attribute RepresentationType must be Curve3D
And The type of attribute Items must be IfcSegmentedReferenceCurve
6 changes: 3 additions & 3 deletions features/steps/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __str__(self):
if len(self.related):
return f"The instance {self.inst} expected type '{self.expected_entity_type}' for the attribute {self.attribute}, but found {misc.fmt(self.related)} "
else:
return f"This instance {self.inst} has no value for attribute {self.attribute}"
return f"The instance {self.inst} has no value for attribute {self.attribute}"


@dataclass
Expand Down Expand Up @@ -129,12 +129,12 @@ def __str__(self):

@dataclass
class InvalidValueError(RuleState):
related: ifcopenshell.entity_instance
inst: ifcopenshell.entity_instance
attribute: str
value: str

def __str__(self):
return f"On instance {misc.fmt(self.related)} the following invalid value for {self.attribute} has been found: {self.value}"
return f"On instance {misc.fmt(self.inst)} the following invalid value for {self.attribute} has been found: {self.value}"


@dataclass
Expand Down
27 changes: 23 additions & 4 deletions features/steps/thens/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,36 @@ def step_impl(context, entity, other_entity):
misc.handle_errors(context, errors)


@then('The type of attribute {attribute} should be {expected_entity_type}')
@then('The type of attribute {attribute} must be {expected_entity_type}')
def step_impl(context, attribute, expected_entity_type):

def _():
for inst in context.instances:
related_entity = getattr(inst, attribute, [])
if not related_entity.is_a(expected_entity_type):
yield err.AttributeTypeError(False, inst, [related_entity], attribute, expected_entity_type)
related_entity = misc.map_state(inst, lambda i: getattr(i, attribute, None))
errors = []
def accumulate_errors(i):
if not i.is_a(expected_entity_type):
misc.map_state(inst, lambda x: errors.append(err.AttributeTypeError(False, x, [i], attribute, expected_entity_type)))
misc.map_state(related_entity, accumulate_errors)
if errors:
yield from errors
elif context.error_on_passed_rule:
yield err.RuleSuccessInst(True, related_entity)

misc.handle_errors(context, list(_()))


@then('The value of attribute {attribute} must be {value}')
def step_impl(context, attribute, value):
if getattr(context, 'applicable', True):
errors = []
for inst in context.instances:
if isinstance(inst, (tuple, list)):
inst = inst[0]
attribute_value = getattr(inst, attribute, 'Attribute not found')
if attribute_value != value:
errors.append(err.InvalidValueError(False, inst, attribute, attribute_value))
elif context.error_on_passed_rule:
errors.append(err.RuleSuccessInst(True, inst))

misc.handle_errors(context, errors)
1 change: 0 additions & 1 deletion features/steps/thens/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

@then('Each {entity} {condition} be {directness} contained in {other_entity}')
def step_impl(context, entity, condition, directness, other_entity):
context.run_via_pytest
stmt_to_op = ['must', 'must not']
assert condition in stmt_to_op

Expand Down
12 changes: 9 additions & 3 deletions features/steps/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ def do_try(fn, default=None):

def get_inst_attributes(dc):
if hasattr(dc, 'inst'):
yield 'inst_guid', getattr(dc.inst, 'GlobalId', None)
yield 'inst_type', dc.inst.is_a()
yield 'inst_id', dc.inst.id()
if isinstance(dc.inst, ifcopenshell.entity_instance):
yield 'inst_guid', getattr(dc.inst, 'GlobalId', None)
yield 'inst_type', dc.inst.is_a()
yield 'inst_id', dc.inst.id()
else:
# apparently mostly for the rule passed logs...
# @todo fix this
yield 'inst_guid', None
yield 'inst_type', type(dc.inst).__name__


def fmt(x):
Expand Down
6 changes: 6 additions & 0 deletions test/files/als003/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
| File name | Expected result | Error log | Description |
|-------------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
| pass-als003-alignment-cant-shape-representation | success | n.a. | |
| fail-als003-scenario01-wrong-representationidentifier-value | fail | On instance (#518=IfcShapeRepresentat...383)),) the following invalid value for RepresentationIdentifier has been found: Profile | The expected RepresentationIdentifier value was Axis. |
| fail-als003-scenario01-wrong-representationtype-value | fail | On instance (#518=IfcShapeRepresentat...383)),) the following invalid value for RepresentationType has been found: Curve2D | The expected RepresentationType value was Curve3D. |
| fail-als003-scenario01-wrong-items-type | fail | The instance #518=IfcShapeRepresentation(#17,'Axis','Curve3D',(#383)) expected type 'IfcSegmentedReferenceCurve' for the attribute Items, but found [#383=IfcPolyline((#384,#...#496))] | The expected type of Items was IfcSegmentedReferenceCurve |
Loading

0 comments on commit d8610c2

Please sign in to comment.