Returns an iterator for the data in the key or nothing if the key
        doesn't exist. Decompresses data on the fly (if compressed is True
        or key ends with .gz) unless raw is True. Pass None for encoding to
        skip encoding.

def cat(
        self,
        source,
        buffersize=None,
        memsize=2 ** 24,
        compressed=False,
        encoding='UTF-8',
        raw=False,
    ):
        """
        Returns an iterator for the data in the key or nothing if the key
        doesn't exist. Decompresses data on the fly (if compressed is True
        or key ends with .gz) unless raw is True. Pass None for encoding to
        skip encoding.

        """
        assert self._is_s3(source) or isinstance(source, Key), 'source must be a valid s3 path'

        key = self._get_key(source) if not isinstance(source, Key) else source
        compressed = (compressed or key.name.endswith('.gz')) and not raw
        if compressed:
            decompress = zlib.decompressobj(16 + zlib.MAX_WBITS)

        size = 0
        bytes_read = 0
        err = None
        undecoded = ''
        if key:
            # try to read the file multiple times
            for i in range(100):
                obj = self.s3.Object(key.bucket.name, key.name)
                buffersize = buffersize if buffersize is not None else 2 ** 20

                if not size:
                    size = obj.content_length
                elif size != obj.content_length:
                    raise AwsError('key size unexpectedly changed while reading')

                r = obj.get(Range="bytes={}-".format(bytes_read))

                try:
                    while bytes_read < size:
                        # this making this weird check because this call is
                        # about 100 times slower if the amt is too high
                        if size - bytes_read > buffersize:
                            bytes = r['Body'].read(amt=buffersize)
                        else:
                            bytes = r['Body'].read()
                        if compressed:
                            s = decompress.decompress(bytes)
                        else:
                            s = bytes

                        if encoding and not raw:
                            try:
                                decoded = undecoded + s.decode(encoding)
                                undecoded = ''
                                yield decoded
                            except UnicodeDecodeError:
                                undecoded += s
                                if len(undecoded) > memsize:
                                    raise
                        else:
                            yield s

                        bytes_read += len(bytes)

                except zlib.error:
                    logger.error("Error while decompressing [%s]", key.name)
                    raise
                except UnicodeDecodeError:
                    raise
                except Exception:
                    err = True
                    pass

                if size <= bytes_read:
                    break

            if size != bytes_read:
                if err:
                    raise Exception
                else:
                    raise AwsError('Failed to fully read [%s]' % source.name)

            if undecoded:
                assert encoding is not None  # only time undecoded is set

                # allow exception to be raised if one is thrown
                decoded = undecoded.decode(encoding)
                yield decoded