Beispiel #1
0
 def sequenceExpander(expander,
                      minfNode,
                      minfNodeIterator,
                      target,
                      targetType,
                      stop_on_error=True,
                      exceptions=[]):
     if target is None:
         result = []
     else:
         result = target
         while len(result) != 0:
             result.pop()
     if isinstance(targetType, Sequence) and targetType.elementType.mutable:
         length = minfNode.attributes.get('length')
         if length and len(result) < int(length):
             result += [
                 targetType.elementType.createValue()
                 for i in xrange(int(length) - len(result))
             ]
     itTarget = iter(result)
     for minfNode in minfNodeIterator:
         if isinstance(minfNode, EndStructure):
             if minfNode.type != listStructure:
                 raise MinfError(
                     _('Wrong Minf structure ending, expecting %(exp)s instead of %(rcv)s'
                       ) % {
                           'exp': listStructure,
                           'rcv': minfNode.type
                       })
             break
         else:
             target = None
             if itTarget is not None:
                 try:
                     target = next(itTarget)
                 except StopIteration:
                     itTarget = None
             if target is not None:
                 r = expander.expand(minfNodeIterator,
                                     minfNode,
                                     target=target,
                                     targetType=targetType.elementType,
                                     stop_on_error=stop_on_error,
                                     exceptions=exceptions)
                 result.append(r)
             else:
                 try:
                     result.append(
                         expander.expand(minfNodeIterator,
                                         minfNode,
                                         stop_on_error=stop_on_error,
                                         exceptions=exceptions))
                 except Exception as e:
                     if stop_on_error:
                         raise e
                     else:
                         result.append(None)
                         exceptions.append(sys.exc_info())
     return result
Beispiel #2
0
def createMinfReducer(name):
    '''
    Return an instance of L{MinfReducer} previously registered.

    @param name: name of the reducer
    @type  name: string
    '''
    reducer = MinfReducer._allReducers.get(name)
    if reducer is None:
        raise MinfError(_('Unknown Minf reducer: %s') % (name, ))
    return reducer
Beispiel #3
0
 def getTypeExpander(self, structureName):
     expander = self.typeExpanders.get(structureName)
     if expander is None:
         for base in self.bases:
             expander = base.getTypeExpander(structureName)
             if expander is not None:
                 break
         else:
             raise MinfError(
                 _('Minf structure %(struct)s cannot be expanded '
                   'from Minf "%(minf)s" structure') % {
                       'struct': structureName,
                       'minf': self.name
                   })
     return expander
Beispiel #4
0
 def getTypeReducer(self, classOrName):
     if not isinstance(classOrName, six.string_types):
         className = classOrName.__module__ + '.' + classOrName.__name__
     else:
         className = classOrName
     reducer = self.typeReducers.get(className)
     if reducer is None:
         for base in self.bases:
             reducer = base.getTypeReducer(className)
             if reducer is not None:
                 break
         else:
             if issubclass(classOrName, HasSignature):
                 return self.hasSignatureReducer
                 raise MinfError(
                     _('Automatic reduction of HasSignature not implemented'
                       ))
             raise MinfError(
                 _('Object of type %(class)s cannot be reduced '
                   'in Minf "%(minf)s" structure') % {
                       'class': className,
                       'minf': self.name
                   })
     return reducer
Beispiel #5
0
 def expand(self,
            minfNodeIterator,
            minfNode=Undefined,
            target=None,
            targetType=Undefined,
            stop_on_error=True,
            exceptions=[]):
     if minfNode is Undefined:
         if sys.version_info[0] >= 3:
             minfNode = next(minfNodeIterator)
         else:
             minfNode = minfNodeIterator.next()
     if isinstance(minfNode, StartStructure):
         identifier = minfNode.identifier
         typeExpander = self.getTypeExpander(minfNode.type)
         try:
             result = typeExpander(self,
                                   minfNode,
                                   minfNodeIterator,
                                   target=target,
                                   targetType=targetType,
                                   stop_on_error=stop_on_error,
                                   exceptions=exceptions)
         except Exception as e:
             if stop_on_error:
                 raise
             else:
                 result = None
                 exceptions.append(sys.exc_info())
         if identifier is not None:
             self.objectsWithIdentifier[identifier] = result
         return result
     elif isinstance(minfNode, EndStructure):
         raise MinfError(
             _('Minf structure %s ended but not started') %
             (minfNode.type, ))
     elif isinstance(minfNode, Reference):
         return self.objectsWithIdentifier[minfNode.identifier]
     else:
         return minfNode
Beispiel #6
0
 def __call__(self,
              expander,
              minfNode,
              minfNodeIterator,
              target,
              targetType,
              stop_on_error=True,
              exceptions=[]):
     structureName = minfNode.type
     args = []
     kwargs = {}
     for minfNode in minfNodeIterator:
         if isinstance(minfNode, EndStructure):
             if minfNode.type != structureName:
                 raise MinfError(
                     _('Wrong Minf structure ending, expecting %(exp)s instead of %(rcv)s'
                       ) % {
                           'exp': structureName,
                           'rcv': minfNode.type
                       })
             break
         else:
             key = expander.expand(minfNodeIterator,
                                   minfNode,
                                   stop_on_error=stop_on_error,
                                   exceptions=exceptions)
             try:
                 value = expander.expand(minfNodeIterator,
                                         stop_on_error=stop_on_error,
                                         exceptions=exceptions)
                 if key is None:
                     args.append(value)
                 else:
                     kwargs[str(key)] = value
             except Exception as e:
                 if stop_on_error:
                     raise e
                 else:
                     exceptions.append(sys.exc_info())
     return self.factory(*args, **kwargs)
Beispiel #7
0
def minfFormat(source):
    '''
    Return a pair (format, reduction) identifying the minf format. If
    source is not a minf file, (None, None) is returned. Otherwise,
    format is a string representing the format of the minf file: 'XML' or
    'python'. reduction is the name of the reducer used to write the minf
    file or None if format is 'python'.

    Example:

    ::

      from soma.minf.api import minfFormat
      format, reduction = minfFormat('/home/me/test.minf')

    If source is a :class:`BufferAndFile` instance, this call behave as if nothing
    has been read from the file. This can be useful if you have an opened file
    that cannot be seeked backward:

    Example:

    ::

      from soma.bufferandfile import BufferAndFile
      from soma.minf.api import minfFormat, readMinf

      bf = BufferAndFile(stream_file_object)
      format, reduction = minfFormat(bf)
      if format is not None:
        minfContent = readMinf(bf)


    Parameters
    ----------
    source: string
      Input file name or file object. If it is a file name, it is
      opened with open(source).
    '''
    if not hasattr(source, 'readline'):
        source = BufferAndFile(open(source))
    elif not isinstance(source, BufferAndFile):
        source.seek(0)
        source = BufferAndFile(source)

    # Check first non white character to see if the minf file is XML or not
    start = source.read(5)
    if start == 'attri':
        source.unread(start)
        return ('python', None)
    elif start != '<?xml':
        # Try gzip compressed file
        gzipSource = source.clone()
        gzipSource.unread(start)
        gunzipSource = gzip.GzipFile(source.name)
        try:
            start = gunzipSource.read(5)
        except IOError:
            start = ''
        if start != '<?xml':
            raise MinfError(_('Invalid minf file: %s') % (source.name, ))
        source.change_file(gunzipSource)
        source.unread(start)
    else:
        source.unread(start)

    r = MinfReader.createReader('XML')
    reduction, buffer = r.reduction(source)
    source.unread(buffer)
    return ('XML', reduction)
Beispiel #8
0
def iterateMinf(source, targets=None, stop_on_error=True, exceptions=[]):
    '''
    Returns an iterator over all objects stored in a minf file.

    Example:

    ::

      from soma.minf.api import iterateMinf

      for item in iterateMinf('test.minf'):
        print(repr(item))

    Parameters
    ----------
    source: string
      Input file name or file object. If it is a file name, it is
      opened with C{open( source )}.
    '''
    if targets is not None:
        targets = iter(targets)

    initial_source = source

    if sys.version_info[0] >= 3 and not hasattr(initial_source, 'readline'):
        # in python3 the encoding of a file should be specified when opening
        # it: it cannot be changed afterwards. So in python3 we cannot read
        # the encoding within the file (for instance in a XML file).
        # This is completely silly, but here it is...
        # So we just have to try several encodings...
        try_encodings = ['UTF-8', 'latin1']
    else:
        try_encodings = [None]

    for encoding in try_encodings:
        if not hasattr(initial_source, 'readline'):
            if sys.version_info[0] >= 3:
                source = BufferAndFile(open(initial_source, encoding=encoding))
            else:
                source = BufferAndFile(open(initial_source))
        elif not isinstance(source, BufferAndFile):
            source.seek(0)
            source = BufferAndFile(source)

        try:
            # Check first non white character to see if the minf file is XML or not
            start = source.read(5)
            source.unread(start)
            if sys.version_info[0] >= 3:

                def next(it):
                    return it.__next__()
            else:

                def next(it):
                    return it.next()

            if start == 'attri':
                try:
                    import numpy
                    d = {'nan': numpy.nan}
                except:
                    d = {'nan': None}
                try:
                    six.exec_(source.read().replace("\r\n", "\n"), d)
                except Exception as e:
                    x = source
                    if hasattr(source, '_BufferAndFile__file'):
                        x = source._BufferAndFile__file
                    x = 'Error in iterateMinf while reading ' + str(x) + ': '
                    msg = x + e.message
                    # e.message = msg
                    # e.args = ( x + e.args[0], ) + e.args[1:]
                    print(x)
                    raise
                minf = d['attributes']
                if targets is not None:
                    result = next(targets)
                    _setTarget(result, minf)
                    yield result
                else:
                    yield minf
                return
            elif start != '<?xml':
                # Try gzip compressed file
                gzSource = gzip.GzipFile(source.name)
                if gzSource.read(5) != '<?xml':
                    raise MinfError(
                        _('Invalid minf file: %s') % (source.name, ))
                source = BufferAndFile(gzSource)
                source.unread('<?xml')

            r = MinfReader.createReader('XML')
            iterator = r.nodeIterator(source)
            minfNode = next(iterator)
            expander = createMinfExpander(minfNode.attributes['reduction'])
            count = 0
            for nodeItem in iterator:
                count += 1
                if isinstance(nodeItem, EndStructure):
                    break
                target = None
                if targets is not None:
                    try:
                        target = next(targets)
                    except StopIteration:
                        targets = None
                yield expander.expand(iterator,
                                      nodeItem,
                                      target=target,
                                      stop_on_error=stop_on_error,
                                      exceptions=exceptions)
        except UnicodeDecodeError as e:
            if encoding == try_encodings[-1]:
                raise
            continue
        break  # no error, don't process next encoding
Beispiel #9
0
    def dictExpander(expander,
                     minfNode,
                     minfNodeIterator,
                     target,
                     targetType,
                     stop_on_error=True,
                     exceptions=[]):
        if target is None:
            result = {}
        else:
            result = target
        for minfNode in minfNodeIterator:
            if isinstance(minfNode, EndStructure):
                if minfNode.type != dictStructure:
                    raise MinfError(
                        _('Wrong Minf structure ending, expectinf %(exp)s instead of %(rcv)s'
                          ) % {
                              'exp': dictStructure,
                              'rcv': minfNode.type
                          })
                break
            else:
                key = expander.expand(minfNodeIterator,
                                      minfNode,
                                      stop_on_error=stop_on_error,
                                      exceptions=exceptions)
                if isinstance(key, list):
                    # list objects are unhashable and cannot be used as dictionary key
                    # in this case they are converted to tuple
                    key = tuple(key)
                if isinstance(result, HasSignature):
                    targetType = result.signature.get(key, Undefined)
                    if targetType is not Undefined:
                        targetType = targetType.type
                    target = getattr(result, key, None)
                    try:
                        if isinstance(target, HasSignature) or isinstance(
                                targetType, Sequence):
                            value = expander.expand(
                                minfNodeIterator,
                                target=target,
                                targetType=targetType,
                                stop_on_error=stop_on_error,
                                exceptions=exceptions)
                        else:
                            value = expander.expand(
                                minfNodeIterator,
                                stop_on_error=stop_on_error,
                                exceptions=exceptions)
                        setattr(result, key, value)
                    except Exception as e:
                        if stop_on_error:
                            raise
                        else:
                            exceptions.append(sys.exc_info())

                else:
                    try:
                        value = expander.expand(minfNodeIterator,
                                                stop_on_error=stop_on_error,
                                                exceptions=exceptions)
                        result[key] = value
                    except Exception as e:
                        if stop_on_error:
                            raise
                        else:
                            exceptions.append(sys.exc_info())

        return result
Beispiel #10
0
    def _write(self, minfNodeIterator, minfNode, level, name):
        if minfNode is Undefined:
            if sys.version_info[0] >= 3:
                minfNode = next(minfNodeIterator)
            else:
                minfNode = minfNodeIterator.next()
        attributes = {}
        if name is not None:
            attributes[nameAttribute] = name
        if isinstance(minfNode, StartStructure):
            if minfNode.type == listStructure:
                naming = False
                stringNaming = False
                length = minfNode.attributes.get('length')
                if length:
                    attributes[lengthAttribute] = length
                tag = listTag
            elif minfNode.type == dictStructure:
                naming = True
                stringNaming = False
                length = minfNode.attributes.get('length')
                if length:
                    attributes[lengthAttribute] = length
                tag = dictionaryTag
            else:
                naming = True
                stringNaming = True
                tag = factoryTag
                attributes[objectTypeAttribute] = minfNode.type
            if attributes:
                attributes = ' ' + \
                    ' '.join([n + '=' + xml_quoteattr(unicode(v))
                             for n, v in six.iteritems(attributes)])
            else:
                attributes = ''
            self._encodeAndWriteLine('<' + tag + attributes + '>', level)
            ntype = minfNode.type
            for minfNode in minfNodeIterator:
                if isinstance(minfNode, EndStructure):
                    if ntype != minfNode.type:
                        raise MinfError(
                            _('Wrong Minf structure ending, expecting %(exp)s instead of %(rcv)s'
                              ) % {
                                  'exp': ntype,
                                  'rcv': minfNode.type
                              })
                    self._encodeAndWriteLine('</' + tag + '>', level)
                    break
                elif naming:
                    if isinstance(minfNode, six.string_types):
                        self._write(minfNodeIterator, Undefined, level + 1,
                                    minfNode)
                    elif minfNode is None:
                        if not stringNaming:
                            self._write(minfNodeIterator, minfNode, level + 1,
                                        None)
                        self._write(minfNodeIterator, Undefined, level + 1,
                                    None)
                    else:
                        self._write(minfNodeIterator, minfNode, level + 1,
                                    None)
                        self._write(minfNodeIterator, Undefined, level + 1,
                                    None)
                else:
                    self._write(minfNodeIterator, minfNode, level + 1, None)
        elif isinstance(minfNode, EndStructure):
            raise MinfError(
                _('Unexpected Minf structure ending: %s') % (minfNode.type, ))
            level -= 1
        else:
            if attributes:
                attributesXML = ' ' + \
                    ' '.join([n + '=' + xml_quoteattr(unicode(v))
                             for n, v in six.iteritems(attributes)])
            else:
                attributesXML = ''
            if minfNode is None:
                self._encodeAndWriteLine('<' + noneTag + attributesXML + '/>',
                                         level)
            elif isinstance(minfNode, bool):
                if minfNode:
                    self._encodeAndWriteLine(
                        '<' + trueTag + attributesXML + '/>', level)
                else:
                    self._encodeAndWriteLine(
                        '<' + falseTag + attributesXML + '/>', level)
            elif isinstance(minfNode, (int, float, long)):
                self._encodeAndWriteLine(
                    '<' + numberTag + attributesXML + '>' + unicode(minfNode) +
                    '</' + numberTag + '>', level)
            elif isinstance(minfNode, six.string_types):

                if type(minfNode) is byte_type:
                    try:
                        minfNode = minfNode.decode("utf-8")
                    except UnicodeDecodeError:
                        minfNode = minfNode.decode("iso-8859-1")
                self._encodeAndWriteLine(
                    '<' + stringTag + attributesXML + '>' +
                    xml_escape(minfNode, xml_replacement) + '</' + stringTag +
                    '>', level)
            elif hasattr(minfNode, '__minfxml__'):
                minfNode.__minfxml__(self, attributes, level)
            else:
                raise MinfError(
                    _('Cannot save an object of type %s as an XML atom') %
                    (str(type(minfNode)), ))
Beispiel #11
0
 def fatalError(self, error):
     raise MinfError(_('XML parse error: %s') %
                    (unicode(error), ) + ' (stack = ' +
                     ','.join(['"' + i + '"' for i in self._stack]) + ')')