Exemplo n.º 1
0
    def _write(self,
               data:    SerializeTypes,
               codec:   Codec,
               context: 'VerediContext') -> StringIO:
        '''
        Write data from a single data stream.

        Returns:
          Output of yaml.safe_dump().
          Mix of:
            - yaml objects
            - our subclasses of yaml objects
            - and python objects

        Raises:
          - exceptions.WriteError
          Maybes:
            - Other yaml/stream errors?
        '''
        self._log_data_processing(self.dotted,
                                  "Writing '{}' to stream...",
                                  type(data),
                                  context=context)
        serialized = StringIO()
        try:
            yaml.safe_dump(data,
                           default_sequence=yaml.SequenceStyle.DEFAULT,
                           stream=serialized)
            # TODO [2020-07-04]: may need to evaluate this in some way to get
            # it past its lazy writing... I want to catch any yaml exceptions
            # here and not let them infect unrelated code.

        except yaml.YAMLError as yaml_error:
            serialized = None
            msg = 'YAML failed while writing the data.'
            self._log_data_processing(self.dotted,
                                      msg,
                                      context=context,
                                      success=False)
            error = exceptions.WriteError(msg,
                                          context=context,
                                          data={
                                              'data': data,
                                          })
            raise log.exception(error, msg, context=context) from yaml_error

        # Apparently yaml doesn't give us the spot in the stream it started
        # writing, so rewind.
        serialized.seek(0)

        self._log_data_processing(self.dotted,
                                  "Wrote '{}' to YAML!",
                                  type(data),
                                  context=context,
                                  success=True)
        return serialized
Exemplo n.º 2
0
    def _write_all(self,
                   data:    SerializeTypes,
                   codec:   Codec,
                   context: 'VerediContext') -> StringIO:
        '''
        Write data from a single data stream.

        Returns:
          Output of yaml.safe_dump_all().
          Mix of:
            - yaml objects
            - our subclasses of yaml objects
            - and python objects

        Raises:
          - exceptions.WriteError
          Maybes:
            - Other yaml/stream errors?
        '''

        self._log_data_processing(self.dotted,
                                  "Writing all '{}' to stream...",
                                  type(data),
                                  context=context)

        serialized = StringIO()
        try:
            yaml.safe_dump_all(data,
                               default_sequence=yaml.SequenceStyle.DEFAULT,
                               stream=serialized)

        except yaml.YAMLError as yaml_error:
            serialized = None
            msg = 'YAML failed while writing all the data.'
            self._log_data_processing(self.dotted,
                                      msg,
                                      context=context,
                                      success=False)
            error = exceptions.WriteError(msg,
                                          context=context,
                                          data={
                                              'data': data,
                                          })
            raise log.exception(error, msg, context=context) from yaml_error

        # Apparently yaml doesn't give us the spot in the stream it started
        # writing, so rewind.
        serialized.seek(0)

        self._log_data_processing(self.dotted,
                                  "Wrote '{}' to YAML!",
                                  type(data),
                                  context=context,
                                  success=True)
        return serialized
Exemplo n.º 3
0
    def _write(self,
               data:    SerializeTypes,
               codec:   Codec,
               context: 'VerediContext') -> StringIO:
        '''
        Write data to a stream.

        Returns:
          The stream with the serialized data in it.

        Raises:
          - exceptions.WriteError
            - wrapped lib/module errors
        '''
        self._log_data_processing(self.dotted,
                                  "Writing '{}' to stream...",
                                  type(data),
                                  context=context)
        serialized = StringIO()
        try:
            self._json_dump(data, serialized, context)
        except (TypeError, OverflowError, ValueError) as json_error:
            serialized = None
            # data_pretty = pretty.indented(data)
            msg = f"Error writing data '{type(data)}' to stream."
            self._log_data_processing(self.dotted,
                                      msg,
                                      context=context,
                                      success=False)
            error = exceptions.WriteError(msg,
                                          context=context,
                                          data={
                                              'data': data,
                                          })
            raise log.exception(error, msg,
                                context=context) from json_error

        self._log_data_processing(self.dotted,
                                  "Wrote '{}' to JSON!",
                                  type(data),
                                  context=context,
                                  success=True)
        return serialized
Exemplo n.º 4
0
    def serialize_all(self,
                      data:    SerializeTypes,
                      codec:   Codec,
                      context: 'VerediContext') -> StringIO:
        '''
        Serializes data from an iterable of data objects. Each will be a
        separate yaml doc in the output.

        Raises:
          - exceptions.WriteError
        '''
        self._log_data_processing(self.dotted,
                                  "Serializing all from '{}'...",
                                  type(data),
                                  context=context)

        to_serialize = self._serialize_prep(data, codec, context)
        self._context_data(context, DataAction.SAVE, codec)
        output = self._write_all(to_serialize, codec, context)
        if not output:
            msg = (f"Serializing all yaml from data "
                   "resulted in no output: {output}")
            self._log_data_processing(self.dotted,
                                      msg,
                                      context=context,
                                      success=False)
            error = exceptions.WriteError(msg,
                                          context=context,
                                          data={
                                              'data': data,
                                          })
            raise log.exception(error, msg, context=context)

        # TODO: Here is where we'd check for sanity and stuff?

        self._log_data_processing(self.dotted,
                                  "Serialized all from '{}'!",
                                  type(data),
                                  context=context,
                                  success=True)
        return output
Exemplo n.º 5
0
    def serialize(self,
                  data:    SerializeTypes,
                  codec:   Codec,
                  context: 'VerediContext') -> StringIO:
        '''
        Serializes data from a single data object.

        Raises:
          - exceptions.WriteError
        '''
        self._log_data_processing(self.dotted,
                                  "Serializing from '{}'...",
                                  type(data),
                                  context=context)

        self._context_data(context, DataAction.SAVE, codec)
        to_serialize = self._serialize_prep(data, codec, context)
        output = self._write(to_serialize, codec, context)
        if not output:
            msg = f"Serializing yaml from data resulted in no output: {output}"
            self._log_data_processing(self.dotted,
                                      msg,
                                      context=context,
                                      success=False)
            error = exceptions.WriteError(msg,
                                          context=context,
                                          data={
                                              'data': data,
                                          })
            raise log.exception(error, msg, context=context)

        self._log_data_processing(self.dotted,
                                  "Serialized from '{}'!",
                                  type(data),
                                  context=context,
                                  success=True)
        return output
Exemplo n.º 6
0
    def _serialize_prep(self,
                        data:    SerializeTypes,
                        codec:   Codec,
                        context: 'VerediContext') -> Mapping[str, Any]:
        '''
        Tries to turn the various possibilities for data (list, dict, etc) into
        something ready for json to serialize.
        '''
        self._log_data_processing(self.dotted,
                                  "Serialize preparation...",
                                  context=context)
        serialized = None
        if null_or_none(data):
            self._log_data_processing(self.dotted,
                                      "No data to prep.",
                                      context=context)
            return serialized

        # Is it just an Encodable object?
        if isinstance(data, Encodable):
            self._log_data_processing(self.dotted,
                                      "Encoding `Encodable` data "
                                      "for serialization.",
                                      context=context)
            serialized = codec.encode(data)
            return serialized

        # Is it a simple type?
        if text.serialize_claim(data) or time.serialize_claim(data):
            # Let json handle it.
            serialized = data
            return serialized
        if paths.serialize_claim(data):
            serialized = paths.serialize(data)
            return serialized
        if numbers.serialize_claim(data):
            serialized = numbers.serialize(data)
            return serialized

        # Mapping?
        with contextlib.suppress(AttributeError, TypeError):
            # Do the thing that spawns the exception before
            # we log about doing the thing...
            keys = data.keys()
            self._log_data_processing(self.dotted,
                                      "Prepping `Mapping` of data "
                                      "for serialization.",
                                      context=context)
            serialized = {}
            for each in keys:
                # TODO [2020-07-29]: Change to non-recursive?
                serialized[str(each)] = self._serialize_prep(data[each],
                                                             codec,
                                                             context)
            return serialized

        # Iterable
        with contextlib.suppress(AttributeError, TypeError):
            # Do the thing that spawns the exception before
            # we log about doing the thing...
            iterable = iter(data)
            self._log_data_processing(self.dotted,
                                      "Prepping `Iterable` of data "
                                      "for serialization.",
                                      context=context)
            serialized = []
            for each in iterable:
                # TODO [2020-07-29]: Change to non-recursive?
                serialized.append(self._serialize_prep(each, codec, context))
            return serialized

        # Falling through to here is bad; raise Exception.
        msg = f"Don't know how to process '{type(data)}' data."
        self._log_data_processing(self.dotted,
                                  msg,
                                  context=context,
                                  success=False)
        error = exceptions.WriteError(msg,
                                      context=context,
                                      data={
                                          'data': data,
                                      })
        raise log.exception(error, msg,
                            context=context)