|
@@ -0,0 +1,311 @@
|
|
1
|
+import xml.etree.ElementTree as ET
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+KEY_DESCRIPTION = 'description'
|
|
5
|
+"""Description (short) of an element"""
|
|
6
|
+KEY_DETAILED_DESCRIPTION = 'detailed_description'
|
|
7
|
+"""Description (short) of an element"""
|
|
8
|
+KEY_ITEM_ID = 'id'
|
|
9
|
+"""The human readable item id"""
|
|
10
|
+KEY_LAST_CHANGE = 'last_change'
|
|
11
|
+"""Date of the last change"""
|
|
12
|
+KEY_SOURCE = 'source'
|
|
13
|
+"""The source of a relation"""
|
|
14
|
+KEY_SPEC_DATA = 'data'
|
|
15
|
+"""A dict holding the data definition (key is the unique id of the data definition). Note this is not the datatype, but a reference to the datatype"""
|
|
16
|
+KEY_START_EXECUTION_FROM_LEVEL = 'start_execution_from_level'
|
|
17
|
+"""The level, of an spec object from where on the test should be executed"""
|
|
18
|
+KEY_SYSTEM_TYPE_UID = 'system_type_uid'
|
|
19
|
+"""The unique id of the corresponding type"""
|
|
20
|
+KEY_SYSTEM_UID = 'system_uid'
|
|
21
|
+"""A unique id"""
|
|
22
|
+KEY_TARGET = 'target'
|
|
23
|
+"""The target of a relation"""
|
|
24
|
+KEY_XML_TAG = 'xml_tag'
|
|
25
|
+"""The tag of the original xml object"""
|
|
26
|
+
|
|
27
|
+PREFIX = '{http://www.omg.org/spec/ReqIF/20110401/reqif.xsd}'
|
|
28
|
+TAG_CHILDREN = '%sCHILDREN' % PREFIX
|
|
29
|
+TAG_DEFINITION = '%sDEFINITION' % PREFIX
|
|
30
|
+TAG_OBJECT = '%sOBJECT' % PREFIX
|
|
31
|
+TAG_OBJECT_REF = '%sSPEC-OBJECT-REF' % PREFIX
|
|
32
|
+TAG_PROPERTIES = '%sPROPERTIES' % PREFIX
|
|
33
|
+TAG_SOURCE = '%sSOURCE' % PREFIX
|
|
34
|
+TAG_SPECIFIED_VALUES = '%sSPECIFIED-VALUES' % PREFIX
|
|
35
|
+TAG_SPEC_ATTRIBUTES = '%sSPEC-ATTRIBUTES' % PREFIX
|
|
36
|
+TAG_TARGET = '%sTARGET' % PREFIX
|
|
37
|
+TAG_THE_VALUE = 'THE-VALUE'
|
|
38
|
+TAG_TYPE = '%sTYPE' % PREFIX
|
|
39
|
+TAG_VALUES = '%sVALUES' % PREFIX
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+class base_object(dict):
|
|
43
|
+ ATTRIB_KEY_DESC = 'DESC'
|
|
44
|
+ ATTRIB_KEY_IDENTIFIER = 'IDENTIFIER'
|
|
45
|
+ ATTRIB_KEY_LONG_NAME = 'LONG-NAME'
|
|
46
|
+ ATTRIB_KEY_LAST_CHANGE = 'LAST-CHANGE'
|
|
47
|
+ ATTRIB_DATA = {KEY_DESCRIPTION: ATTRIB_KEY_LONG_NAME,
|
|
48
|
+ KEY_DETAILED_DESCRIPTION: ATTRIB_KEY_DESC,
|
|
49
|
+ KEY_LAST_CHANGE: ATTRIB_KEY_LAST_CHANGE,
|
|
50
|
+ KEY_SYSTEM_UID: ATTRIB_KEY_IDENTIFIER}
|
|
51
|
+
|
|
52
|
+ def __init__(self, xml_object):
|
|
53
|
+ dict.__init__(self)
|
|
54
|
+ for key in self.ATTRIB_DATA:
|
|
55
|
+ data = xml_object.attrib.get(self.ATTRIB_DATA[key])
|
|
56
|
+ if data is not None:
|
|
57
|
+ self[key] = data
|
|
58
|
+ self[KEY_XML_TAG] = xml_object.tag
|
|
59
|
+ type_obj = xml_object.find(TAG_TYPE)
|
|
60
|
+ if type_obj is not None:
|
|
61
|
+ self[KEY_SYSTEM_TYPE_UID] = type_obj[0].text
|
|
62
|
+
|
|
63
|
+ def __str__(self):
|
|
64
|
+ keys = self.keys()
|
|
65
|
+ keys.sort()
|
|
66
|
+ rv = ''
|
|
67
|
+ for key in keys:
|
|
68
|
+ rv += '%s: %s\n' % (key, self[key])
|
|
69
|
+ return rv
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+class datatype(base_object):
|
|
73
|
+ ATTRIB_KEY_KEY = 'KEY'
|
|
74
|
+
|
|
75
|
+ def __init__(self, xml_datatype_object):
|
|
76
|
+ base_object.__init__(self, xml_datatype_object)
|
|
77
|
+ self.enmu_dict = dict()
|
|
78
|
+ if 'ENUMERATION' in self[KEY_XML_TAG]:
|
|
79
|
+ for child in xml_datatype_object.find(TAG_SPECIFIED_VALUES):
|
|
80
|
+ key = child.attrib[self.ATTRIB_KEY_IDENTIFIER]
|
|
81
|
+ value = None
|
|
82
|
+ if child.find(TAG_PROPERTIES) is not None:
|
|
83
|
+ try:
|
|
84
|
+ value = int(child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY))
|
|
85
|
+ except ValueError:
|
|
86
|
+ value = child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY)
|
|
87
|
+ value = value or child.attrib[self.ATTRIB_KEY_LONG_NAME]
|
|
88
|
+ self.enmu_dict[key] = value
|
|
89
|
+
|
|
90
|
+ def xml_obj_to_value(self, xml_obj):
|
|
91
|
+ if 'STRING' in self[KEY_XML_TAG]:
|
|
92
|
+ data = xml_obj.attrib.get(TAG_THE_VALUE)
|
|
93
|
+ return data
|
|
94
|
+ elif 'INTEGER' in self[KEY_XML_TAG]:
|
|
95
|
+ data = xml_obj.attrib.get(TAG_THE_VALUE)
|
|
96
|
+ return int(data)
|
|
97
|
+ elif 'BOOLEAN' in self[KEY_XML_TAG]:
|
|
98
|
+ data = xml_obj.attrib.get(TAG_THE_VALUE)
|
|
99
|
+ if data.lower() == 'false':
|
|
100
|
+ return False
|
|
101
|
+ else:
|
|
102
|
+ return True
|
|
103
|
+ elif 'ENUMERATION' in self[KEY_XML_TAG]:
|
|
104
|
+ if xml_obj.find(TAG_VALUES) is not None:
|
|
105
|
+ return self.enmu_dict.get(xml_obj.find(TAG_VALUES)[0].text)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+class datatype_dict(dict):
|
|
109
|
+ def __init__(self, xml_datatypes_object):
|
|
110
|
+ dict.__init__(self)
|
|
111
|
+ for child in xml_datatypes_object:
|
|
112
|
+ dt = datatype(child)
|
|
113
|
+ self[dt[KEY_SYSTEM_UID]] = dt
|
|
114
|
+
|
|
115
|
+ def __str__(self):
|
|
116
|
+ rv = ''
|
|
117
|
+ for key in self:
|
|
118
|
+ rv += str(self[key]) + '\n'
|
|
119
|
+ return rv
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+class spec_type(base_object):
|
|
123
|
+ def __init__(self, xml_spec_type_object):
|
|
124
|
+ base_object.__init__(self, xml_spec_type_object)
|
|
125
|
+ self[KEY_SPEC_DATA] = dict()
|
|
126
|
+ for child in xml_spec_type_object.find(TAG_SPEC_ATTRIBUTES):
|
|
127
|
+ a = base_object(child)
|
|
128
|
+ self[KEY_SPEC_DATA][a[KEY_SYSTEM_UID]] = a
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+class spec_types_dict(dict):
|
|
132
|
+ def __init__(self, xml_spec_types_object):
|
|
133
|
+ dict.__init__(self)
|
|
134
|
+ for child in xml_spec_types_object:
|
|
135
|
+ st = spec_type(child)
|
|
136
|
+ self[st[KEY_SYSTEM_UID]] = st
|
|
137
|
+
|
|
138
|
+ def __str__(self):
|
|
139
|
+ rv = ''
|
|
140
|
+ for key in self:
|
|
141
|
+ rv += str(self[key]) + '\n'
|
|
142
|
+ return rv
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+class spec_object(base_object):
|
|
146
|
+ def __init__(self, xml_object, spec_types, data_types):
|
|
147
|
+ base_object.__init__(self, xml_object)
|
|
148
|
+ try:
|
|
149
|
+ for child in xml_object.find(TAG_VALUES):
|
|
150
|
+ attr_id = child.find(TAG_DEFINITION)[0].text
|
|
151
|
+ stype = spec_types[self[KEY_SYSTEM_TYPE_UID]]
|
|
152
|
+ if attr_id in stype[KEY_SPEC_DATA]:
|
|
153
|
+ spec_attr = stype[KEY_SPEC_DATA][attr_id]
|
|
154
|
+ data_type = data_types[spec_attr[KEY_SYSTEM_TYPE_UID]]
|
|
155
|
+ self[spec_attr[KEY_DESCRIPTION]] = data_type.xml_obj_to_value(child)
|
|
156
|
+ except TypeError:
|
|
157
|
+ pass
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+class spec_objects(dict):
|
|
161
|
+ def __init__(self, xml_object, spec_types, data_types):
|
|
162
|
+ dict.__init__(self)
|
|
163
|
+ for child in xml_object:
|
|
164
|
+ so = spec_object(child, spec_types, data_types)
|
|
165
|
+ self[so[KEY_SYSTEM_UID]] = so
|
|
166
|
+
|
|
167
|
+ def __str__(self):
|
|
168
|
+ rv = ''
|
|
169
|
+ for key in self:
|
|
170
|
+ rv += str(self[key]) + '\n'
|
|
171
|
+ return rv
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+class spec_relation(spec_object):
|
|
175
|
+ def __init__(self, xml_object, spec_types, data_types):
|
|
176
|
+ spec_object.__init__(self, xml_object, spec_types, data_types)
|
|
177
|
+ self[KEY_SOURCE] = xml_object.find(TAG_SOURCE).find(TAG_OBJECT_REF).text
|
|
178
|
+ self[KEY_TARGET] = xml_object.find(TAG_TARGET).find(TAG_OBJECT_REF).text
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+class spec_relations(list):
|
|
182
|
+ def __init__(self, xml_object, spec_types, data_types):
|
|
183
|
+ list.__init__(self)
|
|
184
|
+ for child in xml_object:
|
|
185
|
+ self.append(spec_relation(child, spec_types, data_types))
|
|
186
|
+
|
|
187
|
+ def __str__(self):
|
|
188
|
+ rv = ''
|
|
189
|
+ for key in self:
|
|
190
|
+ rv += str(self[key]) + '\n'
|
|
191
|
+ return rv
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+class id_tree(str):
|
|
195
|
+ def __init__(self, system_uid):
|
|
196
|
+ str.__init__(system_uid)
|
|
197
|
+ self.children = list()
|
|
198
|
+
|
|
199
|
+ def append(self, child):
|
|
200
|
+ self.children.append(child)
|
|
201
|
+
|
|
202
|
+ def get_flat_id_tree(self):
|
|
203
|
+ """
|
|
204
|
+ This method returns an ordered but flat list of all id_tree elements.
|
|
205
|
+ """
|
|
206
|
+ obj_list = list()
|
|
207
|
+ for child in self.children:
|
|
208
|
+ obj_list.append(child)
|
|
209
|
+ obj_list.extend(child.get_flat_id_tree())
|
|
210
|
+ return obj_list
|
|
211
|
+
|
|
212
|
+ def executed_or_has_executed_children(self, item_type_id, execution_level, get_spec_object_method, default_execution_level):
|
|
213
|
+ spec_obj = get_spec_object_method(str(self))
|
|
214
|
+ if spec_obj[KEY_SYSTEM_TYPE_UID] == item_type_id:
|
|
215
|
+ if execution_level >= spec_obj.get(KEY_START_EXECUTION_FROM_LEVEL, default_execution_level):
|
|
216
|
+ return True
|
|
217
|
+ for child in self.children:
|
|
218
|
+ if child.executed_or_has_executed_children(item_type_id, execution_level, get_spec_object_method, default_execution_level):
|
|
219
|
+ return True
|
|
220
|
+ return False
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+class specification(spec_object):
|
|
224
|
+ def __init__(self, xml_object, spec_types, data_types, spec_objects):
|
|
225
|
+ spec_object.__init__(self, xml_object, spec_types, data_types)
|
|
226
|
+ self._spec_objects = spec_objects
|
|
227
|
+ self.children = list()
|
|
228
|
+ self._add_hirarchy_objects(xml_object.find(TAG_CHILDREN), self.children)
|
|
229
|
+
|
|
230
|
+ def _add_hirarchy_objects(self, children, parent_list):
|
|
231
|
+ for child in children:
|
|
232
|
+ child_id = child.find('%s/%s' % (TAG_OBJECT, TAG_OBJECT_REF)).text
|
|
233
|
+ child_tree_obj = id_tree(child_id)
|
|
234
|
+ parent_list.append(child_tree_obj)
|
|
235
|
+ next_children = child.find(TAG_CHILDREN)
|
|
236
|
+ if next_children is not None:
|
|
237
|
+ self._add_hirarchy_objects(next_children, child_tree_obj.children)
|
|
238
|
+
|
|
239
|
+ def get_system_uid_list_by_type(self, type_id):
|
|
240
|
+ """
|
|
241
|
+ This method returns an ordered but flat list of all items of this specification with the specified type.
|
|
242
|
+ """
|
|
243
|
+ obj_list = list()
|
|
244
|
+ for child in self.children:
|
|
245
|
+ if self._spec_objects[child][KEY_SYSTEM_TYPE_UID] == type_id:
|
|
246
|
+ obj_list.append(str(child))
|
|
247
|
+ for item_id in child.get_flat_id_tree():
|
|
248
|
+ if self._spec_objects[item_id][KEY_SYSTEM_TYPE_UID] == type_id:
|
|
249
|
+ obj_list.append(str(item_id))
|
|
250
|
+ return obj_list
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+class specifications(list):
|
|
254
|
+ def __init__(self, xml_object, spec_types, data_types, spec_objects):
|
|
255
|
+ list.__init__(self)
|
|
256
|
+ for child in xml_object:
|
|
257
|
+ self.append(specification(child, spec_types, data_types, spec_objects))
|
|
258
|
+
|
|
259
|
+ def __str__(self):
|
|
260
|
+ rv = ''
|
|
261
|
+ for i in self:
|
|
262
|
+ rv += str(i) + '\n'
|
|
263
|
+ return rv
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+class parse(object):
|
|
267
|
+ TAG_HEADER_MAIN = '%sTHE-HEADER' % PREFIX
|
|
268
|
+ TAG_HEADER_REQIF = '%sREQ-IF-HEADER' % PREFIX
|
|
269
|
+ TAG_TITLE = '%sTITLE' % PREFIX
|
|
270
|
+ TAG_COMMENT = '%sCOMMENT' % PREFIX
|
|
271
|
+
|
|
272
|
+ TAG_CORE_CONTENT = '%sCORE-CONTENT' % PREFIX
|
|
273
|
+ TAG_REQ_IF_CONTENT = '%sREQ-IF-CONTENT' % PREFIX
|
|
274
|
+ TAG_DATATYPES = '%sDATATYPES' % PREFIX
|
|
275
|
+ TAG_SPEC_RELATIONS = '%sSPEC-RELATIONS' % PREFIX
|
|
276
|
+ TAG_SPEC_TYPES = '%sSPEC-TYPES' % PREFIX
|
|
277
|
+ TAG_SPEC_OBJECTS = '%sSPEC-OBJECTS' % PREFIX
|
|
278
|
+ TAG_SPECIFICATION = '%sSPECIFICATIONS' % PREFIX
|
|
279
|
+
|
|
280
|
+ def __init__(self, filename):
|
|
281
|
+ tree = ET.parse(filename)
|
|
282
|
+ req_if = tree.getroot()
|
|
283
|
+
|
|
284
|
+ self._title = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_TITLE)).text
|
|
285
|
+ self._comment = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_COMMENT)).text
|
|
286
|
+
|
|
287
|
+ xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_DATATYPES))
|
|
288
|
+ self._datatypes = datatype_dict(xml_obj)
|
|
289
|
+ xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_TYPES))
|
|
290
|
+ self._spec_types = spec_types_dict(xml_obj)
|
|
291
|
+ xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_OBJECTS))
|
|
292
|
+ self._spec_objects = spec_objects(xml_obj, self._spec_types, self._datatypes)
|
|
293
|
+ xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_RELATIONS))
|
|
294
|
+ try:
|
|
295
|
+ self._relations = spec_relations(xml_obj, self._spec_types, self._datatypes)
|
|
296
|
+ except TypeError:
|
|
297
|
+ self._relations = []
|
|
298
|
+ xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPECIFICATION))
|
|
299
|
+ self._specifications = specifications(xml_obj, self._spec_types, self._datatypes, self._spec_objects)
|
|
300
|
+
|
|
301
|
+ def __str__(self):
|
|
302
|
+ rv = 'Title: %s' % self._title
|
|
303
|
+ rv += 'Comment: %s' % self._comment
|
|
304
|
+ rv += 'DATATYPES:\n----------\n'
|
|
305
|
+ rv += str(self._datatypes)
|
|
306
|
+ rv += str(self._spec_types)
|
|
307
|
+ rv += '\n\n\nSPEC_OBJECTS:\n-------------\n'
|
|
308
|
+ rv += str(self._spec_objects)
|
|
309
|
+ rv += '\n\n\nSPECIFICATIONS:\n---------------\n'
|
|
310
|
+ rv += str(self._specifications)
|
|
311
|
+ return rv
|