Example #1
0
    def construct_dicts(self, path, ch_name_dict):
        """
        Constructs and returns python dictionaries keyed on id and name

        This function should not be called directly, instead, use
        get_id_dict(path) and get_name_dict(path)

        Args:
            path (string): Path to the packet definition xml file to parse into
                           a dictionary.
            ch_name_dict (dict()): Channel dictionary with names as keys and
                                   ChTemplate objects as values.

        Returns:
            A tuple with two packet dictionaries (type==dict()):
            (id_dict, name_dict). The keys should be the packets' id and name
            fields respectively and the values should be PktTemplate objects.
        """
        packet_list = self.get_xml_tree(path)
        if packet_list.tag != self.PKT_LIST_TAG:
            raise exceptions.GseControllerParsingException(
                "expected packet list to have tag %s, but found %s" %
                (self.PKT_LIST_TAG, packet_list.tag))

        id_dict = dict()
        name_dict = dict()

        for packet in packet_list:
            # check if this is actually a packet, and not something to ignore
            if packet.tag != self.PKT_TAG:
                continue

            pkt_name = packet.attrib[self.NAME_FIELD]
            pkt_id = int(packet.attrib[self.ID_FIELD])

            ch_list = []
            for ch in packet:
                ch_name = ch.attrib[self.CH_NAME_FIELD]

                if ch_name not in ch_name_dict:
                    raise exceptions.GseControllerParsingException(
                        "Channel %s in pkt %s, but cannot be found in channel dictionary"
                        % (ch_name, pkt_name))

                ch_list.append(ch_name_dict[ch_name])

            pkt_temp = PktTemplate(pkt_id, pkt_name, ch_list)

            id_dict[pkt_id] = pkt_temp
            name_dict[pkt_name] = pkt_temp

        return (id_dict, name_dict)
Example #2
0
    def parse_type(self, type_name, xml_item, xml_tree):
        '''
        Parses the given type string and returns a type object.

        Args:
            type_name (string): Name of the type in the xml
            xml_item (lxml etree root): Parsed xml object for the item
                      containing the type name being parsed. This is used to get
                      meta data such as string lenght.
            xml_tree (lxml etree root): Parsed Xml object containing enum and
                                        serializable type info (may not be used)

        Returns:
            Object of a class derived from the TypeBase class if successful,
            Raises an exception if the parsing fails. The caller will hold the
            only reference to the object.
        '''

        if (type_name == "I8"):
            return I8Type()
        elif (type_name == "I16"):
            return I16Type()
        elif (type_name == "I32"):
            return I32Type()
        elif (type_name == "I64"):
            return I64Type()
        elif (type_name == "U8"):
            return U8Type()
        elif (type_name == "U16"):
            return U16Type()
        elif (type_name == "U32"):
            return U32Type()
        elif (type_name == "U64"):
            return U64Type()
        elif (type_name == "F32"):
            return F32Type()
        elif (type_name == "F64"):
            return F64Type()
        elif (type_name == "bool"):
            return BoolType()
        elif (type_name == "string"):
            if self.STR_LEN_TAG not in xml_item.attrib:
                print("Trying to parse string type, but found %s field" %
                      self.STR_LEN_TAG)
                return None
            return StringType(max_string_len=xml_item.get(self.STR_LEN_TAG))
        else:
            # First try Serialized types:
            result = self.get_serializable_type(type_name, xml_tree)
            if result != None:
                return result

            # Now try enums:
            result = self.get_enum_type(type_name, xml_tree)
            if result != None:
                return result

            # Abandon all hope
            raise exceptions.GseControllerParsingException(
                "Could not find type %s" % type_name)
Example #3
0
    def construct_dicts(self, path):
        """
        Constructs and returns python dictionaries keyed on id and name

        This function should not be called directly, instead, use
        get_id_dict(path) and get_name_dict(path)

        Args:
            path: Path to the xml dictionary file containing event information

        Returns:
            A tuple with two event dictionaries (python type dict):
            (id_idct, name_dict). The keys are the events' id and name fields
            respectively and the values are ChTemplate objects
        """
        xml_tree = self.get_xml_tree(path)

        # Check if xml dict has events section
        event_section = self.get_xml_section(self.EVENT_SECT, xml_tree)
        if event_section is None:
            raise exceptions.GseControllerParsingException(
                "Xml dict did not have a %s section" % self.EVENT_SECT
            )

        id_dict = dict()
        name_dict = dict()

        for event in event_section:
            event_dict = event.attrib

            event_comp = event_dict[self.COMP_TAG]
            event_name = event_dict[self.NAME_TAG]
            event_id = int(event_dict[self.ID_TAG], base=16)
            event_severity = EventSeverity[event_dict[self.SEVERITY_TAG]]
            event_fmt_str = event_dict[self.FMT_STR_TAG]

            event_desc = None
            if self.DESC_TAG in event_dict:
                event_desc = event_dict[self.DESC_TAG]

            # Parse arguments
            args = self.get_args_list(event, xml_tree)

            event_temp = EventTemplate(
                event_id,
                event_name,
                event_comp,
                args,
                event_severity,
                event_fmt_str,
                event_desc,
            )

            id_dict[event_id] = event_temp
            name_dict[event_name] = event_temp

        return (id_dict, name_dict)
Example #4
0
    def construct_dicts(self, path):
        '''
        Constructs and returns python dictionaries keyed on id and name

        This function should not be called directly, instead, use
        get_id_dict(path) and get_name_dict(path)

        Args:
            path: Path to the xml dictionary file containing command information

        Returns:
            A tuple with two command dictionaries (python type dict):
            (id_dict, name_dict). The keys are the events' id and name fields
            respectively and the values are ChTemplate objects
        '''
        xml_tree = self.get_xml_tree(path)

        # Check if xml dict has commands section
        cmd_section = self.get_xml_section(self.CMD_SECT, xml_tree)
        if (cmd_section == None):
            # TODO make this its own error (XML section err or something)
            raise exceptions.GseControllerParsingException(
                    "Xml dict did not have a %s section"%self.EVENT_SECT)

        id_dict = dict()
        name_dict = dict()

        for cmd in cmd_section:
            cmd_dict = cmd.attrib

            cmd_comp = cmd_dict[self.COMP_TAG]
            cmd_mnemonic = cmd_dict[self.MNEMONIC_TAG]
            cmd_opcode = int(cmd_dict[self.OPCODE_TAG], base=16)

            cmd_desc = None
            if (self.DESC_TAG in cmd_dict):
                cmd_desc = cmd_dict[self.DESC_TAG]

            # Parse Arguments
            args = self.get_args_list(cmd, xml_tree)

            cmd_temp = CmdTemplate(cmd_opcode, cmd_mnemonic, cmd_comp, args,
                                   cmd_desc)

            id_dict[cmd_opcode] = cmd_temp
            name_dict[cmd_mnemonic] = cmd_temp

        return (id_dict, name_dict)
Example #5
0
    def parse(self, filename):
        """
        Generator that parses an input sequence file and returns a tuple
        for each valid line of the sequence file.
        @param seqfile: A sequence file name (usually a .seq extension)
        @return A list of tuples:
            (lineNumber, descriptor, seconds, useconds, mnemonic, arguments)
        """
        def subQuoted(f, string):
            """
            Run a substitution function on only substrings within a string that are surrounded
            by single or double quotes
            @param f: a string substitution acting on matchobjs
            @param string: the string to perform the substitution on
            @return the substituted string
            """
            s = re.sub(r'"[^"]*"', f, string)
            return re.sub(r"'[^']*'", f, s)

        def removeTrailingComments(string):
            """
            Remove any trailing comments (proceded by ';') in a string
            @param string: the string to perform comment removal on
            @return the string without trailing comments
            """
            def replaceSemis(matchobj):
                return matchobj.group(0).replace(";", " ")

            # ignore all semicolons in quotes:
            s = subQuoted(replaceSemis, string)
            s = subQuoted(replaceSemis, s)
            # get index of first semicolon, and return everything before it:
            if ";" in s:
                index = s.index(";")
                return string[:index]
            # return original string if no semicolon found:
            return string

        def splitString(string):
            """
            Split a string with ' ' or ',' as a delimiter. Ignore any delimiters
            found within quoted substrings.
            @param string: the string to perform the split on
            @return a list representing the split string
            """
            def replaceSpacesAndCommas(matchobj):
                s = re.sub(r"\s", "_", matchobj.group(0))
                s = re.sub(r"\,", "_", s)
                return s

            # ignore all spaces in quotes:
            s = subQuoted(replaceSpacesAndCommas, string)
            # replace all commas with spaces, since either can be a delimiter:
            s = s.replace(",", " ")
            # get the split indices of the modified string:
            indices = [(m.start(), m.end()) for m in re.finditer(r"\S+", s)]
            toReturn = []
            for start, end in indices:
                toReturn.append(string[start:end])
            return toReturn

        def parseArgs(args):
            """
            Turn .seq command argument list into their appropriate python types
            @param args: a list of parsed arguments
            @return a list of arguments as native python types
            """
            def parseArg(arg):
                # See if argument is a string, if so remove the quotes and return it:
                if (arg[0] == '"' and arg[-1] == '"') or (arg[0] == "'"
                                                          and arg[-1] == "'"):
                    return arg[1:-1]
                # If the string contains a "." assume that it is a float:
                elif "." in arg:
                    return float(arg)
                elif arg == "True" or arg == "true" or arg == "TRUE":
                    return True
                elif arg == "False" or arg == "false" or arg == "FALSE":
                    return False
                else:
                    try:
                        # See if it translates to an integer:
                        return int(arg, 0)
                    except ValueError:
                        try:
                            # See if it translates to a float:
                            return float(arg)
                        except ValueError:
                            # Otherwise it is an enum type:
                            return str(arg)

            return list(map(parseArg, args))

        def parseTime(lineNumber, time):
            """
            Parse a time string and return the command descriptor, seconds, and useconds of the time string
            @param lineNumber: the current line number where the time string was parsed
            @param time: the time string to parse
            @return a tuple (descriptor, seconds, useconds)
            """
            def parseTimeStringOption(timeStr, timeFmts):
                """
                Parse a time string by trying to use different time formats, until one succeeds
                @param timeStr: the time string
                @param timeFmts: the time format used to parse the string
                @return the datetime object containing the parsed string
                """
                def parseTimeString(timeFmt):
                    try:
                        return datetime.strptime(timeStr, timeFmt)
                    except:
                        return None

                for fmt in timeFmts:
                    dt = parseTimeString(fmt)
                    if dt:
                        return dt
                raise BaseException

            def parseRelative(timeStr):
                """
                Parse a relative time string
                @param timeStr: the time string
                @return the datetime object containing the parsed string
                """
                options = ["%H:%M:%S.%f", "%H:%M:%S"]
                return parseTimeStringOption(timeStr, options)

            def parseAbsolute(timeStr):
                """
                Parse an absolute time string
                @param timeStr: the time string
                @return the datetime object containing the parsed string
                """
                options = ["%Y-%jT%H:%M:%S.%f", "%Y-%jT%H:%M:%S"]
                return parseTimeStringOption(timeStr, options)

            descriptor = None
            d = time[0]
            t = time[1:]
            if d == "R":
                descriptor = Descriptor.RELATIVE
                dt = parseRelative(t)
                delta = timedelta(
                    hours=dt.hour,
                    minutes=dt.minute,
                    seconds=dt.second,
                    microseconds=dt.microsecond,
                ).total_seconds()
            elif d == "A":
                descriptor = Descriptor.ABSOLUTE
                dt = parseAbsolute(t)
                # See if timezone was specified. If not, use UTC
                if dt.tzinfo is not None:
                    print("Using timezone %s" % dt.tzinfo.tzname())
                    epoch = datetime.fromtimestamp(0, dt.tzinfo)
                else:
                    print("Using UTC timezone")
                    epoch = datetime.utcfromtimestamp(0)
                delta = (dt - epoch).total_seconds()
            else:
                raise gseExceptions.GseControllerParsingException("Line %d: %s" % (
                    lineNumber + 1,
                    "Invalid time descriptor '" + d +
                    "' found. Descriptor should either be 'A' for absolute times or 'R' for relative times",
                ))
            seconds = int(delta)
            useconds = int((delta - seconds) * 1000000)
            return descriptor, seconds, useconds

        # Open the sequence file and parse each line:
        with open(filename) as inputFile:
            for i, line in enumerate(inputFile):
                line = line.strip()
                # ignore blank lines and comments
                if line and line[0] != ";":
                    line = removeTrailingComments(line)
                    line = splitString(line)
                    length = len(line)
                    if length < 2:
                        raise gseExceptions.GseControllerParsingException(
                            "Line %d: %s" % (
                                i + 1,
                                "Each line must contain a minimum of two fields, time and command mnemonic\n",
                            ))
                    else:
                        try:
                            descriptor, seconds, useconds = parseTime(
                                i, line[0])
                        except:
                            raise gseExceptions.GseControllerParsingException(
                                "Line %d: %s" %
                                (i + 1,
                                 "Encountered syntax error parsing timestamp"))
                        mnemonic = line[1]
                        args = []
                        if length > 2:
                            args = line[2:]
                            try:
                                args = parseArgs(args)
                            except:
                                raise gseExceptions.GseControllerParsingException(
                                    "Line %d: %s" % (
                                        i + 1,
                                        "Encountered sytax error parsing arguments",
                                    ))
                    yield i, descriptor, seconds, useconds, mnemonic, args
Example #6
0
        def parseTime(lineNumber, time):
            """
            Parse a time string and return the command descriptor, seconds, and useconds of the time string
            @param lineNumber: the current line number where the time string was parsed
            @param time: the time string to parse
            @return a tuple (descriptor, seconds, useconds)
            """
            def parseTimeStringOption(timeStr, timeFmts):
                """
                Parse a time string by trying to use different time formats, until one succeeds
                @param timeStr: the time string
                @param timeFmts: the time format used to parse the string
                @return the datetime object containing the parsed string
                """
                def parseTimeString(timeFmt):
                    try:
                        return datetime.strptime(timeStr, timeFmt)
                    except:
                        return None

                for fmt in timeFmts:
                    dt = parseTimeString(fmt)
                    if dt:
                        return dt
                raise BaseException

            def parseRelative(timeStr):
                """
                Parse a relative time string
                @param timeStr: the time string
                @return the datetime object containing the parsed string
                """
                options = ["%H:%M:%S.%f", "%H:%M:%S"]
                return parseTimeStringOption(timeStr, options)

            def parseAbsolute(timeStr):
                """
                Parse an absolute time string
                @param timeStr: the time string
                @return the datetime object containing the parsed string
                """
                options = ["%Y-%jT%H:%M:%S.%f", "%Y-%jT%H:%M:%S"]
                return parseTimeStringOption(timeStr, options)

            descriptor = None
            d = time[0]
            t = time[1:]
            if d == "R":
                descriptor = Descriptor.RELATIVE
                dt = parseRelative(t)
                delta = timedelta(
                    hours=dt.hour,
                    minutes=dt.minute,
                    seconds=dt.second,
                    microseconds=dt.microsecond,
                ).total_seconds()
            elif d == "A":
                descriptor = Descriptor.ABSOLUTE
                dt = parseAbsolute(t)
                # See if timezone was specified. If not, use UTC
                if dt.tzinfo is not None:
                    print("Using timezone %s" % dt.tzinfo.tzname())
                    epoch = datetime.fromtimestamp(0, dt.tzinfo)
                else:
                    print("Using UTC timezone")
                    epoch = datetime.utcfromtimestamp(0)
                delta = (dt - epoch).total_seconds()
            else:
                raise gseExceptions.GseControllerParsingException("Line %d: %s" % (
                    lineNumber + 1,
                    "Invalid time descriptor '" + d +
                    "' found. Descriptor should either be 'A' for absolute times or 'R' for relative times",
                ))
            seconds = int(delta)
            useconds = int((delta - seconds) * 1000000)
            return descriptor, seconds, useconds
Example #7
0
    def construct_dicts(self, path):
        """
        Constructs and returns python dictionaries keyed on id and name

        This function should not be called directly, instead, use
        get_id_dict(path) and get_name_dict(path)

        Args:
            path: Path to the xml dictionary file containing channel information

        Returns:
            A tuple with two channel dictionaries (python type dict):
            (id_idct, name_dict). The keys are the channels' id and name fields
            respectively and the values are ChTemplate objects
        """
        xml_tree = self.get_xml_tree(path)

        # Check if xml dict has channels section
        ch_section = self.get_xml_section(self.CH_SECT, xml_tree)
        if ch_section is None:
            raise exceptions.GseControllerParsingException(
                "Xml dict did not have a %s section" % self.CH_SECT
            )

        id_dict = dict()
        name_dict = dict()
        for ch in ch_section:
            ch_dict = ch.attrib

            # Assume the required fields are present (component, name, id,
            #  description, type). Check for all others
            ch_comp = ch_dict[self.COMP_TAG]
            ch_name = ch_dict[self.NAME_TAG]
            ch_id = int(ch_dict[self.ID_TAG], base=16)
            ch_type_obj = self.parse_type(ch_dict[self.TYPE_TAG], ch, xml_tree)

            ch_desc = None
            ch_fmt_str = None
            ch_low_red = None
            ch_low_orange = None
            ch_low_yellow = None
            ch_high_yellow = None
            ch_high_orange = None
            ch_high_red = None

            if self.DESC_TAG in ch_dict:
                ch_desc = ch_dict[self.DESC_TAG]

            if self.FMT_STR_TAG in ch_dict:
                ch_fmt_str = ch_dict[self.FMT_STR_TAG]

            # TODO we need to convert these into numbers, is this the best
            #  way to do it?
            if self.LOW_R_TAG in ch_dict:
                ch_low_red = float(ch_dict[self.LOW_R_TAG])

            if self.LOW_O_TAG in ch_dict:
                ch_low_orange = float(ch_dict[self.LOW_O_TAG])

            if self.LOW_Y_TAG in ch_dict:
                ch_low_yellow = float(ch_dict[self.LOW_Y_TAG])

            if self.HIGH_Y_TAG in ch_dict:
                ch_high_yellow = float(ch_dict[self.HIGH_Y_TAG])

            if self.HIGH_O_TAG in ch_dict:
                ch_high_orange = float(ch_dict[self.HIGH_O_TAG])

            if self.HIGH_R_TAG in ch_dict:
                ch_high_red = float(ch_dict[self.HIGH_R_TAG])

            ch_temp = ChTemplate(
                ch_id,
                ch_name,
                ch_comp,
                ch_type_obj,
                ch_fmt_str,
                ch_desc,
                ch_low_red,
                ch_low_orange,
                ch_low_yellow,
                ch_high_yellow,
                ch_high_orange,
                ch_high_red,
            )

            id_dict[ch_id] = ch_temp
            name_dict[ch_name] = ch_temp

        return (id_dict, name_dict)