import xml.etree.ElementTree as ET KEY_DESCRIPTION = 'description' """Description (short) of an element""" KEY_DETAILED_DESCRIPTION = 'detailed_description' """Description (short) of an element""" KEY_ITEM_ID = 'id' """The human readable item id""" KEY_LAST_CHANGE = 'last_change' """Date of the last change""" KEY_SOURCE = 'source' """The source of a relation""" KEY_SPEC_DATA = 'data' """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""" KEY_START_EXECUTION_FROM_LEVEL = 'start_execution_from_level' """The level, of an spec object from where on the test should be executed""" KEY_SYSTEM_TYPE_UID = 'system_type_uid' """The unique id of the corresponding type""" KEY_SYSTEM_UID = 'system_uid' """A unique id""" KEY_TARGET = 'target' """The target of a relation""" KEY_XML_TAG = 'xml_tag' """The tag of the original xml object""" PREFIX = '{http://www.omg.org/spec/ReqIF/20110401/reqif.xsd}' TAG_CHILDREN = '%sCHILDREN' % PREFIX TAG_DEFINITION = '%sDEFINITION' % PREFIX TAG_OBJECT = '%sOBJECT' % PREFIX TAG_OBJECT_REF = '%sSPEC-OBJECT-REF' % PREFIX TAG_PROPERTIES = '%sPROPERTIES' % PREFIX TAG_SOURCE = '%sSOURCE' % PREFIX TAG_SPECIFIED_VALUES = '%sSPECIFIED-VALUES' % PREFIX TAG_SPEC_ATTRIBUTES = '%sSPEC-ATTRIBUTES' % PREFIX TAG_TARGET = '%sTARGET' % PREFIX TAG_THE_VALUE = 'THE-VALUE' TAG_TYPE = '%sTYPE' % PREFIX TAG_VALUES = '%sVALUES' % PREFIX class base_object(dict): ATTRIB_KEY_DESC = 'DESC' ATTRIB_KEY_IDENTIFIER = 'IDENTIFIER' ATTRIB_KEY_LONG_NAME = 'LONG-NAME' ATTRIB_KEY_LAST_CHANGE = 'LAST-CHANGE' ATTRIB_DATA = {KEY_DESCRIPTION: ATTRIB_KEY_LONG_NAME, KEY_DETAILED_DESCRIPTION: ATTRIB_KEY_DESC, KEY_LAST_CHANGE: ATTRIB_KEY_LAST_CHANGE, KEY_SYSTEM_UID: ATTRIB_KEY_IDENTIFIER} def __init__(self, xml_object): dict.__init__(self) for key in self.ATTRIB_DATA: data = xml_object.attrib.get(self.ATTRIB_DATA[key]) if data is not None: self[key] = data self[KEY_XML_TAG] = xml_object.tag type_obj = xml_object.find(TAG_TYPE) if type_obj is not None: self[KEY_SYSTEM_TYPE_UID] = type_obj[0].text def __str__(self): keys = self.keys() keys.sort() rv = '' for key in keys: rv += '%s: %s\n' % (key, self[key]) return rv class datatype(base_object): ATTRIB_KEY_KEY = 'KEY' def __init__(self, xml_datatype_object): base_object.__init__(self, xml_datatype_object) self.enmu_dict = dict() if 'ENUMERATION' in self[KEY_XML_TAG]: for child in xml_datatype_object.find(TAG_SPECIFIED_VALUES): key = child.attrib[self.ATTRIB_KEY_IDENTIFIER] value = None if child.find(TAG_PROPERTIES) is not None: try: value = int(child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY)) except ValueError: value = child.find(TAG_PROPERTIES)[0].attrib.get(self.ATTRIB_KEY_KEY) value = value or child.attrib[self.ATTRIB_KEY_LONG_NAME] self.enmu_dict[key] = value def xml_obj_to_value(self, xml_obj): if 'STRING' in self[KEY_XML_TAG]: data = xml_obj.attrib.get(TAG_THE_VALUE) return data elif 'INTEGER' in self[KEY_XML_TAG]: data = xml_obj.attrib.get(TAG_THE_VALUE) return int(data) elif 'BOOLEAN' in self[KEY_XML_TAG]: data = xml_obj.attrib.get(TAG_THE_VALUE) if data.lower() == 'false': return False else: return True elif 'ENUMERATION' in self[KEY_XML_TAG]: if xml_obj.find(TAG_VALUES) is not None: return self.enmu_dict.get(xml_obj.find(TAG_VALUES)[0].text) class datatype_dict(dict): def __init__(self, xml_datatypes_object): dict.__init__(self) for child in xml_datatypes_object: dt = datatype(child) self[dt[KEY_SYSTEM_UID]] = dt def __str__(self): rv = '' for key in self: rv += str(self[key]) + '\n' return rv class spec_type(base_object): def __init__(self, xml_spec_type_object): base_object.__init__(self, xml_spec_type_object) self[KEY_SPEC_DATA] = dict() for child in xml_spec_type_object.find(TAG_SPEC_ATTRIBUTES): a = base_object(child) self[KEY_SPEC_DATA][a[KEY_SYSTEM_UID]] = a class spec_types_dict(dict): def __init__(self, xml_spec_types_object): dict.__init__(self) for child in xml_spec_types_object: st = spec_type(child) self[st[KEY_SYSTEM_UID]] = st def __str__(self): rv = '' for key in self: rv += str(self[key]) + '\n' return rv class spec_object(base_object): def __init__(self, xml_object, spec_types, data_types): base_object.__init__(self, xml_object) try: for child in xml_object.find(TAG_VALUES): attr_id = child.find(TAG_DEFINITION)[0].text stype = spec_types[self[KEY_SYSTEM_TYPE_UID]] if attr_id in stype[KEY_SPEC_DATA]: spec_attr = stype[KEY_SPEC_DATA][attr_id] data_type = data_types[spec_attr[KEY_SYSTEM_TYPE_UID]] self[spec_attr[KEY_DESCRIPTION]] = data_type.xml_obj_to_value(child) except TypeError: pass class spec_objects(dict): def __init__(self, xml_object, spec_types, data_types): dict.__init__(self) for child in xml_object: so = spec_object(child, spec_types, data_types) self[so[KEY_SYSTEM_UID]] = so def __str__(self): rv = '' for key in self: rv += str(self[key]) + '\n' return rv class spec_relation(spec_object): def __init__(self, xml_object, spec_types, data_types): spec_object.__init__(self, xml_object, spec_types, data_types) self[KEY_SOURCE] = xml_object.find(TAG_SOURCE).find(TAG_OBJECT_REF).text self[KEY_TARGET] = xml_object.find(TAG_TARGET).find(TAG_OBJECT_REF).text class spec_relations(list): def __init__(self, xml_object, spec_types, data_types): list.__init__(self) for child in xml_object: self.append(spec_relation(child, spec_types, data_types)) def __str__(self): rv = '' for key in self: rv += str(self[key]) + '\n' return rv class id_tree(str): def __init__(self, system_uid): str.__init__(system_uid) self.children = list() def append(self, child): self.children.append(child) def get_flat_id_tree(self): """ This method returns an ordered but flat list of all id_tree elements. """ obj_list = list() for child in self.children: obj_list.append(child) obj_list.extend(child.get_flat_id_tree()) return obj_list def executed_or_has_executed_children(self, item_type_id, execution_level, get_spec_object_method, default_execution_level): spec_obj = get_spec_object_method(str(self)) if spec_obj[KEY_SYSTEM_TYPE_UID] == item_type_id: if execution_level >= spec_obj.get(KEY_START_EXECUTION_FROM_LEVEL, default_execution_level): return True for child in self.children: if child.executed_or_has_executed_children(item_type_id, execution_level, get_spec_object_method, default_execution_level): return True return False class specification(spec_object): def __init__(self, xml_object, spec_types, data_types, spec_objects): spec_object.__init__(self, xml_object, spec_types, data_types) self._spec_objects = spec_objects self.children = list() self._add_hirarchy_objects(xml_object.find(TAG_CHILDREN), self.children) def _add_hirarchy_objects(self, children, parent_list): for child in children: child_id = child.find('%s/%s' % (TAG_OBJECT, TAG_OBJECT_REF)).text child_tree_obj = id_tree(child_id) parent_list.append(child_tree_obj) next_children = child.find(TAG_CHILDREN) if next_children is not None: self._add_hirarchy_objects(next_children, child_tree_obj.children) def get_system_uid_list_by_type(self, type_id): """ This method returns an ordered but flat list of all items of this specification with the specified type. """ obj_list = list() for child in self.children: if self._spec_objects[child][KEY_SYSTEM_TYPE_UID] == type_id: obj_list.append(str(child)) for item_id in child.get_flat_id_tree(): if self._spec_objects[item_id][KEY_SYSTEM_TYPE_UID] == type_id: obj_list.append(str(item_id)) return obj_list class specifications(list): def __init__(self, xml_object, spec_types, data_types, spec_objects): list.__init__(self) for child in xml_object: self.append(specification(child, spec_types, data_types, spec_objects)) def __str__(self): rv = '' for i in self: rv += str(i) + '\n' return rv class parse(object): TAG_HEADER_MAIN = '%sTHE-HEADER' % PREFIX TAG_HEADER_REQIF = '%sREQ-IF-HEADER' % PREFIX TAG_TITLE = '%sTITLE' % PREFIX TAG_COMMENT = '%sCOMMENT' % PREFIX TAG_CORE_CONTENT = '%sCORE-CONTENT' % PREFIX TAG_REQ_IF_CONTENT = '%sREQ-IF-CONTENT' % PREFIX TAG_DATATYPES = '%sDATATYPES' % PREFIX TAG_SPEC_RELATIONS = '%sSPEC-RELATIONS' % PREFIX TAG_SPEC_TYPES = '%sSPEC-TYPES' % PREFIX TAG_SPEC_OBJECTS = '%sSPEC-OBJECTS' % PREFIX TAG_SPECIFICATION = '%sSPECIFICATIONS' % PREFIX def __init__(self, filename): tree = ET.parse(filename) req_if = tree.getroot() self._title = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_TITLE)).text self._comment = req_if.find('./%s/%s/%s' % (self.TAG_HEADER_MAIN, self.TAG_HEADER_REQIF, self.TAG_COMMENT)).text xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_DATATYPES)) self._datatypes = datatype_dict(xml_obj) xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_TYPES)) self._spec_types = spec_types_dict(xml_obj) xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_OBJECTS)) self._spec_objects = spec_objects(xml_obj, self._spec_types, self._datatypes) xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPEC_RELATIONS)) try: self._relations = spec_relations(xml_obj, self._spec_types, self._datatypes) except TypeError: self._relations = [] xml_obj = req_if.find('./%s/%s/%s' % (self.TAG_CORE_CONTENT, self.TAG_REQ_IF_CONTENT, self.TAG_SPECIFICATION)) self._specifications = specifications(xml_obj, self._spec_types, self._datatypes, self._spec_objects) def __str__(self): rv = 'Title: %s' % self._title rv += 'Comment: %s' % self._comment rv += 'DATATYPES:\n----------\n' rv += str(self._datatypes) rv += str(self._spec_types) rv += '\n\n\nSPEC_OBJECTS:\n-------------\n' rv += str(self._spec_objects) rv += '\n\n\nSPECIFICATIONS:\n---------------\n' rv += str(self._specifications) return rv