Beispiel #1
0
    def validate_xml(self, dict_file, parsed_xml_tree, validator_type,
                     validator_name):
        # Check that validator is valid
        if not validator_type in self.Config or not validator_name in self.Config[
                validator_type]:
            msg = "XML Validator type " + validator_type + " not found in ConfigManager instance"
            raise FprimeXmlException(msg)

        # Create proper xml validator tool
        validator_file_handler = open(
            ROOTDIR + self.Config.get(validator_type, validator_name), 'r')
        validator_parsed = etree.parse(validator_file_handler)
        validator_file_handler.close()
        if validator_type == 'schema':
            validator_compiled = etree.RelaxNG(validator_parsed)
        elif validator_type == 'schematron':
            validator_compiled = isoschematron.Schematron(validator_parsed)

        # Validate XML file
        if not validator_compiled.validate(parsed_xml_tree):
            if validator_type == 'schema':
                msg = "XML file {} is not valid according to {} {}.".format(
                    dict_file, validator_type,
                    ROOTDIR + self.Config.get(validator_type, validator_name))
                raise FprimeXmlException(msg)
            elif validator_type == 'schematron':
                msg = "WARNING: XML file {} is not valid according to {} {}.".format(
                    dict_file, validator_type,
                    ROOTDIR + self.Config.get(validator_type, validator_name))
                PRINT.info(msg)
Beispiel #2
0
 def check_enum_values(self, element_tree):
     """
     Raises exception in case that enum items are inconsistent
     in whether they include attribute 'value'
     """
     if not self.is_attribute_consistent(element_tree, 'value'):
         msg = "If one enum item has a value attribute, all items should have a value attribute"
         raise FprimeXmlException(msg)
Beispiel #3
0
    def __init__(self, xml_file=None):
        """
        Given a well formed XML file (xml_file), read it and turn it into
        a big string.
        """
        self.__root = None
        self.__name = ""
        self.__namespace = None
        # List of C++ include files for serializable *.hpp file
        self.__include_header_files = []
        # List of XML serializable description dependencies
        self.__includes = []
        # List of XML enum type files
        self.__include_enum_files = []
        # List of XML array type files
        self.__include_array_files = []
        # Comment block of text for serializable
        self.__comment = ""
        # List of (name, type, comment) tuples
        self.__members = []
        # Type ID for serialized type
        self.__type_id = None
        #
        if os.path.isfile(xml_file) == False:
            stri = "ERROR: Could not find specified XML file %s." % xml_file
            raise OSError(stri)
        fd = open(xml_file)
        xml_file = os.path.basename(xml_file)
        #        xml_file = os.path.basename(xml_file)
        self.__xml_filename = xml_file

        self.__config = ConfigManager.ConfigManager.getInstance()

        #

        xml_parser = etree.XMLParser(remove_comments=True)
        element_tree = etree.parse(fd, parser=xml_parser)
        fd.close()  #Close the file, which is only used for the parsing above

        # Validate new imports using their root tag as a key to find what schema to use
        rng_file = self.__config.get(
            "schema",
            element_tree.getroot().tag.lower()).lstrip("/")
        try:
            rng_file = locate_build_root(rng_file)
        except (BuildRootMissingException, BuildRootCollisionException) as bre:
            stri = "ERROR: Could not find specified RNG file {}. {}".format(
                rng_file,
                str(bre),
            )
            raise OSError(stri)
        file_handler = open(rng_file)
        relax_parsed = etree.parse(file_handler)
        file_handler.close()
        relax_compiled = etree.RelaxNG(relax_parsed)

        # 2/3 conversion
        if not relax_compiled.validate(element_tree):
            msg = "XML file {} is not valid according to schema {}.".format(
                xml_file, rng_file)
            raise FprimeXmlException(msg)

        serializable = element_tree.getroot()
        if serializable.tag != "serializable":
            PRINT.info("%s is not a serializable definition file" % xml_file)
            sys.exit(-1)

        print("Parsing Serializable %s" % serializable.attrib["name"])

        self.__name = serializable.attrib["name"]

        if "namespace" in serializable.attrib:
            self.__namespace = serializable.attrib["namespace"]
        else:
            self.__namespace = None

        if "typeid" in serializable.attrib:
            self.__type_id = serializable.attrib["typeid"]
        else:
            self.__type_id = None

        for serializable_tag in serializable:
            if serializable_tag.tag == "comment":
                self.__comment = serializable_tag.text.strip()
            elif serializable_tag.tag == "include_header":
                self.__include_header_files.append(serializable_tag.text)
            elif serializable_tag.tag == "import_serializable_type":
                self.__includes.append(serializable_tag.text)
            elif serializable_tag.tag == "import_enum_type":
                self.__include_enum_files.append(serializable_tag.text)
            elif serializable_tag.tag == "import_array_type":
                self.__include_array_files.append(serializable_tag.text)
            elif serializable_tag.tag == "members":
                for member in serializable_tag:
                    if member.tag != "member":
                        PRINT.info(
                            "%s: Invalid tag %s in serializable member definition"
                            % (xml_file, member.tag))
                        sys.exit(-1)
                    n = member.attrib["name"]
                    t = member.attrib["type"]
                    if "size" in list(member.attrib.keys()):
                        if t == "ENUM":
                            PRINT.info(
                                "%s: Member %s: arrays of enums not supported yet!"
                                % (xml_file, n))
                            sys.exit(-1)
                        s = member.attrib["size"]
                        if not s.isdigit():
                            PRINT.info(
                                "{}: Member {}: size must be a number".format(
                                    xml_file, n))
                            sys.exit(-1)
                    else:
                        s = None
                    if "format" in list(member.attrib.keys()):
                        f = member.attrib["format"]
                    else:
                        if t in list(format_dictionary.keys()):
                            f = format_dictionary[t]
                        else:  # Must be included type, which will use toString method
                            f = "%s"
                    if t == "string":
                        if s is None:
                            PRINT.info(
                                "%s: member %s string must specify size tag" %
                                (xml_file, member.tag))
                            sys.exit(-1)

                    if "comment" in list(member.attrib.keys()):
                        c = member.attrib["comment"]
                    else:
                        c = None

                    for member_tag in member:
                        if member_tag.tag == "enum" and t == "ENUM":
                            en = member_tag.attrib["name"]
                            enum_members = []
                            for mem in member_tag:
                                mn = mem.attrib["name"]
                                if "value" in list(mem.attrib.keys()):
                                    v = mem.attrib["value"]
                                else:
                                    v = None
                                if "comment" in list(mem.attrib.keys()):
                                    mc = mem.attrib["comment"].strip()
                                else:
                                    mc = None
                                enum_members.append((mn, v, mc))
                            t = ((t, en), enum_members)
                        else:
                            PRINT.info(
                                "%s: Invalid member tag %s in serializable member %s"
                                % (xml_file, member_tag.tag, n))
                            sys.exit(-1)

                    self.__members.append((n, t, s, f, c))

        #
        # Generate a type id here using SHA256 algorithm and XML stringified file.
        #

        if not "typeid" in serializable.attrib:
            s = etree.tostring(element_tree.getroot())
            h = hashlib.sha256(s)
            n = h.hexdigest()
            self.__type_id = "0x" + n.upper()[-8:]
    def __init__(self, xml_file=None):
        """
        Given a well formed XML file (xml_file), read it and turn it into
        a big string.
        """
        self.__root = None
        self.__name = ""
        self.__namespace = None
        # List of C++ include files for serializable *.hpp file
        self.__include_header_files = []
        # List of XML serializable description dependencies
        self.__includes = []
        # List of XML enum type files
        self.__include_enum_files = []
        # Comment block of text for serializable
        self.__comment = ""
        # List of (name, type, comment) tuples
        self.__members = []
        # Type ID for serialized type
        self.__type_id = None
        #
        if os.path.isfile(xml_file) == False:
            stri = "ERROR: Could not find specified XML file %s." % xml_file
            raise IOError(stri)
        fd = open(xml_file,'r')
#        xml_file = os.path.basename(xml_file)
        self.__xml_filename = xml_file

        self.__config       = ConfigManager.ConfigManager.getInstance()

        #

        xml_parser = etree.XMLParser(remove_comments=True)
        element_tree = etree.parse(fd,parser=xml_parser)

        #Validate new imports using their root tag as a key to find what schema to use
        for possible in [os.environ.get('BUILD_ROOT'), os.environ.get('FPRIME_CORE_DIR',"")]:
            rng_file = os.path.join(possible, self.__config.get('schema' , element_tree.getroot().tag.lower()).lstrip("/"))
            if os.path.isfile(rng_file) == True:
                break
        else:
            stri = "ERROR: Could not find specified RNG file %s." % rng_file
            raise IOError(stri)
        file_handler = open(rng_file, 'r')
        relax_parsed = etree.parse(file_handler)
        file_handler.close()
        relax_compiled = etree.RelaxNG(relax_parsed)

        # 2/3 conversion
        if not relax_compiled.validate(element_tree):
            msg = "XML file {} is not valid according to schema {}.".format(xml_file , os.environ["BUILD_ROOT"] +self.__config.get('schema' , element_tree.getroot().tag.lower()))
            raise FprimeXmlException(msg)

        serializable = element_tree.getroot()
        if serializable.tag != "serializable":
            PRINT.info("%s is not a serializable definition file"%xml_file)
            sys.exit(-1)

        print("Parsing Serializable %s" %serializable.attrib['name'])

        self.__name = serializable.attrib['name']

        if 'namespace' in serializable.attrib:
            self.__namespace = serializable.attrib['namespace']
        else:
            self.__namespace = None

        if 'typeid' in serializable.attrib:
            self.__type_id = serializable.attrib['typeid']
        else:
            self.__type_id = None

        for serializable_tag in serializable:
            if serializable_tag.tag == 'comment':
                self.__comment = serializable_tag.text.strip()
            elif serializable_tag.tag == 'include_header':
                self.__include_header_files.append(serializable_tag.text)
            elif serializable_tag.tag == 'import_serializable_type':
                self.__includes.append(serializable_tag.text)
            elif serializable_tag.tag == 'import_enum_type':
                self.__include_enum_files.append(serializable_tag.text)
            elif serializable_tag.tag == 'members':
                for member in serializable_tag:
                    if member.tag != 'member':
                        PRINT.info("%s: Invalid tag %s in serializable member definition"%(xml_file,member.tag))
                        sys.exit(-1)
                    n = member.attrib['name']
                    t = member.attrib['type']
                    if 'size' in list(member.attrib.keys()):
                        if t == "ENUM":
                            PRINT.info("%s: Member %s: arrays of enums not supported yet!"%(xml_file,n))
                            sys.exit(-1)
                        s = member.attrib['size']
                        if not s.isdigit():
                            PRINT.info("%s: Member %s: size must be a number"%(xml_file,n))
                            sys.exit(-1)
                    else:
                        s = None
                    if 'format' in list(member.attrib.keys()):
                        f = member.attrib['format']
                    else:
                        if t in list(format_dictionary.keys()):
                            f = format_dictionary[t]
                        else: # Must be included type, which will use toString method
                            f = "%s"
                    if t == 'string':
                        if s == None:
                            PRINT.info("%s: member %s string must specify size tag"%(xml_file,member.tag))
                            sys.exit(-1)

                    if 'comment' in list(member.attrib.keys()):
                        c = member.attrib['comment']
                    else:
                        c = None

                    for member_tag in member:
                        if member_tag.tag == 'enum' and t == 'ENUM':
                            en = member_tag.attrib['name']
                            enum_members = []
                            for mem in member_tag:
                                mn = mem.attrib['name']
                                if "value" in list(mem.attrib.keys()):
                                    v = mem.attrib['value']
                                else:
                                    v = None
                                if "comment" in list(mem.attrib.keys()):
                                    mc = mem.attrib['comment'].strip()
                                else:
                                    mc = None
                                enum_members.append((mn,v,mc))
                            t = ((t,en),enum_members)
                        else:
                            PRINT.info("%s: Invalid member tag %s in serializable member %s"%(xml_file,member_tag.tag,n))
                            sys.exit(-1)


                    self.__members.append((n, t, s, f, c))


        #
        # Generate a type id here using SHA256 algorithm and XML stringified file.
        #

        if not 'typeid' in serializable.attrib:
            s = etree.tostring(element_tree.getroot())
            h = hashlib.sha256(s)
            n = h.hexdigest()
            self.__type_id = "0x" + n.upper()[-8:]