Example #1
0
    def parseCat(self, filePath):
        """Parse a catalog given its full file path.
        
        Returns two items:
        - objCat: the catalog as a TUI.TCC.TelTarget.Catalog
        - errList: a list of (line, errMsg) tuples, one per rejected line of object data
        
        Raises RuntimeError if the file cannot be read or a default is invalid.
        
        Uses universal newline support (new in Python 2.3) if possible.
        """
#       print "parseCat(%r)" % (filePath,)
        fp = RO.OS.openUniv(filePath)
        catName = os.path.basename(filePath)

        defOptionDict = self._keyMatcher.matchKeys({
            "CSys": "FK5",
            "RotType": "Object",
        })
        errList = []
        objList = []
        
        # save checkWdg data, then use try/finally to restore no matter what
        ii = 0
        for line in fp:
            ii += 1
#           print "Parsing object %d" % ii
            isDefault = False
            line = line.strip()
            try:
                if not line:
                    # blank line
                    continue
                elif line[0] in ("#", "!"):
                    # comment
                    continue
                elif line[0] in ('"', "'"):
                    # data with quoted object name
                    (objName, nextInd) = GetString.getString(line)
                    pos1, pos2, optionStr = posOptionRE.match(line[nextInd:]).groups()
                else:
                    # data with unquoted object name or default option
                    match = namePosOptionRE.match(line)
                    if match:
                        # data with unquoted object name
                        objName, pos1, pos2, optionStr = match.groups()
                    elif line[0].isdigit():
                        raise ValueError("could not parse; is object name missing?")
                    else:
                        isDefault = True
                        optionStr = line
        
                if optionStr:
                    optDict = ParseData.parseKeyValueData(optionStr)
                else:
                    optDict = {}
                
                if isDefault:
                    # update existing defaults
                    
                    # merge new defaults into existing defaults
                    # and check the result
                    self._combineDicts(defOptionDict, optDict)
                else:
                    # a line of data
                    # the data dictionary starts with the current defaults
                    dataDict = defOptionDict.copy()
                    
                    # add object name and position (non-dictionary items)
                    dataDict.update({
                        "Name": objName,
                        "ObjPos": (pos1, pos2),
                    })

                    # merge new data with a copy of the defaults
                    # and check the result
                    self._combineDicts(dataDict, optDict)
                    
                    objList.append(TUI.TCC.TelTarget.TelTarget(dataDict))
            except Exception, e:
                if isDefault:
                    raise RuntimeError(RO.StringUtil.strFromException(e))
                else:
                    errList.append((line, RO.StringUtil.strFromException(e)))
Example #2
0
def getValues(astr, begInd=0):
    """
Extracts all values (zero or more) for a keyword.

Inputs:
    astr: the string to parse
    begInd: index of start, must point to "=" if the keyword has any values
        or ";" if the keyword has no values. Initial whitespace is skipped.

Returns a duple consisting of:
    a tuple of values (empty if there are no values)
    the index of the beginning of the next keyword, or None if end of string

Exceptions:
    If astr[begInd] is not "=" or ";" then raises a SyntaxError
"""
    if begInd is None:
        return ((), None)

    mo = _StartRE.match(astr, begInd)
    if mo is None:
        raise SyntaxError("cannot find value(s) starting at %d in :%s:" % \
            (begInd, astr))
    sepChar = mo.group('first')
    nextInd = mo.start('next')
    if nextInd < 0:
        # no values and line finished
        return ((), None)
    if sepChar == ';':
        # no values; line not finished
        return ((), nextInd)

    valueList = []

    prevInd = nextInd
#   print "data = :%s:, begInd = %d" % (astr, begInd)
    while True:
#       print "scanning :%s:, i.e. nextInd = %d" % (astr[nextInd:], nextInd)
        nextIsKey = False
        if astr[nextInd] in "\'\"":
            # value is a delimited string
#           print "looking for a delimited string"
            (value, nextInd) = GetString.getString(astr, nextInd)
            valueList.append(value)

        elif astr[nextInd] != ';':
            # value is an undelimited word (e.g. a number, NaN, etc.)
#           print "looking for an undelimited word starting at %d" % (nextInd)
            mo = _UndelimWordRE.match(astr, nextInd)
            if mo is None:
                raise SyntaxError("cannot find an undelimited word starting at %d in :%s:" % \
                    (nextInd, astr))
            value = mo.group('str')
            nextInd = mo.start('next')
            if (nextInd < 0):
                nextInd = None

            valueList.append(value)

#       print "valueList =", valueList, "nextInd =", nextInd,
#       if nextInd is not None:
#           print "char at nextInd =", astr[nextInd]
#       else:
#           print ""
        
        if nextInd is None:
            # done with line
            break

        # nextInd points to comma or semicolon
        if astr[nextInd] == ';':
            nextIsKey = True
        elif astr[nextInd] != ',':
            print("bug; expected comma or semicolon as next token; giving up on line")
            nextInd = None
            break

        if (nextInd <= prevInd) and not nextIsKey:
            print("bug: nextInd = %d <= prevInd = %d" % (nextInd, prevInd))
            nextInd = None
            break

        # find index of next character
        for ind in range(nextInd+1, len(astr)):
            if astr[ind] not in ' \t':
                nextInd = ind
                break
        else:
            print("ignoring separator \"%s\" at end of data :%s:" % \
                (astr[nextInd], astr))
            nextInd = None
            break

        if nextInd >= len(astr):
            break

        if nextIsKey:
            break


        prevInd = nextInd

    return (tuple(valueList), nextInd)
Example #3
0
    def parseCat(self, filePath):
        """Parse a catalog given its full file path.
        
        Returns two items:
        - objCat: the catalog as a TUI.TCC.TelTarget.Catalog
        - errList: a list of (line, errMsg) tuples, one per rejected line of object data
        
        Raises RuntimeError if the file cannot be read or a default is invalid.
        
        Uses universal newline support (new in Python 2.3) if possible.
        """
        #       print "parseCat(%r)" % (filePath,)
        fp = RO.OS.openUniv(filePath)
        catName = os.path.basename(filePath)

        defOptionDict = self._keyMatcher.matchKeys({
            "CSys": "FK5",
            "RotType": "Object",
        })
        errList = []
        objList = []

        # save checkWdg data, then use try/finally to restore no matter what
        ii = 0
        for line in fp:
            ii += 1
            #           print "Parsing object %d" % ii
            isDefault = False
            line = line.strip()
            try:
                if not line:
                    # blank line
                    continue
                elif line[0] in ("#", "!"):
                    # comment
                    continue
                elif line[0] in ('"', "'"):
                    # data with quoted object name
                    (objName, nextInd) = GetString.getString(line)
                    pos1, pos2, optionStr = posOptionRE.match(
                        line[nextInd:]).groups()
                else:
                    # data with unquoted object name or default option
                    match = namePosOptionRE.match(line)
                    if match:
                        # data with unquoted object name
                        objName, pos1, pos2, optionStr = match.groups()
                    elif line[0].isdigit():
                        raise ValueError(
                            "could not parse; is object name missing?")
                    else:
                        isDefault = True
                        optionStr = line

                if optionStr:
                    optDict = ParseData.parseKeyValueData(optionStr)
                else:
                    optDict = {}

                if isDefault:
                    # update existing defaults

                    # merge new defaults into existing defaults
                    # and check the result
                    self._combineDicts(defOptionDict, optDict)
                else:
                    # a line of data
                    # the data dictionary starts with the current defaults
                    dataDict = defOptionDict.copy()

                    # add object name and position (non-dictionary items)
                    dataDict.update({
                        "Name": objName,
                        "ObjPos": (pos1, pos2),
                    })

                    # merge new data with a copy of the defaults
                    # and check the result
                    self._combineDicts(dataDict, optDict)

                    objList.append(TUI.TCC.TelTarget.TelTarget(dataDict))
            except Exception as e:
                if isDefault:
                    raise RuntimeError(RO.StringUtil.strFromException(e))
                else:
                    errList.append((line, RO.StringUtil.strFromException(e)))

        # convert catalog options as appropriate
        self._catOptions["doDisplay"] = RO.CnvUtil.asBool(
            self._catOptions["doDisplay"])

        # create catalog
        #       print "parseCat: catOptions =", self._catOptions
        objCat = TUI.TCC.TelTarget.Catalog(name=catName,
                                           objList=objList,
                                           **self._catOptions)
        #       print "parseCat returning (%r, %r)" % (objCat, errList)
        return objCat, errList
Example #4
0
def getValues(astr, begInd=0):
    """
Extracts all values (zero or more) for a keyword.

Inputs:
    astr: the string to parse
    begInd: index of start, must point to "=" if the keyword has any values
        or ";" if the keyword has no values. Initial whitespace is skipped.

Returns a duple consisting of:
    a tuple of values (empty if there are no values)
    the index of the beginning of the next keyword, or None if end of string

Exceptions:
    If astr[begInd] is not "=" or ";" then raises a SyntaxError
"""
    if begInd is None:
        return ((), None)

    mo = _StartRE.match(astr, begInd)
    if mo is None:
        raise SyntaxError("cannot find value(s) starting at %d in :%s:" % \
            (begInd, astr))
    sepChar = mo.group('first')
    nextInd = mo.start('next')
    if nextInd < 0:
        # no values and line finished
        return ((), None)
    if sepChar == ';':
        # no values; line not finished
        return ((), nextInd)

    valueList = []

    prevInd = nextInd
    #   print "data = :%s:, begInd = %d" % (astr, begInd)
    while True:
        #       print "scanning :%s:, i.e. nextInd = %d" % (astr[nextInd:], nextInd)
        nextIsKey = False
        if astr[nextInd] in "\'\"":
            # value is a delimited string
            #           print "looking for a delimited string"
            (value, nextInd) = GetString.getString(astr, nextInd)
            valueList.append(value)

        elif astr[nextInd] != ';':
            # value is an undelimited word (e.g. a number, NaN, etc.)
            #           print "looking for an undelimited word starting at %d" % (nextInd)
            mo = _UndelimWordRE.match(astr, nextInd)
            if mo is None:
                raise SyntaxError("cannot find an undelimited word starting at %d in :%s:" % \
                    (nextInd, astr))
            value = mo.group('str')
            nextInd = mo.start('next')
            if (nextInd < 0):
                nextInd = None

            valueList.append(value)


#       print "valueList =", valueList, "nextInd =", nextInd,
#       if nextInd is not None:
#           print "char at nextInd =", astr[nextInd]
#       else:
#           print ""

        if nextInd is None:
            # done with line
            break

        # nextInd points to comma or semicolon
        if astr[nextInd] == ';':
            nextIsKey = True
        elif astr[nextInd] != ',':
            print(
                "bug; expected comma or semicolon as next token; giving up on line"
            )
            nextInd = None
            break

        if (nextInd <= prevInd) and not nextIsKey:
            print("bug: nextInd = %d <= prevInd = %d" % (nextInd, prevInd))
            nextInd = None
            break

        # find index of next character
        for ind in range(nextInd + 1, len(astr)):
            if astr[ind] not in ' \t':
                nextInd = ind
                break
        else:
            print("ignoring separator \"%s\" at end of data :%s:" % \
                (astr[nextInd], astr))
            nextInd = None
            break

        if nextInd >= len(astr):
            break

        if nextIsKey:
            break

        prevInd = nextInd

    return (tuple(valueList), nextInd)