1+ from behave import step , given , when , then , use_step_matcher
2+
3+ from utils import IfcFile
4+
5+ use_step_matcher ("parse" )
6+ @step (u"There must be exactly {number} {ifc_class} element" )
7+ @step (u"There must be exactly {number} {ifc_class} elements" )
8+ def step_impl (context , number , ifc_class ):
9+ num = len (IfcFile .get ().by_type (ifc_class ))
10+ assert num == int (number ), "Could not find {} elements of {}. Found {} element(s)." .format (number , ifc_class , num )
11+
12+ @given (u'a set of specific related elements' )
13+ def step_impl (context ):
14+ model = getattr (context , "model" , None )
15+ if not model :
16+ context .model = TableModel ()
17+ for row in context .table :
18+ context .model .add_row (row ["RelatedObjects" ], row ["RelatingGroup" ])
19+
20+ @given (u'a set of specific related elements taken from the file "{path_file}"' )
21+ def step_impl (context , path_file ):
22+ import csv
23+ import os
24+ model = getattr (context , "model" , None )
25+ if not model :
26+ context .model = TableModel ()
27+ if context .config .userdata .get ('path' ):
28+ path_file = os .path .join (context .config .userdata .get ('path' ), path_file )
29+ if not os .path .exists (path_file ):
30+ assert False , "File {} not found" .format (path_file )
31+ with open (path_file , 'r' , encoding = "utf-8-sig" ) as csvfile :
32+ reader = csv .DictReader (csvfile )
33+ for row in reader :
34+ context .model .add_row (row ["RelatedObjects" ], row ["RelatingGroup" ])
35+
36+ @then (u'there must be exactly a number of {ifc_class} equals to the number of distinct row value' )
37+ def step_impl (context , ifc_class ):
38+ try :
39+ context .execute_steps (u"""
40+ then There must be exactly {number} {ifc_class} elements
41+ """ .format (ifc_class = ifc_class , number = context .model .get_count_distinct_values ()))
42+ except AssertionError as error :
43+ str_error = str (error )
44+ assert False , str_error [:str_error .find ("Traceback" )]
45+ assert True
46+
47+ @then (u'there is a relationship {ifc_class} with {left_attribute} and {right_attribute} between the two elements of each row' )
48+ def step_impl (context , ifc_class , left_attribute , right_attribute ):
49+ rows = context .model .rows
50+ elements = IfcFile .by_type (ifc_class )
51+ errors = []
52+ for key , value in rows .items ():
53+ found = False
54+ for element in elements :
55+ if any (x .Name == key for x in getattr (element , left_attribute ))\
56+ and getattr (element , right_attribute ).Name == value :
57+ found = True
58+ if not found :
59+ errors .append (f'The row ({ key } , { value } ) does not have the relationship.' )
60+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
61+
62+ use_step_matcher ("re" )
63+ @step ("all IfcGroup must be linked to a type in the list (?P<linked_ifc_classes>.*)" )
64+ def step_impl (context , linked_ifc_classes ):
65+ groups = IfcFile .by_type ("IfcGroup" )
66+ errors = []
67+ for group in groups :
68+ if not hasattr (group , "IsGroupedBy" ):
69+ errors .append (f'The element "{ group .Name } " has no "IsGroupedBy" attribute.' )
70+ else :
71+ for grouped_by in getattr (group , "IsGroupedBy" ):
72+ if not hasattr (grouped_by , "RelatedObjects" ):
73+ errors .append (f'The element "{ grouped_by .Name } " has no "RelatedObjects" attribute.' )
74+ else :
75+ for related_object in getattr (grouped_by , "RelatedObjects" ):
76+ found = False
77+ for linked_ifc_class in linked_ifc_classes .split ("," ):
78+ if (related_object .is_a (linked_ifc_class )):
79+ found = True
80+ if not found :
81+ errors .append (f'The element "{ related_object .Name } " does not have the right associated type.' )
82+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
83+
84+ @then (u'there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row key' )
85+ def step_impl (context , ifc_types , attribute_name ):
86+ check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , context .model .rows .keys ())
87+
88+ @then (u'there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row value' )
89+ def step_impl (context , ifc_types , attribute_name ):
90+ values = set (context .model .rows .values ())
91+ check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , values )
92+
93+ def check_if_element_exists_by_types_with_attribute_name (ifc_types , attribute_name , attribute_values ):
94+ errors = []
95+ # retrieve all elements of that type
96+ elements = IfcFile .by_types (ifc_types )
97+ # loop
98+ for attribute_value in attribute_values :
99+ found = False
100+ for element in elements :
101+ if hasattr (element , attribute_name ) and getattr (element , attribute_name ) == attribute_value :
102+ found = True
103+ if not found :
104+ errors .append (f'An element with { attribute_name } attribute "{ attribute_value } " was not found.' )
105+ assert not errors , "Errors occured:\n {}" .format ("\n " .join (errors ))
106+
107+ class TableModel (object ):
108+ """This class represents a table of data."""
109+ def __init__ (self ):
110+ self .rows = dict ()
111+
112+ def add_row (self , related , relating ):
113+ self .rows [related ] = relating
114+
115+ def get_count (self ):
116+ return len (self .rows )
117+
118+ def get_count_distinct_values (self ):
119+ return len (set (self .rows .values ()))
0 commit comments