Source code for pyasdm.Parser

# ALMA - Atacama Large Millimeter Array
# (c) European Southern Observatory, 2024
# (c) Associated Universities Inc., 2024
# Copyright by ESO (in the framework of the ALMA collaboration),
# Copyright by AUI (in the framework of the ALMA collaboration),
# All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307  USA
#
# File Parser.py

from pyasdm.exceptions.ConversionException import ConversionException
from pyasdm.types.ArrayTimeInterval import ArrayTimeInterval
import pyasdm.utils


[docs]class Parser: """ A collection of static methods used by the pyasdm classes in producing and consuming XML. This is different from how the strongly typed languages use Parser, but it's similar enough that it's been kept in a class of the same name. This is not generated code. """ def __init__(self): # there are no non-static members, so there should be no need to create a Parser object raise RuntimeError("A Parser instance makes no sense")
[docs] @staticmethod def nameStringToXML(name, strval): """ A method to produce XML using the name and a string value. <name>strval</name> The returned value has a trailing space so that it can be used to add these strings together without worrying about spacing. """ return "<%s> %s </%s> " % (name, strval, name)
[docs] @staticmethod def valueToXML(name, value): """ Return a string of the form '<name> value </name>' to be used in the XML output. The value must be convertable to a string using the simple str(value) method. A value that is an instance of a class with a __str__ method should use the extendedValuetoXML method. """ return Parser.nameStringToXML(name, str(value))
[docs] @staticmethod def extendedValueToXML(name, value): """ Return a string of the form '<name> value </name>' to be used in the XML output. The value must have a __str__ member used to convert that value to a string representation. Extended type values all have that function. ArrayTimeInterval is the exception. The __str__ method there is not used here following the similar case Java. """ valueStr = None if isinstance(value, ArrayTimeInterval): # the string is the mid point and duration values separated by a space valueStr = ( str(value.getMidPoint().get()) + " " + str(value.getDuration().get()) ) else: valueStr = str(value) return Parser.nameStringToXML(name, valueStr)
[docs] @staticmethod def listXMLPrefix(dims): """ Return a string with the dimensions list encoded as expected for XML storage of the associated list. 'no_dims dim0 dim1 ... dimn ' """ result = "%s " % len(dims) for thisDim in dims: result += "%s " % thisDim return result
[docs] @staticmethod def listValuesAsString(theList, dims): """ Turns a list (including a list of lists as used here) into a string for use in an XML output. Values in the list are turned into a string by use of str(value). """ result = "" if len(dims) > 1: for kk in range(dims[0]): result += Parser.listValuesAsString(theList[kk], dims[1:]) else: # these are actual values for jj in range(dims[0]): result += str(theList[jj]) + " " return result
[docs] @staticmethod def listExtendedValuesAsString(theList, dims): """ Turns a list (including a list of lists as used here) into a string for use in an XML output. Values in the list are extended type values and are turned into a string by use of the __str__ method that is part of extended types. """ result = "" if len(dims) > 1: for kk in range(dims[0]): result += Parser.listExtendedValuesAsString(theList[kk], dims[1:]) else: # these are actual values try: for jj in range(dims[0]): result += str(theList[jj]) + " " except: print("exception seen for type " + str(type(theList[jj]))) raise return result
[docs] @staticmethod def listEnumValuesAsString(theList, dims): """ Turns a list (including a list of lists as used here) into a string for use in an XML output. Values in the list are Enumerations and are turned into a string by use of the getName method. """ result = "" if len(dims) > 1: for kk in range(dims[0]): result += Parser.listEnumValuesAsString(theList[kk], dims[1:]) else: # these are actual values for jj in range(dims[0]): result += theList[jj].getName() + " " return result
[docs] @staticmethod def listValueToXML(name, value): """ Return a string of the form '<name> list values </name>' to be used in the XML output. The list values are encoded such that they can be read and the list (which may be a list of lists, i.e. an ND array of values) be fully reconstructed from that XML. For use with standard types which can be expressed as a string using str(value). Arrays are encoded here as <name> ndim dim1 dim2 dim... dimn value value value ... </name> and the most rapidly varying dimension among the values is the last dimension. """ listDims = pyasdm.utils.getListDims(value) result = "<%s> " % name result += Parser.listXMLPrefix(listDims) result += Parser.listValuesAsString(value, listDims) result += "</%s> " % name return result
[docs] @staticmethod def listExtendedValueToXML(name, value): """ Return a string of the form '<name> list values </name>' to be used in the XML output. The list values are encoded such that they can be read and the list (which may be a list of lists, i.e. an ND array of values) be fully reconstructed from that XML. For use with extended types which can be expressed as a string using their __str__ member function. Arrays are encoded here as <name> ndim dim1 dim2 dim... dimn value value value ... </name> and the most rapidly varying dimension among the values is the last dimension. """ listDims = pyasdm.utils.getListDims(value) result = "<%s> " % name result += Parser.listXMLPrefix(listDims) result += Parser.listExtendedValuesAsString(value, listDims) result += "</%s> " % name return result
[docs] @staticmethod def listEnumValueToXML(name, value): """ Return a string of the form '<name> list values </name>' to be used in the XML output. The list values are encoded such that they can be read and the list (which may be a list of lists, i.e. an ND array of values) be fully reconstructed from that XML. For use with enumeration which can be expressed as a string using their name() member function. Arrays are encoded here as <name> ndim dim1 dim2 dim... dimn value value value ... </name> and the most rapidly varying dimension among the values is the last dimension. """ listDims = pyasdm.utils.getListDims(value) result = "<%s> " % name result += Parser.listXMLPrefix(listDims) result += Parser.listEnumValuesAsString(value, listDims) result += "</%s> " % name return result
[docs] @staticmethod def splitStrToClassLists(splitStr, dims, ListClass): result = [] if len(dims) == 1: # this is the result # pull the values off of splitStr and return the altered splitStr and the list it made for k in range(dims[0]): result.append(ListClass(splitStr[k])) splitStr = splitStr[dims[0] :] return (splitStr, result) # else loop through this value and then recursively call this for k in range(dims[0]): splitStr, thisResult = Parser.splitStrToClassLists( splitStr, dims[1:], ListClass ) result.append(thisResult) return (splitStr, result)
[docs] @staticmethod def splitStrToExtendedClassLists(splitStr, dims, ListClass): result = [] if len(dims) == 1: # this is the result # pull the values off of splitStr and return the altered splitStr and the list it made for k in range(dims[0]): thisItem, splitStr = ListClass.getInstance(splitStr) result.append(thisItem) return (splitStr, result) # else loop through this value and then recursively call this for k in range(dims[0]): splitStr, thisResult = Parser.splitStrToExtendedClassLists( splitStr, dims[1:], ListClass ) result.append(thisResult) return (splitStr, result)
[docs] @staticmethod def stringListToLists(strlist, ListClass, tableName, isExtendedType): """ Parse an array expessed in strlist into a list (including lists of list) made up of elements of ListClass that can all be constructed from strings in that list. Some extended type instances use more than one element. When isExtendedType is True then the appropriate function to extra extended type values is used. The tableName is used when raising ConversionException to indicate the responsible table. """ splitStr = strlist.split() # parse the dimensions, which must be integers # there must be at least 2 elements if len(splitStr) < 2: raise ConversionException( "invalid strlist, must be at least 2 elements. ListClass is " + type(ListClass), tableName, ) ndim = int(splitStr[0]) # now there must be at least (ndim+1) elements if len(splitStr) < (ndim + 1): raise ConversionException( "invalid strlist, not enough elements given first value. ListClass is " + type(ListClass), tableName, ) dims = [] count = 1 for i in range(1, (ndim + 1)): dims.append(int(splitStr[i])) count *= dims[i - 1] if len(splitStr) < (count + 2): raise ConversionException( "invalid strlist, not enough elements in string, ListClass is " + str(ListClass), tableName, ) try: if isExtendedType: newstr, result = Parser.splitStrToExtendedClassLists( splitStr[(ndim + 1) :], dims, ListClass ) else: newstr, result = Parser.splitStrToClassLists( splitStr[(ndim + 1) :], dims, ListClass ) except Exception as exc: # raise a ConversionException for anything this unexpected raise ConversionException( "Unexpected exception " + str(exc) + ", ListClass is " + str(ListClass), tableName, ) return result